30#include "llvm/ADT/DepthFirstIterator.h"
31#include "llvm/ADT/PostOrderIterator.h"
32#include "llvm/ADT/ScopeExit.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/ADT/TypeSwitch.h"
35#include "llvm/IR/Comdat.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DebugProgramInstruction.h"
38#include "llvm/IR/InlineAsm.h"
39#include "llvm/IR/InstIterator.h"
40#include "llvm/IR/Instructions.h"
41#include "llvm/IR/IntrinsicInst.h"
42#include "llvm/IR/Metadata.h"
43#include "llvm/IR/Operator.h"
44#include "llvm/Support/LogicalResult.h"
45#include "llvm/Support/ModRef.h"
52#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
57static std::string
diag(
const llvm::Value &value) {
59 llvm::raw_string_ostream os(str);
67static std::string
diagMD(
const llvm::Metadata *node,
68 const llvm::Module *module) {
70 llvm::raw_string_ostream os(str);
71 node->print(os, module,
true);
77 return "llvm.global_ctors";
82 return "mlir.llvm.nameless_global";
87 return "llvm.global_dtors";
93 return "__llvm_global_comdat";
102 std::optional<llvm::SyncScope::ID> syncScopeID =
103 llvm::getAtomicSyncScopeID(inst);
110 llvm::LLVMContext &llvmContext = inst->getContext();
111 llvmContext.getSyncScopeNames(syncScopeName);
112 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
113 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
115 if (it != syncScopeName.end())
117 llvm_unreachable(
"incorrect sync scope identifier");
123 llvm::append_range(position,
indices);
134 llvm::Instruction *inst,
147#include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
156 for (llvm::BasicBlock *basicBlock : basicBlocks) {
157 if (!blocks.contains(basicBlock)) {
158 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
159 blocks.insert_range(traversal);
162 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
167 std::unique_ptr<llvm::Module> llvmModule,
168 bool emitExpensiveWarnings,
169 bool importEmptyDICompositeTypes,
170 bool preferUnregisteredIntrinsics,
171 bool importStructsAsLiterals)
173 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
175 typeTranslator(*mlirModule->
getContext(), importStructsAsLiterals),
177 mlirModule, importEmptyDICompositeTypes)),
178 loopAnnotationImporter(
180 emitExpensiveWarnings(emitExpensiveWarnings),
181 preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
182 builder.setInsertionPointToStart(mlirModule.getBody());
185ComdatOp ModuleImport::getGlobalComdatOp() {
187 return globalComdatOp;
193 globalInsertionOp = globalComdatOp;
194 return globalComdatOp;
197LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
202 auto getIdentityIfRootNode =
203 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
207 if (node->getNumOperands() > 1)
210 if (node->getNumOperands() == 1)
211 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
212 return std::optional<StringRef>{op0->getString()};
213 return std::optional<StringRef>{};
223 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
224 StringRef *identity =
nullptr,
225 SmallVectorImpl<TBAAMemberAttr> *members =
226 nullptr) -> std::optional<bool> {
227 unsigned numOperands = node->getNumOperands();
236 const auto *identityNode =
237 dyn_cast<const llvm::MDString>(node->getOperand(0));
243 *identity = identityNode->getString();
245 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
246 const auto *memberNode =
247 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
249 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
250 <<
diagMD(node, llvmModule.get());
254 if (2 * pairNum + 2 >= numOperands) {
256 if (numOperands != 2) {
257 emitError(loc) <<
"missing member offset: "
258 <<
diagMD(node, llvmModule.get());
262 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
263 node->getOperand(2 * pairNum + 2));
265 emitError(loc) <<
"operand '" << 2 * pairNum + 2
266 <<
"' must be ConstantInt: "
267 <<
diagMD(node, llvmModule.get());
270 offset = offsetCI->getZExtValue();
274 members->push_back(TBAAMemberAttr::get(
275 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
288 auto isTagNode = [&](
const llvm::MDNode *node,
289 TBAATypeDescriptorAttr *baseAttr =
nullptr,
290 TBAATypeDescriptorAttr *accessAttr =
nullptr,
291 int64_t *offset =
nullptr,
292 bool *isConstant =
nullptr) -> std::optional<bool> {
300 unsigned numOperands = node->getNumOperands();
301 if (numOperands != 3 && numOperands != 4)
303 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
304 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
306 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
307 if (!baseMD || !accessMD || !offsetCI)
314 if (accessMD->getNumOperands() < 1 ||
315 !isa<llvm::MDString>(accessMD->getOperand(0)))
317 bool isConst =
false;
318 if (numOperands == 4) {
320 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
322 emitError(loc) <<
"operand '3' must be ConstantInt: "
323 <<
diagMD(node, llvmModule.get());
326 isConst = isConstantCI->getValue()[0];
329 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
331 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
333 *offset = offsetCI->getZExtValue();
335 *isConstant = isConst;
343 SmallVector<const llvm::MDNode *> workList;
344 workList.push_back(node);
345 while (!workList.empty()) {
346 const llvm::MDNode *current = workList.back();
347 if (tbaaMapping.contains(current)) {
356 bool anyChildNotConverted =
false;
357 for (
const llvm::MDOperand &operand : current->operands())
358 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
359 if (!tbaaMapping.contains(childNode)) {
360 workList.push_back(childNode);
361 anyChildNotConverted =
true;
364 if (anyChildNotConverted) {
369 if (!seen.insert(current).second)
370 return emitError(loc) <<
"has cycle in TBAA graph: "
371 <<
diagMD(current, llvmModule.get());
379 FailureOr<std::optional<StringRef>> rootNodeIdentity =
380 getIdentityIfRootNode(current);
381 if (succeeded(rootNodeIdentity)) {
382 StringAttr stringAttr = *rootNodeIdentity
383 ? builder.getStringAttr(**rootNodeIdentity)
387 tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)});
392 SmallVector<TBAAMemberAttr> members;
393 if (std::optional<bool> isValid =
394 isTypeDescriptorNode(current, &identity, &members)) {
395 assert(isValid.value() &&
"type descriptor node must be valid");
397 tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>(
398 identity, members)});
402 TBAATypeDescriptorAttr baseAttr, accessAttr;
405 if (std::optional<bool> isValid =
406 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
407 assert(isValid.value() &&
"access tag node must be valid");
409 {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
414 return emitError(loc) <<
"unsupported TBAA node format: "
415 <<
diagMD(current, llvmModule.get());
421ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
422 Location loc = mlirModule.getLoc();
423 if (
failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
424 return emitError(loc) <<
"unsupported access group node: "
425 <<
diagMD(node, llvmModule.get());
430ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
431 Location loc = mlirModule.getLoc();
433 auto verifySelfRef = [](
const llvm::MDNode *node) {
434 return node->getNumOperands() != 0 &&
435 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
437 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
438 return node->getNumOperands() != 0 &&
439 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
440 isa<llvm::MDString>(node->getOperand(0)));
443 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
444 return idx >= node->getNumOperands() ||
445 isa<llvm::MDString>(node->getOperand(idx));
448 auto getIdAttr = [&](
const llvm::MDNode *node) -> Attribute {
449 if (verifySelfRef(node))
452 auto *name = cast<llvm::MDString>(node->getOperand(0));
453 return builder.getStringAttr(name->getString());
457 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
458 StringAttr description =
nullptr;
459 if (aliasDomain->getNumOperands() >= 2)
460 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
461 description = builder.getStringAttr(operand->getString());
462 Attribute idAttr = getIdAttr(aliasDomain);
463 return builder.getAttr<AliasScopeDomainAttr>(idAttr, description);
467 for (
const llvm::MDOperand &operand : node->operands()) {
468 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
469 llvm::AliasScopeNode aliasScope(scope);
470 const llvm::MDNode *domain = aliasScope.getDomain();
476 if (!verifySelfRefOrString(scope) || !domain ||
477 !verifyDescription(scope, 2))
478 return emitError(loc) <<
"unsupported alias scope node: "
479 <<
diagMD(scope, llvmModule.get());
480 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
481 return emitError(loc) <<
"unsupported alias domain node: "
482 <<
diagMD(domain, llvmModule.get());
484 if (aliasScopeMapping.contains(scope))
488 auto it = aliasScopeMapping.find(aliasScope.getDomain());
489 if (it == aliasScopeMapping.end()) {
490 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
491 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
495 StringAttr description =
nullptr;
496 if (!aliasScope.getName().empty())
497 description = builder.getStringAttr(aliasScope.getName());
498 Attribute idAttr = getIdAttr(scope);
499 auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(
500 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
502 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
508FailureOr<SmallVector<AliasScopeAttr>>
511 aliasScopes.reserve(node->getNumOperands());
512 for (
const llvm::MDOperand &operand : node->operands()) {
513 auto *node = cast<llvm::MDNode>(operand.get());
514 aliasScopes.push_back(
515 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
518 if (llvm::is_contained(aliasScopes,
nullptr))
524 debugIntrinsics.insert(intrinsic);
528 if (!dbgRecords.contains(dbgRecord))
529 dbgRecords.insert(dbgRecord);
533 llvm::MDTuple *mdTuple) {
534 auto getLLVMFunction =
535 [&](
const llvm::MDOperand &funcMDO) -> llvm::Function * {
536 auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);
540 auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());
546 for (
unsigned i = 0; i < mdTuple->getNumOperands(); i++) {
547 const llvm::MDOperand &mdo = mdTuple->getOperand(i);
548 auto *cgEntry = cast<llvm::MDNode>(mdo);
549 llvm::Constant *llvmConstant =
550 cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();
551 uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();
552 auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));
553 auto *toFn = getLLVMFunction(cgEntry->getOperand(1));
555 cgProfile.push_back(ModuleFlagCGProfileEntryAttr::get(
556 mlirModule->getContext(),
564 return ArrayAttr::get(mlirModule->getContext(), cgProfile);
570 const llvm::Module *llvmModule,
571 const llvm::MDOperand &md) {
572 auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
573 if (!tupleEntry || tupleEntry->getNumOperands() != 2)
575 <<
"expected 2-element tuple metadata: " <<
diagMD(md, llvmModule);
583 ModuleOp mlirModule,
const llvm::Module *llvmModule,
584 const llvm::MDOperand &md, StringRef matchKey,
bool optional =
false) {
588 auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
589 if (!keyMD || keyMD->getString() != matchKey) {
592 <<
"expected '" << matchKey <<
"' key, but found: "
593 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
597 return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));
603static FailureOr<uint64_t>
605 const llvm::Module *llvmModule,
606 const llvm::MDOperand &md, StringRef matchKey) {
607 llvm::ConstantAsMetadata *valMD =
612 if (
auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))
613 return cstInt->getZExtValue();
616 <<
"expected integer metadata value for key '" << matchKey
617 <<
"': " <<
diagMD(md, llvmModule);
621static std::optional<ProfileSummaryFormatKind>
623 const llvm::MDOperand &formatMD) {
628 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
629 if (!keyMD || keyMD->getString() !=
"ProfileFormat") {
631 <<
"expected 'ProfileFormat' key: "
632 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
636 llvm::MDString *valMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(1));
637 std::optional<ProfileSummaryFormatKind> fmtKind =
638 symbolizeProfileSummaryFormatKind(valMD->getString());
641 <<
"expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
643 <<
diagMD(valMD, llvmModule);
650static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
652 const llvm::Module *llvmModule,
653 const llvm::MDOperand &summaryMD) {
658 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
659 if (!keyMD || keyMD->getString() !=
"DetailedSummary") {
661 <<
"expected 'DetailedSummary' key: "
662 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
666 llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
669 <<
"expected tuple value for 'DetailedSummary' key: "
670 <<
diagMD(tupleEntry->getOperand(1), llvmModule);
675 for (
auto &&entry : entriesMD->operands()) {
676 llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
677 if (!entryMD || entryMD->getNumOperands() != 3) {
679 <<
"'DetailedSummary' entry expects 3 operands: "
680 <<
diagMD(entry, llvmModule);
684 auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
685 auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
686 auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
687 if (!op0 || !op1 || !op2) {
689 <<
"expected only integer entries in 'DetailedSummary': "
690 <<
diagMD(entry, llvmModule);
694 auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get(
695 mlirModule->getContext(),
696 cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
697 cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
698 cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
699 detailedSummary.push_back(detaildSummaryEntry);
701 return detailedSummary;
706 const llvm::Module *llvmModule,
707 llvm::MDTuple *mdTuple) {
708 unsigned profileNumEntries = mdTuple->getNumOperands();
709 if (profileNumEntries < 8) {
711 <<
"expected at 8 entries in 'ProfileSummary': "
712 <<
diagMD(mdTuple, llvmModule);
716 unsigned summayIdx = 0;
717 auto checkOptionalPosition = [&](
const llvm::MDOperand &md,
718 StringRef matchKey) -> LogicalResult {
722 if (summayIdx + 1 >= profileNumEntries) {
724 <<
"the last summary entry is '" << matchKey
725 <<
"', expected 'DetailedSummary': " <<
diagMD(md, llvmModule);
732 auto getOptIntValue =
733 [&](
const llvm::MDOperand &md,
734 StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
737 return FailureOr<std::optional<uint64_t>>(std::nullopt);
738 if (checkOptionalPosition(md, matchKey).failed())
740 FailureOr<uint64_t> val =
747 auto getOptDoubleValue = [&](
const llvm::MDOperand &md,
748 StringRef matchKey) -> FailureOr<FloatAttr> {
753 if (
auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
754 if (checkOptionalPosition(md, matchKey).failed())
756 return FloatAttr::get(Float64Type::get(mlirModule.getContext()),
757 cstFP->getValueAPF());
760 <<
"expected double metadata value for key '" << matchKey
761 <<
"': " <<
diagMD(md, llvmModule);
768 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
769 if (!format.has_value())
773 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"TotalCount");
774 if (failed(totalCount))
778 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"MaxCount");
779 if (failed(maxCount))
783 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
785 if (failed(maxInternalCount))
789 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
791 if (failed(maxFunctionCount))
795 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumCounts");
796 if (failed(numCounts))
800 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumFunctions");
801 if (failed(numFunctions))
805 FailureOr<std::optional<uint64_t>> isPartialProfile =
806 getOptIntValue(mdTuple->getOperand(summayIdx),
"IsPartialProfile");
807 if (failed(isPartialProfile))
809 if (isPartialProfile->has_value())
812 FailureOr<FloatAttr> partialProfileRatio =
813 getOptDoubleValue(mdTuple->getOperand(summayIdx),
"PartialProfileRatio");
814 if (failed(partialProfileRatio))
816 if (*partialProfileRatio)
820 FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
822 mdTuple->getOperand(summayIdx));
823 if (failed(detailed))
827 return ModuleFlagProfileSummaryAttr::get(
828 mlirModule->getContext(), *format, *totalCount, *maxCount,
829 *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,
830 *isPartialProfile, *partialProfileRatio, *detailed);
837 const llvm::Module *llvmModule, StringRef key,
838 llvm::MDTuple *mdTuple) {
839 if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
841 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
846 Builder builder(mlirModule->getContext());
848 strings.reserve(mdTuple->getNumOperands());
849 for (
const llvm::MDOperand &operand : mdTuple->operands()) {
850 auto *mdString = dyn_cast_if_present<llvm::MDString>(operand.get());
853 strings.push_back(builder.
getStringAttr(mdString->getString()));
860 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
863 for (
const auto [behavior, key, val] : llvmModuleFlags) {
865 if (
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
866 valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
867 }
else if (
auto *mdString = dyn_cast<llvm::MDString>(val)) {
868 valAttr = builder.getStringAttr(mdString->getString());
869 }
else if (
auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
871 key->getString(), mdTuple);
876 <<
"unsupported module flag value for key '" << key->getString()
877 <<
"' : " <<
diagMD(val, llvmModule.get());
881 moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
882 convertModFlagBehaviorFromLLVM(behavior),
883 builder.getStringAttr(key->getString()), valAttr));
886 if (!moduleFlags.empty())
887 LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),
888 builder.getArrayAttr(moduleFlags));
894 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
895 if (named.getName() !=
"llvm.linker.options")
898 for (
const llvm::MDNode *node : named.operands()) {
900 options.reserve(node->getNumOperands());
901 for (
const llvm::MDOperand &option : node->operands())
902 options.push_back(cast<llvm::MDString>(option)->getString());
903 LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),
904 builder.getStrArrayAttr(
options));
911 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
912 if (named.getName() !=
"llvm.dependent-libraries")
915 for (
const llvm::MDNode *node : named.operands()) {
916 if (node->getNumOperands() == 1)
917 if (
auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
918 libraries.push_back(mdString->getString());
920 if (!libraries.empty())
921 mlirModule->setAttr(LLVM::LLVMDialect::getDependentLibrariesAttrName(),
922 builder.getStrArrayAttr(libraries));
928 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
931 if (named.getName() != LLVMDialect::getIdentAttrName())
934 if (named.getNumOperands() == 1)
935 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
936 if (md->getNumOperands() == 1)
937 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
938 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
939 builder.getStringAttr(mdStr->getString()));
945 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
948 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
951 if (nmd.getNumOperands() == 1)
952 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
953 if (md->getNumOperands() == 1)
954 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
955 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
956 builder.getStringAttr(mdStr->getString()));
963 builder.setInsertionPointToEnd(mlirModule.getBody());
964 for (
const llvm::Function &
func : llvmModule->functions()) {
965 for (
const llvm::Instruction &inst : llvm::instructions(
func)) {
967 if (llvm::MDNode *node =
968 inst.getMetadata(llvm::LLVMContext::MD_access_group))
969 if (failed(processAccessGroupMetadata(node)))
973 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
974 if (!aliasAnalysisNodes)
976 if (aliasAnalysisNodes.TBAA)
977 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
979 if (aliasAnalysisNodes.Scope)
980 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
982 if (aliasAnalysisNodes.NoAlias)
983 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
1000void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
1001 if (comdatMapping.contains(comdat))
1004 ComdatOp comdatOp = getGlobalComdatOp();
1007 auto selectorOp = ComdatSelectorOp::create(
1008 builder, mlirModule.getLoc(), comdat->getName(),
1009 convertComdatFromLLVM(comdat->getSelectionKind()));
1013 comdatMapping.try_emplace(comdat, symbolRef);
1017 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1018 if (globalVar.hasComdat())
1019 processComdat(globalVar.getComdat());
1020 for (llvm::Function &
func : llvmModule->functions())
1021 if (
func.hasComdat())
1022 processComdat(
func.getComdat());
1027 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1030 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1031 return emitError(UnknownLoc::get(context))
1032 <<
"unhandled global variable: " <<
diag(globalVar);
1036 if (failed(convertGlobal(&globalVar))) {
1037 return emitError(UnknownLoc::get(context))
1038 <<
"unhandled global variable: " <<
diag(globalVar);
1045 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1046 if (failed(convertAlias(&alias))) {
1047 return emitError(UnknownLoc::get(context))
1048 <<
"unhandled global alias: " <<
diag(alias);
1055 for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1056 if (failed(convertIFunc(&ifunc))) {
1057 return emitError(UnknownLoc::get(context))
1058 <<
"unhandled global ifunc: " <<
diag(ifunc);
1065 Location loc = mlirModule.getLoc();
1067 context, llvmModule->getDataLayout().getStringRepresentation());
1069 return emitError(loc,
"cannot translate data layout: ")
1073 emitWarning(loc,
"unhandled data layout token: ") << token;
1075 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
1081 mlirModule->setAttr(
1082 LLVM::LLVMDialect::getTargetTripleAttrName(),
1083 builder.getStringAttr(llvmModule->getTargetTriple().str()));
1087 llvm::StringRef asmStr = llvmModule->getModuleInlineAsm();
1090 for (llvm::StringRef line : llvm::split(asmStr,
'\n'))
1092 asmArrayAttr.push_back(builder.getStringAttr(line));
1094 mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1095 builder.getArrayAttr(asmArrayAttr));
1099 for (llvm::Function &
func : llvmModule->functions())
1105void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1108 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1109 for (
auto &[kind, node] : allMetadata) {
1113 if (emitExpensiveWarnings) {
1114 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1116 <<
diagMD(node, llvmModule.get()) <<
" on "
1125 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1127 IntegerOverflowFlags value = {};
1128 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1130 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1132 iface.setOverflowFlags(value);
1136 auto iface = cast<ExactFlagInterface>(op);
1138 iface.setIsExact(inst->isExact());
1143 auto iface = cast<DisjointFlagInterface>(op);
1144 auto *instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1146 iface.setIsDisjoint(instDisjoint->isDisjoint());
1150 auto iface = cast<NonNegFlagInterface>(op);
1152 iface.setNonNeg(inst->hasNonNeg());
1157 auto iface = cast<FastmathFlagsInterface>(op);
1163 if (!isa<llvm::FPMathOperator>(inst))
1165 llvm::FastMathFlags flags = inst->getFastMathFlags();
1168 FastmathFlags value = {};
1169 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1170 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1171 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1172 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1173 value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
1174 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1175 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1176 FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
1177 iface->setAttr(iface.getFastmathAttrName(), attr);
1189 if (numElements.isScalable()) {
1191 <<
"scalable vectors not supported";
1196 Type elementType = cast<VectorType>(type).getElementType();
1200 SmallVector<int64_t> shape(arrayShape);
1201 shape.push_back(numElements.getKnownMinValue());
1202 return VectorType::get(shape, elementType);
1205Type ModuleImport::getBuiltinTypeForAttr(Type type) {
1219 SmallVector<int64_t> arrayShape;
1220 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1221 arrayShape.push_back(arrayType.getNumElements());
1222 type = arrayType.getElementType();
1225 return RankedTensorType::get(arrayShape, type);
1232 llvm::Constant *constScalar) {
1235 if (constScalar->getType()->isVectorTy())
1239 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1241 IntegerType::get(context, constInt->getBitWidth()),
1242 constInt->getValue());
1246 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1247 llvm::Type *type = constFloat->getType();
1248 FloatType floatType =
1250 ? BFloat16Type::get(context)
1254 <<
"unexpected floating-point type";
1257 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1264static SmallVector<Attribute>
1266 llvm::ConstantDataSequential *constSequence) {
1268 elementAttrs.reserve(constSequence->getNumElements());
1269 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1270 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1273 return elementAttrs;
1276Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1282 auto getConstantShape = [&](llvm::Type *type) {
1283 return llvm::dyn_cast_if_present<ShapedType>(
1288 if (isa<llvm::ConstantInt, llvm::ConstantFP>(constant)) {
1289 assert(constant->getType()->isVectorTy() &&
"expected a vector splat");
1290 auto shape = getConstantShape(constant->getType());
1293 Attribute splatAttr =
1300 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1301 if (constArray->isString())
1302 return builder.getStringAttr(constArray->getAsString());
1303 auto shape = getConstantShape(constArray->getType());
1307 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1308 if (constVector && constVector->isSplat()) {
1311 builder, constVector->getElementAsConstant(0));
1315 SmallVector<Attribute> elementAttrs =
1322 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1323 auto shape = getConstantShape(constAggregate->getType());
1327 SmallVector<Attribute> elementAttrs;
1328 SmallVector<llvm::Constant *> workList = {constAggregate};
1329 while (!workList.empty()) {
1330 llvm::Constant *current = workList.pop_back_val();
1333 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1335 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1336 workList.push_back(constAggregate->getAggregateElement(idx));
1341 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1342 SmallVector<Attribute> attrs =
1344 elementAttrs.append(attrs.begin(), attrs.end());
1350 elementAttrs.push_back(scalarAttr);
1361 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1362 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1363 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1367 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1368 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1375ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1376 assert(globalVar->getName().empty() &&
1377 "expected to work with a nameless global");
1378 auto [it,
success] = namelessGlobals.try_emplace(globalVar);
1385 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1388 it->getSecond() = symbolRef;
1392OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1393 OpBuilder::InsertionGuard guard(builder);
1394 if (globalInsertionOp)
1395 builder.setInsertionPointAfter(globalInsertionOp);
1397 builder.setInsertionPointToStart(mlirModule.getBody());
1401LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1403 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1406 AliasOp aliasOp = AliasOp::create(builder, mlirModule.getLoc(), type,
1407 convertLinkageFromLLVM(alias->getLinkage()),
1409 alias->isDSOLocal(),
1410 alias->isThreadLocal(),
1411 ArrayRef<NamedAttribute>());
1412 globalInsertionOp = aliasOp;
1415 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1416 setConstantInsertionPointToStart(block);
1417 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1420 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1422 if (alias->hasAtLeastLocalUnnamedAddr())
1423 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1424 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1429LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1430 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1433 llvm::Constant *resolver = ifunc->getResolver();
1434 Type resolverType =
convertType(resolver->getType());
1435 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1436 resolver->getName(), resolverType,
1437 convertLinkageFromLLVM(ifunc->getLinkage()),
1438 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1439 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1440 convertVisibilityFromLLVM(ifunc->getVisibility()));
1450 ArrayRef<StringLiteral> attributePrefixesToSkip = {}) {
1451 SmallVector<Attribute> mlirAttributes;
1452 for (llvm::Attribute attr : attributes) {
1454 if (attr.isStringAttribute())
1455 attrName = attr.getKindAsString();
1457 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1458 if (llvm::is_contained(attributesToSkip, attrName))
1461 auto attrNameStartsWith = [attrName](StringLiteral sl) {
1462 return attrName.starts_with(sl);
1464 if (attributePrefixesToSkip.end() !=
1465 llvm::find_if(attributePrefixesToSkip, attrNameStartsWith))
1468 auto keyAttr = StringAttr::get(context, attrName);
1469 if (attr.isStringAttribute()) {
1470 StringRef val = attr.getValueAsString();
1473 mlirAttributes.push_back(keyAttr);
1477 mlirAttributes.push_back(
1478 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1481 if (attr.isIntAttribute()) {
1484 auto val = std::to_string(attr.getValueAsInt());
1485 mlirAttributes.push_back(
1486 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1489 if (attr.isEnumAttribute()) {
1491 mlirAttributes.push_back(keyAttr);
1497 <<
"' attribute is invalid on current operation, skipping it";
1499 return ArrayAttr::get(context, mlirAttributes);
1505 GlobalOp globalOp) {
1507 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1508 if (!targetSpecificAttrs.empty())
1509 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1512LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1514 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1516 Attribute valueAttr;
1517 if (globalVar->hasInitializer())
1518 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1519 Type type =
convertType(globalVar->getValueType());
1521 uint64_t alignment = 0;
1522 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1523 if (maybeAlign.has_value()) {
1524 llvm::Align align = *maybeAlign;
1525 alignment = align.value();
1530 SmallVector<Attribute> globalExpressionAttrs;
1531 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1532 globalVar->getDebugInfo(globalExpressions);
1534 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1535 DIGlobalVariableExpressionAttr globalExpressionAttr =
1536 debugImporter->translateGlobalVariableExpression(expr);
1537 globalExpressionAttrs.push_back(globalExpressionAttr);
1542 StringRef globalName = globalVar->getName();
1543 if (globalName.empty())
1544 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1546 GlobalOp globalOp = GlobalOp::create(
1547 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1548 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1549 valueAttr, alignment, globalVar->getAddressSpace(),
1550 globalVar->isDSOLocal(),
1551 globalVar->isThreadLocal(), SymbolRefAttr(),
1552 ArrayRef<NamedAttribute>(), globalExpressionAttrs);
1553 globalInsertionOp = globalOp;
1555 if (globalVar->hasInitializer() && !valueAttr) {
1557 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1558 setConstantInsertionPointToStart(block);
1559 FailureOr<Value> initializer =
1560 convertConstantExpr(globalVar->getInitializer());
1563 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1565 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1566 globalOp.setUnnamedAddr(
1567 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1569 if (globalVar->hasSection())
1570 globalOp.setSection(globalVar->getSection());
1571 globalOp.setVisibility_(
1572 convertVisibilityFromLLVM(globalVar->getVisibility()));
1574 if (globalVar->hasComdat())
1575 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1583ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1584 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1586 llvm::Constant *initializer = globalVar->getInitializer();
1588 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1589 isa<llvm::ConstantAggregateZero>(initializer);
1596 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1597 if (caz->getElementCount().getFixedValue() != 0)
1601 SmallVector<Attribute> funcs;
1602 SmallVector<int32_t> priorities;
1603 SmallVector<Attribute> dataList;
1604 for (llvm::Value *operand : initializer->operands()) {
1605 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1606 if (!aggregate || aggregate->getNumOperands() != 3)
1609 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1610 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1611 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1612 if (!priority || !func || !data)
1615 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1619 else if (data->isNullValue())
1620 dataAttr = ZeroAttr::get(context);
1625 priorities.push_back(priority->getValue().getZExtValue());
1626 dataList.push_back(dataAttr);
1630 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1633 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1634 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1635 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1638 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1639 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1640 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1645ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1647 if (valueMapping.contains(constant))
1656 workList.insert(constant);
1657 while (!workList.empty()) {
1658 llvm::Constant *current = workList.back();
1661 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1662 orderedSet.insert(current);
1663 workList.pop_back();
1669 auto [adjacencyIt,
inserted] = adjacencyLists.try_emplace(current);
1673 for (llvm::Value *operand : current->operands())
1674 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1675 adjacencyIt->getSecond().push_back(constDependency);
1678 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1679 unsigned numElements = constAgg->getElementCount().getFixedValue();
1680 for (
unsigned i = 0, e = numElements; i != e; ++i)
1681 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1687 if (adjacencyIt->getSecond().empty()) {
1688 orderedSet.insert(current);
1689 workList.pop_back();
1697 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1698 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1699 orderedSet.contains(dependency))
1701 workList.insert(dependency);
1707FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1708 Location loc = UnknownLoc::get(context);
1711 if (Attribute attr = getConstantAsAttr(constant)) {
1713 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1714 return AddressOfOp::create(builder, loc, type, symbolRef.getValue())
1717 return ConstantOp::create(builder, loc, type, attr).getResult();
1721 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1723 return ZeroOp::create(builder, loc, type).getResult();
1727 if (isa<llvm::ConstantTokenNone>(constant)) {
1728 return NoneTokenOp::create(builder, loc).getResult();
1732 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1734 return PoisonOp::create(builder, loc, type).getResult();
1738 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1740 return UndefOp::create(builder, loc, type).getResult();
1744 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1745 Type type =
convertType(dsoLocalEquivalent->getType());
1746 return DSOLocalEquivalentOp::create(
1749 builder.getContext(),
1750 dsoLocalEquivalent->getGlobalValue()->getName()))
1755 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1757 StringRef globalName = globalObj->getName();
1758 FlatSymbolRefAttr symbolRef;
1760 if (globalName.empty())
1762 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1765 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1769 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1770 Type type =
convertType(globalAliasObj->getType());
1771 StringRef aliaseeName = globalAliasObj->getName();
1773 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1777 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1783 llvm::Instruction *inst = constExpr->getAsInstruction();
1784 llvm::scope_exit guard([&]() {
1785 assert(!noResultOpMapping.contains(inst) &&
1786 "expected constant expression to return a result");
1787 valueMapping.erase(inst);
1788 inst->deleteValue();
1792 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1793 return valueMapping.contains(value);
1795 if (
failed(processInstruction(inst)))
1801 if (
auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1802 Type type =
convertType(aggregateZero->getType());
1803 return ZeroOp::create(builder, loc, type).getResult();
1807 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1809 SmallVector<Value> elementValues;
1811 elementValues.reserve(constAgg->getNumOperands());
1812 for (llvm::Value *operand : constAgg->operands())
1815 assert(llvm::count(elementValues,
nullptr) == 0 &&
1816 "expected all elements have been converted before");
1820 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1822 "unrecognized aggregate type");
1823 Value root = UndefOp::create(builder, loc, rootType);
1824 for (
const auto &it : llvm::enumerate(elementValues)) {
1825 if (isArrayOrStruct) {
1827 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1829 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1831 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1832 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1839 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1840 LLVMTargetExtType targetExtType =
1841 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1842 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1843 "target extension type does not support zero-initialization");
1846 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1849 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1853 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1854 return BlockAddressOp::create(
1856 BlockAddressAttr::get(context, fnSym, blockTag))
1860 StringRef error =
"";
1862 if (isa<llvm::ConstantPtrAuth>(constant))
1863 error =
" since ptrauth(...) is unsupported";
1865 if (isa<llvm::NoCFIValue>(constant))
1866 error =
" since no_cfi is unsupported";
1868 if (isa<llvm::GlobalValue>(constant))
1869 error =
" since global value is unsupported";
1871 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1874FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1878 assert(!valueMapping.contains(constant) &&
1879 "expected constant has not been converted before");
1880 assert(constantInsertionBlock &&
1881 "expected the constant insertion block to be non-null");
1884 OpBuilder::InsertionGuard guard(builder);
1885 if (!constantInsertionOp)
1886 builder.setInsertionPointToStart(constantInsertionBlock);
1888 builder.setInsertionPointAfter(constantInsertionOp);
1892 getConstantsToConvert(constant);
1893 for (llvm::Constant *constantToConvert : constantsToConvert) {
1894 FailureOr<Value> converted = convertConstant(constantToConvert);
1897 mapValue(constantToConvert, *converted);
1902 constantInsertionOp =
result.getDefiningOp();
1907 assert(!isa<llvm::MetadataAsValue>(value) &&
1908 "expected value to not be metadata");
1911 auto it = valueMapping.find(value);
1912 if (it != valueMapping.end())
1913 return it->getSecond();
1916 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1917 return convertConstantExpr(constant);
1919 Location loc = UnknownLoc::get(context);
1920 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1922 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1928 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1931 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1934 value = node->getValue();
1937 auto it = valueMapping.find(value);
1938 if (it != valueMapping.end())
1939 return it->getSecond();
1942 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1943 return convertConstantExpr(constant);
1947FailureOr<SmallVector<Value>>
1950 remapped.reserve(values.size());
1951 for (llvm::Value *value : values) {
1953 if (failed(converted))
1955 remapped.push_back(*converted);
1965 assert(immArgPositions.size() == immArgAttrNames.size() &&
1966 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1970 for (
auto [immArgPos, immArgName] :
1971 llvm::zip(immArgPositions, immArgAttrNames)) {
1972 auto &value = operands[immArgPos];
1973 auto *constant = llvm::cast<llvm::Constant>(value);
1975 assert(attr && attr.getType().isIntOrFloat() &&
1976 "expected immarg to be float or integer constant");
1977 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1978 attrsOut.push_back({nameAttr, attr});
1983 for (llvm::Value *value : operands) {
1987 if (failed(mlirValue))
1989 valuesOut.push_back(*mlirValue);
1994 if (requiresOpBundles) {
1995 opBundleSizes.reserve(opBundles.size());
1996 opBundleTagAttrs.reserve(opBundles.size());
1998 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1999 opBundleSizes.push_back(bundle.Inputs.size());
2000 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
2002 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
2003 auto operandMlirValue =
convertValue(opBundleOperand.get());
2004 if (failed(operandMlirValue))
2006 valuesOut.push_back(*operandMlirValue);
2011 auto opBundleSizesAttrNameAttr =
2012 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
2013 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
2015 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
2016 auto opBundleTagsAttrNameAttr =
2017 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
2018 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
2025 IntegerAttr integerAttr;
2027 bool success = succeeded(converted) &&
2029 assert(
success &&
"expected a constant integer value");
2035 FloatAttr floatAttr;
2039 assert(
success &&
"expected a constant float value");
2046 llvm::DILocalVariable *node =
nullptr;
2047 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2048 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2049 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2051 node = cast<llvm::DILocalVariable *>(valOrVariable);
2053 return debugImporter->translate(node);
2057 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2058 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2059 return debugImporter->translate(node);
2062FPExceptionBehaviorAttr
2064 auto *metadata = cast<llvm::MetadataAsValue>(value);
2065 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2066 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2067 llvm::convertStrToExceptionBehavior(mdstr->getString());
2068 assert(optLLVM &&
"Expecting FP exception behavior");
2069 return builder.getAttr<FPExceptionBehaviorAttr>(
2070 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2074 auto *metadata = cast<llvm::MetadataAsValue>(value);
2075 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2076 std::optional<llvm::RoundingMode> optLLVM =
2077 llvm::convertStrToRoundingMode(mdstr->getString());
2078 assert(optLLVM &&
"Expecting rounding mode");
2079 return builder.getAttr<RoundingModeAttr>(
2080 convertRoundingModeFromLLVM(*optLLVM));
2083FailureOr<SmallVector<AliasScopeAttr>>
2085 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2086 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2091 return debugImporter->translateLoc(loc);
2095ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2096 llvm::BasicBlock *
target,
2098 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2099 auto *phiInst = cast<llvm::PHINode>(&*inst);
2100 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2102 if (failed(converted))
2104 blockArguments.push_back(*converted);
2109FailureOr<SmallVector<Value>>
2110ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2111 bool allowInlineAsm) {
2112 bool isInlineAsm = callInst->isInlineAsm();
2113 if (isInlineAsm && !allowInlineAsm)
2123 llvm::Value *calleeOperand = callInst->getCalledOperand();
2124 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2128 operands.push_back(*called);
2131 SmallVector<llvm::Value *> args(callInst->args());
2132 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2136 llvm::append_range(operands, *arguments);
2144 LLVMFunctionType calleeType) {
2145 if (callType.getReturnType() != calleeType.getReturnType())
2148 if (calleeType.isVarArg()) {
2151 if (callType.getNumParams() < calleeType.getNumParams())
2156 if (callType.getNumParams() != calleeType.getNumParams())
2161 for (
auto [operandType, argumentType] :
2162 llvm::zip(callType.getParams(), calleeType.getParams()))
2163 if (operandType != argumentType)
2169FailureOr<LLVMFunctionType>
2170ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2171 bool &isIncompatibleCall) {
2172 isIncompatibleCall =
false;
2173 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2174 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2180 llvm::Value *calledOperand = callInst->getCalledOperand();
2181 FailureOr<LLVMFunctionType> callType =
2182 castOrFailure(
convertType(callInst->getFunctionType()));
2185 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2187 llvm::FunctionType *origCalleeType =
nullptr;
2189 origCalleeType = callee->getFunctionType();
2190 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2191 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2195 if (!origCalleeType)
2198 FailureOr<LLVMFunctionType> calleeType =
2206 isIncompatibleCall =
true;
2208 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2209 <<
" and " << *calleeType;
2216FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2217 llvm::Value *calledOperand = callInst->getCalledOperand();
2218 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2219 return SymbolRefAttr::get(context, calledOperand->getName());
2223LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2224 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2228 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2232ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2233 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2234 unsigned argIdx = 0;
2235 SmallVector<mlir::Attribute> opAttrs;
2236 bool hasIndirect =
false;
2238 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2240 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2245 if (ci.isIndirect) {
2246 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2247 SmallVector<mlir::NamedAttribute> attrs;
2248 attrs.push_back(builder.getNamedAttr(
2249 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2251 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2255 opAttrs.push_back(builder.getDictionaryAttr({}));
2261 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2265LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2268 if (
auto *brInst = dyn_cast<llvm::UncondBrInst>(inst)) {
2269 llvm::BasicBlock *succ = brInst->getSuccessor();
2270 SmallVector<Value> blockArgs;
2271 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2274 auto brOp = LLVM::BrOp::create(builder, loc, blockArgs,
lookupBlock(succ));
2278 if (
auto *brInst = dyn_cast<llvm::CondBrInst>(inst)) {
2279 SmallVector<Block *> succBlocks;
2280 SmallVector<SmallVector<Value>> succBlockArgs;
2281 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2282 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2283 SmallVector<Value> blockArgs;
2284 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2287 succBlockArgs.push_back(blockArgs);
2290 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2293 auto condBrOp = LLVM::CondBrOp::create(
2294 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2295 succBlocks.back(), succBlockArgs.back());
2299 if (inst->getOpcode() == llvm::Instruction::Switch) {
2300 auto *swInst = cast<llvm::SwitchInst>(inst);
2302 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2305 SmallVector<Value> defaultBlockArgs;
2307 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2308 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2312 unsigned numCases = swInst->getNumCases();
2313 SmallVector<SmallVector<Value>> caseOperands(numCases);
2314 SmallVector<ValueRange> caseOperandRefs(numCases);
2315 SmallVector<APInt> caseValues(numCases);
2316 SmallVector<Block *> caseBlocks(numCases);
2317 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2318 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2319 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2320 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2322 caseOperandRefs[it.index()] = caseOperands[it.index()];
2323 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2327 auto switchOp = SwitchOp::create(builder, loc, *condition,
2329 caseValues, caseBlocks, caseOperandRefs);
2333 if (inst->getOpcode() == llvm::Instruction::PHI) {
2335 mapValue(inst, builder.getInsertionBlock()->addArgument(
2339 if (inst->getOpcode() == llvm::Instruction::Call) {
2340 auto *callInst = cast<llvm::CallInst>(inst);
2341 llvm::Value *calledOperand = callInst->getCalledOperand();
2343 FailureOr<SmallVector<Value>> operands =
2344 convertCallOperands(callInst,
true);
2348 auto callOp = [&]() -> FailureOr<Operation *> {
2349 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2353 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2354 return InlineAsmOp::create(
2355 builder, loc, resultTy, *operands,
2356 builder.getStringAttr(asmI->getAsmString()),
2357 builder.getStringAttr(asmI->getConstraintString()),
2358 asmI->hasSideEffects(), asmI->isAlignStack(),
2359 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2360 AsmDialectAttr::get(
2361 mlirModule.getContext(),
2362 convertAsmDialectFromLLVM(asmI->getDialect())),
2366 bool isIncompatibleCall;
2367 FailureOr<LLVMFunctionType> funcTy =
2368 convertFunctionType(callInst, isIncompatibleCall);
2372 FlatSymbolRefAttr callee =
nullptr;
2373 if (isIncompatibleCall) {
2377 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2378 Value indirectCallVal = LLVM::AddressOfOp::create(
2379 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2380 operands->insert(operands->begin(), indirectCallVal);
2383 callee = convertCalleeName(callInst);
2385 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2387 if (
failed(convertCallAttributes(callInst, callOp)))
2392 if (!isIncompatibleCall)
2394 return callOp.getOperation();
2400 if (!callInst->getType()->isVoidTy())
2401 mapValue(inst, (*callOp)->getResult(0));
2406 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2407 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2409 SmallVector<Value> operands;
2410 operands.reserve(lpInst->getNumClauses());
2411 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2412 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2415 operands.push_back(*operand);
2420 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2424 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2425 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2427 if (invokeInst->isInlineAsm())
2428 return emitError(loc) <<
"invoke of inline assembly is not supported";
2430 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2436 bool invokeResultUsedInPhi = llvm::any_of(
2437 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2438 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2443 Block *directNormalDest = normalDest;
2444 if (invokeResultUsedInPhi) {
2449 OpBuilder::InsertionGuard g(builder);
2450 directNormalDest = builder.createBlock(normalDest);
2453 SmallVector<Value> unwindArgs;
2454 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2458 bool isIncompatibleInvoke;
2459 FailureOr<LLVMFunctionType> funcTy =
2460 convertFunctionType(invokeInst, isIncompatibleInvoke);
2464 FlatSymbolRefAttr calleeName =
nullptr;
2465 if (isIncompatibleInvoke) {
2469 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2470 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2471 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2472 operands->insert(operands->begin(), indirectInvokeVal);
2475 calleeName = convertCalleeName(invokeInst);
2480 auto invokeOp = InvokeOp::create(
2481 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2484 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2489 if (!isIncompatibleInvoke)
2492 if (!invokeInst->getType()->isVoidTy())
2493 mapValue(inst, invokeOp.getResults().front());
2497 SmallVector<Value> normalArgs;
2498 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2502 if (invokeResultUsedInPhi) {
2506 OpBuilder::InsertionGuard g(builder);
2507 builder.setInsertionPointToStart(directNormalDest);
2508 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2512 assert(llvm::none_of(
2514 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2515 "An llvm.invoke operation cannot pass its result as a block "
2517 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2522 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2523 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2524 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2525 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2534 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2542 auto gepOp = GEPOp::create(
2543 builder, loc, type, sourceElementType, *basePtr,
indices,
2544 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2549 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2550 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2552 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2556 SmallVector<Block *> succBlocks;
2557 SmallVector<SmallVector<Value>> succBlockArgs;
2558 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2559 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2560 SmallVector<Value> blockArgs;
2561 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2564 succBlockArgs.push_back(blockArgs);
2566 SmallVector<ValueRange> succBlockArgsRange =
2567 llvm::to_vector_of<ValueRange>(succBlockArgs);
2569 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2570 succBlockArgsRange, succBlocks);
2580 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2583LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2590 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2591 return convertIntrinsic(intrinsic);
2596 if (inst->DebugMarker) {
2597 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2599 if (
auto *dbgVariableRecord =
2600 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2605 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2606 if (!emitExpensiveWarnings)
2609 llvm::raw_string_ostream optionsStream(
options);
2610 dbgRecord.print(optionsStream);
2611 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2615 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2616 DILabelAttr labelAttr =
2617 debugImporter->translate(dbgLabelRecord->getLabel());
2619 return emitUnsupportedWarning();
2620 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2624 return emitUnsupportedWarning();
2629 return convertInstruction(inst);
2632FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2633 if (!f->hasPersonalityFn())
2636 llvm::Constant *pf = f->getPersonalityFn();
2640 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2644 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2645 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2646 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2647 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2648 return SymbolRefAttr::get(builder.getContext(), func->getName());
2651 return FlatSymbolRefAttr();
2655 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2657 auto othermem = convertModRefInfoFromLLVM(
2658 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2659 auto argMem = convertModRefInfoFromLLVM(
2660 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2661 auto inaccessibleMem = convertModRefInfoFromLLVM(
2662 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2663 auto errnoMem = convertModRefInfoFromLLVM(
2664 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2665 auto targetMem0 = convertModRefInfoFromLLVM(
2666 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2667 auto targetMem1 = convertModRefInfoFromLLVM(
2668 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2670 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2671 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2673 if (memAttr.isReadWrite())
2675 funcOp.setMemoryEffectsAttr(memAttr);
2679 llvm::DenormalFPEnv denormalFpEnv =
func->getDenormalFPEnv();
2681 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2684 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2685 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2687 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2688 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2689 convertDenormalModeKindFromLLVM(defaultMode.Input),
2690 convertDenormalModeKindFromLLVM(floatMode.Output),
2691 convertDenormalModeKindFromLLVM(floatMode.Input));
2692 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2698 StringLiteral(
"aarch64_in_za"),
2699 StringLiteral(
"aarch64_inout_za"),
2700 StringLiteral(
"aarch64_new_za"),
2701 StringLiteral(
"aarch64_out_za"),
2702 StringLiteral(
"aarch64_preserves_za"),
2703 StringLiteral(
"aarch64_pstate_sm_body"),
2704 StringLiteral(
"aarch64_pstate_sm_compatible"),
2705 StringLiteral(
"aarch64_pstate_sm_enabled"),
2706 StringLiteral(
"allocsize"),
2707 StringLiteral(
"alwaysinline"),
2708 StringLiteral(
"cold"),
2709 StringLiteral(
"convergent"),
2710 StringLiteral(
"fp-contract"),
2711 StringLiteral(
"frame-pointer"),
2712 StringLiteral(
"hot"),
2713 StringLiteral(
"inlinehint"),
2714 StringLiteral(
"instrument-function-entry"),
2715 StringLiteral(
"instrument-function-exit"),
2716 StringLiteral(
"modular-format"),
2717 StringLiteral(
"memory"),
2718 StringLiteral(
"minsize"),
2719 StringLiteral(
"no_caller_saved_registers"),
2720 StringLiteral(
"no-signed-zeros-fp-math"),
2721 StringLiteral(
"no-builtins"),
2722 StringLiteral(
"nocallback"),
2723 StringLiteral(
"noduplicate"),
2724 StringLiteral(
"noinline"),
2725 StringLiteral(
"noreturn"),
2726 StringLiteral(
"nounwind"),
2727 StringLiteral(
"optnone"),
2728 StringLiteral(
"optsize"),
2729 StringLiteral(
"returns_twice"),
2730 StringLiteral(
"save-reg-params"),
2731 StringLiteral(
"target-features"),
2732 StringLiteral(
"trap-func-name"),
2733 StringLiteral(
"tune-cpu"),
2734 StringLiteral(
"uwtable"),
2735 StringLiteral(
"vscale_range"),
2736 StringLiteral(
"willreturn"),
2737 StringLiteral(
"zero-call-used-regs"),
2738 StringLiteral(
"denormal_fpenv"),
2744 StringLiteral(
"no-builtin-"),
2747template <
typename OpTy>
2749 const llvm::AttributeSet &attrs,
2752 if (attrs.hasAttribute(
"no-builtins")) {
2753 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2758 for (llvm::Attribute attr : attrs) {
2761 if (attr.hasKindAsEnum())
2764 StringRef val = attr.getKindAsString();
2766 if (val.starts_with(
"no-builtin-"))
2768 StringAttr::get(ctx, val.drop_front(
sizeof(
"no-builtin-") - 1)));
2771 if (!nbAttrs.empty())
2772 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2775template <
typename OpTy>
2777 const llvm::AttributeSet &attrs, OpTy
target) {
2778 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2779 if (!attr.isValid())
2782 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2786 static_cast<int32_t
>(*numElems)}));
2797 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2798 llvm::AttributeList::AttrIndex::FunctionIndex);
2800 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2802 if (!passthroughAttr.empty())
2803 funcOp.setPassthroughAttr(passthroughAttr);
2807 LLVMFuncOp funcOp) {
2812 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
2813 funcOp.setNoInline(
true);
2814 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2815 funcOp.setAlwaysInline(
true);
2816 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
2817 funcOp.setInlineHint(
true);
2818 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2819 funcOp.setOptimizeNone(
true);
2820 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
2821 funcOp.setConvergent(
true);
2822 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
2823 funcOp.setNoUnwind(
true);
2824 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
2825 funcOp.setWillReturn(
true);
2826 if (
func->hasFnAttribute(llvm::Attribute::NoReturn))
2827 funcOp.setNoreturn(
true);
2828 if (
func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
2829 funcOp.setOptsize(
true);
2830 if (
func->hasFnAttribute(
"save-reg-params"))
2831 funcOp.setSaveRegParams(
true);
2832 if (
func->hasFnAttribute(llvm::Attribute::MinSize))
2833 funcOp.setMinsize(
true);
2834 if (
func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
2835 funcOp.setReturnsTwice(
true);
2836 if (
func->hasFnAttribute(llvm::Attribute::Cold))
2837 funcOp.setCold(
true);
2838 if (
func->hasFnAttribute(llvm::Attribute::Hot))
2839 funcOp.setHot(
true);
2840 if (
func->hasFnAttribute(llvm::Attribute::NoDuplicate))
2841 funcOp.setNoduplicate(
true);
2842 if (
func->hasFnAttribute(
"no_caller_saved_registers"))
2843 funcOp.setNoCallerSavedRegisters(
true);
2844 if (
func->hasFnAttribute(llvm::Attribute::NoCallback))
2845 funcOp.setNocallback(
true);
2846 if (llvm::Attribute attr =
func->getFnAttribute(
"modular-format");
2847 attr.isStringAttribute())
2848 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
2849 if (llvm::Attribute attr =
func->getFnAttribute(
"zero-call-used-regs");
2850 attr.isStringAttribute())
2851 funcOp.setZeroCallUsedRegsAttr(
2852 StringAttr::get(context, attr.getValueAsString()));
2854 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2855 funcOp.setArmStreaming(
true);
2856 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2857 funcOp.setArmLocallyStreaming(
true);
2858 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2859 funcOp.setArmStreamingCompatible(
true);
2861 if (
func->hasFnAttribute(
"aarch64_new_za"))
2862 funcOp.setArmNewZa(
true);
2863 else if (
func->hasFnAttribute(
"aarch64_in_za"))
2864 funcOp.setArmInZa(
true);
2865 else if (
func->hasFnAttribute(
"aarch64_out_za"))
2866 funcOp.setArmOutZa(
true);
2867 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
2868 funcOp.setArmInoutZa(
true);
2869 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
2870 funcOp.setArmPreservesZa(
true);
2875 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
2876 if (attr.isValid()) {
2878 auto intTy = IntegerType::get(context, 32);
2879 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2880 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2881 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2885 if (
func->hasFnAttribute(
"frame-pointer")) {
2886 StringRef stringRefFramePointerKind =
2887 func->getFnAttribute(
"frame-pointer").getValueAsString();
2888 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2889 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2890 stringRefFramePointerKind)
2894 if (
func->hasFnAttribute(
"use-sample-profile"))
2895 funcOp.setUseSampleProfile(
true);
2897 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
2898 attr.isStringAttribute())
2899 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2901 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
2902 attr.isStringAttribute())
2903 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2905 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
2906 attr.isStringAttribute())
2907 funcOp.setTargetFeaturesAttr(
2908 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2910 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
2911 attr.isStringAttribute())
2912 funcOp.setReciprocalEstimatesAttr(
2913 StringAttr::get(context, attr.getValueAsString()));
2915 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
2916 attr.isStringAttribute())
2917 funcOp.setPreferVectorWidth(attr.getValueAsString());
2919 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
2920 attr.isStringAttribute())
2921 funcOp.setInstrumentFunctionEntry(
2922 StringAttr::get(context, attr.getValueAsString()));
2924 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
2925 attr.isStringAttribute())
2926 funcOp.setInstrumentFunctionExit(
2927 StringAttr::get(context, attr.getValueAsString()));
2929 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
2930 attr.isStringAttribute())
2931 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2933 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
2934 attr.isStringAttribute())
2935 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2937 if (
func->hasUWTable()) {
2938 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
2939 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2940 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2945ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2948 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2950 if (!llvmAttr.isValid())
2955 if (llvmAttr.hasKindAsEnum() &&
2956 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2957 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2958 paramAttrs.push_back(
2964 if (llvmAttr.isTypeAttribute())
2965 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
2966 else if (llvmAttr.isIntAttribute())
2968 else if (llvmAttr.isEnumAttribute())
2970 else if (llvmAttr.isConstantRangeAttribute()) {
2971 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2972 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2975 llvm_unreachable(
"unexpected parameter attribute kind");
2977 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2980 return builder.getDictionaryAttr(paramAttrs);
2984 LLVMFuncOp funcOp) {
2985 auto llvmAttrs = func->getAttributes();
2986 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2987 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2988 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2992 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2993 if (!llvmResAttr.hasAttributes())
2995 funcOp.setResAttrsAttr(
2996 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
3000 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
3003 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
3004 immArgPositions.end());
3006 llvm::AttributeList llvmAttrs = call->getAttributes();
3008 bool anyArgAttrs =
false;
3009 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
3011 if (immArgPositionsSet.contains(i))
3013 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3014 if (llvmArgAttrsSet.back().hasAttributes())
3019 for (
auto &dict : dictAttrs)
3020 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3021 return builder.getArrayAttr(attrs);
3025 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
3026 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3027 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3031 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3032 if (!llvmResAttr.hasAttributes())
3034 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3035 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3038template <
typename Op>
3040 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3044LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3049LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3055 llvm::AttributeList callAttrs = inst->getAttributes();
3057 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3058 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3059 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3060 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3061 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3063 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3064 op.setSaveRegParams(callAttrs.getFnAttr(
"save-reg-params").isValid());
3065 op.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3066 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3067 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3070 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3071 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3072 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3074 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3075 op.setNoCallerSavedRegisters(
3076 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3077 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3079 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3080 attr.isStringAttribute())
3081 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3082 if (llvm::Attribute attr = callAttrs.getFnAttr(
"zero-call-used-regs");
3083 attr.isStringAttribute())
3084 op.setZeroCallUsedRegsAttr(
3085 StringAttr::get(context, attr.getValueAsString()));
3086 if (llvm::Attribute attr = callAttrs.getFnAttr(
"trap-func-name");
3087 attr.isStringAttribute())
3088 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3089 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3091 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3092 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3094 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3095 ModRefInfo othermem = convertModRefInfoFromLLVM(
3096 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3097 ModRefInfo argMem = convertModRefInfoFromLLVM(
3098 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3099 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3100 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3101 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3102 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3103 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3104 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3105 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3106 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3108 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3109 errnoMem, targetMem0, targetMem1);
3111 if (!memAttr.isReadWrite())
3112 op.setMemoryEffectsAttr(memAttr);
3125 if (
func->isIntrinsic() &&
3126 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3129 bool dsoLocal =
func->isDSOLocal();
3130 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3134 builder.setInsertionPointToEnd(mlirModule.getBody());
3136 Location loc = debugImporter->translateFuncLocation(
func);
3137 LLVMFuncOp funcOp = LLVMFuncOp::create(
3138 builder, loc,
func->getName(), functionType,
3139 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3144 funcOp.setPersonalityAttr(personality);
3145 else if (
func->hasPersonalityFn())
3146 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3149 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3151 if (
func->hasAtLeastLocalUnnamedAddr())
3152 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3154 if (
func->hasSection())
3155 funcOp.setSection(StringRef(
func->getSection()));
3157 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3159 if (
func->hasComdat())
3160 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3162 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3163 funcOp.setAlignment(maybeAlign->value());
3170 func->getAllMetadata(allMetadata);
3171 for (
auto &[kind, node] : allMetadata) {
3172 if (!iface.isConvertibleMetadata(kind))
3174 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *
this))) {
3176 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
3181 if (
func->isDeclaration())
3190 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3191 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3196 for (llvm::BasicBlock &basicBlock : *
func) {
3198 if (!reachable.contains(&basicBlock)) {
3199 if (basicBlock.hasAddressTaken())
3201 <<
"unreachable block '" << basicBlock.getName()
3202 <<
"' with address taken";
3205 Region &body = funcOp.getBody();
3206 Block *block = builder.createBlock(&body, body.
end());
3208 reachableBasicBlocks.push_back(&basicBlock);
3212 for (
const auto &it : llvm::enumerate(
func->args())) {
3213 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3214 functionType.getParamType(it.index()), funcOp.getLoc());
3223 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3224 for (llvm::BasicBlock *basicBlock : blocks)
3225 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3230 if (failed(processDebugIntrinsics()))
3235 if (failed(processDebugRecords()))
3244 if (!dbgIntr->isKillLocation())
3246 llvm::Value *value = dbgIntr->getArgOperand(0);
3247 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3250 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3262 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3265 if (dominatedBlocks.empty())
3269 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3272 Value insertPt = argOperand;
3273 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3279 if (!insertionBlock->
empty() &&
3280 isa<LandingpadOp>(insertionBlock->
front()))
3281 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3289std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3290ModuleImport::processDebugOpArgumentsAndInsertionPt(
3292 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3293 llvm::Value *address,
3294 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3295 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3301 FailureOr<Value> argOperand = convertArgOperandToValue();
3302 if (
failed(argOperand)) {
3303 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3311 return {localVarAttr, debugImporter->translateExpression(expression),
3316ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3317 DominanceInfo &domInfo) {
3319 auto emitUnsupportedWarning = [&]() {
3320 if (emitExpensiveWarnings)
3325 OpBuilder::InsertionGuard guard(builder);
3326 auto convertArgOperandToValue = [&]() {
3332 if (dbgIntr->hasArgList())
3333 return emitUnsupportedWarning();
3340 return emitUnsupportedWarning();
3342 auto [localVariableAttr, locationExprAttr, locVal] =
3343 processDebugOpArgumentsAndInsertionPt(
3344 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3345 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3347 if (!localVariableAttr)
3348 return emitUnsupportedWarning();
3353 Operation *op =
nullptr;
3354 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3355 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3357 else if (isa<llvm::DbgValueInst>(dbgIntr))
3358 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3361 return emitUnsupportedWarning();
3364 setNonDebugMetadataAttrs(dbgIntr, op);
3369ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3370 DominanceInfo &domInfo) {
3371 OpBuilder::InsertionGuard guard(builder);
3373 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3374 if (!emitExpensiveWarnings)
3377 llvm::raw_string_ostream optionsStream(
options);
3378 dbgRecord.print(optionsStream);
3379 emitWarning(loc) <<
"unhandled debug variable record "
3380 << optionsStream.str();
3386 if (dbgRecord.hasArgList())
3387 return emitUnsupportedWarning();
3392 if (!dbgRecord.getAddress())
3393 return emitUnsupportedWarning();
3395 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3396 llvm::Value *value = dbgRecord.getAddress();
3399 auto it = valueMapping.find(value);
3400 if (it != valueMapping.end())
3401 return it->getSecond();
3404 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3405 return convertConstantExpr(constant);
3409 auto [localVariableAttr, locationExprAttr, locVal] =
3410 processDebugOpArgumentsAndInsertionPt(
3411 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3412 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3414 if (!localVariableAttr)
3415 return emitUnsupportedWarning();
3420 if (dbgRecord.isDbgDeclare())
3421 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3423 else if (dbgRecord.isDbgValue())
3424 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3427 return emitUnsupportedWarning();
3432LogicalResult ModuleImport::processDebugIntrinsics() {
3433 DominanceInfo domInfo;
3434 for (llvm::Instruction *inst : debugIntrinsics) {
3435 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3436 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3442LogicalResult ModuleImport::processDebugRecords() {
3443 DominanceInfo domInfo;
3444 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3445 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3451LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3453 builder.setInsertionPointToStart(block);
3454 for (llvm::Instruction &inst : *bb) {
3455 if (
failed(processInstruction(&inst)))
3460 if (debugIntrinsics.contains(&inst))
3467 setNonDebugMetadataAttrs(&inst, op);
3468 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3469 if (emitExpensiveWarnings) {
3470 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3476 if (bb->hasAddressTaken()) {
3477 OpBuilder::InsertionGuard guard(builder);
3478 builder.setInsertionPointToStart(block);
3480 BlockTagAttr::get(context, bb->getNumber()));
3485FailureOr<SmallVector<AccessGroupAttr>>
3487 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3493 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3496FailureOr<DereferenceableAttr>
3499 Location loc = mlirModule.getLoc();
3503 if (node->getNumOperands() != 1)
3504 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3505 <<
diagMD(node, llvmModule.get());
3507 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3508 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3509 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3510 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3511 "non-negative constant integer: "
3512 <<
diagMD(node, llvmModule.get());
3514 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3515 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3516 numBytesCst->getZExtValue(), mayBeNull);
3522 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3523 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3524 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3525 bool importStructsAsLiterals) {
3532 LLVMDialect::getDialectNamespace()));
3534 DLTIDialect::getDialectNamespace()));
3535 if (loadAllDialects)
3538 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3542 emitExpensiveWarnings, dropDICompositeTypeElements,
3543 preferUnregisteredIntrinsics,
3544 importStructsAsLiterals);
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static ArrayAttr convertLLVMAttributesToMLIR(Location loc, MLIRContext *context, llvm::AttributeSet attributes, ArrayRef< StringLiteral > attributesToSkip={}, ArrayRef< StringLiteral > attributePrefixesToSkip={})
Converts LLVM string, integer, and enum attributes into MLIR attributes, skipping those in attributes...
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)
Converts LLVM attributes from func into MLIR attributes and adds them to funcOp as passthrough attrib...
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 LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op)
static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, llvm::MDTuple *mdTuple)
static constexpr std::array kExplicitLLVMFuncOpAttributePrefixes
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 Attribute convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, StringRef key, llvm::MDTuple *mdTuple)
Invoke specific handlers for each known module flag value, returns nullptr if the key is unknown or u...
static constexpr std::array kExplicitLLVMFuncOpAttributes
static constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static void convertNoBuiltinAttrs(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static LogicalResult setDebugIntrinsicBuilderInsertionPoint(mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand)
Ensure that the debug intrinsic is inserted right after the operand definition.
static LogicalResult checkFunctionTypeCompatibility(LLVMFunctionType callType, LLVMFunctionType calleeType)
Checks if callType and calleeType are compatible and can be represented in MLIR.
static void processDenormalFPEnv(llvm::Function *func, LLVMFuncOp funcOp)
static std::optional< ProfileSummaryFormatKind > convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &formatMD)
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static FailureOr< uint64_t > convertInt64FromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey)
Extract an integer value from a two element tuple (<key, value>).
static void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar, GlobalOp globalOp)
Converts LLVM attributes from globalVar into MLIR attributes and adds them to globalOp as target-spec...
static Attribute convertProfileSummaryModuleFlagValue(ModuleOp mlirModule, const llvm::Module *llvmModule, llvm::MDTuple *mdTuple)
static llvm::MDTuple * getTwoElementMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md)
Extract a two element MDTuple from a MDOperand.
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 void convertAllocsizeAttr(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static std::string diagMD(const llvm::Metadata *node, const llvm::Module *module)
static llvm::ConstantAsMetadata * getConstantMDFromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey, bool optional=false)
Extract a constant metadata value from a two element tuple (<key, value>).
static FailureOr< SmallVector< ModuleFlagProfileSummaryDetailedAttr > > convertProfileSummaryDetailed(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &summaryMD)
static SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(ArrayRef< llvm::BasicBlock * > basicBlocks)
Get a topologically sorted list of blocks for the given basic blocks.
static llvm::ManagedStatic< PassManagerOptions > options
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.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getIntegerAttr(Type type, int64_t value)
FloatAttr getFloatAttr(Type type, double value)
IntegerAttr getI64IntegerAttr(int64_t value)
StringAttr getStringAttr(const Twine &bytes)
ArrayAttr getArrayAttr(ArrayRef< Attribute > value)
MLIRContext * getContext() const
NamedAttribute getNamedAttr(StringRef name, Attribute val)
Attr getAttr(Args &&...args)
Get or construct an instance of the attribute Attr with provided arguments.
static DenseElementsAttr get(ShapedType type, ArrayRef< Attribute > values)
Constructs a dense elements attribute from an array of element values.
static DistinctAttr create(Attribute referencedAttr)
Creates a distinct attribute that associates a referenced attribute with a unique identifier.
A class for computing basic dominance information.
static FileLineColLoc get(StringAttr filename, unsigned line, unsigned column)
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
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 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.
Module import implementation class that provides methods to import globals and functions from an LLVM...
LogicalResult convertIFuncs()
Converts all ifuncs of the LLVM module to MLIR variables.
LogicalResult convertIntrinsicArguments(ArrayRef< llvm::Value * > values, ArrayRef< llvm::OperandBundleUse > opBundles, bool requiresOpBundles, ArrayRef< unsigned > immArgPositions, ArrayRef< StringLiteral > immArgAttrNames, SmallVectorImpl< Value > &valuesOut, SmallVectorImpl< NamedAttribute > &attrsOut)
Converts the LLVM values for an intrinsic to mixed MLIR values and attributes for LLVM_IntrOpBase.
Location translateLoc(llvm::DILocation *loc)
Translates the debug location.
LogicalResult convertComdats()
Converts all comdat selectors of the LLVM module to MLIR comdat operations.
LogicalResult convertAliases()
Converts all aliases of the LLVM module to MLIR variables.
LogicalResult convertFunctions()
Converts all functions of the LLVM module to MLIR functions.
FailureOr< SmallVector< Value > > convertValues(ArrayRef< llvm::Value * > values)
Converts a range of LLVM values to a range of MLIR values using the convertValue method,...
LogicalResult convertLinkerOptionsMetadata()
Converts !llvm.linker.options metadata to the llvm.linker.options LLVM dialect operation.
Block * lookupBlock(llvm::BasicBlock *block) const
Returns the MLIR block mapped to the given LLVM block.
void mapBlock(llvm::BasicBlock *llvm, Block *mlir)
Stores the mapping between an LLVM block and its MLIR counterpart.
DILocalVariableAttr matchLocalVariableAttr(llvm::PointerUnion< llvm::Value *, llvm::DILocalVariable * > valOrVariable)
Converts valOrVariable to a local variable attribute.
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.
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 convertModuleLevelAsm()
Converts the module level asm of the LLVM module to an MLIR module level asm specification.
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.
ModuleImport(ModuleOp mlirModule, std::unique_ptr< llvm::Module > llvmModule, bool emitExpensiveWarnings, bool importEmptyDICompositeTypes, bool preferUnregisteredIntrinsics, bool importStructsAsLiterals)
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.
Operation * lookupOperation(llvm::Instruction *inst)
Returns the MLIR operation mapped to the given LLVM instruction.
LogicalResult processFunction(llvm::Function *func)
Imports func into the current module.
LogicalResult convertDependentLibrariesMetadata()
Converts !llvm.dependent-libraries metadata to llvm.dependent_libraries LLVM ModuleOp attribute.
RoundingModeAttr matchRoundingModeAttr(llvm::Value *value)
Converts value to a rounding mode attribute.
void convertTargetTriple()
Converts target triple of the LLVM module to an MLIR target triple specification.
void addDebugRecord(llvm::DbgVariableRecord *dbgRecord)
Adds a debug record to the list of debug records that need to be imported after the function conversi...
void convertArgAndResultAttrs(llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp, ArrayRef< unsigned > immArgPositions={})
Converts the argument and result attributes attached to call and adds them to attrsOp.
LogicalResult convertModuleFlagsMetadata()
Converts !llvm.module.flags metadata.
void mapValue(llvm::Value *llvm, Value mlir)
Stores the mapping between an LLVM value and its MLIR counterpart.
FailureOr< SmallVector< AccessGroupAttr > > lookupAccessGroupAttrs(const llvm::MDNode *node) const
Returns the access group attributes that map to the access group nodes starting from the access group...
LogicalResult convertGlobals()
Converts all global variables of the LLVM module to MLIR global variables.
void setIntegerOverflowFlags(llvm::Instruction *inst, Operation *op) const
Sets the integer overflow flags (nsw/nuw) attribute for the imported operation op given the original ...
LogicalResult convertCommandlineMetadata()
Converts !llvm.commandline metadata to the llvm.commandline LLVM ModuleOp attribute.
FPExceptionBehaviorAttr matchFPExceptionBehaviorAttr(llvm::Value *value)
Converts value to a FP exception behavior attribute.
void setNonNegFlag(llvm::Instruction *inst, Operation *op) const
Sets the nneg flag attribute for the imported operation op given the original instruction inst.
FailureOr< DereferenceableAttr > translateDereferenceableAttr(const llvm::MDNode *node, unsigned kindID)
Returns the dereferenceable attribute that corresponds to the given LLVM dereferenceable or dereferen...
LogicalResult convertDataLayout()
Converts the data layout of the LLVM module to an MLIR data layout specification.
IntegerAttr matchIntegerAttr(llvm::Value *value)
Converts value to an integer attribute. Asserts if the matching fails.
Helper class that translates an LLVM data layout string 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.
ArrayRef< StringRef > getUnhandledTokens() const
Returns the data layout tokens that have not been handled during the data layout translation.
DataLayoutSpecInterface getDataLayoutSpec() const
Returns the MLIR data layout specification translated from the LLVM data layout.
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 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.
void setInsertionPointAfterValue(Value val)
Sets the insertion point to the node after the specified value.
This class provides the API for ops that are known to be terminators.
This provides public APIs that all operations should have.
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Location getLoc()
The source location the operation was defined or derived from.
This class acts as an owning reference to an op, and will automatically destroy the held op on destru...
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.
static SmallString< N > generateSymbolName(StringRef name, UniqueChecker uniqueChecker, unsigned &uniquingCounter)
Generate a unique symbol name.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Block * getParentBlock()
Return the Block in which this Value is defined.
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)
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.
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.
llvm::DenseSet< ValueT, ValueInfoT > DenseSet
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::SetVector< T, Vector, Set, N > SetVector
llvm::DenseMap< KeyT, ValueT, KeyInfoT, BucketT > DenseMap
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
OwningOpRef< ModuleOp > translateLLVMIRToModule(std::unique_ptr< llvm::Module > llvmModule, MLIRContext *context, bool emitExpensiveWarnings=true, bool dropDICompositeTypeElements=false, bool loadAllDialects=true, bool preferUnregisteredIntrinsics=false, bool importStructsAsLiterals=false)
Translates the LLVM module into an MLIR module living in the given context.