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())
849 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
852 for (
const auto [behavior, key, val] : llvmModuleFlags) {
854 if (
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
855 valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
856 }
else if (
auto *mdString = dyn_cast<llvm::MDString>(val)) {
857 valAttr = builder.getStringAttr(mdString->getString());
858 }
else if (
auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
860 key->getString(), mdTuple);
865 <<
"unsupported module flag value for key '" << key->getString()
866 <<
"' : " <<
diagMD(val, llvmModule.get());
870 moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
871 convertModFlagBehaviorFromLLVM(behavior),
872 builder.getStringAttr(key->getString()), valAttr));
875 if (!moduleFlags.empty())
876 LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),
877 builder.getArrayAttr(moduleFlags));
883 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
884 if (named.getName() !=
"llvm.linker.options")
887 for (
const llvm::MDNode *node : named.operands()) {
889 options.reserve(node->getNumOperands());
890 for (
const llvm::MDOperand &option : node->operands())
891 options.push_back(cast<llvm::MDString>(option)->getString());
892 LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),
893 builder.getStrArrayAttr(
options));
900 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
901 if (named.getName() !=
"llvm.dependent-libraries")
904 for (
const llvm::MDNode *node : named.operands()) {
905 if (node->getNumOperands() == 1)
906 if (
auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
907 libraries.push_back(mdString->getString());
909 if (!libraries.empty())
910 mlirModule->setAttr(LLVM::LLVMDialect::getDependentLibrariesAttrName(),
911 builder.getStrArrayAttr(libraries));
917 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
920 if (named.getName() != LLVMDialect::getIdentAttrName())
923 if (named.getNumOperands() == 1)
924 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
925 if (md->getNumOperands() == 1)
926 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
927 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
928 builder.getStringAttr(mdStr->getString()));
934 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
937 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
940 if (nmd.getNumOperands() == 1)
941 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
942 if (md->getNumOperands() == 1)
943 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
944 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
945 builder.getStringAttr(mdStr->getString()));
952 builder.setInsertionPointToEnd(mlirModule.getBody());
953 for (
const llvm::Function &
func : llvmModule->functions()) {
954 for (
const llvm::Instruction &inst : llvm::instructions(
func)) {
956 if (llvm::MDNode *node =
957 inst.getMetadata(llvm::LLVMContext::MD_access_group))
958 if (failed(processAccessGroupMetadata(node)))
962 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
963 if (!aliasAnalysisNodes)
965 if (aliasAnalysisNodes.TBAA)
966 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
968 if (aliasAnalysisNodes.Scope)
969 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
971 if (aliasAnalysisNodes.NoAlias)
972 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
989void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
990 if (comdatMapping.contains(comdat))
993 ComdatOp comdatOp = getGlobalComdatOp();
996 auto selectorOp = ComdatSelectorOp::create(
997 builder, mlirModule.getLoc(), comdat->getName(),
998 convertComdatFromLLVM(comdat->getSelectionKind()));
1002 comdatMapping.try_emplace(comdat, symbolRef);
1006 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1007 if (globalVar.hasComdat())
1008 processComdat(globalVar.getComdat());
1009 for (llvm::Function &
func : llvmModule->functions())
1010 if (
func.hasComdat())
1011 processComdat(
func.getComdat());
1016 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1019 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1020 return emitError(UnknownLoc::get(context))
1021 <<
"unhandled global variable: " <<
diag(globalVar);
1025 if (failed(convertGlobal(&globalVar))) {
1026 return emitError(UnknownLoc::get(context))
1027 <<
"unhandled global variable: " <<
diag(globalVar);
1034 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1035 if (failed(convertAlias(&alias))) {
1036 return emitError(UnknownLoc::get(context))
1037 <<
"unhandled global alias: " <<
diag(alias);
1044 for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1045 if (failed(convertIFunc(&ifunc))) {
1046 return emitError(UnknownLoc::get(context))
1047 <<
"unhandled global ifunc: " <<
diag(ifunc);
1054 Location loc = mlirModule.getLoc();
1056 context, llvmModule->getDataLayout().getStringRepresentation());
1058 return emitError(loc,
"cannot translate data layout: ")
1062 emitWarning(loc,
"unhandled data layout token: ") << token;
1064 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
1070 mlirModule->setAttr(
1071 LLVM::LLVMDialect::getTargetTripleAttrName(),
1072 builder.getStringAttr(llvmModule->getTargetTriple().str()));
1076 llvm::StringRef asmStr = llvmModule->getModuleInlineAsm();
1079 for (llvm::StringRef line : llvm::split(asmStr,
'\n'))
1081 asmArrayAttr.push_back(builder.getStringAttr(line));
1083 mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1084 builder.getArrayAttr(asmArrayAttr));
1088 for (llvm::Function &
func : llvmModule->functions())
1094void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1097 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1098 for (
auto &[kind, node] : allMetadata) {
1102 if (emitExpensiveWarnings) {
1103 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1105 <<
diagMD(node, llvmModule.get()) <<
" on "
1114 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1116 IntegerOverflowFlags value = {};
1117 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1119 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1121 iface.setOverflowFlags(value);
1125 auto iface = cast<ExactFlagInterface>(op);
1127 iface.setIsExact(inst->isExact());
1132 auto iface = cast<DisjointFlagInterface>(op);
1133 auto *instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1135 iface.setIsDisjoint(instDisjoint->isDisjoint());
1139 auto iface = cast<NonNegFlagInterface>(op);
1141 iface.setNonNeg(inst->hasNonNeg());
1146 auto iface = cast<FastmathFlagsInterface>(op);
1152 if (!isa<llvm::FPMathOperator>(inst))
1154 llvm::FastMathFlags flags = inst->getFastMathFlags();
1157 FastmathFlags value = {};
1158 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1159 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1160 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1161 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1162 value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
1163 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1164 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1165 FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
1166 iface->setAttr(iface.getFastmathAttrName(), attr);
1178 if (numElements.isScalable()) {
1180 <<
"scalable vectors not supported";
1185 Type elementType = cast<VectorType>(type).getElementType();
1189 SmallVector<int64_t> shape(arrayShape);
1190 shape.push_back(numElements.getKnownMinValue());
1191 return VectorType::get(shape, elementType);
1194Type ModuleImport::getBuiltinTypeForAttr(Type type) {
1208 SmallVector<int64_t> arrayShape;
1209 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1210 arrayShape.push_back(arrayType.getNumElements());
1211 type = arrayType.getElementType();
1214 return RankedTensorType::get(arrayShape, type);
1221 llvm::Constant *constScalar) {
1225 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1227 IntegerType::get(context, constInt->getBitWidth()),
1228 constInt->getValue());
1232 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1233 llvm::Type *type = constFloat->getType();
1234 FloatType floatType =
1236 ? BFloat16Type::get(context)
1240 <<
"unexpected floating-point type";
1243 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1250static SmallVector<Attribute>
1252 llvm::ConstantDataSequential *constSequence) {
1254 elementAttrs.reserve(constSequence->getNumElements());
1255 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1256 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1259 return elementAttrs;
1262Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1268 auto getConstantShape = [&](llvm::Type *type) {
1269 return llvm::dyn_cast_if_present<ShapedType>(
1275 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1276 if (constArray->isString())
1277 return builder.getStringAttr(constArray->getAsString());
1278 auto shape = getConstantShape(constArray->getType());
1282 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1283 if (constVector && constVector->isSplat()) {
1286 builder, constVector->getElementAsConstant(0));
1290 SmallVector<Attribute> elementAttrs =
1297 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1298 auto shape = getConstantShape(constAggregate->getType());
1302 SmallVector<Attribute> elementAttrs;
1303 SmallVector<llvm::Constant *> workList = {constAggregate};
1304 while (!workList.empty()) {
1305 llvm::Constant *current = workList.pop_back_val();
1308 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1310 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1311 workList.push_back(constAggregate->getAggregateElement(idx));
1316 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1317 SmallVector<Attribute> attrs =
1319 elementAttrs.append(attrs.begin(), attrs.end());
1325 elementAttrs.push_back(scalarAttr);
1336 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1337 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1338 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1342 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1343 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1350ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1351 assert(globalVar->getName().empty() &&
1352 "expected to work with a nameless global");
1353 auto [it,
success] = namelessGlobals.try_emplace(globalVar);
1360 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1363 it->getSecond() = symbolRef;
1367OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1368 OpBuilder::InsertionGuard guard(builder);
1369 if (globalInsertionOp)
1370 builder.setInsertionPointAfter(globalInsertionOp);
1372 builder.setInsertionPointToStart(mlirModule.getBody());
1376LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1378 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1381 AliasOp aliasOp = AliasOp::create(builder, mlirModule.getLoc(), type,
1382 convertLinkageFromLLVM(alias->getLinkage()),
1384 alias->isDSOLocal(),
1385 alias->isThreadLocal(),
1386 ArrayRef<NamedAttribute>());
1387 globalInsertionOp = aliasOp;
1390 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1391 setConstantInsertionPointToStart(block);
1392 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1395 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1397 if (alias->hasAtLeastLocalUnnamedAddr())
1398 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1399 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1404LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1405 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1408 llvm::Constant *resolver = ifunc->getResolver();
1409 Type resolverType =
convertType(resolver->getType());
1410 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1411 resolver->getName(), resolverType,
1412 convertLinkageFromLLVM(ifunc->getLinkage()),
1413 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1414 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1415 convertVisibilityFromLLVM(ifunc->getVisibility()));
1425 ArrayRef<StringLiteral> attributePrefixesToSkip = {}) {
1426 SmallVector<Attribute> mlirAttributes;
1427 for (llvm::Attribute attr : attributes) {
1429 if (attr.isStringAttribute())
1430 attrName = attr.getKindAsString();
1432 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1433 if (llvm::is_contained(attributesToSkip, attrName))
1436 auto attrNameStartsWith = [attrName](StringLiteral sl) {
1437 return attrName.starts_with(sl);
1439 if (attributePrefixesToSkip.end() !=
1440 llvm::find_if(attributePrefixesToSkip, attrNameStartsWith))
1443 auto keyAttr = StringAttr::get(context, attrName);
1444 if (attr.isStringAttribute()) {
1445 StringRef val = attr.getValueAsString();
1448 mlirAttributes.push_back(keyAttr);
1452 mlirAttributes.push_back(
1453 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1456 if (attr.isIntAttribute()) {
1459 auto val = std::to_string(attr.getValueAsInt());
1460 mlirAttributes.push_back(
1461 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1464 if (attr.isEnumAttribute()) {
1466 mlirAttributes.push_back(keyAttr);
1472 <<
"' attribute is invalid on current operation, skipping it";
1474 return ArrayAttr::get(context, mlirAttributes);
1480 GlobalOp globalOp) {
1482 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1483 if (!targetSpecificAttrs.empty())
1484 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1487LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1489 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1491 Attribute valueAttr;
1492 if (globalVar->hasInitializer())
1493 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1494 Type type =
convertType(globalVar->getValueType());
1496 uint64_t alignment = 0;
1497 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1498 if (maybeAlign.has_value()) {
1499 llvm::Align align = *maybeAlign;
1500 alignment = align.value();
1505 SmallVector<Attribute> globalExpressionAttrs;
1506 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1507 globalVar->getDebugInfo(globalExpressions);
1509 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1510 DIGlobalVariableExpressionAttr globalExpressionAttr =
1511 debugImporter->translateGlobalVariableExpression(expr);
1512 globalExpressionAttrs.push_back(globalExpressionAttr);
1517 StringRef globalName = globalVar->getName();
1518 if (globalName.empty())
1519 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1521 GlobalOp globalOp = GlobalOp::create(
1522 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1523 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1524 valueAttr, alignment, globalVar->getAddressSpace(),
1525 globalVar->isDSOLocal(),
1526 globalVar->isThreadLocal(), SymbolRefAttr(),
1527 ArrayRef<NamedAttribute>(), globalExpressionAttrs);
1528 globalInsertionOp = globalOp;
1530 if (globalVar->hasInitializer() && !valueAttr) {
1532 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1533 setConstantInsertionPointToStart(block);
1534 FailureOr<Value> initializer =
1535 convertConstantExpr(globalVar->getInitializer());
1538 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1540 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1541 globalOp.setUnnamedAddr(
1542 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1544 if (globalVar->hasSection())
1545 globalOp.setSection(globalVar->getSection());
1546 globalOp.setVisibility_(
1547 convertVisibilityFromLLVM(globalVar->getVisibility()));
1549 if (globalVar->hasComdat())
1550 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1558ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1559 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1561 llvm::Constant *initializer = globalVar->getInitializer();
1563 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1564 isa<llvm::ConstantAggregateZero>(initializer);
1571 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1572 if (caz->getElementCount().getFixedValue() != 0)
1576 SmallVector<Attribute> funcs;
1577 SmallVector<int32_t> priorities;
1578 SmallVector<Attribute> dataList;
1579 for (llvm::Value *operand : initializer->operands()) {
1580 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1581 if (!aggregate || aggregate->getNumOperands() != 3)
1584 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1585 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1586 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1587 if (!priority || !func || !data)
1590 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1594 else if (data->isNullValue())
1595 dataAttr = ZeroAttr::get(context);
1600 priorities.push_back(priority->getValue().getZExtValue());
1601 dataList.push_back(dataAttr);
1605 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1608 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1609 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1610 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1613 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1614 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1615 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1620ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1622 if (valueMapping.contains(constant))
1631 workList.insert(constant);
1632 while (!workList.empty()) {
1633 llvm::Constant *current = workList.back();
1636 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1637 orderedSet.insert(current);
1638 workList.pop_back();
1644 auto [adjacencyIt,
inserted] = adjacencyLists.try_emplace(current);
1648 for (llvm::Value *operand : current->operands())
1649 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1650 adjacencyIt->getSecond().push_back(constDependency);
1653 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1654 unsigned numElements = constAgg->getElementCount().getFixedValue();
1655 for (
unsigned i = 0, e = numElements; i != e; ++i)
1656 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1662 if (adjacencyIt->getSecond().empty()) {
1663 orderedSet.insert(current);
1664 workList.pop_back();
1672 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1673 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1674 orderedSet.contains(dependency))
1676 workList.insert(dependency);
1682FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1683 Location loc = UnknownLoc::get(context);
1686 if (Attribute attr = getConstantAsAttr(constant)) {
1688 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1689 return AddressOfOp::create(builder, loc, type, symbolRef.getValue())
1692 return ConstantOp::create(builder, loc, type, attr).getResult();
1696 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1698 return ZeroOp::create(builder, loc, type).getResult();
1702 if (isa<llvm::ConstantTokenNone>(constant)) {
1703 return NoneTokenOp::create(builder, loc).getResult();
1707 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1709 return PoisonOp::create(builder, loc, type).getResult();
1713 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1715 return UndefOp::create(builder, loc, type).getResult();
1719 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1720 Type type =
convertType(dsoLocalEquivalent->getType());
1721 return DSOLocalEquivalentOp::create(
1724 builder.getContext(),
1725 dsoLocalEquivalent->getGlobalValue()->getName()))
1730 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1732 StringRef globalName = globalObj->getName();
1733 FlatSymbolRefAttr symbolRef;
1735 if (globalName.empty())
1737 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1740 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1744 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1745 Type type =
convertType(globalAliasObj->getType());
1746 StringRef aliaseeName = globalAliasObj->getName();
1748 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1752 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1758 llvm::Instruction *inst = constExpr->getAsInstruction();
1759 llvm::scope_exit guard([&]() {
1760 assert(!noResultOpMapping.contains(inst) &&
1761 "expected constant expression to return a result");
1762 valueMapping.erase(inst);
1763 inst->deleteValue();
1767 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1768 return valueMapping.contains(value);
1770 if (
failed(processInstruction(inst)))
1776 if (
auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1777 Type type =
convertType(aggregateZero->getType());
1778 return ZeroOp::create(builder, loc, type).getResult();
1782 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1784 SmallVector<Value> elementValues;
1786 elementValues.reserve(constAgg->getNumOperands());
1787 for (llvm::Value *operand : constAgg->operands())
1790 assert(llvm::count(elementValues,
nullptr) == 0 &&
1791 "expected all elements have been converted before");
1795 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1797 "unrecognized aggregate type");
1798 Value root = UndefOp::create(builder, loc, rootType);
1799 for (
const auto &it : llvm::enumerate(elementValues)) {
1800 if (isArrayOrStruct) {
1802 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1804 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1806 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1807 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1814 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1815 LLVMTargetExtType targetExtType =
1816 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1817 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1818 "target extension type does not support zero-initialization");
1821 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1824 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1828 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1829 return BlockAddressOp::create(
1831 BlockAddressAttr::get(context, fnSym, blockTag))
1835 StringRef error =
"";
1837 if (isa<llvm::ConstantPtrAuth>(constant))
1838 error =
" since ptrauth(...) is unsupported";
1840 if (isa<llvm::NoCFIValue>(constant))
1841 error =
" since no_cfi is unsupported";
1843 if (isa<llvm::GlobalValue>(constant))
1844 error =
" since global value is unsupported";
1846 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1849FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1853 assert(!valueMapping.contains(constant) &&
1854 "expected constant has not been converted before");
1855 assert(constantInsertionBlock &&
1856 "expected the constant insertion block to be non-null");
1859 OpBuilder::InsertionGuard guard(builder);
1860 if (!constantInsertionOp)
1861 builder.setInsertionPointToStart(constantInsertionBlock);
1863 builder.setInsertionPointAfter(constantInsertionOp);
1867 getConstantsToConvert(constant);
1868 for (llvm::Constant *constantToConvert : constantsToConvert) {
1869 FailureOr<Value> converted = convertConstant(constantToConvert);
1872 mapValue(constantToConvert, *converted);
1877 constantInsertionOp =
result.getDefiningOp();
1882 assert(!isa<llvm::MetadataAsValue>(value) &&
1883 "expected value to not be metadata");
1886 auto it = valueMapping.find(value);
1887 if (it != valueMapping.end())
1888 return it->getSecond();
1891 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1892 return convertConstantExpr(constant);
1894 Location loc = UnknownLoc::get(context);
1895 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1897 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1903 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1906 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1909 value = node->getValue();
1912 auto it = valueMapping.find(value);
1913 if (it != valueMapping.end())
1914 return it->getSecond();
1917 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1918 return convertConstantExpr(constant);
1922FailureOr<SmallVector<Value>>
1925 remapped.reserve(values.size());
1926 for (llvm::Value *value : values) {
1928 if (failed(converted))
1930 remapped.push_back(*converted);
1940 assert(immArgPositions.size() == immArgAttrNames.size() &&
1941 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1945 for (
auto [immArgPos, immArgName] :
1946 llvm::zip(immArgPositions, immArgAttrNames)) {
1947 auto &value = operands[immArgPos];
1948 auto *constant = llvm::cast<llvm::Constant>(value);
1950 assert(attr && attr.getType().isIntOrFloat() &&
1951 "expected immarg to be float or integer constant");
1952 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1953 attrsOut.push_back({nameAttr, attr});
1958 for (llvm::Value *value : operands) {
1962 if (failed(mlirValue))
1964 valuesOut.push_back(*mlirValue);
1969 if (requiresOpBundles) {
1970 opBundleSizes.reserve(opBundles.size());
1971 opBundleTagAttrs.reserve(opBundles.size());
1973 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1974 opBundleSizes.push_back(bundle.Inputs.size());
1975 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
1977 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1978 auto operandMlirValue =
convertValue(opBundleOperand.get());
1979 if (failed(operandMlirValue))
1981 valuesOut.push_back(*operandMlirValue);
1986 auto opBundleSizesAttrNameAttr =
1987 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
1988 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1990 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
1991 auto opBundleTagsAttrNameAttr =
1992 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
1993 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
2000 IntegerAttr integerAttr;
2002 bool success = succeeded(converted) &&
2004 assert(
success &&
"expected a constant integer value");
2010 FloatAttr floatAttr;
2014 assert(
success &&
"expected a constant float value");
2021 llvm::DILocalVariable *node =
nullptr;
2022 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2023 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2024 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2026 node = cast<llvm::DILocalVariable *>(valOrVariable);
2028 return debugImporter->translate(node);
2032 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2033 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2034 return debugImporter->translate(node);
2037FPExceptionBehaviorAttr
2039 auto *metadata = cast<llvm::MetadataAsValue>(value);
2040 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2041 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2042 llvm::convertStrToExceptionBehavior(mdstr->getString());
2043 assert(optLLVM &&
"Expecting FP exception behavior");
2044 return builder.getAttr<FPExceptionBehaviorAttr>(
2045 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2049 auto *metadata = cast<llvm::MetadataAsValue>(value);
2050 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2051 std::optional<llvm::RoundingMode> optLLVM =
2052 llvm::convertStrToRoundingMode(mdstr->getString());
2053 assert(optLLVM &&
"Expecting rounding mode");
2054 return builder.getAttr<RoundingModeAttr>(
2055 convertRoundingModeFromLLVM(*optLLVM));
2058FailureOr<SmallVector<AliasScopeAttr>>
2060 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2061 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2066 return debugImporter->translateLoc(loc);
2070ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2071 llvm::BasicBlock *
target,
2073 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2074 auto *phiInst = cast<llvm::PHINode>(&*inst);
2075 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2077 if (failed(converted))
2079 blockArguments.push_back(*converted);
2084FailureOr<SmallVector<Value>>
2085ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2086 bool allowInlineAsm) {
2087 bool isInlineAsm = callInst->isInlineAsm();
2088 if (isInlineAsm && !allowInlineAsm)
2098 llvm::Value *calleeOperand = callInst->getCalledOperand();
2099 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2103 operands.push_back(*called);
2106 SmallVector<llvm::Value *> args(callInst->args());
2107 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2111 llvm::append_range(operands, *arguments);
2119 LLVMFunctionType calleeType) {
2120 if (callType.getReturnType() != calleeType.getReturnType())
2123 if (calleeType.isVarArg()) {
2126 if (callType.getNumParams() < calleeType.getNumParams())
2131 if (callType.getNumParams() != calleeType.getNumParams())
2136 for (
auto [operandType, argumentType] :
2137 llvm::zip(callType.getParams(), calleeType.getParams()))
2138 if (operandType != argumentType)
2144FailureOr<LLVMFunctionType>
2145ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2146 bool &isIncompatibleCall) {
2147 isIncompatibleCall =
false;
2148 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2149 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2155 llvm::Value *calledOperand = callInst->getCalledOperand();
2156 FailureOr<LLVMFunctionType> callType =
2157 castOrFailure(
convertType(callInst->getFunctionType()));
2160 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2162 llvm::FunctionType *origCalleeType =
nullptr;
2164 origCalleeType = callee->getFunctionType();
2165 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2166 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2170 if (!origCalleeType)
2173 FailureOr<LLVMFunctionType> calleeType =
2181 isIncompatibleCall =
true;
2183 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2184 <<
" and " << *calleeType;
2191FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2192 llvm::Value *calledOperand = callInst->getCalledOperand();
2193 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2194 return SymbolRefAttr::get(context, calledOperand->getName());
2198LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2199 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2203 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2207ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2208 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2209 unsigned argIdx = 0;
2210 SmallVector<mlir::Attribute> opAttrs;
2211 bool hasIndirect =
false;
2213 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2215 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2220 if (ci.isIndirect) {
2221 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2222 SmallVector<mlir::NamedAttribute> attrs;
2223 attrs.push_back(builder.getNamedAttr(
2224 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2226 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2230 opAttrs.push_back(builder.getDictionaryAttr({}));
2236 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2240LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2243 if (inst->getOpcode() == llvm::Instruction::Br) {
2244 auto *brInst = cast<llvm::BranchInst>(inst);
2246 SmallVector<Block *> succBlocks;
2247 SmallVector<SmallVector<Value>> succBlockArgs;
2248 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2249 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2250 SmallVector<Value> blockArgs;
2251 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2254 succBlockArgs.push_back(blockArgs);
2257 if (!brInst->isConditional()) {
2258 auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),
2259 succBlocks.front());
2263 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2266 auto condBrOp = LLVM::CondBrOp::create(
2267 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2268 succBlocks.back(), succBlockArgs.back());
2272 if (inst->getOpcode() == llvm::Instruction::Switch) {
2273 auto *swInst = cast<llvm::SwitchInst>(inst);
2275 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2278 SmallVector<Value> defaultBlockArgs;
2280 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2281 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2285 unsigned numCases = swInst->getNumCases();
2286 SmallVector<SmallVector<Value>> caseOperands(numCases);
2287 SmallVector<ValueRange> caseOperandRefs(numCases);
2288 SmallVector<APInt> caseValues(numCases);
2289 SmallVector<Block *> caseBlocks(numCases);
2290 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2291 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2292 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2293 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2295 caseOperandRefs[it.index()] = caseOperands[it.index()];
2296 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2300 auto switchOp = SwitchOp::create(builder, loc, *condition,
2302 caseValues, caseBlocks, caseOperandRefs);
2306 if (inst->getOpcode() == llvm::Instruction::PHI) {
2308 mapValue(inst, builder.getInsertionBlock()->addArgument(
2312 if (inst->getOpcode() == llvm::Instruction::Call) {
2313 auto *callInst = cast<llvm::CallInst>(inst);
2314 llvm::Value *calledOperand = callInst->getCalledOperand();
2316 FailureOr<SmallVector<Value>> operands =
2317 convertCallOperands(callInst,
true);
2321 auto callOp = [&]() -> FailureOr<Operation *> {
2322 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2326 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2327 return InlineAsmOp::create(
2328 builder, loc, resultTy, *operands,
2329 builder.getStringAttr(asmI->getAsmString()),
2330 builder.getStringAttr(asmI->getConstraintString()),
2331 asmI->hasSideEffects(), asmI->isAlignStack(),
2332 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2333 AsmDialectAttr::get(
2334 mlirModule.getContext(),
2335 convertAsmDialectFromLLVM(asmI->getDialect())),
2339 bool isIncompatibleCall;
2340 FailureOr<LLVMFunctionType> funcTy =
2341 convertFunctionType(callInst, isIncompatibleCall);
2345 FlatSymbolRefAttr callee =
nullptr;
2346 if (isIncompatibleCall) {
2350 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2351 Value indirectCallVal = LLVM::AddressOfOp::create(
2352 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2353 operands->insert(operands->begin(), indirectCallVal);
2356 callee = convertCalleeName(callInst);
2358 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2360 if (
failed(convertCallAttributes(callInst, callOp)))
2365 if (!isIncompatibleCall)
2367 return callOp.getOperation();
2373 if (!callInst->getType()->isVoidTy())
2374 mapValue(inst, (*callOp)->getResult(0));
2379 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2380 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2382 SmallVector<Value> operands;
2383 operands.reserve(lpInst->getNumClauses());
2384 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2385 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2388 operands.push_back(*operand);
2393 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2397 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2398 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2400 if (invokeInst->isInlineAsm())
2401 return emitError(loc) <<
"invoke of inline assembly is not supported";
2403 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2409 bool invokeResultUsedInPhi = llvm::any_of(
2410 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2411 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2416 Block *directNormalDest = normalDest;
2417 if (invokeResultUsedInPhi) {
2422 OpBuilder::InsertionGuard g(builder);
2423 directNormalDest = builder.createBlock(normalDest);
2426 SmallVector<Value> unwindArgs;
2427 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2431 bool isIncompatibleInvoke;
2432 FailureOr<LLVMFunctionType> funcTy =
2433 convertFunctionType(invokeInst, isIncompatibleInvoke);
2437 FlatSymbolRefAttr calleeName =
nullptr;
2438 if (isIncompatibleInvoke) {
2442 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2443 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2444 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2445 operands->insert(operands->begin(), indirectInvokeVal);
2448 calleeName = convertCalleeName(invokeInst);
2453 auto invokeOp = InvokeOp::create(
2454 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2457 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2462 if (!isIncompatibleInvoke)
2465 if (!invokeInst->getType()->isVoidTy())
2466 mapValue(inst, invokeOp.getResults().front());
2470 SmallVector<Value> normalArgs;
2471 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2475 if (invokeResultUsedInPhi) {
2479 OpBuilder::InsertionGuard g(builder);
2480 builder.setInsertionPointToStart(directNormalDest);
2481 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2485 assert(llvm::none_of(
2487 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2488 "An llvm.invoke operation cannot pass its result as a block "
2490 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2495 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2496 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2497 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2498 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2507 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2515 auto gepOp = GEPOp::create(
2516 builder, loc, type, sourceElementType, *basePtr,
indices,
2517 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2522 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2523 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2525 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2529 SmallVector<Block *> succBlocks;
2530 SmallVector<SmallVector<Value>> succBlockArgs;
2531 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2532 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2533 SmallVector<Value> blockArgs;
2534 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2537 succBlockArgs.push_back(blockArgs);
2539 SmallVector<ValueRange> succBlockArgsRange =
2540 llvm::to_vector_of<ValueRange>(succBlockArgs);
2542 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2543 succBlockArgsRange, succBlocks);
2553 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2556LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2563 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2564 return convertIntrinsic(intrinsic);
2569 if (inst->DebugMarker) {
2570 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2572 if (
auto *dbgVariableRecord =
2573 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2578 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2579 if (!emitExpensiveWarnings)
2582 llvm::raw_string_ostream optionsStream(
options);
2583 dbgRecord.print(optionsStream);
2584 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2588 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2589 DILabelAttr labelAttr =
2590 debugImporter->translate(dbgLabelRecord->getLabel());
2592 return emitUnsupportedWarning();
2593 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2597 return emitUnsupportedWarning();
2602 return convertInstruction(inst);
2605FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2606 if (!f->hasPersonalityFn())
2609 llvm::Constant *pf = f->getPersonalityFn();
2613 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2617 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2618 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2619 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2620 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2621 return SymbolRefAttr::get(builder.getContext(), func->getName());
2624 return FlatSymbolRefAttr();
2628 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2630 auto othermem = convertModRefInfoFromLLVM(
2631 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2632 auto argMem = convertModRefInfoFromLLVM(
2633 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2634 auto inaccessibleMem = convertModRefInfoFromLLVM(
2635 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2636 auto errnoMem = convertModRefInfoFromLLVM(
2637 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2638 auto targetMem0 = convertModRefInfoFromLLVM(
2639 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2640 auto targetMem1 = convertModRefInfoFromLLVM(
2641 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2643 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2644 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2646 if (memAttr.isReadWrite())
2648 funcOp.setMemoryEffectsAttr(memAttr);
2652 llvm::DenormalFPEnv denormalFpEnv =
func->getDenormalFPEnv();
2654 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2657 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2658 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2660 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2661 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2662 convertDenormalModeKindFromLLVM(defaultMode.Input),
2663 convertDenormalModeKindFromLLVM(floatMode.Output),
2664 convertDenormalModeKindFromLLVM(floatMode.Input));
2665 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2671 StringLiteral(
"aarch64_in_za"),
2672 StringLiteral(
"aarch64_inout_za"),
2673 StringLiteral(
"aarch64_new_za"),
2674 StringLiteral(
"aarch64_out_za"),
2675 StringLiteral(
"aarch64_preserves_za"),
2676 StringLiteral(
"aarch64_pstate_sm_body"),
2677 StringLiteral(
"aarch64_pstate_sm_compatible"),
2678 StringLiteral(
"aarch64_pstate_sm_enabled"),
2679 StringLiteral(
"allocsize"),
2680 StringLiteral(
"alwaysinline"),
2681 StringLiteral(
"cold"),
2682 StringLiteral(
"convergent"),
2683 StringLiteral(
"fp-contract"),
2684 StringLiteral(
"frame-pointer"),
2685 StringLiteral(
"hot"),
2686 StringLiteral(
"inlinehint"),
2687 StringLiteral(
"instrument-function-entry"),
2688 StringLiteral(
"instrument-function-exit"),
2689 StringLiteral(
"modular-format"),
2690 StringLiteral(
"memory"),
2691 StringLiteral(
"no_caller_saved_registers"),
2692 StringLiteral(
"no-infs-fp-math"),
2693 StringLiteral(
"no-nans-fp-math"),
2694 StringLiteral(
"no-signed-zeros-fp-math"),
2695 StringLiteral(
"no-builtins"),
2696 StringLiteral(
"nocallback"),
2697 StringLiteral(
"noduplicate"),
2698 StringLiteral(
"noinline"),
2699 StringLiteral(
"noreturn"),
2700 StringLiteral(
"nounwind"),
2701 StringLiteral(
"optnone"),
2702 StringLiteral(
"returns_twice"),
2703 StringLiteral(
"target-features"),
2704 StringLiteral(
"tune-cpu"),
2705 StringLiteral(
"uwtable"),
2706 StringLiteral(
"vscale_range"),
2707 StringLiteral(
"willreturn"),
2708 StringLiteral(
"denormal_fpenv"),
2714 StringLiteral(
"no-builtin-"),
2717template <
typename OpTy>
2719 const llvm::AttributeSet &attrs,
2722 if (attrs.hasAttribute(
"no-builtins")) {
2723 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2728 for (llvm::Attribute attr : attrs) {
2731 if (attr.hasKindAsEnum())
2734 StringRef val = attr.getKindAsString();
2736 if (val.starts_with(
"no-builtin-"))
2738 StringAttr::get(ctx, val.drop_front(
sizeof(
"no-builtin-") - 1)));
2741 if (!nbAttrs.empty())
2742 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2745template <
typename OpTy>
2747 const llvm::AttributeSet &attrs, OpTy
target) {
2748 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2749 if (!attr.isValid())
2752 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2756 static_cast<int32_t
>(*numElems)}));
2767 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2768 llvm::AttributeList::AttrIndex::FunctionIndex);
2770 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2772 if (!passthroughAttr.empty())
2773 funcOp.setPassthroughAttr(passthroughAttr);
2777 LLVMFuncOp funcOp) {
2782 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
2783 funcOp.setNoInline(
true);
2784 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2785 funcOp.setAlwaysInline(
true);
2786 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
2787 funcOp.setInlineHint(
true);
2788 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2789 funcOp.setOptimizeNone(
true);
2790 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
2791 funcOp.setConvergent(
true);
2792 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
2793 funcOp.setNoUnwind(
true);
2794 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
2795 funcOp.setWillReturn(
true);
2796 if (
func->hasFnAttribute(llvm::Attribute::NoReturn))
2797 funcOp.setNoreturn(
true);
2798 if (
func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
2799 funcOp.setReturnsTwice(
true);
2800 if (
func->hasFnAttribute(llvm::Attribute::Cold))
2801 funcOp.setCold(
true);
2802 if (
func->hasFnAttribute(llvm::Attribute::Hot))
2803 funcOp.setHot(
true);
2804 if (
func->hasFnAttribute(llvm::Attribute::NoDuplicate))
2805 funcOp.setNoduplicate(
true);
2806 if (
func->hasFnAttribute(
"no_caller_saved_registers"))
2807 funcOp.setNoCallerSavedRegisters(
true);
2808 if (
func->hasFnAttribute(llvm::Attribute::NoCallback))
2809 funcOp.setNocallback(
true);
2810 if (llvm::Attribute attr =
func->getFnAttribute(
"modular-format");
2811 attr.isStringAttribute())
2812 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
2814 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2815 funcOp.setArmStreaming(
true);
2816 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2817 funcOp.setArmLocallyStreaming(
true);
2818 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2819 funcOp.setArmStreamingCompatible(
true);
2821 if (
func->hasFnAttribute(
"aarch64_new_za"))
2822 funcOp.setArmNewZa(
true);
2823 else if (
func->hasFnAttribute(
"aarch64_in_za"))
2824 funcOp.setArmInZa(
true);
2825 else if (
func->hasFnAttribute(
"aarch64_out_za"))
2826 funcOp.setArmOutZa(
true);
2827 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
2828 funcOp.setArmInoutZa(
true);
2829 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
2830 funcOp.setArmPreservesZa(
true);
2835 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
2836 if (attr.isValid()) {
2838 auto intTy = IntegerType::get(context, 32);
2839 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2840 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2841 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2845 if (
func->hasFnAttribute(
"frame-pointer")) {
2846 StringRef stringRefFramePointerKind =
2847 func->getFnAttribute(
"frame-pointer").getValueAsString();
2848 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2849 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2850 stringRefFramePointerKind)
2854 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
2855 attr.isStringAttribute())
2856 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2858 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
2859 attr.isStringAttribute())
2860 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2862 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
2863 attr.isStringAttribute())
2864 funcOp.setTargetFeaturesAttr(
2865 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2867 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
2868 attr.isStringAttribute())
2869 funcOp.setReciprocalEstimatesAttr(
2870 StringAttr::get(context, attr.getValueAsString()));
2872 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
2873 attr.isStringAttribute())
2874 funcOp.setPreferVectorWidth(attr.getValueAsString());
2876 if (llvm::Attribute attr =
func->getFnAttribute(
"no-infs-fp-math");
2877 attr.isStringAttribute())
2878 funcOp.setNoInfsFpMath(attr.getValueAsBool());
2880 if (llvm::Attribute attr =
func->getFnAttribute(
"no-nans-fp-math");
2881 attr.isStringAttribute())
2882 funcOp.setNoNansFpMath(attr.getValueAsBool());
2884 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
2885 attr.isStringAttribute())
2886 funcOp.setInstrumentFunctionEntry(
2887 StringAttr::get(context, attr.getValueAsString()));
2889 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
2890 attr.isStringAttribute())
2891 funcOp.setInstrumentFunctionExit(
2892 StringAttr::get(context, attr.getValueAsString()));
2894 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
2895 attr.isStringAttribute())
2896 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2898 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
2899 attr.isStringAttribute())
2900 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2902 if (
func->hasUWTable()) {
2903 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
2904 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2905 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2910ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2913 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2915 if (!llvmAttr.isValid())
2920 if (llvmAttr.hasKindAsEnum() &&
2921 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2922 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2923 paramAttrs.push_back(
2929 if (llvmAttr.isTypeAttribute())
2930 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
2931 else if (llvmAttr.isIntAttribute())
2933 else if (llvmAttr.isEnumAttribute())
2935 else if (llvmAttr.isConstantRangeAttribute()) {
2936 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2937 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2940 llvm_unreachable(
"unexpected parameter attribute kind");
2942 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2945 return builder.getDictionaryAttr(paramAttrs);
2949 LLVMFuncOp funcOp) {
2950 auto llvmAttrs = func->getAttributes();
2951 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2952 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2953 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2957 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2958 if (!llvmResAttr.hasAttributes())
2960 funcOp.setResAttrsAttr(
2961 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2965 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2968 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2969 immArgPositions.end());
2971 llvm::AttributeList llvmAttrs = call->getAttributes();
2973 bool anyArgAttrs =
false;
2974 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
2976 if (immArgPositionsSet.contains(i))
2978 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
2979 if (llvmArgAttrsSet.back().hasAttributes())
2984 for (
auto &dict : dictAttrs)
2985 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
2986 return builder.getArrayAttr(attrs);
2990 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
2991 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
2992 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
2996 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2997 if (!llvmResAttr.hasAttributes())
2999 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3000 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3003template <
typename Op>
3005 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3009LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3014LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3020 llvm::AttributeList callAttrs = inst->getAttributes();
3022 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3023 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3024 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3025 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3026 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3028 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3029 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3030 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3032 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3033 op.setNoCallerSavedRegisters(
3034 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3035 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3037 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3038 attr.isStringAttribute())
3039 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3040 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3042 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3043 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3045 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3046 ModRefInfo othermem = convertModRefInfoFromLLVM(
3047 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3048 ModRefInfo argMem = convertModRefInfoFromLLVM(
3049 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3050 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3051 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3052 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3053 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3054 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3055 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3056 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3057 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3059 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3060 errnoMem, targetMem0, targetMem1);
3062 if (!memAttr.isReadWrite())
3063 op.setMemoryEffectsAttr(memAttr);
3076 if (
func->isIntrinsic() &&
3077 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3080 bool dsoLocal =
func->isDSOLocal();
3081 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3085 builder.setInsertionPointToEnd(mlirModule.getBody());
3087 Location loc = debugImporter->translateFuncLocation(
func);
3088 LLVMFuncOp funcOp = LLVMFuncOp::create(
3089 builder, loc,
func->getName(), functionType,
3090 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3095 funcOp.setPersonalityAttr(personality);
3096 else if (
func->hasPersonalityFn())
3097 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3100 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3102 if (
func->hasAtLeastLocalUnnamedAddr())
3103 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3105 if (
func->hasSection())
3106 funcOp.setSection(StringRef(
func->getSection()));
3108 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3110 if (
func->hasComdat())
3111 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3113 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3114 funcOp.setAlignment(maybeAlign->value());
3121 func->getAllMetadata(allMetadata);
3122 for (
auto &[kind, node] : allMetadata) {
3123 if (!iface.isConvertibleMetadata(kind))
3125 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *
this))) {
3127 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
3132 if (
func->isDeclaration())
3141 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3142 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3147 for (llvm::BasicBlock &basicBlock : *
func) {
3149 if (!reachable.contains(&basicBlock)) {
3150 if (basicBlock.hasAddressTaken())
3152 <<
"unreachable block '" << basicBlock.getName()
3153 <<
"' with address taken";
3156 Region &body = funcOp.getBody();
3157 Block *block = builder.createBlock(&body, body.
end());
3159 reachableBasicBlocks.push_back(&basicBlock);
3163 for (
const auto &it : llvm::enumerate(
func->args())) {
3164 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3165 functionType.getParamType(it.index()), funcOp.getLoc());
3174 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3175 for (llvm::BasicBlock *basicBlock : blocks)
3176 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3181 if (failed(processDebugIntrinsics()))
3186 if (failed(processDebugRecords()))
3195 if (!dbgIntr->isKillLocation())
3197 llvm::Value *value = dbgIntr->getArgOperand(0);
3198 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3201 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3213 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3216 if (dominatedBlocks.empty())
3220 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3223 Value insertPt = argOperand;
3224 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3230 if (!insertionBlock->
empty() &&
3231 isa<LandingpadOp>(insertionBlock->
front()))
3232 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3240std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3241ModuleImport::processDebugOpArgumentsAndInsertionPt(
3243 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3244 llvm::Value *address,
3245 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3246 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3252 FailureOr<Value> argOperand = convertArgOperandToValue();
3253 if (
failed(argOperand)) {
3254 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3262 return {localVarAttr, debugImporter->translateExpression(expression),
3267ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3268 DominanceInfo &domInfo) {
3270 auto emitUnsupportedWarning = [&]() {
3271 if (emitExpensiveWarnings)
3276 OpBuilder::InsertionGuard guard(builder);
3277 auto convertArgOperandToValue = [&]() {
3283 if (dbgIntr->hasArgList())
3284 return emitUnsupportedWarning();
3291 return emitUnsupportedWarning();
3293 auto [localVariableAttr, locationExprAttr, locVal] =
3294 processDebugOpArgumentsAndInsertionPt(
3295 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3296 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3298 if (!localVariableAttr)
3299 return emitUnsupportedWarning();
3304 Operation *op =
nullptr;
3305 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3306 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3308 else if (isa<llvm::DbgValueInst>(dbgIntr))
3309 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3312 return emitUnsupportedWarning();
3315 setNonDebugMetadataAttrs(dbgIntr, op);
3320ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3321 DominanceInfo &domInfo) {
3322 OpBuilder::InsertionGuard guard(builder);
3324 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3325 if (!emitExpensiveWarnings)
3328 llvm::raw_string_ostream optionsStream(
options);
3329 dbgRecord.print(optionsStream);
3330 emitWarning(loc) <<
"unhandled debug variable record "
3331 << optionsStream.str();
3337 if (dbgRecord.hasArgList())
3338 return emitUnsupportedWarning();
3343 if (!dbgRecord.getAddress())
3344 return emitUnsupportedWarning();
3346 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3347 llvm::Value *value = dbgRecord.getAddress();
3350 auto it = valueMapping.find(value);
3351 if (it != valueMapping.end())
3352 return it->getSecond();
3355 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3356 return convertConstantExpr(constant);
3360 auto [localVariableAttr, locationExprAttr, locVal] =
3361 processDebugOpArgumentsAndInsertionPt(
3362 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3363 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3365 if (!localVariableAttr)
3366 return emitUnsupportedWarning();
3371 if (dbgRecord.isDbgDeclare())
3372 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3374 else if (dbgRecord.isDbgValue())
3375 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3378 return emitUnsupportedWarning();
3383LogicalResult ModuleImport::processDebugIntrinsics() {
3384 DominanceInfo domInfo;
3385 for (llvm::Instruction *inst : debugIntrinsics) {
3386 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3387 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3393LogicalResult ModuleImport::processDebugRecords() {
3394 DominanceInfo domInfo;
3395 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3396 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3402LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3404 builder.setInsertionPointToStart(block);
3405 for (llvm::Instruction &inst : *bb) {
3406 if (
failed(processInstruction(&inst)))
3411 if (debugIntrinsics.contains(&inst))
3418 setNonDebugMetadataAttrs(&inst, op);
3419 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3420 if (emitExpensiveWarnings) {
3421 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3427 if (bb->hasAddressTaken()) {
3428 OpBuilder::InsertionGuard guard(builder);
3429 builder.setInsertionPointToStart(block);
3431 BlockTagAttr::get(context, bb->getNumber()));
3436FailureOr<SmallVector<AccessGroupAttr>>
3438 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3444 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3447FailureOr<DereferenceableAttr>
3450 Location loc = mlirModule.getLoc();
3454 if (node->getNumOperands() != 1)
3455 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3456 <<
diagMD(node, llvmModule.get());
3458 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3459 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3460 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3461 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3462 "non-negative constant integer: "
3463 <<
diagMD(node, llvmModule.get());
3465 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3466 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3467 numBytesCst->getZExtValue(), mayBeNull);
3473 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3474 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3475 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3476 bool importStructsAsLiterals) {
3483 LLVMDialect::getDialectNamespace()));
3485 DLTIDialect::getDialectNamespace()));
3486 if (loadAllDialects)
3489 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3493 emitExpensiveWarnings, dropDICompositeTypeElements,
3494 preferUnregisteredIntrinsics,
3495 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.
IntegerAttr getIntegerAttr(Type type, int64_t value)
FloatAttr getFloatAttr(Type type, double value)
IntegerAttr getI64IntegerAttr(int64_t 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.