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(),
541 for (
const llvm::Function &func : llvmModule->functions()) {
542 for (
const llvm::Instruction &inst : llvm::instructions(func)) {
544 if (llvm::MDNode *node =
545 inst.getMetadata(llvm::LLVMContext::MD_access_group))
546 if (failed(processAccessGroupMetadata(node)))
550 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
551 if (!aliasAnalysisNodes)
553 if (aliasAnalysisNodes.TBAA)
554 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
556 if (aliasAnalysisNodes.Scope)
557 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
559 if (aliasAnalysisNodes.NoAlias)
560 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
571 void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
572 if (comdatMapping.contains(comdat))
575 ComdatOp comdatOp = getGlobalComdatOp();
578 auto selectorOp = builder.
create<ComdatSelectorOp>(
579 mlirModule.getLoc(), comdat->getName(),
580 convertComdatFromLLVM(comdat->getSelectionKind()));
584 comdatMapping.try_emplace(comdat, symbolRef);
588 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
589 if (globalVar.hasComdat())
590 processComdat(globalVar.getComdat());
591 for (llvm::Function &func : llvmModule->functions())
592 if (func.hasComdat())
593 processComdat(func.getComdat());
598 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
601 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
603 <<
"unhandled global variable: " <<
diag(globalVar);
607 if (failed(convertGlobal(&globalVar))) {
609 <<
"unhandled global variable: " <<
diag(globalVar);
619 return emitError(loc,
"cannot translate data layout: ")
623 emitWarning(loc,
"unhandled data layout token: ") << token;
625 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
631 for (llvm::Function &func : llvmModule->functions())
637 void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
640 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
641 for (
auto &[kind, node] : allMetadata) {
645 if (emitExpensiveWarnings) {
646 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
648 <<
diagMD(node, llvmModule.get()) <<
" on "
657 auto iface = cast<IntegerOverflowFlagsInterface>(op);
659 IntegerOverflowFlags value = {};
660 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
662 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
664 iface.setOverflowFlags(value);
669 auto iface = cast<FastmathFlagsInterface>(op);
675 if (!isa<llvm::FPMathOperator>(inst))
677 llvm::FastMathFlags flags = inst->getFastMathFlags();
680 FastmathFlags value = {};
681 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
682 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
683 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
684 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
686 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
687 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
689 iface->setAttr(iface.getFastmathAttrName(), attr);
694 return isa<IntegerType, FloatType>(type);
706 if (numElements.isScalable()) {
708 <<
"scalable vectors not supported";
718 shape.push_back(numElements.getKnownMinValue());
722 Type ModuleImport::getBuiltinTypeForAttr(
Type type) {
737 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
738 arrayShape.push_back(arrayType.getNumElements());
739 type = arrayType.getElementType();
749 llvm::Constant *constScalar) {
753 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
756 constInt->getValue());
760 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
761 llvm::Type *type = constFloat->getType();
768 <<
"unexpected floating-point type";
771 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
780 llvm::ConstantDataSequential *constSequence) {
782 elementAttrs.reserve(constSequence->getNumElements());
783 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
784 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
790 Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
796 auto getConstantShape = [&](llvm::Type *type) {
797 return llvm::dyn_cast_if_present<ShapedType>(
803 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
804 if (constArray->isString())
806 auto shape = getConstantShape(constArray->getType());
810 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
811 if (constVector && constVector->isSplat()) {
814 builder, constVector->getElementAsConstant(0));
825 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
826 auto shape = getConstantShape(constAggregate->getType());
832 while (!workList.empty()) {
833 llvm::Constant *current = workList.pop_back_val();
836 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
838 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
839 workList.push_back(constAggregate->getAggregateElement(idx));
844 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
847 elementAttrs.append(attrs.begin(), attrs.end());
853 elementAttrs.push_back(scalarAttr);
864 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
865 auto shape = llvm::dyn_cast_if_present<ShapedType>(
866 getBuiltinTypeForAttr(
convertType(constZero->getType())));
871 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
878 ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
879 assert(globalVar->getName().empty() &&
880 "expected to work with a nameless global");
881 auto [it, success] = namelessGlobals.try_emplace(globalVar);
888 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
891 it->getSecond() = symbolRef;
895 LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
898 if (!globalInsertionOp)
904 if (globalVar->hasInitializer())
905 valueAttr = getConstantAsAttr(globalVar->getInitializer());
908 uint64_t alignment = 0;
909 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
910 if (maybeAlign.has_value()) {
911 llvm::Align align = *maybeAlign;
912 alignment = align.value();
917 DIGlobalVariableExpressionAttr globalExpressionAttr;
919 globalVar->getDebugInfo(globalExpressions);
922 if (!globalExpressions.empty())
923 globalExpressionAttr =
924 debugImporter->translateGlobalVariableExpression(globalExpressions[0]);
928 StringRef globalName = globalVar->getName();
929 if (globalName.empty())
930 globalName = getOrCreateNamelessSymbolName(globalVar).
getValue();
932 GlobalOp globalOp = builder.
create<GlobalOp>(
933 mlirModule.getLoc(), type, globalVar->isConstant(),
934 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
935 valueAttr, alignment, globalVar->getAddressSpace(),
936 globalVar->isDSOLocal(),
937 globalVar->isThreadLocal(), SymbolRefAttr(),
939 globalInsertionOp = globalOp;
941 if (globalVar->hasInitializer() && !valueAttr) {
944 setConstantInsertionPointToStart(block);
945 FailureOr<Value> initializer =
946 convertConstantExpr(globalVar->getInitializer());
947 if (failed(initializer))
949 builder.
create<ReturnOp>(globalOp.getLoc(), *initializer);
951 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
952 globalOp.setUnnamedAddr(
953 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
955 if (globalVar->hasSection())
956 globalOp.setSection(globalVar->getSection());
957 globalOp.setVisibility_(
958 convertVisibilityFromLLVM(globalVar->getVisibility()));
960 if (globalVar->hasComdat())
961 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
967 ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
968 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
971 dyn_cast<llvm::ConstantArray>(globalVar->getInitializer());
977 for (llvm::Value *operand : initializer->operands()) {
978 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
979 if (!aggregate || aggregate->getNumOperands() != 3)
982 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
983 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
984 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
985 if (!priority || !func || !data)
989 if (!data->isNullValue())
993 priorities.push_back(priority->getValue().getZExtValue());
997 if (!globalInsertionOp)
1003 globalInsertionOp = builder.
create<LLVM::GlobalCtorsOp>(
1008 globalInsertionOp = builder.
create<LLVM::GlobalDtorsOp>(
1015 ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1017 if (valueMapping.contains(constant))
1026 workList.insert(constant);
1027 while (!workList.empty()) {
1028 llvm::Constant *current = workList.back();
1031 if (isa<llvm::GlobalObject>(current)) {
1032 orderedSet.insert(current);
1033 workList.pop_back();
1039 auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);
1043 for (llvm::Value *operand : current->operands())
1044 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1045 adjacencyIt->getSecond().push_back(constDependency);
1048 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1049 unsigned numElements = constAgg->getElementCount().getFixedValue();
1050 for (
unsigned i = 0, e = numElements; i != e; ++i)
1051 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1057 if (adjacencyIt->getSecond().empty()) {
1058 orderedSet.insert(current);
1059 workList.pop_back();
1067 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1068 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1069 orderedSet.contains(dependency))
1071 workList.insert(dependency);
1077 FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1081 if (
Attribute attr = getConstantAsAttr(constant)) {
1083 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1084 return builder.
create<AddressOfOp>(loc, type, symbolRef.getValue())
1087 return builder.
create<ConstantOp>(loc, type, attr).getResult();
1091 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1093 return builder.
create<ZeroOp>(loc, type).getResult();
1097 if (isa<llvm::ConstantTokenNone>(constant)) {
1098 return builder.
create<NoneTokenOp>(loc).getResult();
1102 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1104 return builder.
create<PoisonOp>(loc, type).getResult();
1108 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1110 return builder.
create<UndefOp>(loc, type).getResult();
1114 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1116 StringRef globalName = globalObj->getName();
1119 if (globalName.empty())
1121 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1124 return builder.
create<AddressOfOp>(loc, type, symbolRef).getResult();
1128 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1134 llvm::Instruction *inst = constExpr->getAsInstruction();
1135 auto guard = llvm::make_scope_exit([&]() {
1136 assert(!noResultOpMapping.contains(inst) &&
1137 "expected constant expression to return a result");
1138 valueMapping.erase(inst);
1139 inst->deleteValue();
1143 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1144 return valueMapping.contains(value);
1146 if (failed(processInstruction(inst)))
1152 if (isa<llvm::ConstantAggregate>(constant) ||
1153 isa<llvm::ConstantAggregateZero>(constant)) {
1156 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1157 elementValues.reserve(constAgg->getNumOperands());
1158 for (llvm::Value *operand : constAgg->operands())
1161 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1162 unsigned numElements = constAgg->getElementCount().getFixedValue();
1163 elementValues.reserve(numElements);
1164 for (
unsigned i = 0, e = numElements; i != e; ++i)
1165 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1167 assert(llvm::count(elementValues,
nullptr) == 0 &&
1168 "expected all elements have been converted before");
1172 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1174 "unrecognized aggregate type");
1175 Value root = builder.
create<UndefOp>(loc, rootType);
1177 if (isArrayOrStruct) {
1178 root = builder.
create<InsertValueOp>(loc, root, it.value(), it.index());
1183 root = builder.
create<InsertElementOp>(loc, rootType, root, it.value(),
1190 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1191 LLVMTargetExtType targetExtType =
1192 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1193 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1194 "target extension type does not support zero-initialization");
1197 return builder.
create<LLVM::ZeroOp>(loc, targetExtType).getRes();
1200 StringRef error =
"";
1201 if (isa<llvm::BlockAddress>(constant))
1202 error =
" since blockaddress(...) is unsupported";
1204 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1207 FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1211 assert(!valueMapping.contains(constant) &&
1212 "expected constant has not been converted before");
1213 assert(constantInsertionBlock &&
1214 "expected the constant insertion block to be non-null");
1218 if (!constantInsertionOp)
1225 getConstantsToConvert(constant);
1226 for (llvm::Constant *constantToConvert : constantsToConvert) {
1227 FailureOr<Value> converted = convertConstant(constantToConvert);
1228 if (failed(converted))
1230 mapValue(constantToConvert, *converted);
1240 assert(!isa<llvm::MetadataAsValue>(value) &&
1241 "expected value to not be metadata");
1244 auto it = valueMapping.find(value);
1245 if (it != valueMapping.end())
1246 return it->getSecond();
1249 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1250 return convertConstantExpr(constant);
1253 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1255 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1261 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1264 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1267 value = node->getValue();
1270 auto it = valueMapping.find(value);
1271 if (it != valueMapping.end())
1272 return it->getSecond();
1275 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1276 return convertConstantExpr(constant);
1280 FailureOr<SmallVector<Value>>
1283 remapped.reserve(values.size());
1284 for (llvm::Value *value : values) {
1286 if (failed(converted))
1288 remapped.push_back(*converted);
1297 assert(immArgPositions.size() == immArgAttrNames.size() &&
1298 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1302 for (
auto [immArgPos, immArgName] :
1303 llvm::zip(immArgPositions, immArgAttrNames)) {
1304 auto &value = operands[immArgPos];
1305 auto *constant = llvm::cast<llvm::Constant>(value);
1307 assert(attr && attr.getType().isIntOrFloat() &&
1308 "expected immarg to be float or integer constant");
1310 attrsOut.push_back({nameAttr, attr});
1315 for (llvm::Value *value : operands) {
1319 if (failed(mlirValue))
1321 valuesOut.push_back(*mlirValue);
1328 IntegerAttr integerAttr;
1330 bool success = succeeded(converted) &&
1332 assert(success &&
"expected a constant integer value");
1338 FloatAttr floatAttr;
1342 assert(success &&
"expected a constant float value");
1348 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1349 auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
1350 return debugImporter->translate(node);
1354 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1355 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
1356 return debugImporter->translate(node);
1359 FPExceptionBehaviorAttr
1361 auto *metadata = cast<llvm::MetadataAsValue>(value);
1362 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1363 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
1364 llvm::convertStrToExceptionBehavior(mdstr->getString());
1365 assert(optLLVM &&
"Expecting FP exception behavior");
1366 return builder.
getAttr<FPExceptionBehaviorAttr>(
1367 convertFPExceptionBehaviorFromLLVM(*optLLVM));
1371 auto *metadata = cast<llvm::MetadataAsValue>(value);
1372 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
1373 std::optional<llvm::RoundingMode> optLLVM =
1374 llvm::convertStrToRoundingMode(mdstr->getString());
1375 assert(optLLVM &&
"Expecting rounding mode");
1376 return builder.
getAttr<RoundingModeAttr>(
1377 convertRoundingModeFromLLVM(*optLLVM));
1380 FailureOr<SmallVector<AliasScopeAttr>>
1382 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
1383 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
1388 return debugImporter->translateLoc(loc);
1392 ModuleImport::convertBranchArgs(llvm::Instruction *branch,
1393 llvm::BasicBlock *target,
1395 for (
auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
1396 auto *phiInst = cast<llvm::PHINode>(&*inst);
1397 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
1399 if (failed(converted))
1401 blockArguments.push_back(*converted);
1407 ModuleImport::convertCallTypeAndOperands(llvm::CallBase *callInst,
1410 if (!callInst->getType()->isVoidTy())
1411 types.push_back(
convertType(callInst->getType()));
1413 if (!callInst->getCalledFunction()) {
1414 FailureOr<Value> called =
convertValue(callInst->getCalledOperand());
1417 operands.push_back(*called);
1420 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
1421 if (failed(arguments))
1423 llvm::append_range(operands, *arguments);
1427 LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
1432 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
1435 LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
1438 if (inst->getOpcode() == llvm::Instruction::Br) {
1439 auto *brInst = cast<llvm::BranchInst>(inst);
1443 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
1444 llvm::BasicBlock *succ = brInst->getSuccessor(i);
1446 if (failed(convertBranchArgs(brInst, succ, blockArgs)))
1449 succBlockArgs.push_back(blockArgs);
1452 if (!brInst->isConditional()) {
1453 auto brOp = builder.
create<LLVM::BrOp>(loc, succBlockArgs.front(),
1454 succBlocks.front());
1458 FailureOr<Value> condition =
convertValue(brInst->getCondition());
1459 if (failed(condition))
1461 auto condBrOp = builder.
create<LLVM::CondBrOp>(
1462 loc, *condition, succBlocks.front(), succBlockArgs.front(),
1463 succBlocks.back(), succBlockArgs.back());
1467 if (inst->getOpcode() == llvm::Instruction::Switch) {
1468 auto *swInst = cast<llvm::SwitchInst>(inst);
1470 FailureOr<Value> condition =
convertValue(swInst->getCondition());
1471 if (failed(condition))
1475 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
1476 if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
1480 unsigned numCases = swInst->getNumCases();
1486 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
1487 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
1488 if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
1490 caseOperandRefs[it.index()] = caseOperands[it.index()];
1491 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
1495 auto switchOp = builder.
create<SwitchOp>(
1496 loc, *condition,
lookupBlock(defaultBB), defaultBlockArgs, caseValues,
1497 caseBlocks, caseOperandRefs);
1501 if (inst->getOpcode() == llvm::Instruction::PHI) {
1507 if (inst->getOpcode() == llvm::Instruction::Call) {
1508 auto *callInst = cast<llvm::CallInst>(inst);
1512 if (failed(convertCallTypeAndOperands(callInst, types, operands)))
1516 dyn_cast<LLVMFunctionType>(
convertType(callInst->getFunctionType()));
1522 if (llvm::Function *callee = callInst->getCalledFunction()) {
1523 callOp = builder.
create<CallOp>(
1527 callOp = builder.
create<CallOp>(loc, funcTy, operands);
1529 callOp.setCConv(convertCConvFromLLVM(callInst->getCallingConv()));
1530 callOp.setTailCallKind(
1531 convertTailCallKindFromLLVM(callInst->getTailCallKind()));
1535 if (callInst->hasFnAttr(llvm::Attribute::Convergent))
1536 callOp.setConvergent(
true);
1537 if (callInst->hasFnAttr(llvm::Attribute::NoUnwind))
1538 callOp.setNoUnwind(
true);
1539 if (callInst->hasFnAttr(llvm::Attribute::WillReturn))
1540 callOp.setWillReturn(
true);
1542 llvm::MemoryEffects memEffects = callInst->getMemoryEffects();
1543 ModRefInfo othermem = convertModRefInfoFromLLVM(
1544 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1545 ModRefInfo argMem = convertModRefInfoFromLLVM(
1546 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1547 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
1548 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1552 if (!memAttr.isReadWrite())
1553 callOp.setMemoryEffectsAttr(memAttr);
1555 if (!callInst->getType()->isVoidTy())
1556 mapValue(inst, callOp.getResult());
1561 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
1562 auto *lpInst = cast<llvm::LandingPadInst>(inst);
1565 operands.reserve(lpInst->getNumClauses());
1566 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
1567 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
1568 if (failed(operand))
1570 operands.push_back(*operand);
1575 builder.
create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands);
1579 if (inst->getOpcode() == llvm::Instruction::Invoke) {
1580 auto *invokeInst = cast<llvm::InvokeInst>(inst);
1584 if (failed(convertCallTypeAndOperands(invokeInst, types, operands)))
1589 bool invokeResultUsedInPhi = llvm::any_of(
1590 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
1591 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
1596 Block *directNormalDest = normalDest;
1597 if (invokeResultUsedInPhi) {
1603 directNormalDest = builder.
createBlock(normalDest);
1607 if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
1612 dyn_cast<LLVMFunctionType>(
convertType(invokeInst->getFunctionType()));
1620 if (llvm::Function *callee = invokeInst->getCalledFunction()) {
1621 invokeOp = builder.
create<InvokeOp>(
1625 lookupBlock(invokeInst->getUnwindDest()), unwindArgs);
1627 invokeOp = builder.
create<InvokeOp>(
1628 loc, funcTy,
nullptr, operands, directNormalDest,
1631 invokeOp.setCConv(convertCConvFromLLVM(invokeInst->getCallingConv()));
1632 if (!invokeInst->getType()->isVoidTy())
1633 mapValue(inst, invokeOp.getResults().front());
1638 if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
1642 if (invokeResultUsedInPhi) {
1648 builder.
create<LLVM::BrOp>(loc, normalArgs, normalDest);
1652 assert(llvm::none_of(
1655 "An llvm.invoke operation cannot pass its result as a block "
1657 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
1662 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
1663 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
1664 Type sourceElementType =
convertType(gepInst->getSourceElementType());
1665 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
1666 if (failed(basePtr))
1674 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
1678 indices.push_back(*index);
1682 auto gepOp = builder.
create<GEPOp>(loc, type, sourceElementType, *basePtr,
1683 indices, gepInst->isInBounds());
1692 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
1695 LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
1702 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
1703 return convertIntrinsic(intrinsic);
1706 return convertInstruction(inst);
1710 if (!f->hasPersonalityFn())
1713 llvm::Constant *pf = f->getPersonalityFn();
1721 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1722 if (ce->getOpcode() == llvm::Instruction::BitCast &&
1723 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
1724 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
1732 llvm::MemoryEffects memEffects = func->getMemoryEffects();
1734 auto othermem = convertModRefInfoFromLLVM(
1735 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
1736 auto argMem = convertModRefInfoFromLLVM(
1737 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
1738 auto inaccessibleMem = convertModRefInfoFromLLVM(
1739 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
1743 if (memAttr.isReadWrite())
1745 funcOp.setMemoryEffectsAttr(memAttr);
1751 StringLiteral(
"aarch64_in_za"),
1752 StringLiteral(
"aarch64_inout_za"),
1753 StringLiteral(
"aarch64_new_za"),
1754 StringLiteral(
"aarch64_out_za"),
1755 StringLiteral(
"aarch64_preserves_za"),
1756 StringLiteral(
"aarch64_pstate_sm_body"),
1757 StringLiteral(
"aarch64_pstate_sm_compatible"),
1758 StringLiteral(
"aarch64_pstate_sm_enabled"),
1759 StringLiteral(
"alwaysinline"),
1760 StringLiteral(
"approx-func-fp-math"),
1761 StringLiteral(
"convergent"),
1762 StringLiteral(
"denormal-fp-math"),
1763 StringLiteral(
"denormal-fp-math-f32"),
1764 StringLiteral(
"fp-contract"),
1765 StringLiteral(
"frame-pointer"),
1766 StringLiteral(
"no-infs-fp-math"),
1767 StringLiteral(
"no-nans-fp-math"),
1768 StringLiteral(
"no-signed-zeros-fp-math"),
1769 StringLiteral(
"noinline"),
1770 StringLiteral(
"nounwind"),
1771 StringLiteral(
"optnone"),
1772 StringLiteral(
"target-features"),
1773 StringLiteral(
"tune-cpu"),
1774 StringLiteral(
"unsafe-fp-math"),
1775 StringLiteral(
"vscale_range"),
1776 StringLiteral(
"willreturn"),
1782 llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(
1783 llvm::AttributeList::AttrIndex::FunctionIndex);
1784 for (llvm::Attribute attr : funcAttrs) {
1787 if (attr.hasAttribute(llvm::Attribute::Memory))
1791 if (attr.isTypeAttribute()) {
1793 "type attributes on a function are invalid, skipping it");
1798 if (attr.isStringAttribute())
1799 attrName = attr.getKindAsString();
1801 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1808 if (attr.isStringAttribute()) {
1809 StringRef val = attr.getValueAsString();
1811 passthroughs.push_back(keyAttr);
1814 passthroughs.push_back(
1818 if (attr.isIntAttribute()) {
1819 auto val = std::to_string(attr.getValueAsInt());
1820 passthroughs.push_back(
1824 if (attr.isEnumAttribute()) {
1825 passthroughs.push_back(keyAttr);
1829 llvm_unreachable(
"unexpected attribute kind");
1832 if (!passthroughs.empty())
1833 funcOp.setPassthroughAttr(
ArrayAttr::get(context, passthroughs));
1837 LLVMFuncOp funcOp) {
1841 if (func->hasFnAttribute(llvm::Attribute::NoInline))
1842 funcOp.setNoInline(
true);
1843 if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))
1844 funcOp.setAlwaysInline(
true);
1845 if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))
1846 funcOp.setOptimizeNone(
true);
1847 if (func->hasFnAttribute(llvm::Attribute::Convergent))
1848 funcOp.setConvergent(
true);
1849 if (func->hasFnAttribute(llvm::Attribute::NoUnwind))
1850 funcOp.setNoUnwind(
true);
1851 if (func->hasFnAttribute(llvm::Attribute::WillReturn))
1852 funcOp.setWillReturn(
true);
1854 if (func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
1855 funcOp.setArmStreaming(
true);
1856 else if (func->hasFnAttribute(
"aarch64_pstate_sm_body"))
1857 funcOp.setArmLocallyStreaming(
true);
1858 else if (func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
1859 funcOp.setArmStreamingCompatible(
true);
1861 if (func->hasFnAttribute(
"aarch64_new_za"))
1862 funcOp.setArmNewZa(
true);
1863 else if (func->hasFnAttribute(
"aarch64_in_za"))
1864 funcOp.setArmInZa(
true);
1865 else if (func->hasFnAttribute(
"aarch64_out_za"))
1866 funcOp.setArmOutZa(
true);
1867 else if (func->hasFnAttribute(
"aarch64_inout_za"))
1868 funcOp.setArmInoutZa(
true);
1869 else if (func->hasFnAttribute(
"aarch64_preserves_za"))
1870 funcOp.setArmPreservesZa(
true);
1872 llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);
1873 if (attr.isValid()) {
1882 if (func->hasFnAttribute(
"frame-pointer")) {
1883 StringRef stringRefFramePointerKind =
1884 func->getFnAttribute(
"frame-pointer").getValueAsString();
1886 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
1887 stringRefFramePointerKind)
1891 if (llvm::Attribute attr = func->getFnAttribute(
"target-cpu");
1892 attr.isStringAttribute())
1893 funcOp.setTargetCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
1895 if (llvm::Attribute attr = func->getFnAttribute(
"tune-cpu");
1896 attr.isStringAttribute())
1897 funcOp.setTuneCpuAttr(
StringAttr::get(context, attr.getValueAsString()));
1899 if (llvm::Attribute attr = func->getFnAttribute(
"target-features");
1900 attr.isStringAttribute())
1901 funcOp.setTargetFeaturesAttr(
1904 if (llvm::Attribute attr = func->getFnAttribute(
"unsafe-fp-math");
1905 attr.isStringAttribute())
1906 funcOp.setUnsafeFpMath(attr.getValueAsBool());
1908 if (llvm::Attribute attr = func->getFnAttribute(
"no-infs-fp-math");
1909 attr.isStringAttribute())
1910 funcOp.setNoInfsFpMath(attr.getValueAsBool());
1912 if (llvm::Attribute attr = func->getFnAttribute(
"no-nans-fp-math");
1913 attr.isStringAttribute())
1914 funcOp.setNoNansFpMath(attr.getValueAsBool());
1916 if (llvm::Attribute attr = func->getFnAttribute(
"approx-func-fp-math");
1917 attr.isStringAttribute())
1918 funcOp.setApproxFuncFpMath(attr.getValueAsBool());
1920 if (llvm::Attribute attr = func->getFnAttribute(
"no-signed-zeros-fp-math");
1921 attr.isStringAttribute())
1922 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
1924 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math");
1925 attr.isStringAttribute())
1926 funcOp.setDenormalFpMathAttr(
1929 if (llvm::Attribute attr = func->getFnAttribute(
"denormal-fp-math-f32");
1930 attr.isStringAttribute())
1931 funcOp.setDenormalFpMathF32Attr(
1934 if (llvm::Attribute attr = func->getFnAttribute(
"fp-contract");
1935 attr.isStringAttribute())
1936 funcOp.setFpContractAttr(
StringAttr::get(context, attr.getValueAsString()));
1940 ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs,
1944 auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind);
1946 if (!llvmAttr.isValid())
1949 if (llvmAttr.isTypeAttribute())
1951 else if (llvmAttr.isIntAttribute())
1953 else if (llvmAttr.isEnumAttribute())
1956 llvm_unreachable(
"unexpected parameter attribute kind");
1957 paramAttrs.push_back(builder.
getNamedAttr(mlirName, mlirAttr));
1963 void ModuleImport::convertParameterAttributes(llvm::Function *func,
1966 auto llvmAttrs = func->getAttributes();
1967 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
1968 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
1969 funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder));
1973 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
1974 if (!llvmResAttr.hasAttributes())
1976 funcOp.setResAttrsAttr(
1977 builder.
getArrayAttr(convertParameterAttribute(llvmResAttr, builder)));
1984 dyn_cast<LLVMFunctionType>(
convertType(func->getFunctionType()));
1985 if (func->isIntrinsic() &&
1989 bool dsoLocal = func->hasLocalLinkage();
1990 CConv cconv = convertCConvFromLLVM(func->getCallingConv());
1996 Location loc = debugImporter->translateFuncLocation(func);
1997 LLVMFuncOp funcOp = builder.
create<LLVMFuncOp>(
1998 loc, func->getName(), functionType,
1999 convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);
2001 convertParameterAttributes(func, funcOp, builder);
2004 funcOp.setPersonalityAttr(personality);
2005 else if (func->hasPersonalityFn())
2006 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
2009 funcOp.setGarbageCollector(StringRef(func->getGC()));
2011 if (func->hasAtLeastLocalUnnamedAddr())
2012 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));
2014 if (func->hasSection())
2015 funcOp.setSection(StringRef(func->getSection()));
2017 funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));
2019 if (func->hasComdat())
2020 funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));
2022 if (llvm::MaybeAlign maybeAlign = func->getAlign())
2023 funcOp.setAlignment(maybeAlign->value());
2030 func->getAllMetadata(allMetadata);
2031 for (
auto &[kind, node] : allMetadata) {
2036 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
2037 <<
" on " <<
diag(*func);
2041 if (func->isDeclaration())
2050 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
2051 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))
2056 for (llvm::BasicBlock &basicBlock : *func) {
2058 if (!reachable.contains(&basicBlock))
2060 Region &body = funcOp.getBody();
2063 reachableBasicBlocks.push_back(&basicBlock);
2068 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
2069 functionType.getParamType(it.index()), funcOp.getLoc());
2078 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
2079 for (llvm::BasicBlock *basicBlock : blocks)
2080 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
2085 if (failed(processDebugIntrinsics()))
2094 if (!dbgIntr->isKillLocation())
2096 llvm::Value *value = dbgIntr->getArgOperand(0);
2097 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2100 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2104 ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
2107 auto emitUnsupportedWarning = [&]() {
2108 if (emitExpensiveWarnings)
2114 if (dbgIntr->hasArgList())
2115 return emitUnsupportedWarning();
2120 return emitUnsupportedWarning();
2124 DILocalVariableAttr localVariableAttr =
2126 if (!localVariableAttr)
2127 return emitUnsupportedWarning();
2129 if (failed(argOperand))
2130 return emitError(loc) <<
"failed to convert a debug intrinsic operand: "
2138 if (
Operation *op = argOperand->getDefiningOp();
2144 if (dominatedBlocks.empty())
2145 return emitUnsupportedWarning();
2148 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
2153 auto locationExprAttr =
2154 debugImporter->translateExpression(dbgIntr->getExpression());
2157 .Case([&](llvm::DbgDeclareInst *) {
2158 return builder.
create<LLVM::DbgDeclareOp>(
2159 loc, *argOperand, localVariableAttr, locationExprAttr);
2161 .Case([&](llvm::DbgValueInst *) {
2162 return builder.
create<LLVM::DbgValueOp>(
2163 loc, *argOperand, localVariableAttr, locationExprAttr);
2166 setNonDebugMetadataAttrs(dbgIntr, op);
2170 LogicalResult ModuleImport::processDebugIntrinsics() {
2172 for (llvm::Instruction *inst : debugIntrinsics) {
2173 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
2174 if (failed(processDebugIntrinsic(intrCall, domInfo)))
2180 LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
2183 for (llvm::Instruction &inst : *bb) {
2184 if (failed(processInstruction(&inst)))
2189 if (debugIntrinsics.contains(&inst))
2196 setNonDebugMetadataAttrs(&inst, op);
2197 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
2198 if (emitExpensiveWarnings) {
2199 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
2207 FailureOr<SmallVector<AccessGroupAttr>>
2209 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
2215 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
2221 bool dropDICompositeTypeElements) {
2228 LLVMDialect::getDialectNamespace()));
2230 DLTIDialect::getDialectNamespace()));
2237 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...
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LogicalResult convertComdats()
Converts all comdat selectors of the LLVM module to MLIR comdat operations.
LogicalResult convertFunctions()
Converts all functions of the LLVM module to MLIR functions.
FailureOr< SmallVector< Value > > convertValues(ArrayRef< llvm::Value * > values)
Converts a range of LLVM values to a range of MLIR values using the convertValue method,...
DILocalVariableAttr matchLocalVariableAttr(llvm::Value *value)
Converts value to a local variable attribute.
LogicalResult convertLinkerOptionsMetadata()
Converts !llvm.linker.options metadata to the llvm.linker.options LLVM dialect operation.
void mapBlock(llvm::BasicBlock *llvm, Block *mlir)
Stores the mapping between an LLVM block and its MLIR counterpart.
void processFunctionAttributes(llvm::Function *func, LLVMFuncOp funcOp)
Converts function attributes of LLVM Function func into LLVM dialect attributes of LLVMFuncOp funcOp.
LogicalResult convertMetadata()
Converts all LLVM metadata nodes that translate to attributes such as alias analysis or access group ...
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, ArrayRef< unsigned > immArgPositions, ArrayRef< StringLiteral > immArgAttrNames, SmallVectorImpl< Value > &valuesOut, SmallVectorImpl< NamedAttribute > &attrsOut)
Converts the LLVM values for an intrinsic to mixed MLIR values and attributes for LLVM_IntrOpBase.
FailureOr< Value > convertValue(llvm::Value *value)
Converts an LLVM value to an MLIR value, or returns failure if the conversion fails.
LogicalResult initializeImportInterface()
Calls the LLVMImportInterface initialization that queries the registered dialect interfaces for the s...
void addDebugIntrinsic(llvm::CallInst *intrinsic)
Adds a debug intrinsics to the list of intrinsics that should be converted after the function convers...
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 mapNoResultOp(llvm::Instruction *llvm, Operation *mlir)
Stores a mapping between an LLVM instruction and the imported MLIR operation if the operation returns...
Type convertType(llvm::Type *type)
Converts the type from LLVM to MLIR LLVM dialect.
Operation * lookupOperation(llvm::Instruction *inst)
Returns the MLIR operation mapped to the given LLVM instruction.
DILabelAttr matchLabelAttr(llvm::Value *value)
Converts value to a label attribute. Asserts if the matching fails.
FloatAttr matchFloatAttr(llvm::Value *value)
Converts value to a float attribute. Asserts if the matching fails.
LoopAnnotationAttr translateLoopAnnotationAttr(const llvm::MDNode *node, Location loc) const
Returns the loop annotation attribute that corresponds to the given LLVM loop metadata node.
void setFastmathFlagsAttr(llvm::Instruction *inst, Operation *op) const
Sets the fastmath flags attribute for the imported operation op given the original instruction inst.
FailureOr< SmallVector< AliasScopeAttr > > matchAliasScopeAttrs(llvm::Value *value)
Converts value to an array of alias scopes or returns failure if the conversion fails.
Value lookupValue(llvm::Value *value)
Returns the MLIR value mapped to the given LLVM value.
LogicalResult processFunction(llvm::Function *func)
Imports func into the current module.
RoundingModeAttr matchRoundingModeAttr(llvm::Value *value)
Converts value to a rounding mode attribute.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes)
FailureOr< SmallVector< AccessGroupAttr > > lookupAccessGroupAttrs(const llvm::MDNode *node) const
Returns the access group attributes that map to the access group nodes starting from the access group...
LogicalResult convertGlobals()
Converts all global variables of the LLVM module to MLIR global variables.
void setIntegerOverflowFlags(llvm::Instruction *inst, Operation *op) const
Sets the integer overflow flags (nsw/nuw) attribute for the imported operation op given the original ...
FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value)
Converts value to a FP exception behavior attribute.
LogicalResult convertDataLayout()
Converts the data layout of the LLVM module to an MLIR data layout specification.
IntegerAttr matchIntegerAttr(llvm::Value *value)
Converts value to an integer attribute. Asserts if the matching fails.
Helper class that translates an LLVM data layout to an MLIR data layout specification.
StringRef getLastToken() const
Returns the last data layout token that has been processed before the data layout translation failed.
DataLayoutSpecInterface getDataLayout() const
Returns the MLIR data layout specification translated from the LLVM data layout.
ArrayRef< StringRef > getUnhandledTokens() const
Returns the data layout tokens that have not been handled during the data layout translation.
A helper class that converts llvm.loop metadata nodes into corresponding LoopAnnotationAttrs and llvm...
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
std::vector< StringRef > getAvailableDialects()
Return information about all available dialects in the registry in this context.
void loadAllAvailableDialects()
Load all dialects available in the registry in this context.
RAII guard to reset the insertion point of the builder when destroyed.
This class helps build Operations.
void setInsertionPointToStart(Block *block)
Sets the insertion point to the start of the specified block.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void setInsertionPointToEnd(Block *block)
Sets the insertion point to the end of the specified block.
Block * createBlock(Region *parent, Region::iterator insertPt={}, TypeRange argTypes=std::nullopt, ArrayRef< Location > locs=std::nullopt)
Add new block with 'argTypes' arguments and set the insertion point to the end of it.
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
Block * getInsertionBlock() const
Return the block the current insertion point belongs to.
This class provides the API for ops that are known to be terminators.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Block * getBlock()
Returns the operation block that contains this operation.
OpTy get() const
Allow accessing the internal op.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
DominanceInfoNode * getNode(Block *a)
Return the dominance node from the Region containing block A.
static llvm::ArrayRef< std::pair< llvm::Attribute::AttrKind, llvm::StringRef > > getAttrKindToNameMapping()
Returns a list of pairs that each hold a mapping from LLVM attribute kinds to their corresponding str...
FloatType getFloatType(MLIRContext *context, unsigned width)
Returns a supported MLIR floating point type of the given bit width or null if the bit width is not s...
bool isCompatibleVectorType(Type type)
Returns true if the given type is a vector type compatible with the LLVM dialect.
llvm::ElementCount getVectorNumElements(Type type)
Returns the element count of any LLVM-compatible vector type.
Type getVectorElementType(Type type)
Returns the element type of any vector type compatible with the LLVM dialect.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
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.