29 #include "llvm/ADT/DepthFirstIterator.h"
30 #include "llvm/ADT/PostOrderIterator.h"
31 #include "llvm/ADT/ScopeExit.h"
32 #include "llvm/ADT/StringSet.h"
33 #include "llvm/ADT/TypeSwitch.h"
34 #include "llvm/IR/Comdat.h"
35 #include "llvm/IR/Constants.h"
36 #include "llvm/IR/InlineAsm.h"
37 #include "llvm/IR/InstIterator.h"
38 #include "llvm/IR/Instructions.h"
39 #include "llvm/IR/IntrinsicInst.h"
40 #include "llvm/IR/Metadata.h"
41 #include "llvm/IR/Operator.h"
42 #include "llvm/Support/ModRef.h"
48 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
53 static std::string
diag(
const llvm::Value &value) {
55 llvm::raw_string_ostream os(str);
63 static std::string
diagMD(
const llvm::Metadata *node,
64 const llvm::Module *module) {
66 llvm::raw_string_ostream os(str);
67 node->print(os, module,
true);
73 return "llvm.global_ctors";
78 return "llvm.global_dtors";
84 return "__llvm_global_comdat";
93 std::optional<llvm::SyncScope::ID> syncScopeID =
94 llvm::getAtomicSyncScopeID(inst);
101 llvm::LLVMContext &llvmContext = inst->getContext();
102 llvmContext.getSyncScopeNames(syncScopeName);
103 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
104 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
106 if (it != syncScopeName.end())
108 llvm_unreachable(
"incorrect sync scope identifier");
114 llvm::append_range(position, indices);
125 llvm::Instruction *inst,
138 #include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
146 for (llvm::BasicBlock *basicBlock : basicBlocks) {
147 if (!blocks.contains(basicBlock)) {
148 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
149 blocks.insert(traversal.begin(), traversal.end());
152 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
157 std::unique_ptr<llvm::Module> llvmModule,
158 bool emitExpensiveWarnings,
159 bool importEmptyDICompositeTypes)
161 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
165 mlirModule, importEmptyDICompositeTypes)),
166 loopAnnotationImporter(
168 emitExpensiveWarnings(emitExpensiveWarnings) {
172 ComdatOp ModuleImport::getGlobalComdatOp() {
174 return globalComdatOp;
180 globalInsertionOp = globalComdatOp;
181 return globalComdatOp;
184 LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
189 auto getIdentityIfRootNode =
190 [&](
const llvm::MDNode *node) ->
FailureOr<std::optional<StringRef>> {
194 if (node->getNumOperands() > 1)
197 if (node->getNumOperands() == 1)
198 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
199 return std::optional<StringRef>{op0->getString()};
200 return std::optional<StringRef>{};
210 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
211 StringRef *identity =
nullptr,
213 nullptr) -> std::optional<bool> {
214 unsigned numOperands = node->getNumOperands();
223 const auto *identityNode =
224 dyn_cast<const llvm::MDString>(node->getOperand(0));
230 *identity = identityNode->getString();
232 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
233 const auto *memberNode =
234 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
236 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
237 <<
diagMD(node, llvmModule.get());
241 if (2 * pairNum + 2 >= numOperands) {
243 if (numOperands != 2) {
244 emitError(loc) <<
"missing member offset: "
245 <<
diagMD(node, llvmModule.get());
249 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
250 node->getOperand(2 * pairNum + 2));
252 emitError(loc) <<
"operand '" << 2 * pairNum + 2
253 <<
"' must be ConstantInt: "
254 <<
diagMD(node, llvmModule.get());
257 offset = offsetCI->getZExtValue();
262 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
275 auto isTagNode = [&](
const llvm::MDNode *node,
276 TBAATypeDescriptorAttr *baseAttr =
nullptr,
277 TBAATypeDescriptorAttr *accessAttr =
nullptr,
278 int64_t *offset =
nullptr,
279 bool *isConstant =
nullptr) -> std::optional<bool> {
287 unsigned numOperands = node->getNumOperands();
288 if (numOperands != 3 && numOperands != 4)
290 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
291 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
293 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
294 if (!baseMD || !accessMD || !offsetCI)
301 if (accessMD->getNumOperands() < 1 ||
302 !isa<llvm::MDString>(accessMD->getOperand(0)))
304 bool isConst =
false;
305 if (numOperands == 4) {
307 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
309 emitError(loc) <<
"operand '3' must be ConstantInt: "
310 <<
diagMD(node, llvmModule.get());
313 isConst = isConstantCI->getValue()[0];
316 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
318 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
320 *offset = offsetCI->getZExtValue();
322 *isConstant = isConst;
331 workList.push_back(node);
332 while (!workList.empty()) {
333 const llvm::MDNode *current = workList.back();
334 if (tbaaMapping.contains(current)) {
343 bool anyChildNotConverted =
false;
344 for (
const llvm::MDOperand &operand : current->operands())
345 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
346 if (!tbaaMapping.contains(childNode)) {
347 workList.push_back(childNode);
348 anyChildNotConverted =
true;
351 if (anyChildNotConverted) {
356 if (!seen.insert(current).second)
357 return emitError(loc) <<
"has cycle in TBAA graph: "
358 <<
diagMD(current, llvmModule.get());
367 getIdentityIfRootNode(current);
369 StringAttr stringAttr = *rootNodeIdentity
374 tbaaMapping.insert({current, builder.
getAttr<TBAARootAttr>(stringAttr)});
380 if (std::optional<bool> isValid =
381 isTypeDescriptorNode(current, &identity, &members)) {
382 assert(isValid.value() &&
"type descriptor node must be valid");
384 tbaaMapping.insert({current, builder.
getAttr<TBAATypeDescriptorAttr>(
385 identity, members)});
389 TBAATypeDescriptorAttr baseAttr, accessAttr;
392 if (std::optional<bool> isValid =
393 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
394 assert(isValid.value() &&
"access tag node must be valid");
396 {current, builder.
getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
401 return emitError(loc) <<
"unsupported TBAA node format: "
402 <<
diagMD(current, llvmModule.get());
408 ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
410 if (
failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
411 return emitError(loc) <<
"unsupported access group node: "
412 <<
diagMD(node, llvmModule.get());
417 ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
420 auto verifySelfRef = [](
const llvm::MDNode *node) {
421 return node->getNumOperands() != 0 &&
422 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
425 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
426 return idx >= node->getNumOperands() ||
427 isa<llvm::MDString>(node->getOperand(idx));
430 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
431 StringAttr description =
nullptr;
432 if (aliasDomain->getNumOperands() >= 2)
433 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
435 return builder.
getAttr<AliasScopeDomainAttr>(
440 for (
const llvm::MDOperand &operand : node->operands()) {
441 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
442 llvm::AliasScopeNode aliasScope(scope);
443 const llvm::MDNode *domain = aliasScope.getDomain();
449 if (!verifySelfRef(scope) || !domain || !verifyDescription(scope, 2))
450 return emitError(loc) <<
"unsupported alias scope node: "
451 <<
diagMD(scope, llvmModule.get());
452 if (!verifySelfRef(domain) || !verifyDescription(domain, 1))
453 return emitError(loc) <<
"unsupported alias domain node: "
454 <<
diagMD(domain, llvmModule.get());
456 if (aliasScopeMapping.contains(scope))
460 auto it = aliasScopeMapping.find(aliasScope.getDomain());
461 if (it == aliasScopeMapping.end()) {
462 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
463 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
467 StringAttr description =
nullptr;
468 if (!aliasScope.getName().empty())
470 auto aliasScopeOp = builder.
getAttr<AliasScopeAttr>(
472 cast<AliasScopeDomainAttr>(it->second), description);
473 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
482 aliasScopes.reserve(node->getNumOperands());
483 for (
const llvm::MDOperand &operand : node->operands()) {
484 auto *node = cast<llvm::MDNode>(operand.get());
485 aliasScopes.push_back(
486 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
489 if (llvm::is_contained(aliasScopes,
nullptr))
495 debugIntrinsics.insert(intrinsic);
499 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
500 if (named.getName() !=
"llvm.linker.options")
503 for (
const llvm::MDNode *md : named.operands()) {
505 options.reserve(md->getNumOperands());
506 for (
const llvm::MDOperand &option : md->operands())
507 options.push_back(cast<llvm::MDString>(option)->getString());
508 builder.
create<LLVM::LinkerOptionsOp>(mlirModule.getLoc(),
518 for (
const llvm::Function &func : llvmModule->functions()) {
519 for (
const llvm::Instruction &inst : llvm::instructions(func)) {
521 if (llvm::MDNode *node =
522 inst.getMetadata(llvm::LLVMContext::MD_access_group))
523 if (
failed(processAccessGroupMetadata(node)))
527 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
528 if (!aliasAnalysisNodes)
530 if (aliasAnalysisNodes.TBAA)
531 if (
failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
533 if (aliasAnalysisNodes.Scope)
534 if (
failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
536 if (aliasAnalysisNodes.NoAlias)
537 if (
failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
546 void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
547 if (comdatMapping.contains(comdat))
550 ComdatOp comdatOp = getGlobalComdatOp();
553 auto selectorOp = builder.
create<ComdatSelectorOp>(
554 mlirModule.getLoc(), comdat->getName(),
555 convertComdatFromLLVM(comdat->getSelectionKind()));
559 comdatMapping.try_emplace(comdat, symbolRef);
563 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
564 if (globalVar.hasComdat())
565 processComdat(globalVar.getComdat());
566 for (llvm::Function &func : llvmModule->functions())
567 if (func.hasComdat())
568 processComdat(func.getComdat());
573 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
576 if (
failed(convertGlobalCtorsAndDtors(&globalVar))) {
578 <<
"unhandled global variable: " <<
diag(globalVar);
582 if (
failed(convertGlobal(&globalVar))) {
584 <<
"unhandled global variable: " <<
diag(globalVar);
594 return emitError(loc,
"cannot translate data layout: ")
598 emitWarning(loc,
"unhandled data layout token: ") << token;
600 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
606 for (llvm::Function &func : llvmModule->functions())
612 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
615 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
616 for (
auto &[kind, node] : allMetadata) {
620 if (emitExpensiveWarnings) {
621 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
623 <<
diagMD(node, llvmModule.get()) <<
" on "
632 auto iface = cast<IntegerOverflowFlagsInterface>(op);
634 IntegerOverflowFlags value = {};
635 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
637 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
639 iface.setOverflowFlags(value);
644 auto iface = cast<FastmathFlagsInterface>(op);
650 if (!isa<llvm::FPMathOperator>(inst))
652 llvm::FastMathFlags flags = inst->getFastMathFlags();
655 FastmathFlags value = {};
656 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
657 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
658 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
659 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
661 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
662 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
664 iface->setAttr(iface.getFastmathAttrName(), attr);
669 return isa<IntegerType, FloatType>(type);
681 if (numElements.isScalable()) {
683 <<
"scalable vectors not supported";
693 shape.push_back(numElements.getKnownMinValue());
697 Type ModuleImport::getBuiltinTypeForAttr(
Type type) {
712 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
713 arrayShape.push_back(arrayType.getNumElements());
714 type = arrayType.getElementType();
724 llvm::Constant *constScalar) {
728 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
731 constInt->getValue());
735 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
736 llvm::Type *type = constFloat->getType();
743 <<
"unexpected floating-point type";
746 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
755 llvm::ConstantDataSequential *constSequence) {
757 elementAttrs.reserve(constSequence->getNumElements());
758 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
759 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
765 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
771 if (
auto *func = dyn_cast<llvm::Function>(constant))
775 auto getConstantShape = [&](llvm::Type *type) {
776 return llvm::dyn_cast_if_present<ShapedType>(
782 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
783 if (constArray->isString())
785 auto shape = getConstantShape(constArray->getType());
789 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
790 if (constVector && constVector->isSplat()) {
793 builder, constVector->getElementAsConstant(0));
804 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
805 auto shape = getConstantShape(constAggregate->getType());
811 while (!workList.empty()) {
812 llvm::Constant *current = workList.pop_back_val();
815 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
817 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
818 workList.push_back(constAggregate->getAggregateElement(idx));
823 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
826 elementAttrs.append(attrs.begin(), attrs.end());
832 elementAttrs.push_back(scalarAttr);
843 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
844 auto shape = llvm::dyn_cast_if_present<ShapedType>(
845 getBuiltinTypeForAttr(
convertType(constZero->getType())));
850 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
856 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
859 if (!globalInsertionOp)
865 if (globalVar->hasInitializer())
866 valueAttr = getConstantAsAttr(globalVar->getInitializer());
869 uint64_t alignment = 0;
870 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
871 if (maybeAlign.has_value()) {
872 llvm::Align align = *maybeAlign;
873 alignment = align.value();
878 DIGlobalVariableExpressionAttr globalExpressionAttr;
880 globalVar->getDebugInfo(globalExpressions);
883 if (!globalExpressions.empty())
884 globalExpressionAttr =
885 debugImporter->translateGlobalVariableExpression(globalExpressions[0]);
887 GlobalOp globalOp = builder.
create<GlobalOp>(
888 mlirModule.getLoc(), type, globalVar->isConstant(),
889 convertLinkageFromLLVM(globalVar->getLinkage()), globalVar->getName(),
890 valueAttr, alignment, globalVar->getAddressSpace(),
891 globalVar->isDSOLocal(),
892 globalVar->isThreadLocal(), SymbolRefAttr(),
894 globalInsertionOp = globalOp;
896 if (globalVar->hasInitializer() && !valueAttr) {
899 setConstantInsertionPointToStart(block);
901 convertConstantExpr(globalVar->getInitializer());
904 builder.
create<ReturnOp>(globalOp.getLoc(), *initializer);
906 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
907 globalOp.setUnnamedAddr(
908 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
910 if (globalVar->hasSection())
911 globalOp.setSection(globalVar->getSection());
912 globalOp.setVisibility_(
913 convertVisibilityFromLLVM(globalVar->getVisibility()));
915 if (globalVar->hasComdat())
916 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
922 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
923 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
926 dyn_cast<llvm::ConstantArray>(globalVar->getInitializer());
932 for (llvm::Value *operand : initializer->operands()) {
933 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
934 if (!aggregate || aggregate->getNumOperands() != 3)
937 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
938 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
939 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
940 if (!priority || !func || !data)
944 if (!data->isNullValue())
948 priorities.push_back(priority->getValue().getZExtValue());
952 if (!globalInsertionOp)
958 globalInsertionOp = builder.
create<LLVM::GlobalCtorsOp>(
963 globalInsertionOp = builder.
create<LLVM::GlobalDtorsOp>(
970 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
972 if (valueMapping.contains(constant))
981 workList.insert(constant);
982 while (!workList.empty()) {
983 llvm::Constant *current = workList.back();
986 auto adjacencyIt = adjacencyLists.find(current);
987 if (adjacencyIt == adjacencyLists.end()) {
988 adjacencyIt = adjacencyLists.try_emplace(current).first;
991 for (llvm::Value *operand : current->operands())
992 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
993 adjacencyIt->getSecond().push_back(constDependency);
996 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
997 unsigned numElements = constAgg->getElementCount().getFixedValue();
998 for (
unsigned i = 0, e = numElements; i != e; ++i)
999 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1005 if (adjacencyIt->getSecond().empty()) {
1006 orderedSet.insert(current);
1007 workList.pop_back();
1015 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1016 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1017 orderedSet.contains(dependency))
1019 workList.insert(dependency);
1029 if (
Attribute attr = getConstantAsAttr(constant)) {
1031 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1032 return builder.
create<AddressOfOp>(loc, type, symbolRef.getValue())
1035 return builder.
create<ConstantOp>(loc, type, attr).getResult();
1039 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1041 return builder.
create<ZeroOp>(loc, type).getResult();
1045 if (isa<llvm::ConstantTokenNone>(constant)) {
1046 return builder.
create<NoneTokenOp>(loc).getResult();
1050 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1052 return builder.
create<PoisonOp>(loc, type).getResult();
1056 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1058 return builder.
create<UndefOp>(loc, type).getResult();
1062 if (
auto *globalVar = dyn_cast<llvm::GlobalVariable>(constant)) {
1065 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1069 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1075 llvm::Instruction *inst = constExpr->getAsInstruction();
1076 auto guard = llvm::make_scope_exit([&]() {
1077 assert(!noResultOpMapping.contains(inst) &&
1078 "expected constant expression to return a result");
1079 valueMapping.erase(inst);
1080 inst->deleteValue();
1084 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1085 return valueMapping.contains(value);
1087 if (
failed(processInstruction(inst)))
1093 if (isa<llvm::ConstantAggregate>(constant) ||
1094 isa<llvm::ConstantAggregateZero>(constant)) {
1097 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1098 elementValues.reserve(constAgg->getNumOperands());
1099 for (llvm::Value *operand : constAgg->operands())
1102 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1103 unsigned numElements = constAgg->getElementCount().getFixedValue();
1104 elementValues.reserve(numElements);
1105 for (
unsigned i = 0, e = numElements; i != e; ++i)
1106 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1108 assert(llvm::count(elementValues,
nullptr) == 0 &&
1109 "expected all elements have been converted before");
1113 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1115 "unrecognized aggregate type");
1116 Value root = builder.
create<UndefOp>(loc, rootType);
1118 if (isArrayOrStruct) {
1119 root = builder.
create<InsertValueOp>(loc, root, it.value(), it.index());
1124 root = builder.
create<InsertElementOp>(loc, rootType, root, it.value(),
1131 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1132 LLVMTargetExtType targetExtType =
1133 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1134 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1135 "target extension type does not support zero-initialization");
1138 return builder.
create<LLVM::ZeroOp>(loc, targetExtType).getRes();
1141 StringRef error =
"";
1142 if (isa<llvm::BlockAddress>(constant))
1143 error =
" since blockaddress(...) is unsupported";
1145 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1148 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1152 assert(!valueMapping.contains(constant) &&
1153 "expected constant has not been converted before");
1154 assert(constantInsertionBlock &&
1155 "expected the constant insertion block to be non-null");
1159 if (!constantInsertionOp)
1166 getConstantsToConvert(constant);
1167 for (llvm::Constant *constantToConvert : constantsToConvert) {
1171 mapValue(constantToConvert, *converted);
1181 assert(!isa<llvm::MetadataAsValue>(value) &&
1182 "expected value to not be metadata");
1185 auto it = valueMapping.find(value);
1186 if (it != valueMapping.end())
1187 return it->getSecond();
1190 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1191 return convertConstantExpr(constant);
1194 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1196 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1202 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1205 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1208 value = node->getValue();
1211 auto it = valueMapping.find(value);
1212 if (it != valueMapping.end())
1213 return it->getSecond();
1216 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1217 return convertConstantExpr(constant);
1224 remapped.reserve(values.size());
1225 for (llvm::Value *value : values) {
1229 remapped.push_back(*converted);
1238 assert(immArgPositions.size() == immArgAttrNames.size() &&
1239 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1243 for (
auto [immArgPos, immArgName] :
1244 llvm::zip(immArgPositions, immArgAttrNames)) {
1245 auto &value = operands[immArgPos];
1246 auto *constant = llvm::cast<llvm::Constant>(value);
1248 assert(attr && attr.getType().isIntOrFloat() &&
1249 "expected immarg to be float or integer constant");
1251 attrsOut.push_back({nameAttr, attr});
1256 for (llvm::Value *value : operands) {
1262 valuesOut.push_back(*mlirValue);
1269 IntegerAttr integerAttr;
1273 assert(
success &&
"expected a constant integer value");
1279 FloatAttr floatAttr;
1283 assert(
success &&
"expected a constant float value");
1289 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1290 auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
1291 return debugImporter->translate(node);
1295 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1296 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
1297 return debugImporter->translate(node);
1300 FPExceptionBehaviorAttr
1302 auto *metadata = cast<llvm::MetadataAsValue>(value);
1303 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1304 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
1305 llvm::convertStrToExceptionBehavior(mdstr->getString());
1306 assert(optLLVM &&
"Expecting FP exception behavior");
1307 return builder.
getAttr<FPExceptionBehaviorAttr>(
1308 convertFPExceptionBehaviorFromLLVM(*optLLVM));
1312 auto *metadata = cast<llvm::MetadataAsValue>(value);
1313 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1314 std::optional<llvm::RoundingMode> optLLVM =
1315 llvm::convertStrToRoundingMode(mdstr->getString());
1316 assert(optLLVM &&
"Expecting rounding mode");
1317 return builder.
getAttr<RoundingModeAttr>(
1318 convertRoundingModeFromLLVM(*optLLVM));
1323 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1324 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
1329 return debugImporter->translateLoc(loc);
1333 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
1334 llvm::BasicBlock *target,
1336 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
1337 auto *phiInst = cast<llvm::PHINode>(&*inst);
1338 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
1342 blockArguments.push_back(*converted);
1348 ModuleImport::convertCallTypeAndOperands(llvm::CallBase *callInst,
1351 if (!callInst->getType()->isVoidTy())
1352 types.push_back(
convertType(callInst->getType()));
1354 if (!callInst->getCalledFunction()) {
1358 operands.push_back(*called);
1364 llvm::append_range(operands, *arguments);
1368 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
1373 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
1376 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1379 if (inst->getOpcode() == llvm::Instruction::Br) {
1380 auto *brInst = cast<llvm::BranchInst>(inst);
1384 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
1385 llvm::BasicBlock *succ = brInst->getSuccessor(i);
1387 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
1390 succBlockArgs.push_back(blockArgs);
1393 if (!brInst->isConditional()) {
1394 auto brOp = builder.
create<LLVM::BrOp>(loc, succBlockArgs.front(),
1395 succBlocks.front());
1402 auto condBrOp = builder.
create<LLVM::CondBrOp>(
1403 loc, *condition, succBlocks.front(), succBlockArgs.front(),
1404 succBlocks.back(), succBlockArgs.back());
1408 if (inst->getOpcode() == llvm::Instruction::Switch) {
1409 auto *swInst = cast<llvm::SwitchInst>(inst);
1416 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
1417 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
1421 unsigned numCases = swInst->getNumCases();
1427 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
1428 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
1429 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
1431 caseOperandRefs[it.index()] = caseOperands[it.index()];
1432 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
1436 auto switchOp = builder.
create<SwitchOp>(
1437 loc, *condition,
lookupBlock(defaultBB), defaultBlockArgs, caseValues,
1438 caseBlocks, caseOperandRefs);
1442 if (inst->getOpcode() == llvm::Instruction::PHI) {
1448 if (inst->getOpcode() == llvm::Instruction::Call) {
1449 auto *callInst = cast<llvm::CallInst>(inst);
1453 if (
failed(convertCallTypeAndOperands(callInst, types, operands)))
1457 dyn_cast<LLVMFunctionType>(
convertType(callInst->getFunctionType()));
1463 if (llvm::Function *callee = callInst->getCalledFunction()) {
1464 callOp = builder.
create<CallOp>(
1468 callOp = builder.
create<CallOp>(loc, funcTy, operands);
1470 callOp.setCConv(convertCConvFromLLVM(callInst->getCallingConv()));
1472 if (!callInst->getType()->isVoidTy())
1473 mapValue(inst, callOp.getResult());
1478 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
1479 auto *lpInst = cast<llvm::LandingPadInst>(inst);
1482 operands.reserve(lpInst->getNumClauses());
1483 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
1487 operands.push_back(*operand);
1492 builder.
create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
1496 if (inst->getOpcode() == llvm::Instruction::Invoke) {
1497 auto *invokeInst = cast<llvm::InvokeInst>(inst);
1501 if (
failed(convertCallTypeAndOperands(invokeInst, types, operands)))
1506 bool invokeResultUsedInPhi = llvm::any_of(
1507 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
1508 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
1513 Block *directNormalDest = normalDest;
1514 if (invokeResultUsedInPhi) {
1520 directNormalDest = builder.
createBlock(normalDest);
1524 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
1529 dyn_cast<LLVMFunctionType>(
convertType(invokeInst->getFunctionType()));
1537 if (llvm::Function *callee = invokeInst->getCalledFunction()) {
1538 invokeOp = builder.
create<InvokeOp>(
1542 lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
1544 invokeOp = builder.
create<InvokeOp>(
1545 loc, funcTy,
nullptr, operands, directNormalDest,
1548 invokeOp.setCConv(convertCConvFromLLVM(invokeInst->getCallingConv()));
1549 if (!invokeInst->getType()->isVoidTy())
1550 mapValue(inst, invokeOp.getResults().front());
1555 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
1559 if (invokeResultUsedInPhi) {
1565 builder.
create<LLVM::BrOp>(loc, normalArgs, normalDest);
1569 assert(llvm::none_of(
1572 "An llvm.invoke operation cannot pass its result as a block "
1574 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
1579 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
1580 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
1581 Type sourceElementType =
convertType(gepInst->getSourceElementType());
1591 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
1595 indices.push_back(*index);
1599 auto gepOp = builder.
create<GEPOp>(loc, type, sourceElementType, *basePtr,
1600 indices, gepInst->isInBounds());
1609 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
1612 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
1619 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
1620 return convertIntrinsic(intrinsic);
1623 return convertInstruction(inst);
1627 if (!f->hasPersonalityFn())
1630 llvm::Constant *pf = f->getPersonalityFn();
1638 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1639 if (ce->getOpcode() == llvm::Instruction::BitCast &&
1640 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
1641 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
1649 llvm::MemoryEffects memEffects = func->getMemoryEffects();
1651 auto othermem = convertModRefInfoFromLLVM(
1652 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1653 auto argMem = convertModRefInfoFromLLVM(
1654 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1655 auto inaccessibleMem = convertModRefInfoFromLLVM(
1656 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1660 if (memAttr.isReadWrite())
1662 funcOp.setMemoryAttr(memAttr);
1668 StringLiteral(
"aarch64_pstate_sm_enabled"),
1669 StringLiteral(
"aarch64_pstate_sm_body"),
1670 StringLiteral(
"aarch64_pstate_sm_compatible"),
1671 StringLiteral(
"aarch64_new_za"),
1672 StringLiteral(
"aarch64_preserves_za"),
1673 StringLiteral(
"aarch64_in_za"),
1674 StringLiteral(
"aarch64_out_za"),
1675 StringLiteral(
"aarch64_inout_za"),
1676 StringLiteral(
"vscale_range"),
1677 StringLiteral(
"frame-pointer"),
1678 StringLiteral(
"target-features"),
1679 StringLiteral(
"unsafe-fp-math"),
1680 StringLiteral(
"no-infs-fp-math"),
1681 StringLiteral(
"no-nans-fp-math"),
1682 StringLiteral(
"approx-func-fp-math"),
1683 StringLiteral(
"no-signed-zeros-fp-math"),
1689 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
1690 llvm::AttributeList::AttrIndex::FunctionIndex);
1691 for (llvm::Attribute attr : funcAttrs) {
1694 if (attr.hasAttribute(llvm::Attribute::Memory))
1698 if (attr.isTypeAttribute()) {
1700 "type attributes on a function are invalid, skipping it");
1705 if (attr.isStringAttribute())
1706 attrName = attr.getKindAsString();
1708 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1715 if (attr.isStringAttribute()) {
1716 StringRef val = attr.getValueAsString();
1718 passthroughs.push_back(keyAttr);
1721 passthroughs.push_back(
1725 if (attr.isIntAttribute()) {
1726 auto val = std::to_string(attr.getValueAsInt());
1727 passthroughs.push_back(
1731 if (attr.isEnumAttribute()) {
1732 passthroughs.push_back(keyAttr);
1736 llvm_unreachable(
"unexpected attribute kind");
1739 if (!passthroughs.empty())
1740 funcOp.setPassthroughAttr(
ArrayAttr::get(context, passthroughs));
1744 LLVMFuncOp funcOp) {
1748 if (func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
1749 funcOp.setArmStreaming(
true);
1750 else if (func->hasFnAttribute(
"aarch64_pstate_sm_body"))
1751 funcOp.setArmLocallyStreaming(
true);
1752 else if (func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
1753 funcOp.setArmStreamingCompatible(
true);
1755 if (func->hasFnAttribute(
"aarch64_new_za"))
1756 funcOp.setArmNewZa(
true);
1757 else if (func->hasFnAttribute(
"aarch64_in_za"))
1758 funcOp.setArmInZa(
true);
1759 else if (func->hasFnAttribute(
"aarch64_out_za"))
1760 funcOp.setArmOutZa(
true);
1761 else if (func->hasFnAttribute(
"aarch64_inout_za"))
1762 funcOp.setArmInoutZa(
true);
1763 else if (func->hasFnAttribute(
"aarch64_preserves_za"))
1764 funcOp.setArmPreservesZa(
true);
1766 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
1767 if (attr.isValid()) {
1776 if (func->hasFnAttribute(
"frame-pointer")) {
1777 StringRef stringRefFramePointerKind =
1778 func->getFnAttribute(
"frame-pointer").getValueAsString();
1780 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
1781 stringRefFramePointerKind)
1785 if (llvm::Attribute attr = func->getFnAttribute(
"target-cpu");
1786 attr.isStringAttribute())
1787 funcOp.setTargetCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
1789 if (llvm::Attribute attr = func->getFnAttribute(
"target-features");
1790 attr.isStringAttribute())
1791 funcOp.setTargetFeaturesAttr(
1794 if (llvm::Attribute attr = func->getFnAttribute(
"unsafe-fp-math");
1795 attr.isStringAttribute())
1796 funcOp.setUnsafeFpMath(attr.getValueAsBool());
1798 if (llvm::Attribute attr = func->getFnAttribute(
"no-infs-fp-math");
1799 attr.isStringAttribute())
1800 funcOp.setNoInfsFpMath(attr.getValueAsBool());
1802 if (llvm::Attribute attr = func->getFnAttribute(
"no-nans-fp-math");
1803 attr.isStringAttribute())
1804 funcOp.setNoNansFpMath(attr.getValueAsBool());
1806 if (llvm::Attribute attr = func->getFnAttribute(
"approx-func-fp-math");
1807 attr.isStringAttribute())
1808 funcOp.setApproxFuncFpMath(attr.getValueAsBool());
1810 if (llvm::Attribute attr = func->getFnAttribute(
"no-signed-zeros-fp-math");
1811 attr.isStringAttribute())
1812 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
1816 ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
1820 auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
1822 if (!llvmAttr.isValid())
1825 if (llvmAttr.isTypeAttribute())
1827 else if (llvmAttr.isIntAttribute())
1829 else if (llvmAttr.isEnumAttribute())
1832 llvm_unreachable(
"unexpected parameter attribute kind");
1833 paramAttrs.push_back(builder.
getNamedAttr(mlirName, mlirAttr));
1839 void ModuleImport::convertParameterAttributes(llvm::Function *func,
1842 auto llvmAttrs = func->getAttributes();
1843 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
1844 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
1845 funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder));
1849 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
1850 if (!llvmResAttr.hasAttributes())
1852 funcOp.setResAttrsAttr(
1853 builder.
getArrayAttr(convertParameterAttribute(llvmResAttr, builder)));
1860 dyn_cast<LLVMFunctionType>(
convertType(func->getFunctionType()));
1861 if (func->isIntrinsic() &&
1865 bool dsoLocal = func->hasLocalLinkage();
1866 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
1872 Location loc = debugImporter->translateFuncLocation(func);
1873 LLVMFuncOp funcOp = builder.
create<LLVMFuncOp>(
1874 loc, func->getName(), functionType,
1875 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
1877 convertParameterAttributes(func, funcOp, builder);
1880 funcOp.setPersonalityAttr(personality);
1881 else if (func->hasPersonalityFn())
1882 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
1885 funcOp.setGarbageCollector(StringRef(func->getGC()));
1887 if (func->hasAtLeastLocalUnnamedAddr())
1888 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
1890 if (func->hasSection())
1891 funcOp.setSection(StringRef(func->getSection()));
1893 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
1895 if (func->hasComdat())
1896 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
1898 if (llvm::MaybeAlign maybeAlign = func->getAlign())
1899 funcOp.setAlignment(maybeAlign->value());
1906 func->getAllMetadata(allMetadata);
1907 for (
auto &[kind, node] : allMetadata) {
1912 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
1913 <<
" on " <<
diag(*func);
1917 if (func->isDeclaration())
1926 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
1927 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
1932 for (llvm::BasicBlock &basicBlock : *func) {
1934 if (!reachable.contains(&basicBlock))
1936 Region &body = funcOp.getBody();
1939 reachableBasicBlocks.push_back(&basicBlock);
1944 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
1945 functionType.getParamType(it.index()), funcOp.getLoc());
1954 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
1955 for (llvm::BasicBlock *basicBlock : blocks)
1961 if (
failed(processDebugIntrinsics()))
1970 if (!dbgIntr->isKillLocation())
1972 llvm::Value *value = dbgIntr->getArgOperand(0);
1973 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1976 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1980 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
1983 auto emitUnsupportedWarning = [&]() {
1984 if (emitExpensiveWarnings)
1990 if (dbgIntr->hasArgList())
1991 return emitUnsupportedWarning();
1996 return emitUnsupportedWarning();
2000 DILocalVariableAttr localVariableAttr =
2002 if (!localVariableAttr)
2003 return emitUnsupportedWarning();
2006 return emitError(loc) <<
"failed to convert a debug intrinsic operand: "
2014 if (
Operation *op = argOperand->getDefiningOp();
2020 if (dominatedBlocks.empty())
2021 return emitUnsupportedWarning();
2024 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
2029 auto locationExprAttr =
2030 debugImporter->translateExpression(dbgIntr->getExpression());
2033 .Case([&](llvm::DbgDeclareInst *) {
2034 return builder.
create<LLVM::DbgDeclareOp>(
2035 loc, *argOperand, localVariableAttr, locationExprAttr);
2037 .Case([&](llvm::DbgValueInst *) {
2038 return builder.
create<LLVM::DbgValueOp>(
2039 loc, *argOperand, localVariableAttr, locationExprAttr);
2042 setNonDebugMetadataAttrs(dbgIntr, op);
2048 for (llvm::Instruction *inst : debugIntrinsics) {
2049 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
2050 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
2056 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
2059 for (llvm::Instruction &inst : *bb) {
2060 if (
failed(processInstruction(&inst)))
2065 if (debugIntrinsics.contains(&inst))
2072 setNonDebugMetadataAttrs(&inst, op);
2073 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
2074 if (emitExpensiveWarnings) {
2075 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
2085 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
2091 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
2097 bool dropDICompositeTypeElements) {
2104 LLVMDialect::getDialectNamespace()));
2106 DLTIDialect::getDialectNamespace()));
2113 emitExpensiveWarnings, dropDICompositeTypeElements);
static MLIRContext * getContext(OpFoldResult val)
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static StringRef getLLVMSyncScope(llvm::Instruction *inst)
Converts the sync scope identifier of inst to the string representation necessary to build an atomic ...
static std::string diag(const llvm::Value &value)
static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp)
static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static constexpr StringRef getGlobalDtorsVarName()
Returns the name of the global_dtors global variables.
static Type getVectorTypeForAttr(Type type, ArrayRef< int64_t > arrayShape={})
Returns type if it is a builtin integer or floating-point vector type that can be used to create an a...
static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder, llvm::Instruction *inst, ModuleImport &moduleImport, LLVMImportInterface &iface)
Converts the LLVM instructions that have a generated MLIR builder.
static constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
static TypedAttr getScalarConstantAsAttr(OpBuilder &builder, llvm::Constant *constScalar)
Returns an integer or float attribute for the provided scalar constant constScalar or nullptr if the ...
static std::string diagMD(const llvm::Metadata *node, const llvm::Module *module)
static constexpr std::array ExplicitAttributes
static bool isScalarType(Type type)
Returns if type is a scalar integer or floating-point type.
static SmallVector< Attribute > getSequenceConstantAsAttrs(OpBuilder &builder, llvm::ConstantDataSequential *constSequence)
Returns an integer or float attribute array for the provided constant sequence constSequence or nullp...
static llvm::ManagedStatic< PassManagerOptions > options
static void contract(RootOrderingGraph &graph, ArrayRef< Value > cycle, const DenseMap< Value, unsigned > &parentDepths, DenseMap< Value, Value > &actualSource, DenseMap< Value, Value > &actualTarget)
Contracts the specified cycle in the given graph in-place.
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
Operation * getTerminator()
Get the terminator operation of this block.
BlockArgument addArgument(Type type, Location loc)
Add one value to the argument list.
IntegerAttr getI32IntegerAttr(int32_t value)
IntegerAttr getIntegerAttr(Type type, int64_t value)
ArrayAttr getI32ArrayAttr(ArrayRef< int32_t > values)
FloatAttr getFloatAttr(Type type, double value)
IntegerAttr getI64IntegerAttr(int64_t value)
StringAttr getStringAttr(const Twine &bytes)
TypedAttr getZeroAttr(Type type)
MLIRContext * getContext() const
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
DictionaryAttr getDictionaryAttr(ArrayRef< NamedAttribute > value)
NamedAttribute getNamedAttr(StringRef name, Attribute val)
ArrayAttr getStrArrayAttr(ArrayRef< StringRef > values)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
A class for computing basic dominance information.
This class provides support for representing a failure result, or a valid value of type T.
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
static FloatType getBF16(MLIRContext *ctx)
Interface collection for the import of LLVM IR that dispatches to a concrete dialect interface implem...
LogicalResult convertInstruction(OpBuilder &builder, llvm::Instruction *inst, ArrayRef< llvm::Value * > llvmOperands, LLVM::ModuleImport &moduleImport) const
Converts the LLVM instruction to an MLIR operation if a conversion exists.
LogicalResult convertIntrinsic(OpBuilder &builder, llvm::CallInst *inst, LLVM::ModuleImport &moduleImport) const
Converts the LLVM intrinsic to an MLIR operation if a conversion exists.
LogicalResult setMetadataAttrs(OpBuilder &builder, unsigned kind, llvm::MDNode *node, Operation *op, LLVM::ModuleImport &moduleImport) const
Attaches the given LLVM metadata to the imported operation if a conversion to one or more MLIR dialec...
bool isConvertibleMetadata(unsigned kind)
Returns true if the given LLVM IR metadata is convertible to an MLIR attribute.
bool isConvertibleInstruction(unsigned id)
Returns true if the given LLVM IR instruction is convertible to an MLIR operation.
bool isConvertibleIntrinsic(llvm::Intrinsic::ID id)
Returns true if the given LLVM IR intrinsic is convertible to an MLIR operation.
Module import implementation class that provides methods to import globals and functions from an LLVM...
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LogicalResult convertComdats()
Converts all comdat selectors of the LLVM module to MLIR comdat operations.
LogicalResult convertFunctions()
Converts all functions of the LLVM module to MLIR functions.
FailureOr< SmallVector< Value > > convertValues(ArrayRef< llvm::Value * > values)
Converts a range of LLVM values to a range of MLIR values using the convertValue method,...
DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value)
Converts value to a local variable attribute.
LogicalResult convertLinkerOptionsMetadata()
Converts !llvm.linker.options metadata to the llvm.linker.options LLVM dialect operation.
void mapBlock(llvm::BasicBlock *llvm, Block *mlir)
Stores the mapping between an LLVM block and its MLIR counterpart.
void processFunctionAttributes(llvm::Function *func, LLVMFuncOp funcOp)
Converts function attributes of LLVM Function func into LLVM dialect attributes of LLVMFuncOp funcOp.
LogicalResult convertMetadata()
Converts all LLVM metadata nodes that translate to attributes such as alias analysis or access group ...
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, ArrayRef< unsigned > immArgPositions, ArrayRef< StringLiteral > immArgAttrNames, SmallVectorImpl< Value > &valuesOut, SmallVectorImpl< NamedAttribute > &attrsOut)
Converts the LLVM values for an intrinsic to mixed MLIR values and attributes for LLVM_IntrOpBase.
FailureOr< Value > convertValue(llvm::Value *value)
Converts an LLVM value to an MLIR value, or returns failure if the conversion fails.
LogicalResult initializeImportInterface()
Calls the LLVMImportInterface initialization that queries the registered dialect interfaces for the s...
void addDebugIntrinsic(llvm::CallInst *intrinsic)
Adds a debug intrinsics to the list of intrinsics that should be converted after the function convers...
Block * lookupBlock(llvm::BasicBlock *block) const
Returns the MLIR block mapped to the given LLVM block.
FailureOr< Value > convertMetadataValue(llvm::Value *value)
Converts an LLVM metadata value to an MLIR value, or returns failure if the conversion fails.
FailureOr< SmallVector< AliasScopeAttr > > lookupAliasScopeAttrs(const llvm::MDNode *node) const
Returns the alias scope attributes that map to the alias scope nodes starting from the metadata node.
void mapNoResultOp(llvm::Instruction *llvm, Operation *mlir)
Stores a mapping between an LLVM instruction and the imported MLIR operation if the operation returns...
Type convertType(llvm::Type *type)
Converts the type from LLVM to MLIR LLVM dialect.
Operation * lookupOperation(llvm::Instruction *inst)
Returns the MLIR operation mapped to the given LLVM instruction.
DILabelAttr matchLabelAttr(llvm::Value *value)
Converts value to a label attribute. Asserts if the matching fails.
FloatAttr matchFloatAttr(llvm::Value *value)
Converts value to a float attribute. Asserts if the matching fails.
LoopAnnotationAttr translateLoopAnnotationAttr(const llvm::MDNode *node, Location loc) const
Returns the loop annotation attribute that corresponds to the given LLVM loop metadata node.
void setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const
Sets the fastmath flags attribute for the imported operation op given the original instruction inst.
FailureOr< SmallVector< AliasScopeAttr > > matchAliasScopeAttrs(llvm::Value *value)
Converts value to an array of alias scopes or returns failure if the conversion fails.
Value lookupValue(llvm::Value *value)
Returns the MLIR value mapped to the given LLVM value.
LogicalResult processFunction(llvm::Function *func)
Imports func into the current module.
RoundingModeAttr matchRoundingModeAttr(llvm::Value *value)
Converts value to a rounding mode attribute.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes)
FailureOr< SmallVector< AccessGroupAttr > > lookupAccessGroupAttrs(const llvm::MDNode *node) const
Returns the access group attributes that map to the access group nodes starting from the access group...
LogicalResult convertGlobals()
Converts all global variables of the LLVM module to MLIR global variables.
void setIntegerOverflowFlags(llvm::Instruction *inst, Operation *op) const
Sets the integer overflow flags (nsw/nuw) attribute for the imported operation op given the original ...
FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value)
Converts value to a FP exception behavior attribute.
LogicalResult convertDataLayout()
Converts the data layout of the LLVM module to an MLIR data layout specification.
IntegerAttr matchIntegerAttr(llvm::Value *value)
Converts value to an integer attribute. Asserts if the matching fails.
Helper class that translates an LLVM data layout to an MLIR data layout specification.
StringRef getLastToken() const
Returns the last data layout token that has been processed before the data layout translation failed.
DataLayoutSpecInterface getDataLayout() const
Returns the MLIR data layout specification translated from the LLVM data layout.
ArrayRef< StringRef > getUnhandledTokens() const
Returns the data layout tokens that have not been handled during the data layout translation.
A helper class that converts llvm.loop metadata nodes into corresponding LoopAnnotationAttrs and llvm...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
std::vector< StringRef > getAvailableDialects()
Return information about all available dialects in the registry in this context.
void loadAllAvailableDialects()
Load all dialects available in the registry in this context.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Block * getBlock()
Returns the operation block that contains this operation.
OpTy get() const
Allow accessing the internal op.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
DominanceInfoNode * getNode(Block *a)
Return the dominance node from the Region containing block A.
static llvm::ArrayRef< std::pair< llvm::Attribute::AttrKind, llvm::StringRef > > getAttrKindToNameMapping()
Returns a list of pairs that each hold a mapping from LLVM attribute kinds to their corresponding str...
FloatType getFloatType(MLIRContext *context, unsigned width)
Returns a supported MLIR floating point type of the given bit width or null if the bit width is not s...
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true, bool dropDICompositeTypeElements=false)
Translates the LLVM module into an MLIR module living in the given context.
SetVector< Block * > getTopologicallySortedBlocks(Region ®ion)
Get a topologically sorted list of blocks of the given region.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
bool succeeded(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a success value.
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.