30 #include "llvm/ADT/DepthFirstIterator.h"
31 #include "llvm/ADT/PostOrderIterator.h"
32 #include "llvm/ADT/ScopeExit.h"
33 #include "llvm/ADT/StringSet.h"
34 #include "llvm/ADT/TypeSwitch.h"
35 #include "llvm/IR/Comdat.h"
36 #include "llvm/IR/Constants.h"
37 #include "llvm/IR/InlineAsm.h"
38 #include "llvm/IR/InstIterator.h"
39 #include "llvm/IR/Instructions.h"
40 #include "llvm/IR/IntrinsicInst.h"
41 #include "llvm/IR/Metadata.h"
42 #include "llvm/IR/Operator.h"
43 #include "llvm/Support/ModRef.h"
49 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
54 static std::string
diag(
const llvm::Value &value) {
56 llvm::raw_string_ostream os(str);
64 static std::string
diagMD(
const llvm::Metadata *node,
65 const llvm::Module *module) {
67 llvm::raw_string_ostream os(str);
68 node->print(os, module,
true);
74 return "llvm.global_ctors";
79 return "mlir.llvm.nameless_global";
84 return "llvm.global_dtors";
90 return "__llvm_global_comdat";
99 std::optional<llvm::SyncScope::ID> syncScopeID =
100 llvm::getAtomicSyncScopeID(inst);
107 llvm::LLVMContext &llvmContext = inst->getContext();
108 llvmContext.getSyncScopeNames(syncScopeName);
109 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
110 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
112 if (it != syncScopeName.end())
114 llvm_unreachable(
"incorrect sync scope identifier");
120 llvm::append_range(position, indices);
131 llvm::Instruction *inst,
144 #include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
152 for (llvm::BasicBlock *basicBlock : basicBlocks) {
153 if (!blocks.contains(basicBlock)) {
154 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
155 blocks.insert_range(traversal);
158 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
163 std::unique_ptr<llvm::Module> llvmModule,
164 bool emitExpensiveWarnings,
165 bool importEmptyDICompositeTypes,
166 bool preferUnregisteredIntrinsics)
168 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
172 mlirModule, importEmptyDICompositeTypes)),
173 loopAnnotationImporter(
175 emitExpensiveWarnings(emitExpensiveWarnings),
176 preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
180 ComdatOp ModuleImport::getGlobalComdatOp() {
182 return globalComdatOp;
188 globalInsertionOp = globalComdatOp;
189 return globalComdatOp;
192 LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
197 auto getIdentityIfRootNode =
198 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
202 if (node->getNumOperands() > 1)
205 if (node->getNumOperands() == 1)
206 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
207 return std::optional<StringRef>{op0->getString()};
208 return std::optional<StringRef>{};
218 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
219 StringRef *identity =
nullptr,
221 nullptr) -> std::optional<bool> {
222 unsigned numOperands = node->getNumOperands();
231 const auto *identityNode =
232 dyn_cast<const llvm::MDString>(node->getOperand(0));
238 *identity = identityNode->getString();
240 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
241 const auto *memberNode =
242 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
244 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
245 <<
diagMD(node, llvmModule.get());
249 if (2 * pairNum + 2 >= numOperands) {
251 if (numOperands != 2) {
252 emitError(loc) <<
"missing member offset: "
253 <<
diagMD(node, llvmModule.get());
257 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
258 node->getOperand(2 * pairNum + 2));
260 emitError(loc) <<
"operand '" << 2 * pairNum + 2
261 <<
"' must be ConstantInt: "
262 <<
diagMD(node, llvmModule.get());
265 offset = offsetCI->getZExtValue();
270 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
283 auto isTagNode = [&](
const llvm::MDNode *node,
284 TBAATypeDescriptorAttr *baseAttr =
nullptr,
285 TBAATypeDescriptorAttr *accessAttr =
nullptr,
286 int64_t *offset =
nullptr,
287 bool *isConstant =
nullptr) -> std::optional<bool> {
295 unsigned numOperands = node->getNumOperands();
296 if (numOperands != 3 && numOperands != 4)
298 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
299 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
301 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
302 if (!baseMD || !accessMD || !offsetCI)
309 if (accessMD->getNumOperands() < 1 ||
310 !isa<llvm::MDString>(accessMD->getOperand(0)))
312 bool isConst =
false;
313 if (numOperands == 4) {
315 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
317 emitError(loc) <<
"operand '3' must be ConstantInt: "
318 <<
diagMD(node, llvmModule.get());
321 isConst = isConstantCI->getValue()[0];
324 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
326 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
328 *offset = offsetCI->getZExtValue();
330 *isConstant = isConst;
339 workList.push_back(node);
340 while (!workList.empty()) {
341 const llvm::MDNode *current = workList.back();
342 if (tbaaMapping.contains(current)) {
351 bool anyChildNotConverted =
false;
352 for (
const llvm::MDOperand &operand : current->operands())
353 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
354 if (!tbaaMapping.contains(childNode)) {
355 workList.push_back(childNode);
356 anyChildNotConverted =
true;
359 if (anyChildNotConverted) {
364 if (!seen.insert(current).second)
365 return emitError(loc) <<
"has cycle in TBAA graph: "
366 <<
diagMD(current, llvmModule.get());
374 FailureOr<std::optional<StringRef>> rootNodeIdentity =
375 getIdentityIfRootNode(current);
376 if (succeeded(rootNodeIdentity)) {
377 StringAttr stringAttr = *rootNodeIdentity
382 tbaaMapping.insert({current, builder.
getAttr<TBAARootAttr>(stringAttr)});
388 if (std::optional<bool> isValid =
389 isTypeDescriptorNode(current, &identity, &members)) {
390 assert(isValid.value() &&
"type descriptor node must be valid");
392 tbaaMapping.insert({current, builder.
getAttr<TBAATypeDescriptorAttr>(
393 identity, members)});
397 TBAATypeDescriptorAttr baseAttr, accessAttr;
400 if (std::optional<bool> isValid =
401 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
402 assert(isValid.value() &&
"access tag node must be valid");
404 {current, builder.
getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
409 return emitError(loc) <<
"unsupported TBAA node format: "
410 <<
diagMD(current, llvmModule.get());
416 ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
418 if (failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
419 return emitError(loc) <<
"unsupported access group node: "
420 <<
diagMD(node, llvmModule.get());
425 ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
428 auto verifySelfRef = [](
const llvm::MDNode *node) {
429 return node->getNumOperands() != 0 &&
430 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
432 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
433 return node->getNumOperands() != 0 &&
434 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
435 isa<llvm::MDString>(node->getOperand(0)));
438 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
439 return idx >= node->getNumOperands() ||
440 isa<llvm::MDString>(node->getOperand(idx));
443 auto getIdAttr = [&](
const llvm::MDNode *node) ->
Attribute {
444 if (verifySelfRef(node))
447 auto name = cast<llvm::MDString>(node->getOperand(0));
452 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
453 StringAttr description =
nullptr;
454 if (aliasDomain->getNumOperands() >= 2)
455 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
457 Attribute idAttr = getIdAttr(aliasDomain);
458 return builder.
getAttr<AliasScopeDomainAttr>(idAttr, description);
462 for (
const llvm::MDOperand &operand : node->operands()) {
463 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
464 llvm::AliasScopeNode aliasScope(scope);
465 const llvm::MDNode *domain = aliasScope.getDomain();
471 if (!verifySelfRefOrString(scope) || !domain ||
472 !verifyDescription(scope, 2))
473 return emitError(loc) <<
"unsupported alias scope node: "
474 <<
diagMD(scope, llvmModule.get());
475 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
476 return emitError(loc) <<
"unsupported alias domain node: "
477 <<
diagMD(domain, llvmModule.get());
479 if (aliasScopeMapping.contains(scope))
483 auto it = aliasScopeMapping.find(aliasScope.getDomain());
484 if (it == aliasScopeMapping.end()) {
485 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
486 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
490 StringAttr description =
nullptr;
491 if (!aliasScope.getName().empty())
494 auto aliasScopeOp = builder.
getAttr<AliasScopeAttr>(
495 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
497 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
503 FailureOr<SmallVector<AliasScopeAttr>>
506 aliasScopes.reserve(node->getNumOperands());
507 for (
const llvm::MDOperand &operand : node->operands()) {
508 auto *node = cast<llvm::MDNode>(operand.get());
509 aliasScopes.push_back(
510 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
513 if (llvm::is_contained(aliasScopes,
nullptr))
519 debugIntrinsics.insert(intrinsic);
524 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
527 for (
const auto [behavior, key, val] : llvmModuleFlags) {
529 auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val);
532 <<
"unsupported module flag value: " <<
diagMD(val, llvmModule.get())
533 <<
", only constant integer currently supported";
537 moduleFlags.push_back(builder.
getAttr<ModuleFlagAttr>(
538 convertModFlagBehaviorFromLLVM(behavior),
539 builder.
getStringAttr(key->getString()), constInt->getZExtValue()));
542 if (!moduleFlags.empty())
543 builder.
create<LLVM::ModuleFlagsOp>(mlirModule.getLoc(),
550 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
551 if (named.getName() !=
"llvm.linker.options")
554 for (
const llvm::MDNode *node : named.operands()) {
556 options.reserve(node->getNumOperands());
557 for (
const llvm::MDOperand &option : node->operands())
558 options.push_back(cast<llvm::MDString>(option)->getString());
559 builder.
create<LLVM::LinkerOptionsOp>(mlirModule.getLoc(),
567 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
570 if (named.getName() != LLVMDialect::getIdentAttrName())
573 if (named.getNumOperands() == 1)
574 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
575 if (md->getNumOperands() == 1)
576 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
577 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
584 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
587 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
590 if (nmd.getNumOperands() == 1)
591 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
592 if (md->getNumOperands() == 1)
593 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
594 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
603 for (
const llvm::Function &func : llvmModule->functions()) {
604 for (
const llvm::Instruction &inst : llvm::instructions(func)) {
606 if (llvm::MDNode *node =
607 inst.getMetadata(llvm::LLVMContext::MD_access_group))
608 if (failed(processAccessGroupMetadata(node)))
612 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
613 if (!aliasAnalysisNodes)
615 if (aliasAnalysisNodes.TBAA)
616 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
618 if (aliasAnalysisNodes.Scope)
619 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
621 if (aliasAnalysisNodes.NoAlias)
622 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
637 void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
638 if (comdatMapping.contains(comdat))
641 ComdatOp comdatOp = getGlobalComdatOp();
644 auto selectorOp = builder.
create<ComdatSelectorOp>(
645 mlirModule.getLoc(), comdat->getName(),
646 convertComdatFromLLVM(comdat->getSelectionKind()));
650 comdatMapping.try_emplace(comdat, symbolRef);
654 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
655 if (globalVar.hasComdat())
656 processComdat(globalVar.getComdat());
657 for (llvm::Function &func : llvmModule->functions())
658 if (func.hasComdat())
659 processComdat(func.getComdat());
664 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
667 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
669 <<
"unhandled global variable: " <<
diag(globalVar);
673 if (failed(convertGlobal(&globalVar))) {
675 <<
"unhandled global variable: " <<
diag(globalVar);
682 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
683 if (failed(convertAlias(&alias))) {
685 <<
"unhandled global alias: " <<
diag(alias);
695 return emitError(loc,
"cannot translate data layout: ")
699 emitWarning(loc,
"unhandled data layout token: ") << token;
701 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
708 LLVM::LLVMDialect::getTargetTripleAttrName(),
713 for (llvm::Function &func : llvmModule->functions())
719 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
722 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
723 for (
auto &[
kind, node] : allMetadata) {
727 if (emitExpensiveWarnings) {
728 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
730 <<
diagMD(node, llvmModule.get()) <<
" on "
739 auto iface = cast<IntegerOverflowFlagsInterface>(op);
741 IntegerOverflowFlags value = {};
742 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
744 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
746 iface.setOverflowFlags(value);
750 auto iface = cast<ExactFlagInterface>(op);
752 iface.setIsExact(inst->isExact());
757 auto iface = cast<DisjointFlagInterface>(op);
758 auto instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
760 iface.setIsDisjoint(instDisjoint->isDisjoint());
764 auto iface = cast<NonNegFlagInterface>(op);
766 iface.setNonNeg(inst->hasNonNeg());
771 auto iface = cast<FastmathFlagsInterface>(op);
777 if (!isa<llvm::FPMathOperator>(inst))
779 llvm::FastMathFlags flags = inst->getFastMathFlags();
782 FastmathFlags value = {};
783 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
784 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
785 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
786 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
788 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
789 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
791 iface->setAttr(iface.getFastmathAttrName(), attr);
803 if (numElements.isScalable()) {
805 <<
"scalable vectors not supported";
815 shape.push_back(numElements.getKnownMinValue());
819 Type ModuleImport::getBuiltinTypeForAttr(
Type type) {
834 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
835 arrayShape.push_back(arrayType.getNumElements());
836 type = arrayType.getElementType();
846 llvm::Constant *constScalar) {
850 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
853 constInt->getValue());
857 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
858 llvm::Type *type = constFloat->getType();
859 FloatType floatType =
865 <<
"unexpected floating-point type";
868 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
877 llvm::ConstantDataSequential *constSequence) {
879 elementAttrs.reserve(constSequence->getNumElements());
880 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
881 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
887 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
893 auto getConstantShape = [&](llvm::Type *type) {
894 return llvm::dyn_cast_if_present<ShapedType>(
900 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
901 if (constArray->isString())
903 auto shape = getConstantShape(constArray->getType());
907 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
908 if (constVector && constVector->isSplat()) {
911 builder, constVector->getElementAsConstant(0));
922 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
923 auto shape = getConstantShape(constAggregate->getType());
929 while (!workList.empty()) {
930 llvm::Constant *current = workList.pop_back_val();
933 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
935 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
936 workList.push_back(constAggregate->getAggregateElement(idx));
941 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
944 elementAttrs.append(attrs.begin(), attrs.end());
950 elementAttrs.push_back(scalarAttr);
961 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
962 auto shape = llvm::dyn_cast_if_present<ShapedType>(
963 getBuiltinTypeForAttr(
convertType(constZero->getType())));
968 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
975 ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
976 assert(globalVar->getName().empty() &&
977 "expected to work with a nameless global");
978 auto [it, success] = namelessGlobals.try_emplace(globalVar);
985 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
988 it->getSecond() = symbolRef;
994 if (globalInsertionOp)
1001 LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1006 AliasOp aliasOp = builder.
create<AliasOp>(
1007 mlirModule.getLoc(), type, convertLinkageFromLLVM(alias->getLinkage()),
1009 alias->isDSOLocal(),
1010 alias->isThreadLocal(),
1012 globalInsertionOp = aliasOp;
1016 setConstantInsertionPointToStart(block);
1017 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1018 if (failed(initializer))
1020 builder.
create<ReturnOp>(aliasOp.getLoc(), *initializer);
1022 if (alias->hasAtLeastLocalUnnamedAddr())
1023 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1024 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1029 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1034 if (globalVar->hasInitializer())
1035 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1038 uint64_t alignment = 0;
1039 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1040 if (maybeAlign.has_value()) {
1041 llvm::Align align = *maybeAlign;
1042 alignment = align.value();
1049 globalVar->getDebugInfo(globalExpressions);
1051 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1052 DIGlobalVariableExpressionAttr globalExpressionAttr =
1053 debugImporter->translateGlobalVariableExpression(expr);
1054 globalExpressionAttrs.push_back(globalExpressionAttr);
1059 StringRef globalName = globalVar->getName();
1060 if (globalName.empty())
1061 globalName = getOrCreateNamelessSymbolName(globalVar).
getValue();
1063 GlobalOp globalOp = builder.
create<GlobalOp>(
1064 mlirModule.getLoc(), type, globalVar->isConstant(),
1065 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1066 valueAttr, alignment, globalVar->getAddressSpace(),
1067 globalVar->isDSOLocal(),
1068 globalVar->isThreadLocal(), SymbolRefAttr(),
1070 globalInsertionOp = globalOp;
1072 if (globalVar->hasInitializer() && !valueAttr) {
1075 setConstantInsertionPointToStart(block);
1076 FailureOr<Value> initializer =
1077 convertConstantExpr(globalVar->getInitializer());
1078 if (failed(initializer))
1080 builder.
create<ReturnOp>(globalOp.getLoc(), *initializer);
1082 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1083 globalOp.setUnnamedAddr(
1084 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1086 if (globalVar->hasSection())
1087 globalOp.setSection(globalVar->getSection());
1088 globalOp.setVisibility_(
1089 convertVisibilityFromLLVM(globalVar->getVisibility()));
1091 if (globalVar->hasComdat())
1092 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1098 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1099 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1101 llvm::Constant *initializer = globalVar->getInitializer();
1103 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1104 isa<llvm::ConstantAggregateZero>(initializer);
1111 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1112 if (caz->getElementCount().getFixedValue() != 0)
1119 for (llvm::Value *operand : initializer->operands()) {
1120 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1121 if (!aggregate || aggregate->getNumOperands() != 3)
1124 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1125 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1126 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1127 if (!priority || !func || !data)
1130 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1134 else if (data->isNullValue())
1140 priorities.push_back(priority->getValue().getZExtValue());
1141 dataList.push_back(dataAttr);
1148 globalInsertionOp = builder.
create<LLVM::GlobalCtorsOp>(
1153 globalInsertionOp = builder.
create<LLVM::GlobalDtorsOp>(
1160 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1162 if (valueMapping.contains(constant))
1171 workList.insert(constant);
1172 while (!workList.empty()) {
1173 llvm::Constant *current = workList.back();
1176 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1177 orderedSet.insert(current);
1178 workList.pop_back();
1184 auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);
1188 for (llvm::Value *operand : current->operands())
1189 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1190 adjacencyIt->getSecond().push_back(constDependency);
1193 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1194 unsigned numElements = constAgg->getElementCount().getFixedValue();
1195 for (
unsigned i = 0, e = numElements; i != e; ++i)
1196 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1202 if (adjacencyIt->getSecond().empty()) {
1203 orderedSet.insert(current);
1204 workList.pop_back();
1212 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1213 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1214 orderedSet.contains(dependency))
1216 workList.insert(dependency);
1222 FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1226 if (
Attribute attr = getConstantAsAttr(constant)) {
1228 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1229 return builder.
create<AddressOfOp>(loc, type, symbolRef.getValue())
1232 return builder.
create<ConstantOp>(loc, type, attr).getResult();
1236 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1238 return builder.
create<ZeroOp>(loc, type).getResult();
1242 if (isa<llvm::ConstantTokenNone>(constant)) {
1243 return builder.
create<NoneTokenOp>(loc).getResult();
1247 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1249 return builder.
create<PoisonOp>(loc, type).getResult();
1253 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1255 return builder.
create<UndefOp>(loc, type).getResult();
1259 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1262 .
create<DSOLocalEquivalentOp>(
1266 dsoLocalEquivalent->getGlobalValue()->getName()))
1271 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1273 StringRef globalName = globalObj->getName();
1276 if (globalName.empty())
1278 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1281 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1285 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1287 StringRef aliaseeName = globalAliasObj->getName();
1289 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1293 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1299 llvm::Instruction *inst = constExpr->getAsInstruction();
1300 auto guard = llvm::make_scope_exit([&]() {
1301 assert(!noResultOpMapping.contains(inst) &&
1302 "expected constant expression to return a result");
1303 valueMapping.erase(inst);
1304 inst->deleteValue();
1308 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1309 return valueMapping.contains(value);
1311 if (failed(processInstruction(inst)))
1317 if (isa<llvm::ConstantAggregate>(constant) ||
1318 isa<llvm::ConstantAggregateZero>(constant)) {
1321 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1322 elementValues.reserve(constAgg->getNumOperands());
1323 for (llvm::Value *operand : constAgg->operands())
1326 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1327 unsigned numElements = constAgg->getElementCount().getFixedValue();
1328 elementValues.reserve(numElements);
1329 for (
unsigned i = 0, e = numElements; i != e; ++i)
1330 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1332 assert(llvm::count(elementValues,
nullptr) == 0 &&
1333 "expected all elements have been converted before");
1337 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1339 "unrecognized aggregate type");
1340 Value root = builder.
create<UndefOp>(loc, rootType);
1342 if (isArrayOrStruct) {
1343 root = builder.
create<InsertValueOp>(loc, root, it.value(), it.index());
1348 root = builder.
create<InsertElementOp>(loc, rootType, root, it.value(),
1355 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1356 LLVMTargetExtType targetExtType =
1357 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1358 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1359 "target extension type does not support zero-initialization");
1362 return builder.
create<LLVM::ZeroOp>(loc, targetExtType).getRes();
1365 StringRef error =
"";
1366 if (isa<llvm::BlockAddress>(constant))
1367 error =
" since blockaddress(...) is unsupported";
1369 if (isa<llvm::ConstantPtrAuth>(constant))
1370 error =
" since ptrauth(...) is unsupported";
1372 if (isa<llvm::NoCFIValue>(constant))
1373 error =
" since no_cfi is unsupported";
1375 if (isa<llvm::GlobalValue>(constant))
1376 error =
" since global value is unsupported";
1378 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1381 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1385 assert(!valueMapping.contains(constant) &&
1386 "expected constant has not been converted before");
1387 assert(constantInsertionBlock &&
1388 "expected the constant insertion block to be non-null");
1392 if (!constantInsertionOp)
1399 getConstantsToConvert(constant);
1400 for (llvm::Constant *constantToConvert : constantsToConvert) {
1401 FailureOr<Value> converted = convertConstant(constantToConvert);
1402 if (failed(converted))
1404 mapValue(constantToConvert, *converted);
1414 assert(!isa<llvm::MetadataAsValue>(value) &&
1415 "expected value to not be metadata");
1418 auto it = valueMapping.find(value);
1419 if (it != valueMapping.end())
1420 return it->getSecond();
1423 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1424 return convertConstantExpr(constant);
1427 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1429 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1435 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1438 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1441 value = node->getValue();
1444 auto it = valueMapping.find(value);
1445 if (it != valueMapping.end())
1446 return it->getSecond();
1449 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1450 return convertConstantExpr(constant);
1454 FailureOr<SmallVector<Value>>
1457 remapped.reserve(values.size());
1458 for (llvm::Value *value : values) {
1460 if (failed(converted))
1462 remapped.push_back(*converted);
1472 assert(immArgPositions.size() == immArgAttrNames.size() &&
1473 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1477 for (
auto [immArgPos, immArgName] :
1478 llvm::zip(immArgPositions, immArgAttrNames)) {
1479 auto &value = operands[immArgPos];
1480 auto *constant = llvm::cast<llvm::Constant>(value);
1482 assert(attr && attr.getType().isIntOrFloat() &&
1483 "expected immarg to be float or integer constant");
1485 attrsOut.push_back({nameAttr, attr});
1490 for (llvm::Value *value : operands) {
1494 if (failed(mlirValue))
1496 valuesOut.push_back(*mlirValue);
1501 if (requiresOpBundles) {
1502 opBundleSizes.reserve(opBundles.size());
1503 opBundleTagAttrs.reserve(opBundles.size());
1505 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1506 opBundleSizes.push_back(bundle.Inputs.size());
1507 opBundleTagAttrs.push_back(
StringAttr::get(context, bundle.getTagName()));
1509 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1510 auto operandMlirValue =
convertValue(opBundleOperand.get());
1511 if (failed(operandMlirValue))
1513 valuesOut.push_back(*operandMlirValue);
1518 auto opBundleSizesAttrNameAttr =
1520 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1522 auto opBundleTagsAttr =
ArrayAttr::get(context, opBundleTagAttrs);
1523 auto opBundleTagsAttrNameAttr =
1525 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1532 IntegerAttr integerAttr;
1534 bool success = succeeded(converted) &&
1536 assert(success &&
"expected a constant integer value");
1542 FloatAttr floatAttr;
1546 assert(success &&
"expected a constant float value");
1552 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1553 auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
1554 return debugImporter->translate(node);
1558 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1559 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
1560 return debugImporter->translate(node);
1563 FPExceptionBehaviorAttr
1565 auto *metadata = cast<llvm::MetadataAsValue>(value);
1566 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1567 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
1568 llvm::convertStrToExceptionBehavior(mdstr->getString());
1569 assert(optLLVM &&
"Expecting FP exception behavior");
1570 return builder.
getAttr<FPExceptionBehaviorAttr>(
1571 convertFPExceptionBehaviorFromLLVM(*optLLVM));
1575 auto *metadata = cast<llvm::MetadataAsValue>(value);
1576 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1577 std::optional<llvm::RoundingMode> optLLVM =
1578 llvm::convertStrToRoundingMode(mdstr->getString());
1579 assert(optLLVM &&
"Expecting rounding mode");
1580 return builder.
getAttr<RoundingModeAttr>(
1581 convertRoundingModeFromLLVM(*optLLVM));
1584 FailureOr<SmallVector<AliasScopeAttr>>
1586 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1587 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
1592 return debugImporter->translateLoc(loc);
1596 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
1597 llvm::BasicBlock *target,
1599 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
1600 auto *phiInst = cast<llvm::PHINode>(&*inst);
1601 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
1603 if (failed(converted))
1605 blockArguments.push_back(*converted);
1610 FailureOr<SmallVector<Value>>
1611 ModuleImport::convertCallOperands(llvm::CallBase *callInst,
1612 bool allowInlineAsm) {
1613 bool isInlineAsm = callInst->isInlineAsm();
1614 if (isInlineAsm && !allowInlineAsm)
1624 if (!isa<llvm::Function>(callInst->getCalledOperand()) && !isInlineAsm) {
1625 FailureOr<Value> called =
convertValue(callInst->getCalledOperand());
1628 operands.push_back(*called);
1632 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
1633 if (failed(arguments))
1636 llvm::append_range(operands, *arguments);
1642 static LogicalResult
1644 LLVMFunctionType calleeType) {
1645 if (callType.getReturnType() != calleeType.getReturnType())
1648 if (calleeType.isVarArg()) {
1651 if (callType.getNumParams() < calleeType.getNumParams())
1656 if (callType.getNumParams() != calleeType.getNumParams())
1661 for (
auto [operandType, argumentType] :
1662 llvm::zip(callType.getParams(), calleeType.getParams()))
1663 if (operandType != argumentType)
1669 FailureOr<LLVMFunctionType>
1670 ModuleImport::convertFunctionType(llvm::CallBase *callInst) {
1671 auto castOrFailure = [](
Type convertedType) -> FailureOr<LLVMFunctionType> {
1672 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
1678 llvm::Value *calledOperand = callInst->getCalledOperand();
1679 FailureOr<LLVMFunctionType> callType =
1680 castOrFailure(
convertType(callInst->getFunctionType()));
1681 if (failed(callType))
1683 auto *callee = dyn_cast<llvm::Function>(calledOperand);
1688 FailureOr<LLVMFunctionType> calleeType =
1689 castOrFailure(
convertType(callee->getFunctionType()));
1690 if (failed(calleeType))
1696 return emitError(loc) <<
"incompatible call and callee types: " << *callType
1697 <<
" and " << *calleeType;
1704 llvm::Value *calledOperand = callInst->getCalledOperand();
1705 if (
auto *callee = dyn_cast<llvm::Function>(calledOperand))
1710 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
1715 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
1718 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1721 if (inst->getOpcode() == llvm::Instruction::Br) {
1722 auto *brInst = cast<llvm::BranchInst>(inst);
1726 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
1727 llvm::BasicBlock *succ = brInst->getSuccessor(i);
1729 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
1732 succBlockArgs.push_back(blockArgs);
1735 if (!brInst->isConditional()) {
1736 auto brOp = builder.
create<LLVM::BrOp>(loc, succBlockArgs.front(),
1737 succBlocks.front());
1741 FailureOr<Value> condition =
convertValue(brInst->getCondition());
1742 if (failed(condition))
1744 auto condBrOp = builder.
create<LLVM::CondBrOp>(
1745 loc, *condition, succBlocks.front(), succBlockArgs.front(),
1746 succBlocks.back(), succBlockArgs.back());
1750 if (inst->getOpcode() == llvm::Instruction::Switch) {
1751 auto *swInst = cast<llvm::SwitchInst>(inst);
1753 FailureOr<Value> condition =
convertValue(swInst->getCondition());
1754 if (failed(condition))
1758 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
1759 if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
1763 unsigned numCases = swInst->getNumCases();
1769 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
1770 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
1771 if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
1773 caseOperandRefs[it.index()] = caseOperands[it.index()];
1774 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
1778 auto switchOp = builder.
create<SwitchOp>(
1779 loc, *condition,
lookupBlock(defaultBB), defaultBlockArgs, caseValues,
1780 caseBlocks, caseOperandRefs);
1784 if (inst->getOpcode() == llvm::Instruction::PHI) {
1790 if (inst->getOpcode() == llvm::Instruction::Call) {
1791 auto *callInst = cast<llvm::CallInst>(inst);
1792 llvm::Value *calledOperand = callInst->getCalledOperand();
1794 FailureOr<SmallVector<Value>> operands =
1795 convertCallOperands(callInst,
true);
1796 if (failed(operands))
1799 auto callOp = [&]() -> FailureOr<Operation *> {
1800 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
1806 loc, resultTy, *operands,
1814 FailureOr<LLVMFunctionType> funcTy = convertFunctionType(callInst);
1819 auto callOp = builder.
create<CallOp>(loc, *funcTy, callee, *operands);
1820 if (failed(convertCallAttributes(callInst, callOp)))
1824 return callOp.getOperation();
1830 if (!callInst->getType()->isVoidTy())
1831 mapValue(inst, (*callOp)->getResult(0));
1836 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
1837 auto *lpInst = cast<llvm::LandingPadInst>(inst);
1840 operands.reserve(lpInst->getNumClauses());
1841 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
1842 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
1843 if (failed(operand))
1845 operands.push_back(*operand);
1850 builder.
create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
1854 if (inst->getOpcode() == llvm::Instruction::Invoke) {
1855 auto *invokeInst = cast<llvm::InvokeInst>(inst);
1857 if (invokeInst->isInlineAsm())
1858 return emitError(loc) <<
"invoke of inline assembly is not supported";
1860 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
1861 if (failed(operands))
1866 bool invokeResultUsedInPhi = llvm::any_of(
1867 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
1868 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
1873 Block *directNormalDest = normalDest;
1874 if (invokeResultUsedInPhi) {
1880 directNormalDest = builder.
createBlock(normalDest);
1884 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
1888 FailureOr<LLVMFunctionType> funcTy = convertFunctionType(invokeInst);
1897 auto invokeOp = builder.
create<InvokeOp>(
1898 loc, *funcTy, calleeName, *operands, directNormalDest,
ValueRange(),
1899 lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
1901 if (failed(convertInvokeAttributes(invokeInst, invokeOp)))
1907 if (!invokeInst->getType()->isVoidTy())
1908 mapValue(inst, invokeOp.getResults().front());
1913 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
1917 if (invokeResultUsedInPhi) {
1923 builder.
create<LLVM::BrOp>(loc, normalArgs, normalDest);
1927 assert(llvm::none_of(
1930 "An llvm.invoke operation cannot pass its result as a block "
1932 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
1937 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
1938 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
1939 Type sourceElementType =
convertType(gepInst->getSourceElementType());
1940 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
1941 if (failed(basePtr))
1949 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
1953 indices.push_back(*index);
1957 auto gepOp = builder.
create<GEPOp>(loc, type, sourceElementType, *basePtr,
1958 indices, gepInst->isInBounds());
1967 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
1970 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
1977 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
1978 return convertIntrinsic(intrinsic);
1981 return convertInstruction(inst);
1985 if (!f->hasPersonalityFn())
1988 llvm::Constant *pf = f->getPersonalityFn();
1996 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1997 if (ce->getOpcode() == llvm::Instruction::BitCast &&
1998 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
1999 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2007 llvm::MemoryEffects memEffects = func->getMemoryEffects();
2009 auto othermem = convertModRefInfoFromLLVM(
2010 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2011 auto argMem = convertModRefInfoFromLLVM(
2012 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2013 auto inaccessibleMem = convertModRefInfoFromLLVM(
2014 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2018 if (memAttr.isReadWrite())
2020 funcOp.setMemoryEffectsAttr(memAttr);
2026 StringLiteral(
"aarch64_in_za"),
2027 StringLiteral(
"aarch64_inout_za"),
2028 StringLiteral(
"aarch64_new_za"),
2029 StringLiteral(
"aarch64_out_za"),
2030 StringLiteral(
"aarch64_preserves_za"),
2031 StringLiteral(
"aarch64_pstate_sm_body"),
2032 StringLiteral(
"aarch64_pstate_sm_compatible"),
2033 StringLiteral(
"aarch64_pstate_sm_enabled"),
2034 StringLiteral(
"alwaysinline"),
2035 StringLiteral(
"approx-func-fp-math"),
2036 StringLiteral(
"convergent"),
2037 StringLiteral(
"denormal-fp-math"),
2038 StringLiteral(
"denormal-fp-math-f32"),
2039 StringLiteral(
"fp-contract"),
2040 StringLiteral(
"frame-pointer"),
2041 StringLiteral(
"no-infs-fp-math"),
2042 StringLiteral(
"no-nans-fp-math"),
2043 StringLiteral(
"no-signed-zeros-fp-math"),
2044 StringLiteral(
"noinline"),
2045 StringLiteral(
"nounwind"),
2046 StringLiteral(
"optnone"),
2047 StringLiteral(
"target-features"),
2048 StringLiteral(
"tune-cpu"),
2049 StringLiteral(
"unsafe-fp-math"),
2050 StringLiteral(
"vscale_range"),
2051 StringLiteral(
"willreturn"),
2057 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
2058 llvm::AttributeList::AttrIndex::FunctionIndex);
2059 for (llvm::Attribute attr : funcAttrs) {
2062 if (attr.hasAttribute(llvm::Attribute::Memory))
2066 if (attr.isTypeAttribute()) {
2068 "type attributes on a function are invalid, skipping it");
2073 if (attr.isStringAttribute())
2074 attrName = attr.getKindAsString();
2076 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
2083 if (attr.isStringAttribute()) {
2084 StringRef val = attr.getValueAsString();
2086 passthroughs.push_back(keyAttr);
2089 passthroughs.push_back(
2093 if (attr.isIntAttribute()) {
2094 auto val = std::to_string(attr.getValueAsInt());
2095 passthroughs.push_back(
2099 if (attr.isEnumAttribute()) {
2100 passthroughs.push_back(keyAttr);
2104 llvm_unreachable(
"unexpected attribute kind");
2107 if (!passthroughs.empty())
2108 funcOp.setPassthroughAttr(
ArrayAttr::get(context, passthroughs));
2112 LLVMFuncOp funcOp) {
2116 if (func->hasFnAttribute(llvm::Attribute::NoInline))
2117 funcOp.setNoInline(
true);
2118 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2119 funcOp.setAlwaysInline(
true);
2120 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2121 funcOp.setOptimizeNone(
true);
2122 if (func->hasFnAttribute(llvm::Attribute::Convergent))
2123 funcOp.setConvergent(
true);
2124 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
2125 funcOp.setNoUnwind(
true);
2126 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
2127 funcOp.setWillReturn(
true);
2129 if (func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2130 funcOp.setArmStreaming(
true);
2131 else if (func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2132 funcOp.setArmLocallyStreaming(
true);
2133 else if (func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2134 funcOp.setArmStreamingCompatible(
true);
2136 if (func->hasFnAttribute(
"aarch64_new_za"))
2137 funcOp.setArmNewZa(
true);
2138 else if (func->hasFnAttribute(
"aarch64_in_za"))
2139 funcOp.setArmInZa(
true);
2140 else if (func->hasFnAttribute(
"aarch64_out_za"))
2141 funcOp.setArmOutZa(
true);
2142 else if (func->hasFnAttribute(
"aarch64_inout_za"))
2143 funcOp.setArmInoutZa(
true);
2144 else if (func->hasFnAttribute(
"aarch64_preserves_za"))
2145 funcOp.setArmPreservesZa(
true);
2147 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
2148 if (attr.isValid()) {
2157 if (func->hasFnAttribute(
"frame-pointer")) {
2158 StringRef stringRefFramePointerKind =
2159 func->getFnAttribute(
"frame-pointer").getValueAsString();
2161 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2162 stringRefFramePointerKind)
2166 if (llvm::Attribute attr = func->getFnAttribute(
"target-cpu");
2167 attr.isStringAttribute())
2168 funcOp.setTargetCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
2170 if (llvm::Attribute attr = func->getFnAttribute(
"tune-cpu");
2171 attr.isStringAttribute())
2172 funcOp.setTuneCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
2174 if (llvm::Attribute attr = func->getFnAttribute(
"target-features");
2175 attr.isStringAttribute())
2176 funcOp.setTargetFeaturesAttr(
2179 if (llvm::Attribute attr = func->getFnAttribute(
"unsafe-fp-math");
2180 attr.isStringAttribute())
2181 funcOp.setUnsafeFpMath(attr.getValueAsBool());
2183 if (llvm::Attribute attr = func->getFnAttribute(
"no-infs-fp-math");
2184 attr.isStringAttribute())
2185 funcOp.setNoInfsFpMath(attr.getValueAsBool());
2187 if (llvm::Attribute attr = func->getFnAttribute(
"no-nans-fp-math");
2188 attr.isStringAttribute())
2189 funcOp.setNoNansFpMath(attr.getValueAsBool());
2191 if (llvm::Attribute attr = func->getFnAttribute(
"approx-func-fp-math");
2192 attr.isStringAttribute())
2193 funcOp.setApproxFuncFpMath(attr.getValueAsBool());
2195 if (llvm::Attribute attr = func->getFnAttribute(
"no-signed-zeros-fp-math");
2196 attr.isStringAttribute())
2197 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2199 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math");
2200 attr.isStringAttribute())
2201 funcOp.setDenormalFpMathAttr(
2204 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math-f32");
2205 attr.isStringAttribute())
2206 funcOp.setDenormalFpMathF32Attr(
2209 if (llvm::Attribute attr = func->getFnAttribute(
"fp-contract");
2210 attr.isStringAttribute())
2211 funcOp.setFpContractAttr(
StringAttr::get(context, attr.getValueAsString()));
2215 ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
2219 auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
2221 if (!llvmAttr.isValid())
2226 if (llvmAttr.hasKindAsEnum() &&
2227 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2228 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2229 paramAttrs.push_back(
2235 if (llvmAttr.isTypeAttribute())
2237 else if (llvmAttr.isIntAttribute())
2239 else if (llvmAttr.isEnumAttribute())
2241 else if (llvmAttr.isConstantRangeAttribute()) {
2242 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2243 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2246 llvm_unreachable(
"unexpected parameter attribute kind");
2247 paramAttrs.push_back(builder.
getNamedAttr(mlirName, mlirAttr));
2256 auto llvmAttrs = func->getAttributes();
2257 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2258 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2259 funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder));
2263 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2264 if (!llvmResAttr.hasAttributes())
2266 funcOp.setResAttrsAttr(
2267 builder.
getArrayAttr(convertParameterAttribute(llvmResAttr, builder)));
2271 ArrayAttr &argsAttr,
2274 llvm::AttributeList llvmAttrs = call->getAttributes();
2276 bool anyArgAttrs =
false;
2277 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
2278 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
2279 if (llvmArgAttrsSet.back().hasAttributes())
2284 for (
auto &dict : dictAttrs)
2290 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
2291 argAttrs.emplace_back(convertParameterAttribute(llvmArgAttrs, builder));
2292 argsAttr = getArrayAttr(argAttrs);
2295 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2296 if (!llvmResAttr.hasAttributes())
2298 DictionaryAttr resAttrs = convertParameterAttribute(llvmResAttr, builder);
2299 resAttr = getArrayAttr({resAttrs});
2303 CallOpInterface callOp,
2305 ArrayAttr argsAttr, resAttr;
2307 callOp.setArgAttrsAttr(argsAttr);
2308 callOp.setResAttrsAttr(resAttr);
2311 template <
typename Op>
2313 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
2317 LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
2322 LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
2328 llvm::AttributeList callAttrs = inst->getAttributes();
2330 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
2331 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
2332 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
2333 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
2335 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
2336 ModRefInfo othermem = convertModRefInfoFromLLVM(
2337 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2338 ModRefInfo argMem = convertModRefInfoFromLLVM(
2339 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2340 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
2341 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2345 if (!memAttr.isReadWrite())
2346 op.setMemoryEffectsAttr(memAttr);
2355 dyn_cast<LLVMFunctionType>(
convertType(func->getFunctionType()));
2356 if (func->isIntrinsic() &&
2360 bool dsoLocal = func->isDSOLocal();
2361 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
2367 Location loc = debugImporter->translateFuncLocation(func);
2368 LLVMFuncOp funcOp = builder.
create<LLVMFuncOp>(
2369 loc, func->getName(), functionType,
2370 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
2375 funcOp.setPersonalityAttr(personality);
2376 else if (func->hasPersonalityFn())
2377 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
2380 funcOp.setGarbageCollector(StringRef(func->getGC()));
2382 if (func->hasAtLeastLocalUnnamedAddr())
2383 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
2385 if (func->hasSection())
2386 funcOp.setSection(StringRef(func->getSection()));
2388 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
2390 if (func->hasComdat())
2391 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
2393 if (llvm::MaybeAlign maybeAlign = func->getAlign())
2394 funcOp.setAlignment(maybeAlign->value());
2401 func->getAllMetadata(allMetadata);
2402 for (
auto &[
kind, node] : allMetadata) {
2407 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
2408 <<
" on " <<
diag(*func);
2412 if (func->isDeclaration())
2421 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
2422 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
2427 for (llvm::BasicBlock &basicBlock : *func) {
2429 if (!reachable.contains(&basicBlock))
2431 Region &body = funcOp.getBody();
2434 reachableBasicBlocks.push_back(&basicBlock);
2439 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
2440 functionType.getParamType(it.index()), funcOp.getLoc());
2449 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
2450 for (llvm::BasicBlock *basicBlock : blocks)
2451 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
2456 if (failed(processDebugIntrinsics()))
2465 if (!dbgIntr->isKillLocation())
2467 llvm::Value *value = dbgIntr->getArgOperand(0);
2468 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2471 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2475 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
2478 auto emitUnsupportedWarning = [&]() {
2479 if (emitExpensiveWarnings)
2485 if (dbgIntr->hasArgList())
2486 return emitUnsupportedWarning();
2491 return emitUnsupportedWarning();
2495 DILocalVariableAttr localVariableAttr =
2497 if (!localVariableAttr)
2498 return emitUnsupportedWarning();
2500 if (failed(argOperand))
2501 return emitError(loc) <<
"failed to convert a debug intrinsic operand: "
2509 if (
Operation *op = argOperand->getDefiningOp();
2512 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
2515 if (dominatedBlocks.empty())
2516 return emitUnsupportedWarning();
2519 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
2522 Value insertPt = *argOperand;
2523 if (
auto blockArg = dyn_cast<BlockArgument>(*argOperand)) {
2528 Block *insertionBlock = argOperand->getParentBlock();
2529 if (!insertionBlock->
empty() &&
2530 isa<LandingpadOp>(insertionBlock->
front()))
2531 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
2536 auto locationExprAttr =
2537 debugImporter->translateExpression(dbgIntr->getExpression());
2540 .Case([&](llvm::DbgDeclareInst *) {
2541 return builder.
create<LLVM::DbgDeclareOp>(
2542 loc, *argOperand, localVariableAttr, locationExprAttr);
2544 .Case([&](llvm::DbgValueInst *) {
2545 return builder.
create<LLVM::DbgValueOp>(
2546 loc, *argOperand, localVariableAttr, locationExprAttr);
2549 setNonDebugMetadataAttrs(dbgIntr, op);
2553 LogicalResult ModuleImport::processDebugIntrinsics() {
2555 for (llvm::Instruction *inst : debugIntrinsics) {
2556 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
2557 if (failed(processDebugIntrinsic(intrCall, domInfo)))
2563 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
2566 for (llvm::Instruction &inst : *bb) {
2567 if (failed(processInstruction(&inst)))
2572 if (debugIntrinsics.contains(&inst))
2579 setNonDebugMetadataAttrs(&inst, op);
2580 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
2581 if (emitExpensiveWarnings) {
2582 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
2590 FailureOr<SmallVector<AccessGroupAttr>>
2592 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
2598 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
2601 FailureOr<DereferenceableAttr>
2604 Location loc = mlirModule.getLoc();
2608 if (node->getNumOperands() != 1)
2609 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
2610 <<
diagMD(node, llvmModule.get());
2612 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
2613 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
2614 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
2615 return emitError(loc) <<
"dereferenceable metadata operand must be a "
2616 "non-negative constant integer: "
2617 <<
diagMD(node, llvmModule.get());
2619 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
2620 auto derefAttr = builder.
getAttr<DereferenceableAttr>(
2621 numBytesCst->getZExtValue(), mayBeNull);
2627 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
2628 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
2629 bool loadAllDialects,
bool preferUnregisteredIntrinsics) {
2636 LLVMDialect::getDialectNamespace()));
2638 DLTIDialect::getDialectNamespace()));
2639 if (loadAllDialects)
2646 emitExpensiveWarnings, dropDICompositeTypeElements,
2647 preferUnregisteredIntrinsics);
static MLIRContext * getContext(OpFoldResult val)
union mlir::linalg::@1183::ArityGroupAndKind::Kind kind
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static constexpr std::array kExplicitAttributes
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 LogicalResult verifyFunctionTypeCompatibility(LLVMFunctionType callType, LLVMFunctionType calleeType)
Checks if callType and calleeType are compatible and can be represented in MLIR.
static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp)
static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op)
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 getNamelessGlobalPrefix()
Prefix used for symbols of nameless llvm globals.
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 SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(ArrayRef< llvm::BasicBlock * > basicBlocks)
Get a topologically sorted list of blocks for the given basic blocks.
static std::string diagMD(const llvm::Metadata *node, const llvm::Module *module)
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.
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
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.
StringRef getValue() const
Returns the name of the held symbol reference.
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...
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, ArrayRef< llvm::OperandBundleUse > opBundles, bool requiresOpBundles, 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.
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LogicalResult convertComdats()
Converts all comdat selectors of the LLVM module to MLIR comdat operations.
LogicalResult convertAliases()
Converts all aliases of the LLVM module to MLIR variables.
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 ...
void convertParameterAttributes(llvm::CallBase *call, ArrayAttr &argsAttr, ArrayAttr &resAttr, OpBuilder &builder)
Converts the parameter and result attributes in argsAttr and resAttr and add them to the callOp.
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes, bool preferUnregisteredIntrinsics)
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...
LogicalResult convertIdentMetadata()
Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute.
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 setDisjointFlag(llvm::Instruction *inst, Operation *op) const
Sets the disjoint flag attribute for the imported operation op given the original instruction inst.
void mapNoResultOp(llvm::Instruction *llvm, Operation *mlir)
Stores a mapping between an LLVM instruction and the imported MLIR operation if the operation returns...
void setExactFlag(llvm::Instruction *inst, Operation *op) const
Sets the exact flag attribute for the imported operation op given the original instruction inst.
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 convertTargetTriple()
Converts target triple of the LLVM module to an MLIR target triple specification.
LogicalResult convertModuleFlagsMetadata()
Converts !llvm.module.flags metadata.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
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 ...
LogicalResult convertCommandlineMetadata()
Converts !llvm.commandline metadata to the llvm.commandline LLVM ModuleOp attribute.
FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value)
Converts value to a FP exception behavior attribute.
void setNonNegFlag(llvm::Instruction *inst, Operation *op) const
Sets the nneg flag attribute for the imported operation op given the original instruction inst.
FailureOr< DereferenceableAttr > translateDereferenceableAttr(const llvm::MDNode *node, unsigned kindID)
Returns the dereferenceable attribute that corresponds to the given LLVM dereferenceable or dereferen...
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.
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
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.
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
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.
static DenseArrayAttrImpl get(MLIRContext *context, ArrayRef< int32_t > content)
Builder from ArrayRef<T>.
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.
InFlightDiagnostic emitWarning(Location loc)
Utility method to emit a warning message using this location.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true, bool dropDICompositeTypeElements=false, bool loadAllDialects=true, bool preferUnregisteredIntrinsics=false)
Translates the LLVM module into an MLIR module living in the given context.
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.