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(traversal.begin(), traversal.end());
158 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
163 std::unique_ptr<llvm::Module> llvmModule,
164 bool emitExpensiveWarnings,
165 bool importEmptyDICompositeTypes)
167 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
171 mlirModule, importEmptyDICompositeTypes)),
172 loopAnnotationImporter(
174 emitExpensiveWarnings(emitExpensiveWarnings) {
178 ComdatOp ModuleImport::getGlobalComdatOp() {
180 return globalComdatOp;
186 globalInsertionOp = globalComdatOp;
187 return globalComdatOp;
190 LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
195 auto getIdentityIfRootNode =
196 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
200 if (node->getNumOperands() > 1)
203 if (node->getNumOperands() == 1)
204 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
205 return std::optional<StringRef>{op0->getString()};
206 return std::optional<StringRef>{};
216 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
217 StringRef *identity =
nullptr,
219 nullptr) -> std::optional<bool> {
220 unsigned numOperands = node->getNumOperands();
229 const auto *identityNode =
230 dyn_cast<const llvm::MDString>(node->getOperand(0));
236 *identity = identityNode->getString();
238 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
239 const auto *memberNode =
240 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
242 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
243 <<
diagMD(node, llvmModule.get());
247 if (2 * pairNum + 2 >= numOperands) {
249 if (numOperands != 2) {
250 emitError(loc) <<
"missing member offset: "
251 <<
diagMD(node, llvmModule.get());
255 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
256 node->getOperand(2 * pairNum + 2));
258 emitError(loc) <<
"operand '" << 2 * pairNum + 2
259 <<
"' must be ConstantInt: "
260 <<
diagMD(node, llvmModule.get());
263 offset = offsetCI->getZExtValue();
268 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
281 auto isTagNode = [&](
const llvm::MDNode *node,
282 TBAATypeDescriptorAttr *baseAttr =
nullptr,
283 TBAATypeDescriptorAttr *accessAttr =
nullptr,
284 int64_t *offset =
nullptr,
285 bool *isConstant =
nullptr) -> std::optional<bool> {
293 unsigned numOperands = node->getNumOperands();
294 if (numOperands != 3 && numOperands != 4)
296 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
297 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
299 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
300 if (!baseMD || !accessMD || !offsetCI)
307 if (accessMD->getNumOperands() < 1 ||
308 !isa<llvm::MDString>(accessMD->getOperand(0)))
310 bool isConst =
false;
311 if (numOperands == 4) {
313 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
315 emitError(loc) <<
"operand '3' must be ConstantInt: "
316 <<
diagMD(node, llvmModule.get());
319 isConst = isConstantCI->getValue()[0];
322 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
324 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
326 *offset = offsetCI->getZExtValue();
328 *isConstant = isConst;
337 workList.push_back(node);
338 while (!workList.empty()) {
339 const llvm::MDNode *current = workList.back();
340 if (tbaaMapping.contains(current)) {
349 bool anyChildNotConverted =
false;
350 for (
const llvm::MDOperand &operand : current->operands())
351 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
352 if (!tbaaMapping.contains(childNode)) {
353 workList.push_back(childNode);
354 anyChildNotConverted =
true;
357 if (anyChildNotConverted) {
362 if (!seen.insert(current).second)
363 return emitError(loc) <<
"has cycle in TBAA graph: "
364 <<
diagMD(current, llvmModule.get());
372 FailureOr<std::optional<StringRef>> rootNodeIdentity =
373 getIdentityIfRootNode(current);
374 if (succeeded(rootNodeIdentity)) {
375 StringAttr stringAttr = *rootNodeIdentity
380 tbaaMapping.insert({current, builder.
getAttr<TBAARootAttr>(stringAttr)});
386 if (std::optional<bool> isValid =
387 isTypeDescriptorNode(current, &identity, &members)) {
388 assert(isValid.value() &&
"type descriptor node must be valid");
390 tbaaMapping.insert({current, builder.
getAttr<TBAATypeDescriptorAttr>(
391 identity, members)});
395 TBAATypeDescriptorAttr baseAttr, accessAttr;
398 if (std::optional<bool> isValid =
399 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
400 assert(isValid.value() &&
"access tag node must be valid");
402 {current, builder.
getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
407 return emitError(loc) <<
"unsupported TBAA node format: "
408 <<
diagMD(current, llvmModule.get());
414 ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
416 if (failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
417 return emitError(loc) <<
"unsupported access group node: "
418 <<
diagMD(node, llvmModule.get());
423 ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
426 auto verifySelfRef = [](
const llvm::MDNode *node) {
427 return node->getNumOperands() != 0 &&
428 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
431 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
432 return idx >= node->getNumOperands() ||
433 isa<llvm::MDString>(node->getOperand(idx));
436 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
437 StringAttr description =
nullptr;
438 if (aliasDomain->getNumOperands() >= 2)
439 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
441 return builder.
getAttr<AliasScopeDomainAttr>(
446 for (
const llvm::MDOperand &operand : node->operands()) {
447 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
448 llvm::AliasScopeNode aliasScope(scope);
449 const llvm::MDNode *domain = aliasScope.getDomain();
455 if (!verifySelfRef(scope) || !domain || !verifyDescription(scope, 2))
456 return emitError(loc) <<
"unsupported alias scope node: "
457 <<
diagMD(scope, llvmModule.get());
458 if (!verifySelfRef(domain) || !verifyDescription(domain, 1))
459 return emitError(loc) <<
"unsupported alias domain node: "
460 <<
diagMD(domain, llvmModule.get());
462 if (aliasScopeMapping.contains(scope))
466 auto it = aliasScopeMapping.find(aliasScope.getDomain());
467 if (it == aliasScopeMapping.end()) {
468 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
469 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
473 StringAttr description =
nullptr;
474 if (!aliasScope.getName().empty())
476 auto aliasScopeOp = builder.
getAttr<AliasScopeAttr>(
478 cast<AliasScopeDomainAttr>(it->second), description);
479 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
485 FailureOr<SmallVector<AliasScopeAttr>>
488 aliasScopes.reserve(node->getNumOperands());
489 for (
const llvm::MDOperand &operand : node->operands()) {
490 auto *node = cast<llvm::MDNode>(operand.get());
491 aliasScopes.push_back(
492 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
495 if (llvm::is_contained(aliasScopes,
nullptr))
501 debugIntrinsics.insert(intrinsic);
505 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
506 if (named.getName() !=
"llvm.linker.options")
509 for (
const llvm::MDNode *node : named.operands()) {
511 options.reserve(node->getNumOperands());
512 for (
const llvm::MDOperand &option : node->operands())
513 options.push_back(cast<llvm::MDString>(option)->getString());
514 builder.
create<LLVM::LinkerOptionsOp>(mlirModule.getLoc(),
522 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
525 if (named.getName() != LLVMDialect::getIdentAttrName())
528 if (named.getNumOperands() == 1)
529 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
530 if (md->getNumOperands() == 1)
531 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
532 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
539 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
542 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
545 if (nmd.getNumOperands() == 1)
546 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
547 if (md->getNumOperands() == 1)
548 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
549 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
558 for (
const llvm::Function &func : llvmModule->functions()) {
559 for (
const llvm::Instruction &inst : llvm::instructions(func)) {
561 if (llvm::MDNode *node =
562 inst.getMetadata(llvm::LLVMContext::MD_access_group))
563 if (failed(processAccessGroupMetadata(node)))
567 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
568 if (!aliasAnalysisNodes)
570 if (aliasAnalysisNodes.TBAA)
571 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
573 if (aliasAnalysisNodes.Scope)
574 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
576 if (aliasAnalysisNodes.NoAlias)
577 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
590 void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
591 if (comdatMapping.contains(comdat))
594 ComdatOp comdatOp = getGlobalComdatOp();
597 auto selectorOp = builder.
create<ComdatSelectorOp>(
598 mlirModule.getLoc(), comdat->getName(),
599 convertComdatFromLLVM(comdat->getSelectionKind()));
603 comdatMapping.try_emplace(comdat, symbolRef);
607 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
608 if (globalVar.hasComdat())
609 processComdat(globalVar.getComdat());
610 for (llvm::Function &func : llvmModule->functions())
611 if (func.hasComdat())
612 processComdat(func.getComdat());
617 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
620 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
622 <<
"unhandled global variable: " <<
diag(globalVar);
626 if (failed(convertGlobal(&globalVar))) {
628 <<
"unhandled global variable: " <<
diag(globalVar);
638 return emitError(loc,
"cannot translate data layout: ")
642 emitWarning(loc,
"unhandled data layout token: ") << token;
644 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
650 for (llvm::Function &func : llvmModule->functions())
656 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
659 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
660 for (
auto &[kind, node] : allMetadata) {
664 if (emitExpensiveWarnings) {
665 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
667 <<
diagMD(node, llvmModule.get()) <<
" on "
676 auto iface = cast<IntegerOverflowFlagsInterface>(op);
678 IntegerOverflowFlags value = {};
679 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
681 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
683 iface.setOverflowFlags(value);
687 auto iface = cast<ExactFlagInterface>(op);
689 iface.setIsExact(inst->isExact());
694 auto iface = cast<DisjointFlagInterface>(op);
695 auto instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
697 iface.setIsDisjoint(instDisjoint->isDisjoint());
701 auto iface = cast<NonNegFlagInterface>(op);
703 iface.setNonNeg(inst->hasNonNeg());
708 auto iface = cast<FastmathFlagsInterface>(op);
714 if (!isa<llvm::FPMathOperator>(inst))
716 llvm::FastMathFlags flags = inst->getFastMathFlags();
719 FastmathFlags value = {};
720 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
721 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
722 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
723 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
725 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
726 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
728 iface->setAttr(iface.getFastmathAttrName(), attr);
733 return isa<IntegerType, FloatType>(type);
745 if (numElements.isScalable()) {
747 <<
"scalable vectors not supported";
757 shape.push_back(numElements.getKnownMinValue());
761 Type ModuleImport::getBuiltinTypeForAttr(
Type type) {
776 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
777 arrayShape.push_back(arrayType.getNumElements());
778 type = arrayType.getElementType();
788 llvm::Constant *constScalar) {
792 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
795 constInt->getValue());
799 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
800 llvm::Type *type = constFloat->getType();
807 <<
"unexpected floating-point type";
810 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
819 llvm::ConstantDataSequential *constSequence) {
821 elementAttrs.reserve(constSequence->getNumElements());
822 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
823 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
829 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
835 auto getConstantShape = [&](llvm::Type *type) {
836 return llvm::dyn_cast_if_present<ShapedType>(
842 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
843 if (constArray->isString())
845 auto shape = getConstantShape(constArray->getType());
849 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
850 if (constVector && constVector->isSplat()) {
853 builder, constVector->getElementAsConstant(0));
864 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
865 auto shape = getConstantShape(constAggregate->getType());
871 while (!workList.empty()) {
872 llvm::Constant *current = workList.pop_back_val();
875 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
877 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
878 workList.push_back(constAggregate->getAggregateElement(idx));
883 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
886 elementAttrs.append(attrs.begin(), attrs.end());
892 elementAttrs.push_back(scalarAttr);
903 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
904 auto shape = llvm::dyn_cast_if_present<ShapedType>(
905 getBuiltinTypeForAttr(
convertType(constZero->getType())));
910 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
917 ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
918 assert(globalVar->getName().empty() &&
919 "expected to work with a nameless global");
920 auto [it, success] = namelessGlobals.try_emplace(globalVar);
927 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
930 it->getSecond() = symbolRef;
934 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
937 if (!globalInsertionOp)
943 if (globalVar->hasInitializer())
944 valueAttr = getConstantAsAttr(globalVar->getInitializer());
947 uint64_t alignment = 0;
948 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
949 if (maybeAlign.has_value()) {
950 llvm::Align align = *maybeAlign;
951 alignment = align.value();
958 globalVar->getDebugInfo(globalExpressions);
960 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
961 DIGlobalVariableExpressionAttr globalExpressionAttr =
962 debugImporter->translateGlobalVariableExpression(expr);
963 globalExpressionAttrs.push_back(globalExpressionAttr);
968 StringRef globalName = globalVar->getName();
969 if (globalName.empty())
970 globalName = getOrCreateNamelessSymbolName(globalVar).
getValue();
972 GlobalOp globalOp = builder.
create<GlobalOp>(
973 mlirModule.getLoc(), type, globalVar->isConstant(),
974 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
975 valueAttr, alignment, globalVar->getAddressSpace(),
976 globalVar->isDSOLocal(),
977 globalVar->isThreadLocal(), SymbolRefAttr(),
979 globalInsertionOp = globalOp;
981 if (globalVar->hasInitializer() && !valueAttr) {
984 setConstantInsertionPointToStart(block);
985 FailureOr<Value> initializer =
986 convertConstantExpr(globalVar->getInitializer());
987 if (failed(initializer))
989 builder.
create<ReturnOp>(globalOp.getLoc(), *initializer);
991 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
992 globalOp.setUnnamedAddr(
993 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
995 if (globalVar->hasSection())
996 globalOp.setSection(globalVar->getSection());
997 globalOp.setVisibility_(
998 convertVisibilityFromLLVM(globalVar->getVisibility()));
1000 if (globalVar->hasComdat())
1001 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1007 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1008 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1011 dyn_cast<llvm::ConstantArray>(globalVar->getInitializer());
1017 for (llvm::Value *operand : initializer->operands()) {
1018 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1019 if (!aggregate || aggregate->getNumOperands() != 3)
1022 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1023 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1024 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1025 if (!priority || !func || !data)
1029 if (!data->isNullValue())
1033 priorities.push_back(priority->getValue().getZExtValue());
1037 if (!globalInsertionOp)
1043 globalInsertionOp = builder.
create<LLVM::GlobalCtorsOp>(
1048 globalInsertionOp = builder.
create<LLVM::GlobalDtorsOp>(
1055 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1057 if (valueMapping.contains(constant))
1066 workList.insert(constant);
1067 while (!workList.empty()) {
1068 llvm::Constant *current = workList.back();
1071 if (isa<llvm::GlobalObject>(current)) {
1072 orderedSet.insert(current);
1073 workList.pop_back();
1079 auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);
1083 for (llvm::Value *operand : current->operands())
1084 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1085 adjacencyIt->getSecond().push_back(constDependency);
1088 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1089 unsigned numElements = constAgg->getElementCount().getFixedValue();
1090 for (
unsigned i = 0, e = numElements; i != e; ++i)
1091 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1097 if (adjacencyIt->getSecond().empty()) {
1098 orderedSet.insert(current);
1099 workList.pop_back();
1107 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1108 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1109 orderedSet.contains(dependency))
1111 workList.insert(dependency);
1117 FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1121 if (
Attribute attr = getConstantAsAttr(constant)) {
1123 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1124 return builder.
create<AddressOfOp>(loc, type, symbolRef.getValue())
1127 return builder.
create<ConstantOp>(loc, type, attr).getResult();
1131 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1133 return builder.
create<ZeroOp>(loc, type).getResult();
1137 if (isa<llvm::ConstantTokenNone>(constant)) {
1138 return builder.
create<NoneTokenOp>(loc).getResult();
1142 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1144 return builder.
create<PoisonOp>(loc, type).getResult();
1148 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1150 return builder.
create<UndefOp>(loc, type).getResult();
1154 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1156 StringRef globalName = globalObj->getName();
1159 if (globalName.empty())
1161 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1164 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1168 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1174 llvm::Instruction *inst = constExpr->getAsInstruction();
1175 auto guard = llvm::make_scope_exit([&]() {
1176 assert(!noResultOpMapping.contains(inst) &&
1177 "expected constant expression to return a result");
1178 valueMapping.erase(inst);
1179 inst->deleteValue();
1183 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1184 return valueMapping.contains(value);
1186 if (failed(processInstruction(inst)))
1192 if (isa<llvm::ConstantAggregate>(constant) ||
1193 isa<llvm::ConstantAggregateZero>(constant)) {
1196 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1197 elementValues.reserve(constAgg->getNumOperands());
1198 for (llvm::Value *operand : constAgg->operands())
1201 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1202 unsigned numElements = constAgg->getElementCount().getFixedValue();
1203 elementValues.reserve(numElements);
1204 for (
unsigned i = 0, e = numElements; i != e; ++i)
1205 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1207 assert(llvm::count(elementValues,
nullptr) == 0 &&
1208 "expected all elements have been converted before");
1212 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1214 "unrecognized aggregate type");
1215 Value root = builder.
create<UndefOp>(loc, rootType);
1217 if (isArrayOrStruct) {
1218 root = builder.
create<InsertValueOp>(loc, root, it.value(), it.index());
1223 root = builder.
create<InsertElementOp>(loc, rootType, root, it.value(),
1230 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1231 LLVMTargetExtType targetExtType =
1232 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1233 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1234 "target extension type does not support zero-initialization");
1237 return builder.
create<LLVM::ZeroOp>(loc, targetExtType).getRes();
1240 StringRef error =
"";
1241 if (isa<llvm::BlockAddress>(constant))
1242 error =
" since blockaddress(...) is unsupported";
1244 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1247 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1251 assert(!valueMapping.contains(constant) &&
1252 "expected constant has not been converted before");
1253 assert(constantInsertionBlock &&
1254 "expected the constant insertion block to be non-null");
1258 if (!constantInsertionOp)
1265 getConstantsToConvert(constant);
1266 for (llvm::Constant *constantToConvert : constantsToConvert) {
1267 FailureOr<Value> converted = convertConstant(constantToConvert);
1268 if (failed(converted))
1270 mapValue(constantToConvert, *converted);
1280 assert(!isa<llvm::MetadataAsValue>(value) &&
1281 "expected value to not be metadata");
1284 auto it = valueMapping.find(value);
1285 if (it != valueMapping.end())
1286 return it->getSecond();
1289 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1290 return convertConstantExpr(constant);
1293 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1295 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1301 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1304 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1307 value = node->getValue();
1310 auto it = valueMapping.find(value);
1311 if (it != valueMapping.end())
1312 return it->getSecond();
1315 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1316 return convertConstantExpr(constant);
1320 FailureOr<SmallVector<Value>>
1323 remapped.reserve(values.size());
1324 for (llvm::Value *value : values) {
1326 if (failed(converted))
1328 remapped.push_back(*converted);
1338 assert(immArgPositions.size() == immArgAttrNames.size() &&
1339 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1343 for (
auto [immArgPos, immArgName] :
1344 llvm::zip(immArgPositions, immArgAttrNames)) {
1345 auto &value = operands[immArgPos];
1346 auto *constant = llvm::cast<llvm::Constant>(value);
1348 assert(attr && attr.getType().isIntOrFloat() &&
1349 "expected immarg to be float or integer constant");
1351 attrsOut.push_back({nameAttr, attr});
1356 for (llvm::Value *value : operands) {
1360 if (failed(mlirValue))
1362 valuesOut.push_back(*mlirValue);
1367 if (requiresOpBundles) {
1368 opBundleSizes.reserve(opBundles.size());
1369 opBundleTagAttrs.reserve(opBundles.size());
1371 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1372 opBundleSizes.push_back(bundle.Inputs.size());
1373 opBundleTagAttrs.push_back(
StringAttr::get(context, bundle.getTagName()));
1375 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1376 auto operandMlirValue =
convertValue(opBundleOperand.get());
1377 if (failed(operandMlirValue))
1379 valuesOut.push_back(*operandMlirValue);
1384 auto opBundleSizesAttrNameAttr =
1386 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1388 auto opBundleTagsAttr =
ArrayAttr::get(context, opBundleTagAttrs);
1389 auto opBundleTagsAttrNameAttr =
1391 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1398 IntegerAttr integerAttr;
1400 bool success = succeeded(converted) &&
1402 assert(success &&
"expected a constant integer value");
1408 FloatAttr floatAttr;
1412 assert(success &&
"expected a constant float value");
1418 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1419 auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
1420 return debugImporter->translate(node);
1424 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1425 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
1426 return debugImporter->translate(node);
1429 FPExceptionBehaviorAttr
1431 auto *metadata = cast<llvm::MetadataAsValue>(value);
1432 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1433 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
1434 llvm::convertStrToExceptionBehavior(mdstr->getString());
1435 assert(optLLVM &&
"Expecting FP exception behavior");
1436 return builder.
getAttr<FPExceptionBehaviorAttr>(
1437 convertFPExceptionBehaviorFromLLVM(*optLLVM));
1441 auto *metadata = cast<llvm::MetadataAsValue>(value);
1442 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1443 std::optional<llvm::RoundingMode> optLLVM =
1444 llvm::convertStrToRoundingMode(mdstr->getString());
1445 assert(optLLVM &&
"Expecting rounding mode");
1446 return builder.
getAttr<RoundingModeAttr>(
1447 convertRoundingModeFromLLVM(*optLLVM));
1450 FailureOr<SmallVector<AliasScopeAttr>>
1452 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1453 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
1458 return debugImporter->translateLoc(loc);
1462 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
1463 llvm::BasicBlock *target,
1465 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
1466 auto *phiInst = cast<llvm::PHINode>(&*inst);
1467 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
1469 if (failed(converted))
1471 blockArguments.push_back(*converted);
1477 ModuleImport::convertCallTypeAndOperands(llvm::CallBase *callInst,
1480 if (!callInst->getType()->isVoidTy())
1481 types.push_back(
convertType(callInst->getType()));
1483 if (!callInst->getCalledFunction()) {
1484 FailureOr<Value> called =
convertValue(callInst->getCalledOperand());
1487 operands.push_back(*called);
1490 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
1491 if (failed(arguments))
1493 llvm::append_range(operands, *arguments);
1497 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
1502 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
1505 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1508 if (inst->getOpcode() == llvm::Instruction::Br) {
1509 auto *brInst = cast<llvm::BranchInst>(inst);
1513 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
1514 llvm::BasicBlock *succ = brInst->getSuccessor(i);
1516 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
1519 succBlockArgs.push_back(blockArgs);
1522 if (!brInst->isConditional()) {
1523 auto brOp = builder.
create<LLVM::BrOp>(loc, succBlockArgs.front(),
1524 succBlocks.front());
1528 FailureOr<Value> condition =
convertValue(brInst->getCondition());
1529 if (failed(condition))
1531 auto condBrOp = builder.
create<LLVM::CondBrOp>(
1532 loc, *condition, succBlocks.front(), succBlockArgs.front(),
1533 succBlocks.back(), succBlockArgs.back());
1537 if (inst->getOpcode() == llvm::Instruction::Switch) {
1538 auto *swInst = cast<llvm::SwitchInst>(inst);
1540 FailureOr<Value> condition =
convertValue(swInst->getCondition());
1541 if (failed(condition))
1545 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
1546 if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
1550 unsigned numCases = swInst->getNumCases();
1556 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
1557 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
1558 if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
1560 caseOperandRefs[it.index()] = caseOperands[it.index()];
1561 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
1565 auto switchOp = builder.
create<SwitchOp>(
1566 loc, *condition,
lookupBlock(defaultBB), defaultBlockArgs, caseValues,
1567 caseBlocks, caseOperandRefs);
1571 if (inst->getOpcode() == llvm::Instruction::PHI) {
1577 if (inst->getOpcode() == llvm::Instruction::Call) {
1578 auto *callInst = cast<llvm::CallInst>(inst);
1582 if (failed(convertCallTypeAndOperands(callInst, types, operands)))
1586 dyn_cast<LLVMFunctionType>(
convertType(callInst->getFunctionType()));
1592 if (llvm::Function *callee = callInst->getCalledFunction()) {
1593 callOp = builder.
create<CallOp>(
1597 callOp = builder.
create<CallOp>(loc, funcTy, operands);
1599 callOp.setCConv(convertCConvFromLLVM(callInst->getCallingConv()));
1600 callOp.setTailCallKind(
1601 convertTailCallKindFromLLVM(callInst->getTailCallKind()));
1605 if (callInst->hasFnAttr(llvm::Attribute::Convergent))
1606 callOp.setConvergent(
true);
1607 if (callInst->hasFnAttr(llvm::Attribute::NoUnwind))
1608 callOp.setNoUnwind(
true);
1609 if (callInst->hasFnAttr(llvm::Attribute::WillReturn))
1610 callOp.setWillReturn(
true);
1612 llvm::MemoryEffects memEffects = callInst->getMemoryEffects();
1613 ModRefInfo othermem = convertModRefInfoFromLLVM(
1614 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1615 ModRefInfo argMem = convertModRefInfoFromLLVM(
1616 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1617 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
1618 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1622 if (!memAttr.isReadWrite())
1623 callOp.setMemoryEffectsAttr(memAttr);
1625 if (!callInst->getType()->isVoidTy())
1626 mapValue(inst, callOp.getResult());
1631 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
1632 auto *lpInst = cast<llvm::LandingPadInst>(inst);
1635 operands.reserve(lpInst->getNumClauses());
1636 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
1637 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
1638 if (failed(operand))
1640 operands.push_back(*operand);
1645 builder.
create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
1649 if (inst->getOpcode() == llvm::Instruction::Invoke) {
1650 auto *invokeInst = cast<llvm::InvokeInst>(inst);
1654 if (failed(convertCallTypeAndOperands(invokeInst, types, operands)))
1659 bool invokeResultUsedInPhi = llvm::any_of(
1660 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
1661 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
1666 Block *directNormalDest = normalDest;
1667 if (invokeResultUsedInPhi) {
1673 directNormalDest = builder.
createBlock(normalDest);
1677 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
1682 dyn_cast<LLVMFunctionType>(
convertType(invokeInst->getFunctionType()));
1690 if (llvm::Function *callee = invokeInst->getCalledFunction()) {
1691 invokeOp = builder.
create<InvokeOp>(
1695 lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
1697 invokeOp = builder.
create<InvokeOp>(
1698 loc, funcTy,
nullptr, operands, directNormalDest,
1701 invokeOp.setCConv(convertCConvFromLLVM(invokeInst->getCallingConv()));
1702 if (!invokeInst->getType()->isVoidTy())
1703 mapValue(inst, invokeOp.getResults().front());
1708 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
1712 if (invokeResultUsedInPhi) {
1718 builder.
create<LLVM::BrOp>(loc, normalArgs, normalDest);
1722 assert(llvm::none_of(
1725 "An llvm.invoke operation cannot pass its result as a block "
1727 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
1732 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
1733 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
1734 Type sourceElementType =
convertType(gepInst->getSourceElementType());
1735 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
1736 if (failed(basePtr))
1744 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
1748 indices.push_back(*index);
1752 auto gepOp = builder.
create<GEPOp>(loc, type, sourceElementType, *basePtr,
1753 indices, gepInst->isInBounds());
1762 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
1765 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
1772 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
1773 return convertIntrinsic(intrinsic);
1776 return convertInstruction(inst);
1780 if (!f->hasPersonalityFn())
1783 llvm::Constant *pf = f->getPersonalityFn();
1791 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1792 if (ce->getOpcode() == llvm::Instruction::BitCast &&
1793 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
1794 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
1802 llvm::MemoryEffects memEffects = func->getMemoryEffects();
1804 auto othermem = convertModRefInfoFromLLVM(
1805 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1806 auto argMem = convertModRefInfoFromLLVM(
1807 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1808 auto inaccessibleMem = convertModRefInfoFromLLVM(
1809 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1813 if (memAttr.isReadWrite())
1815 funcOp.setMemoryEffectsAttr(memAttr);
1821 StringLiteral(
"aarch64_in_za"),
1822 StringLiteral(
"aarch64_inout_za"),
1823 StringLiteral(
"aarch64_new_za"),
1824 StringLiteral(
"aarch64_out_za"),
1825 StringLiteral(
"aarch64_preserves_za"),
1826 StringLiteral(
"aarch64_pstate_sm_body"),
1827 StringLiteral(
"aarch64_pstate_sm_compatible"),
1828 StringLiteral(
"aarch64_pstate_sm_enabled"),
1829 StringLiteral(
"alwaysinline"),
1830 StringLiteral(
"approx-func-fp-math"),
1831 StringLiteral(
"convergent"),
1832 StringLiteral(
"denormal-fp-math"),
1833 StringLiteral(
"denormal-fp-math-f32"),
1834 StringLiteral(
"fp-contract"),
1835 StringLiteral(
"frame-pointer"),
1836 StringLiteral(
"no-infs-fp-math"),
1837 StringLiteral(
"no-nans-fp-math"),
1838 StringLiteral(
"no-signed-zeros-fp-math"),
1839 StringLiteral(
"noinline"),
1840 StringLiteral(
"nounwind"),
1841 StringLiteral(
"optnone"),
1842 StringLiteral(
"target-features"),
1843 StringLiteral(
"tune-cpu"),
1844 StringLiteral(
"unsafe-fp-math"),
1845 StringLiteral(
"vscale_range"),
1846 StringLiteral(
"willreturn"),
1852 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
1853 llvm::AttributeList::AttrIndex::FunctionIndex);
1854 for (llvm::Attribute attr : funcAttrs) {
1857 if (attr.hasAttribute(llvm::Attribute::Memory))
1861 if (attr.isTypeAttribute()) {
1863 "type attributes on a function are invalid, skipping it");
1868 if (attr.isStringAttribute())
1869 attrName = attr.getKindAsString();
1871 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1878 if (attr.isStringAttribute()) {
1879 StringRef val = attr.getValueAsString();
1881 passthroughs.push_back(keyAttr);
1884 passthroughs.push_back(
1888 if (attr.isIntAttribute()) {
1889 auto val = std::to_string(attr.getValueAsInt());
1890 passthroughs.push_back(
1894 if (attr.isEnumAttribute()) {
1895 passthroughs.push_back(keyAttr);
1899 llvm_unreachable(
"unexpected attribute kind");
1902 if (!passthroughs.empty())
1903 funcOp.setPassthroughAttr(
ArrayAttr::get(context, passthroughs));
1907 LLVMFuncOp funcOp) {
1911 if (func->hasFnAttribute(llvm::Attribute::NoInline))
1912 funcOp.setNoInline(
true);
1913 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
1914 funcOp.setAlwaysInline(
true);
1915 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
1916 funcOp.setOptimizeNone(
true);
1917 if (func->hasFnAttribute(llvm::Attribute::Convergent))
1918 funcOp.setConvergent(
true);
1919 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
1920 funcOp.setNoUnwind(
true);
1921 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
1922 funcOp.setWillReturn(
true);
1924 if (func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
1925 funcOp.setArmStreaming(
true);
1926 else if (func->hasFnAttribute(
"aarch64_pstate_sm_body"))
1927 funcOp.setArmLocallyStreaming(
true);
1928 else if (func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
1929 funcOp.setArmStreamingCompatible(
true);
1931 if (func->hasFnAttribute(
"aarch64_new_za"))
1932 funcOp.setArmNewZa(
true);
1933 else if (func->hasFnAttribute(
"aarch64_in_za"))
1934 funcOp.setArmInZa(
true);
1935 else if (func->hasFnAttribute(
"aarch64_out_za"))
1936 funcOp.setArmOutZa(
true);
1937 else if (func->hasFnAttribute(
"aarch64_inout_za"))
1938 funcOp.setArmInoutZa(
true);
1939 else if (func->hasFnAttribute(
"aarch64_preserves_za"))
1940 funcOp.setArmPreservesZa(
true);
1942 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
1943 if (attr.isValid()) {
1952 if (func->hasFnAttribute(
"frame-pointer")) {
1953 StringRef stringRefFramePointerKind =
1954 func->getFnAttribute(
"frame-pointer").getValueAsString();
1956 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
1957 stringRefFramePointerKind)
1961 if (llvm::Attribute attr = func->getFnAttribute(
"target-cpu");
1962 attr.isStringAttribute())
1963 funcOp.setTargetCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
1965 if (llvm::Attribute attr = func->getFnAttribute(
"tune-cpu");
1966 attr.isStringAttribute())
1967 funcOp.setTuneCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
1969 if (llvm::Attribute attr = func->getFnAttribute(
"target-features");
1970 attr.isStringAttribute())
1971 funcOp.setTargetFeaturesAttr(
1974 if (llvm::Attribute attr = func->getFnAttribute(
"unsafe-fp-math");
1975 attr.isStringAttribute())
1976 funcOp.setUnsafeFpMath(attr.getValueAsBool());
1978 if (llvm::Attribute attr = func->getFnAttribute(
"no-infs-fp-math");
1979 attr.isStringAttribute())
1980 funcOp.setNoInfsFpMath(attr.getValueAsBool());
1982 if (llvm::Attribute attr = func->getFnAttribute(
"no-nans-fp-math");
1983 attr.isStringAttribute())
1984 funcOp.setNoNansFpMath(attr.getValueAsBool());
1986 if (llvm::Attribute attr = func->getFnAttribute(
"approx-func-fp-math");
1987 attr.isStringAttribute())
1988 funcOp.setApproxFuncFpMath(attr.getValueAsBool());
1990 if (llvm::Attribute attr = func->getFnAttribute(
"no-signed-zeros-fp-math");
1991 attr.isStringAttribute())
1992 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
1994 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math");
1995 attr.isStringAttribute())
1996 funcOp.setDenormalFpMathAttr(
1999 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math-f32");
2000 attr.isStringAttribute())
2001 funcOp.setDenormalFpMathF32Attr(
2004 if (llvm::Attribute attr = func->getFnAttribute(
"fp-contract");
2005 attr.isStringAttribute())
2006 funcOp.setFpContractAttr(
StringAttr::get(context, attr.getValueAsString()));
2010 ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
2014 auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
2016 if (!llvmAttr.isValid())
2019 if (llvmAttr.isTypeAttribute())
2021 else if (llvmAttr.isIntAttribute())
2023 else if (llvmAttr.isEnumAttribute())
2026 llvm_unreachable(
"unexpected parameter attribute kind");
2027 paramAttrs.push_back(builder.
getNamedAttr(mlirName, mlirAttr));
2033 void ModuleImport::convertParameterAttributes(llvm::Function *func,
2036 auto llvmAttrs = func->getAttributes();
2037 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2038 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2039 funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder));
2043 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2044 if (!llvmResAttr.hasAttributes())
2046 funcOp.setResAttrsAttr(
2047 builder.
getArrayAttr(convertParameterAttribute(llvmResAttr, builder)));
2054 dyn_cast<LLVMFunctionType>(
convertType(func->getFunctionType()));
2055 if (func->isIntrinsic() &&
2059 bool dsoLocal = func->hasLocalLinkage();
2060 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
2066 Location loc = debugImporter->translateFuncLocation(func);
2067 LLVMFuncOp funcOp = builder.
create<LLVMFuncOp>(
2068 loc, func->getName(), functionType,
2069 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
2071 convertParameterAttributes(func, funcOp, builder);
2074 funcOp.setPersonalityAttr(personality);
2075 else if (func->hasPersonalityFn())
2076 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
2079 funcOp.setGarbageCollector(StringRef(func->getGC()));
2081 if (func->hasAtLeastLocalUnnamedAddr())
2082 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
2084 if (func->hasSection())
2085 funcOp.setSection(StringRef(func->getSection()));
2087 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
2089 if (func->hasComdat())
2090 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
2092 if (llvm::MaybeAlign maybeAlign = func->getAlign())
2093 funcOp.setAlignment(maybeAlign->value());
2100 func->getAllMetadata(allMetadata);
2101 for (
auto &[kind, node] : allMetadata) {
2106 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
2107 <<
" on " <<
diag(*func);
2111 if (func->isDeclaration())
2120 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
2121 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
2126 for (llvm::BasicBlock &basicBlock : *func) {
2128 if (!reachable.contains(&basicBlock))
2130 Region &body = funcOp.getBody();
2133 reachableBasicBlocks.push_back(&basicBlock);
2138 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
2139 functionType.getParamType(it.index()), funcOp.getLoc());
2148 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
2149 for (llvm::BasicBlock *basicBlock : blocks)
2150 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
2155 if (failed(processDebugIntrinsics()))
2164 if (!dbgIntr->isKillLocation())
2166 llvm::Value *value = dbgIntr->getArgOperand(0);
2167 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2170 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2174 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
2177 auto emitUnsupportedWarning = [&]() {
2178 if (emitExpensiveWarnings)
2184 if (dbgIntr->hasArgList())
2185 return emitUnsupportedWarning();
2190 return emitUnsupportedWarning();
2194 DILocalVariableAttr localVariableAttr =
2196 if (!localVariableAttr)
2197 return emitUnsupportedWarning();
2199 if (failed(argOperand))
2200 return emitError(loc) <<
"failed to convert a debug intrinsic operand: "
2208 if (
Operation *op = argOperand->getDefiningOp();
2214 if (dominatedBlocks.empty())
2215 return emitUnsupportedWarning();
2218 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
2223 auto locationExprAttr =
2224 debugImporter->translateExpression(dbgIntr->getExpression());
2227 .Case([&](llvm::DbgDeclareInst *) {
2228 return builder.
create<LLVM::DbgDeclareOp>(
2229 loc, *argOperand, localVariableAttr, locationExprAttr);
2231 .Case([&](llvm::DbgValueInst *) {
2232 return builder.
create<LLVM::DbgValueOp>(
2233 loc, *argOperand, localVariableAttr, locationExprAttr);
2236 setNonDebugMetadataAttrs(dbgIntr, op);
2240 LogicalResult ModuleImport::processDebugIntrinsics() {
2242 for (llvm::Instruction *inst : debugIntrinsics) {
2243 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
2244 if (failed(processDebugIntrinsic(intrCall, domInfo)))
2250 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
2253 for (llvm::Instruction &inst : *bb) {
2254 if (failed(processInstruction(&inst)))
2259 if (debugIntrinsics.contains(&inst))
2266 setNonDebugMetadataAttrs(&inst, op);
2267 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
2268 if (emitExpensiveWarnings) {
2269 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
2277 FailureOr<SmallVector<AccessGroupAttr>>
2279 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
2285 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
2291 bool dropDICompositeTypeElements) {
2298 LLVMDialect::getDialectNamespace()));
2300 DLTIDialect::getDialectNamespace()));
2307 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 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 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 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 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.
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.
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...
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 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 ...
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 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 ...
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.
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.
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.
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.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
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.