25 #include "llvm/ADT/StringSet.h" 26 #include "llvm/ADT/TypeSwitch.h" 27 #include "llvm/IR/Attributes.h" 28 #include "llvm/IR/Constants.h" 29 #include "llvm/IR/DerivedTypes.h" 30 #include "llvm/IR/Function.h" 31 #include "llvm/IR/InlineAsm.h" 32 #include "llvm/IR/Instructions.h" 33 #include "llvm/IR/Intrinsics.h" 34 #include "llvm/IR/Type.h" 35 #include "llvm/IRReader/IRReader.h" 36 #include "llvm/Support/Error.h" 37 #include "llvm/Support/SourceMgr.h" 42 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc" 47 static std::string
diag(llvm::Value &v) {
49 llvm::raw_string_ostream os(s);
59 auto i32 = IntegerType::get(&ctx, 32);
61 StringRef abiString, preferredString;
62 std::tie(abiString, preferredString) = spec.split(
':');
64 if (abiString.getAsInteger(10, abi))
67 if (preferredString.empty())
69 else if (preferredString.getAsInteger(10, preferred))
94 DataLayoutSpecInterface
97 assert(context &&
"expected MLIR context");
98 std::string layoutstr = dataLayout.getStringRepresentation();
104 "p:64:64:64-S0-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f16:16:16-f64:" 105 "64:64-f128:128:128-v64:64:64-v128:128:128-a:0:64";
106 if (layoutstr.empty())
109 layoutstr = layoutstr +
"-" + append;
111 StringRef layout(layoutstr);
115 while (!layout.empty()) {
117 std::pair<StringRef, StringRef> split = layout.split(
'-');
119 std::tie(current, layout) = split;
122 StringRef kind, spec;
123 std::tie(kind, spec) = current.split(
':');
124 if (seen.contains(kind))
128 char symbol = kind.front();
129 StringRef parameter = kind.substr(1);
131 if (symbol ==
'i' || symbol ==
'f') {
133 if (parameter.getAsInteger(10, bitwidth))
139 symbol ==
'i' ? static_cast<Type>(IntegerType::get(context, bitwidth))
142 entries.emplace_back(entry);
143 }
else if (symbol ==
'e' || symbol ==
'E') {
144 auto value = StringAttr::get(
145 context, symbol ==
'e' ? DLTIDialect::kDataLayoutEndiannessLittle
146 : DLTIDialect::kDataLayoutEndiannessBig);
148 StringAttr::get(context, DLTIDialect::kDataLayoutEndiannessKey),
150 entries.emplace_back(entry);
162 : b(context), context(context), module(module),
163 unknownLoc(FileLineColLoc::get(context,
"imported-bitcode", 0, 0)),
164 typeTranslator(*context) {
165 b.setInsertionPointToStart(module.getBody());
172 GlobalOp processGlobal(llvm::GlobalVariable *gv);
182 Type processType(llvm::Type *type);
190 Location processDebugLoc(
const llvm::DebugLoc &loc,
191 llvm::Instruction *inst =
nullptr);
196 llvm::BasicBlock *target,
216 Block *currentEntryBlock =
nullptr;
220 auto it = module.getBody()->
begin();
221 auto endIt = module.getBody()->end();
222 while (it != endIt && !isa<LLVMFuncOp>(it))
229 return std::prev(module.getBody()->end());
248 Location Importer::processDebugLoc(
const llvm::DebugLoc &loc,
249 llvm::Instruction *inst) {
252 llvm::raw_string_ostream os(s);
253 os <<
"llvm-imported-inst-%";
254 inst->printAsOperand(os,
false);
255 return FileLineColLoc::get(context, os.str(), 0, 0);
261 return FileLineColLoc::get(context,
"imported-bitcode", loc.getLine(),
265 Type Importer::processType(llvm::Type *type) {
266 if (
Type result = typeTranslator.translateType(type))
272 llvm::raw_string_ostream os(s);
274 emitError(unknownLoc) <<
"unhandled type: " << os.str();
283 Type Importer::getStdTypeForAttr(
Type type) {
293 if (numElements.isScalable()) {
294 emitError(unknownLoc) <<
"scalable vectors not supported";
300 return VectorType::get(numElements.getKnownMinValue(), elementType);
307 shape.push_back(arrayType.getNumElements());
309 arrayType = arrayType.getElementType().cast<
LLVMArrayType>();
310 shape.push_back(arrayType.getNumElements());
317 if (numElements.isScalable()) {
318 emitError(unknownLoc) <<
"scalable vectors not supported";
321 shape.push_back(numElements.getKnownMinValue());
323 Type elementType = getStdTypeForAttr(
327 return VectorType::get(shape, elementType);
331 Type elementType = getStdTypeForAttr(arrayType.getElementType());
334 return RankedTensorType::get(shape, elementType);
343 if (
auto *ci = dyn_cast<llvm::ConstantInt>(value))
344 return b.getIntegerAttr(
345 IntegerType::get(context, ci->getType()->getBitWidth()),
347 if (
auto *c = dyn_cast<llvm::ConstantDataArray>(value))
349 return b.getStringAttr(c->getAsString());
350 if (
auto *c = dyn_cast<llvm::ConstantFP>(value)) {
351 auto *type = c->getType();
353 if (type->isBFloatTy())
357 assert(floatTy &&
"unsupported floating point type");
358 return b.getFloatAttr(floatTy, c->getValueAPF());
360 if (
auto *f = dyn_cast<llvm::Function>(value))
361 return SymbolRefAttr::get(b.getContext(), f->getName());
364 if (
auto *cd = dyn_cast<llvm::ConstantDataSequential>(value)) {
365 Type type = processType(cd->getElementType());
369 auto attrType = getStdTypeForAttr(processType(cd->getType()))
374 if (type.
isa<IntegerType>()) {
376 values.reserve(cd->getNumElements());
377 for (
unsigned i = 0, e = cd->getNumElements(); i < e; ++i)
378 values.push_back(cd->getElementAsAPInt(i));
382 if (type.
isa<Float32Type, Float64Type>()) {
384 values.reserve(cd->getNumElements());
385 for (
unsigned i = 0, e = cd->getNumElements(); i < e; ++i)
386 values.push_back(cd->getElementAsAPFloat(i));
395 if (isa<llvm::ConstantAggregate>(value)) {
396 auto outerType = getStdTypeForAttr(processType(value->getType()))
397 .dyn_cast_or_null<ShapedType>();
404 for (
unsigned i = 0, e = value->getNumOperands(); i < e; ++i) {
405 auto nested = getConstantAsAttr(value->getAggregateElement(i))
406 .dyn_cast_or_null<DenseElementsAttr>();
410 values.append(nested.value_begin<
Attribute>(),
420 GlobalOp Importer::processGlobal(llvm::GlobalVariable *gv) {
421 auto it = globals.find(gv);
422 if (it != globals.end())
425 OpBuilder b(module.getBody(), getGlobalInsertPt());
427 if (gv->hasInitializer())
428 valueAttr = getConstantAsAttr(gv->getInitializer());
429 Type type = processType(gv->getValueType());
433 uint64_t alignment = 0;
434 llvm::MaybeAlign maybeAlign = gv->getAlign();
435 if (maybeAlign.hasValue()) {
436 llvm::Align align = maybeAlign.getValue();
437 alignment = align.value();
440 GlobalOp op = b.create<GlobalOp>(
441 UnknownLoc::get(context), type, gv->isConstant(),
442 convertLinkageFromLLVM(gv->getLinkage()), gv->getName(), valueAttr,
443 alignment, gv->getAddressSpace(),
444 gv->isDSOLocal(), gv->isThreadLocal());
446 if (gv->hasInitializer() && !valueAttr) {
447 Region &r = op.getInitializerRegion();
448 currentEntryBlock = b.createBlock(&r);
449 b.setInsertionPoint(currentEntryBlock, currentEntryBlock->begin());
450 Value v = processConstant(gv->getInitializer());
455 if (gv->hasAtLeastLocalUnnamedAddr())
456 op.setUnnamedAddrAttr(UnnamedAddrAttr::get(
457 context, convertUnnamedAddrFromLLVM(gv->getUnnamedAddr())));
458 if (gv->hasSection())
459 op.setSectionAttr(b.getStringAttr(gv->getSection()));
461 return globals[gv] = op;
465 OpBuilder bEntry(currentEntryBlock, currentEntryBlock->begin());
466 if (
Attribute attr = getConstantAsAttr(c)) {
468 OpBuilder b(currentEntryBlock, currentEntryBlock->begin());
469 Type type = processType(c->getType());
473 return bEntry.create<AddressOfOp>(unknownLoc, type, symbolRef.getValue());
474 return bEntry.create<ConstantOp>(unknownLoc, type, attr);
476 if (
auto *cn = dyn_cast<llvm::ConstantPointerNull>(c)) {
477 Type type = processType(cn->getType());
480 return bEntry.create<NullOp>(unknownLoc, type);
482 if (
auto *gv = dyn_cast<llvm::GlobalVariable>(c))
483 return bEntry.create<AddressOfOp>(UnknownLoc::get(context),
486 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(c)) {
487 llvm::Instruction *i = ce->getAsInstruction();
489 b.setInsertionPoint(currentEntryBlock, currentEntryBlock->begin());
490 if (
failed(processInstruction(i)))
492 assert(instMap.count(i));
507 if (
auto *ue = dyn_cast<llvm::UndefValue>(c)) {
508 Type type = processType(ue->getType());
511 return bEntry.create<UndefOp>(UnknownLoc::get(context), type);
514 if (isa<llvm::ConstantAggregate>(c) || isa<llvm::ConstantAggregateZero>(c)) {
515 unsigned numElements = c->getNumOperands();
516 std::function<llvm::Constant *(unsigned)> getElement =
518 return c->getAggregateElement(index);
522 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(c)) {
523 numElements = caz->getElementCount().getFixedValue();
528 return caz->getElementValue(index);
533 Type rootType = processType(c->getType());
538 "unrecognized aggregate type");
539 Value root = bEntry.create<UndefOp>(unknownLoc, rootType);
540 for (
unsigned i = 0; i < numElements; ++i) {
542 Value elementValue = processConstant(element);
545 if (useInsertValue) {
546 ArrayAttr indexAttr = bEntry.getI32ArrayAttr({
static_cast<int32_t
>(i)});
547 root = bEntry.create<InsertValueOp>(UnknownLoc::get(context), rootType,
548 root, elementValue, indexAttr);
550 Attribute indexAttr = bEntry.getI32IntegerAttr(static_cast<int32_t>(i));
551 Value indexValue = bEntry.create<ConstantOp>(
552 unknownLoc, bEntry.getI32Type(), indexAttr);
555 root = bEntry.create<InsertElementOp>(
556 UnknownLoc::get(context), rootType, root, elementValue, indexValue);
567 auto it = instMap.find(value);
568 if (it != instMap.end())
573 if (isa<llvm::Instruction>(value)) {
574 Type type = processType(value->getType());
577 unknownInstMap[
value] =
578 b.create(UnknownLoc::get(context), b.getStringAttr(
"llvm.unknown"),
580 return unknownInstMap[
value]->getResult(0);
583 if (
auto *c = dyn_cast<llvm::Constant>(value))
584 return processConstant(c);
586 emitError(unknownLoc) <<
"unhandled value: " <<
diag(*value);
595 #define INST(llvm_n, mlir_n) \ 596 { llvm::Instruction::llvm_n, LLVM::mlir_n##Op::getOperationName() } 604 INST(Resume, Resume),
605 INST(Unreachable, Unreachable),
629 INST(ExtractElement, ExtractElement),
630 INST(InsertElement, InsertElement),
634 INST(Alloca, Alloca),
644 INST(FPToUI, FPToUI),
645 INST(FPToSI, FPToSI),
646 INST(UIToFP, UIToFP),
647 INST(SIToFP, SIToFP),
648 INST(FPTrunc, FPTrunc),
650 INST(PtrToInt, PtrToInt),
651 INST(IntToPtr, IntToPtr),
652 INST(BitCast, Bitcast),
653 INST(AddrSpaceCast, AddrSpaceCast),
657 INST(Select, Select),
658 INST(Freeze, Freeze),
668 return opcMap.lookup(opcode);
675 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicToLLVMIROpPairs.inc" 677 return intrMap.lookup(
id);
683 llvm_unreachable(
"incorrect comparison predicate");
684 case llvm::CmpInst::Predicate::ICMP_EQ:
685 return LLVM::ICmpPredicate::eq;
686 case llvm::CmpInst::Predicate::ICMP_NE:
687 return LLVM::ICmpPredicate::ne;
688 case llvm::CmpInst::Predicate::ICMP_SLT:
689 return LLVM::ICmpPredicate::slt;
690 case llvm::CmpInst::Predicate::ICMP_SLE:
691 return LLVM::ICmpPredicate::sle;
692 case llvm::CmpInst::Predicate::ICMP_SGT:
693 return LLVM::ICmpPredicate::sgt;
694 case llvm::CmpInst::Predicate::ICMP_SGE:
695 return LLVM::ICmpPredicate::sge;
696 case llvm::CmpInst::Predicate::ICMP_ULT:
697 return LLVM::ICmpPredicate::ult;
698 case llvm::CmpInst::Predicate::ICMP_ULE:
699 return LLVM::ICmpPredicate::ule;
700 case llvm::CmpInst::Predicate::ICMP_UGT:
701 return LLVM::ICmpPredicate::ugt;
702 case llvm::CmpInst::Predicate::ICMP_UGE:
703 return LLVM::ICmpPredicate::uge;
705 llvm_unreachable(
"incorrect integer comparison predicate");
711 llvm_unreachable(
"incorrect comparison predicate");
712 case llvm::CmpInst::Predicate::FCMP_FALSE:
713 return LLVM::FCmpPredicate::_false;
714 case llvm::CmpInst::Predicate::FCMP_TRUE:
715 return LLVM::FCmpPredicate::_true;
716 case llvm::CmpInst::Predicate::FCMP_OEQ:
717 return LLVM::FCmpPredicate::oeq;
718 case llvm::CmpInst::Predicate::FCMP_ONE:
719 return LLVM::FCmpPredicate::one;
720 case llvm::CmpInst::Predicate::FCMP_OLT:
721 return LLVM::FCmpPredicate::olt;
722 case llvm::CmpInst::Predicate::FCMP_OLE:
723 return LLVM::FCmpPredicate::ole;
724 case llvm::CmpInst::Predicate::FCMP_OGT:
725 return LLVM::FCmpPredicate::ogt;
726 case llvm::CmpInst::Predicate::FCMP_OGE:
727 return LLVM::FCmpPredicate::oge;
728 case llvm::CmpInst::Predicate::FCMP_ORD:
729 return LLVM::FCmpPredicate::ord;
730 case llvm::CmpInst::Predicate::FCMP_ULT:
731 return LLVM::FCmpPredicate::ult;
732 case llvm::CmpInst::Predicate::FCMP_ULE:
733 return LLVM::FCmpPredicate::ule;
734 case llvm::CmpInst::Predicate::FCMP_UGT:
735 return LLVM::FCmpPredicate::ugt;
736 case llvm::CmpInst::Predicate::FCMP_UGE:
737 return LLVM::FCmpPredicate::uge;
738 case llvm::CmpInst::Predicate::FCMP_UNO:
739 return LLVM::FCmpPredicate::uno;
740 case llvm::CmpInst::Predicate::FCMP_UEQ:
741 return LLVM::FCmpPredicate::ueq;
742 case llvm::CmpInst::Predicate::FCMP_UNE:
743 return LLVM::FCmpPredicate::une;
745 llvm_unreachable(
"incorrect floating point comparison predicate");
750 case llvm::AtomicOrdering::NotAtomic:
751 return LLVM::AtomicOrdering::not_atomic;
752 case llvm::AtomicOrdering::Unordered:
753 return LLVM::AtomicOrdering::unordered;
754 case llvm::AtomicOrdering::Monotonic:
755 return LLVM::AtomicOrdering::monotonic;
756 case llvm::AtomicOrdering::Acquire:
757 return LLVM::AtomicOrdering::acquire;
758 case llvm::AtomicOrdering::Release:
759 return LLVM::AtomicOrdering::release;
760 case llvm::AtomicOrdering::AcquireRelease:
761 return LLVM::AtomicOrdering::acq_rel;
762 case llvm::AtomicOrdering::SequentiallyConsistent:
763 return LLVM::AtomicOrdering::seq_cst;
765 llvm_unreachable(
"incorrect atomic ordering");
771 Importer::processBranchArgs(llvm::Instruction *br, llvm::BasicBlock *target,
773 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
774 auto *pn = cast<llvm::PHINode>(&*inst);
778 blockArguments.push_back(value);
783 LogicalResult Importer::processInstruction(llvm::Instruction *inst) {
786 Location loc = processDebugLoc(inst->getDebugLoc(), inst);
787 assert(!instMap.count(inst) &&
788 "processInstruction must be called only once per instruction!");
789 switch (inst->getOpcode()) {
791 return emitError(loc) <<
"unknown instruction: " <<
diag(*inst);
792 case llvm::Instruction::Add:
793 case llvm::Instruction::FAdd:
794 case llvm::Instruction::Sub:
795 case llvm::Instruction::FSub:
796 case llvm::Instruction::Mul:
797 case llvm::Instruction::FMul:
798 case llvm::Instruction::UDiv:
799 case llvm::Instruction::SDiv:
800 case llvm::Instruction::FDiv:
801 case llvm::Instruction::URem:
802 case llvm::Instruction::SRem:
803 case llvm::Instruction::FRem:
804 case llvm::Instruction::Shl:
805 case llvm::Instruction::LShr:
806 case llvm::Instruction::AShr:
807 case llvm::Instruction::And:
808 case llvm::Instruction::Or:
809 case llvm::Instruction::Xor:
810 case llvm::Instruction::Load:
811 case llvm::Instruction::Store:
812 case llvm::Instruction::Ret:
813 case llvm::Instruction::Resume:
814 case llvm::Instruction::Trunc:
815 case llvm::Instruction::ZExt:
816 case llvm::Instruction::SExt:
817 case llvm::Instruction::FPToUI:
818 case llvm::Instruction::FPToSI:
819 case llvm::Instruction::UIToFP:
820 case llvm::Instruction::SIToFP:
821 case llvm::Instruction::FPTrunc:
822 case llvm::Instruction::FPExt:
823 case llvm::Instruction::PtrToInt:
824 case llvm::Instruction::IntToPtr:
825 case llvm::Instruction::AddrSpaceCast:
826 case llvm::Instruction::Freeze:
827 case llvm::Instruction::BitCast:
828 case llvm::Instruction::ExtractElement:
829 case llvm::Instruction::InsertElement:
830 case llvm::Instruction::Select:
831 case llvm::Instruction::FNeg:
832 case llvm::Instruction::Unreachable: {
835 ops.reserve(inst->getNumOperands());
836 for (
auto *op : inst->operand_values()) {
840 ops.push_back(value);
843 if (!inst->getType()->isVoidTy()) {
844 Type type = processType(inst->getType());
850 if (!inst->getType()->isVoidTy())
854 case llvm::Instruction::Alloca: {
859 auto *allocaInst = cast<llvm::AllocaInst>(inst);
861 b.create<AllocaOp>(loc, processType(inst->getType()),
862 processType(allocaInst->getAllocatedType()), size,
863 allocaInst->getAlign().value());
866 case llvm::Instruction::ICmp: {
871 instMap[inst] = b.create<ICmpOp>(
876 case llvm::Instruction::FCmp: {
881 instMap[inst] = b.create<FCmpOp>(
886 case llvm::Instruction::Br: {
887 auto *brInst = cast<llvm::BranchInst>(inst);
889 brInst->isConditional() ?
"llvm.cond_br" :
"llvm.br");
890 if (brInst->isConditional()) {
894 state.addOperands(condition);
897 std::array<int32_t, 3> operandSegmentSizes = {1, 0, 0};
898 for (
int i : llvm::seq<int>(0, brInst->getNumSuccessors())) {
899 auto *succ = brInst->getSuccessor(i);
901 if (
failed(processBranchArgs(brInst, succ, blockArguments)))
903 state.addSuccessors(blocks[succ]);
904 state.addOperands(blockArguments);
905 operandSegmentSizes[i + 1] = blockArguments.size();
908 if (brInst->isConditional()) {
909 state.addAttribute(LLVM::CondBrOp::getOperandSegmentSizeAttr(),
910 b.getI32VectorAttr(operandSegmentSizes));
916 case llvm::Instruction::Switch: {
917 auto *swInst = cast<llvm::SwitchInst>(inst);
925 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
926 if (
failed(processBranchArgs(swInst, defaultBB, defaultBlockArgs)))
930 unsigned numCases = swInst->getNumCases();
936 const llvm::SwitchInst::CaseHandle &caseHandle = en.value();
937 unsigned i = en.index();
938 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
939 if (
failed(processBranchArgs(swInst, succBB, caseOperands[i])))
941 caseOperandRefs[i] = caseOperands[i];
942 caseValues[i] = caseHandle.getCaseValue()->getSExtValue();
943 caseBlocks[i] = blocks[succBB];
946 b.create<SwitchOp>(loc, condition, blocks[defaultBB], defaultBlockArgs,
947 caseValues, caseBlocks, caseOperandRefs);
950 case llvm::Instruction::PHI: {
951 Type type = processType(inst->getType());
954 instMap[inst] = b.getInsertionBlock()->addArgument(
955 type, processDebugLoc(inst->getDebugLoc(), inst));
958 case llvm::Instruction::Call: {
959 llvm::CallInst *ci = cast<llvm::CallInst>(inst);
961 ops.reserve(inst->getNumOperands());
962 for (
auto &op : ci->args()) {
970 if (!ci->getType()->isVoidTy()) {
971 Type type = processType(inst->getType());
977 if (llvm::Function *callee = ci->getCalledFunction()) {
979 if (callee->isIntrinsic()) {
980 auto id = callee->getIntrinsicID();
982 if (!opName.empty()) {
987 if (!inst->getType()->isVoidTy())
993 loc, tys, SymbolRefAttr::get(b.getContext(), callee->getName()), ops);
998 ops.insert(ops.begin(), calledValue);
999 op = b.
create<CallOp>(loc, tys, ops);
1001 if (!ci->getType()->isVoidTy())
1005 case llvm::Instruction::LandingPad: {
1006 llvm::LandingPadInst *lpi = cast<llvm::LandingPadInst>(inst);
1009 for (
unsigned i = 0, ie = lpi->getNumClauses(); i < ie; i++)
1010 ops.push_back(processConstant(lpi->getClause(i)));
1012 Type ty = processType(lpi->getType());
1016 instMap[inst] = b.create<LandingpadOp>(loc, ty, lpi->isCleanup(), ops);
1019 case llvm::Instruction::Invoke: {
1020 llvm::InvokeInst *ii = cast<llvm::InvokeInst>(inst);
1023 if (!ii->getType()->isVoidTy())
1024 tys.push_back(processType(inst->getType()));
1027 ops.reserve(inst->getNumOperands() + 1);
1028 for (
auto &op : ii->args())
1032 (
void)processBranchArgs(ii, ii->getNormalDest(), normalArgs);
1033 (
void)processBranchArgs(ii, ii->getUnwindDest(), unwindArgs);
1036 if (llvm::Function *callee = ii->getCalledFunction()) {
1038 loc, tys, SymbolRefAttr::get(b.getContext(), callee->getName()), ops,
1039 blocks[ii->getNormalDest()], normalArgs, blocks[ii->getUnwindDest()],
1042 ops.insert(ops.begin(),
processValue(ii->getCalledOperand()));
1043 op = b.
create<InvokeOp>(loc, tys, ops, blocks[ii->getNormalDest()],
1044 normalArgs, blocks[ii->getUnwindDest()],
1048 if (!ii->getType()->isVoidTy())
1052 case llvm::Instruction::Fence: {
1053 StringRef syncscope;
1055 llvm::LLVMContext &llvmContext = inst->getContext();
1056 llvm::FenceInst *fence = cast<llvm::FenceInst>(inst);
1057 llvmContext.getSyncScopeNames(ssNs);
1058 int fenceSyncScopeID = fence->getSyncScopeID();
1059 for (
unsigned i = 0, e = ssNs.size(); i != e; i++) {
1060 if (fenceSyncScopeID == llvmContext.getOrInsertSyncScopeID(ssNs[i])) {
1061 syncscope = ssNs[i];
1069 case llvm::Instruction::GetElementPtr: {
1071 llvm::GetElementPtrInst *gep = cast<llvm::GetElementPtrInst>(inst);
1073 Type sourceElementType = processType(gep->getSourceElementType());
1076 for (llvm::Value *operand : llvm::drop_begin(gep->operand_values())) {
1078 if (!indices.back())
1086 LLVM::GEPOp::kDynamicIndex);
1088 Type type = processType(inst->getType());
1091 instMap[inst] = b.create<GEPOp>(loc, type, sourceElementType, basePtr,
1092 indices, structIndices);
1095 case llvm::Instruction::InsertValue: {
1096 auto *ivInst = cast<llvm::InsertValueInst>(inst);
1105 for (
unsigned idx : ivInst->getIndices())
1106 idxValues.push_back(static_cast<int32_t>(idx));
1107 ArrayAttr indices = b.getI32ArrayAttr(idxValues);
1109 instMap[inst] = b.create<InsertValueOp>(loc, aggOperand, inserted, indices);
1112 case llvm::Instruction::ExtractValue: {
1113 auto *evInst = cast<llvm::ExtractValueInst>(inst);
1118 Type type = processType(inst->getType());
1123 for (
unsigned idx : evInst->getIndices())
1124 idxValues.push_back(static_cast<int32_t>(idx));
1125 ArrayAttr indices = b.getI32ArrayAttr(idxValues);
1127 instMap[inst] = b.create<ExtractValueOp>(loc, type, aggOperand, indices);
1130 case llvm::Instruction::ShuffleVector: {
1131 auto *svInst = cast<llvm::ShuffleVectorInst>(inst);
1139 ArrayAttr mask = b.getI32ArrayAttr(svInst->getShuffleMask());
1141 instMap[inst] = b.create<ShuffleVectorOp>(loc, vec1, vec2, mask);
1148 if (!f->hasPersonalityFn())
1155 return SymbolRefAttr::get(b.getContext(), pf->getName());
1159 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1160 if (ce->getOpcode() == llvm::Instruction::BitCast &&
1161 ce->getType() == llvm::Type::getInt8PtrTy(f->getContext())) {
1162 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
1163 return SymbolRefAttr::get(b.getContext(), func->getName());
1169 LogicalResult Importer::processFunction(llvm::Function *f) {
1172 unknownInstMap.clear();
1175 processType(f->getFunctionType()).dyn_cast<LLVMFunctionType>();
1179 if (f->isIntrinsic()) {
1182 if (!opName.empty())
1186 bool dsoLocal = f->hasLocalLinkage();
1187 CConv cconv = convertCConvFromLLVM(f->getCallingConv());
1189 b.setInsertionPoint(module.getBody(), getFuncInsertPt());
1190 LLVMFuncOp fop = b.create<LLVMFuncOp>(
1191 UnknownLoc::get(context), f->getName(), functionType,
1192 convertLinkageFromLLVM(f->getLinkage()), dsoLocal, cconv);
1195 fop->setAttr(b.getStringAttr(
"personality"), personality);
1196 else if (f->hasPersonalityFn())
1198 "could not deduce personality, skipping it");
1201 fop.setGarbageCollectorAttr(b.getStringAttr(f->getGC()));
1203 if (f->isDeclaration())
1208 for (llvm::BasicBlock &bb : *f) {
1209 blockList.push_back(b.createBlock(&fop.getBody(), fop.getBody().end()));
1210 blocks[&bb] = blockList.back();
1212 currentEntryBlock = blockList[0];
1216 instMap[&kv.value()] = blockList[0]->addArgument(
1217 functionType.getParamType(kv.index()), fop.getLoc());
1220 for (
auto bbs : llvm::zip(*f, blockList)) {
1221 if (
failed(processBasicBlock(&std::get<0>(bbs), std::get<1>(bbs))))
1227 for (
auto &llvmAndUnknown : unknownInstMap) {
1228 assert(instMap.count(llvmAndUnknown.first));
1229 Value newValue = instMap[llvmAndUnknown.first];
1230 Value oldValue = llvmAndUnknown.second->getResult(0);
1232 llvmAndUnknown.second->erase();
1238 b.setInsertionPointToStart(block);
1239 for (llvm::Instruction &inst : *bb) {
1240 if (
failed(processInstruction(&inst)))
1252 FileLineColLoc::get(context,
"", 0, 0)));
1254 DataLayoutSpecInterface dlSpec =
1257 emitError(UnknownLoc::get(context),
"can't translate data layout");
1261 module.get()->setAttr(DLTIDialect::kDataLayoutAttrName, dlSpec);
1263 Importer deserializer(context, module.get());
1264 for (llvm::GlobalVariable &gv : llvmModule->globals()) {
1265 if (!deserializer.processGlobal(&gv))
1268 for (llvm::Function &f : llvmModule->functions()) {
1269 if (
failed(deserializer.processFunction(&f)))
1280 llvm::SMDiagnostic err;
1281 llvm::LLVMContext llvmContext;
1282 std::unique_ptr<llvm::Module> llvmModule = llvm::parseIR(
1283 *sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID()), err, llvmContext);
1286 llvm::raw_string_ostream errStream(errStr);
1287 err.print(
"", errStream);
1288 emitError(UnknownLoc::get(context)) << errStream.str();
1297 "import-llvm", [](llvm::SourceMgr &sourceMgr,
MLIRContext *context) {
Use Translate[ToMLIR|FromMLIR]Registration as an initializer that registers a function and associates...
TODO: Remove this file when SCCP and integer range analysis have been ported to the new framework...
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, ArrayRef< NamedAttribute > attributes, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
This class contains a list of basic blocks and a link to the parent operation it is attached to...
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
static std::string diag(llvm::Value &v)
OwningOpRef< ModuleOp > translateLLVMIRToModule(llvm::SourceMgr &sourceMgr, MLIRContext *context)
Operation is a basic unit of execution within MLIR.
void registerFromLLVMIRTranslation()
Block represents an ordered list of Operations.
A symbol reference with a reference path containing a single element.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value...
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static FCmpPredicate getFCmpPredicate(llvm::CmpInst::Predicate p)
static StringRef lookupOperationNameFromOpcode(unsigned opcode)
Return the MLIR OperationName for the given LLVM opcode.
static FloatType getF32(MLIRContext *ctx)
void loadDialect()
Load a dialect in the context.
static FloatType getDLFloatType(MLIRContext &ctx, int32_t bitwidth)
Returns a supported MLIR floating point type of the given bit width or null if the bit width is not s...
static FloatType getBF16(MLIRContext *ctx)
void replaceAllUsesWith(Value newValue) const
Replace all uses of 'this' value with the new value, updating anything in the IR that uses 'this' to ...
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
static constexpr const bool value
static DenseIntElementsAttr parseDataLayoutAlignment(MLIRContext &ctx, StringRef spec)
Creates an attribute containing ABI and preferred alignment numbers parsed a string.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
static DataLayoutEntryAttr get(StringAttr key, Attribute value)
Returns the entry with the given key and value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
This class represents an efficient way to signal success or failure.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
OpListType::iterator iterator
static ICmpPredicate getICmpPredicate(llvm::CmpInst::Predicate p)
void addOperands(ValueRange newOperands)
U dyn_cast_or_null() const
Attributes are known-constant values of operations.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
static DenseIntElementsAttr get(const ShapedType &type, Arg &&arg)
Get an instance of a DenseIntElementsAttr with the given arguments.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
RHS of mul is always a constant or a symbolic expression.
static FloatType getF128(MLIRContext *ctx)
void addTypes(ArrayRef< Type > newTypes)
static StringRef lookupOperationNameFromIntrinsicID(unsigned id)
Return the MLIR OperationName for the given LLVM intrinsic ID.
This represents an operation in an abstracted form, suitable for use with the builder APIs...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
RAII guard to reset the insertion point of the builder when destroyed.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
Utility class to translate LLVM IR types to the MLIR LLVM dialect.
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect. ...
MLIRContext is the top-level object for a collection of MLIR operations.
static FloatType getF80(MLIRContext *ctx)
static FloatType getF16(MLIRContext *ctx)
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context)
Convert the given LLVM module into MLIR's LLVM dialect.
static DataLayoutSpecAttr get(MLIRContext *ctx, ArrayRef< DataLayoutEntryInterface > entries)
Returns the specification containing the given list of keys.
static AtomicOrdering getLLVMAtomicOrdering(llvm::AtomicOrdering ordering)
This class helps build Operations.
DataLayoutSpecInterface translateDataLayout(const llvm::DataLayout &dataLayout, MLIRContext *context)
Translate the given LLVM data layout into an MLIR equivalent using the DLTI dialect.
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
static FloatType getF64(MLIRContext *ctx)
#define INST(llvm_n, mlir_n)
static void processValue(Value value, LiveMap &liveMap)
An attribute that represents a reference to a dense integer vector or tensor object.