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) {
1224 if (constScalar->getType()->isVectorTy())
1228 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1230 IntegerType::get(context, constInt->getBitWidth()),
1231 constInt->getValue());
1235 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1236 llvm::Type *type = constFloat->getType();
1237 FloatType floatType =
1239 ? BFloat16Type::get(context)
1243 <<
"unexpected floating-point type";
1246 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1253static SmallVector<Attribute>
1255 llvm::ConstantDataSequential *constSequence) {
1257 elementAttrs.reserve(constSequence->getNumElements());
1258 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1259 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1262 return elementAttrs;
1265Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1271 auto getConstantShape = [&](llvm::Type *type) {
1272 return llvm::dyn_cast_if_present<ShapedType>(
1277 if (isa<llvm::ConstantInt, llvm::ConstantFP>(constant)) {
1278 assert(constant->getType()->isVectorTy() &&
"expected a vector splat");
1279 auto shape = getConstantShape(constant->getType());
1282 Attribute splatAttr =
1289 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1290 if (constArray->isString())
1291 return builder.getStringAttr(constArray->getAsString());
1292 auto shape = getConstantShape(constArray->getType());
1296 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1297 if (constVector && constVector->isSplat()) {
1300 builder, constVector->getElementAsConstant(0));
1304 SmallVector<Attribute> elementAttrs =
1311 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1312 auto shape = getConstantShape(constAggregate->getType());
1316 SmallVector<Attribute> elementAttrs;
1317 SmallVector<llvm::Constant *> workList = {constAggregate};
1318 while (!workList.empty()) {
1319 llvm::Constant *current = workList.pop_back_val();
1322 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1324 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1325 workList.push_back(constAggregate->getAggregateElement(idx));
1330 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1331 SmallVector<Attribute> attrs =
1333 elementAttrs.append(attrs.begin(), attrs.end());
1339 elementAttrs.push_back(scalarAttr);
1350 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1351 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1352 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1356 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1357 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1364ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1365 assert(globalVar->getName().empty() &&
1366 "expected to work with a nameless global");
1367 auto [it,
success] = namelessGlobals.try_emplace(globalVar);
1374 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1377 it->getSecond() = symbolRef;
1381OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1382 OpBuilder::InsertionGuard guard(builder);
1383 if (globalInsertionOp)
1384 builder.setInsertionPointAfter(globalInsertionOp);
1386 builder.setInsertionPointToStart(mlirModule.getBody());
1390LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1392 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1395 AliasOp aliasOp = AliasOp::create(builder, mlirModule.getLoc(), type,
1396 convertLinkageFromLLVM(alias->getLinkage()),
1398 alias->isDSOLocal(),
1399 alias->isThreadLocal(),
1400 ArrayRef<NamedAttribute>());
1401 globalInsertionOp = aliasOp;
1404 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1405 setConstantInsertionPointToStart(block);
1406 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1409 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1411 if (alias->hasAtLeastLocalUnnamedAddr())
1412 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1413 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1418LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1419 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1422 llvm::Constant *resolver = ifunc->getResolver();
1423 Type resolverType =
convertType(resolver->getType());
1424 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1425 resolver->getName(), resolverType,
1426 convertLinkageFromLLVM(ifunc->getLinkage()),
1427 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1428 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1429 convertVisibilityFromLLVM(ifunc->getVisibility()));
1439 ArrayRef<StringLiteral> attributePrefixesToSkip = {}) {
1440 SmallVector<Attribute> mlirAttributes;
1441 for (llvm::Attribute attr : attributes) {
1443 if (attr.isStringAttribute())
1444 attrName = attr.getKindAsString();
1446 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1447 if (llvm::is_contained(attributesToSkip, attrName))
1450 auto attrNameStartsWith = [attrName](StringLiteral sl) {
1451 return attrName.starts_with(sl);
1453 if (attributePrefixesToSkip.end() !=
1454 llvm::find_if(attributePrefixesToSkip, attrNameStartsWith))
1457 auto keyAttr = StringAttr::get(context, attrName);
1458 if (attr.isStringAttribute()) {
1459 StringRef val = attr.getValueAsString();
1462 mlirAttributes.push_back(keyAttr);
1466 mlirAttributes.push_back(
1467 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1470 if (attr.isIntAttribute()) {
1473 auto val = std::to_string(attr.getValueAsInt());
1474 mlirAttributes.push_back(
1475 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1478 if (attr.isEnumAttribute()) {
1480 mlirAttributes.push_back(keyAttr);
1486 <<
"' attribute is invalid on current operation, skipping it";
1488 return ArrayAttr::get(context, mlirAttributes);
1494 GlobalOp globalOp) {
1496 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1497 if (!targetSpecificAttrs.empty())
1498 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1501LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1503 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1505 Attribute valueAttr;
1506 if (globalVar->hasInitializer())
1507 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1508 Type type =
convertType(globalVar->getValueType());
1510 uint64_t alignment = 0;
1511 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1512 if (maybeAlign.has_value()) {
1513 llvm::Align align = *maybeAlign;
1514 alignment = align.value();
1519 SmallVector<Attribute> globalExpressionAttrs;
1520 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1521 globalVar->getDebugInfo(globalExpressions);
1523 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1524 DIGlobalVariableExpressionAttr globalExpressionAttr =
1525 debugImporter->translateGlobalVariableExpression(expr);
1526 globalExpressionAttrs.push_back(globalExpressionAttr);
1531 StringRef globalName = globalVar->getName();
1532 if (globalName.empty())
1533 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1535 GlobalOp globalOp = GlobalOp::create(
1536 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1537 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1538 valueAttr, alignment, globalVar->getAddressSpace(),
1539 globalVar->isDSOLocal(),
1540 globalVar->isThreadLocal(), SymbolRefAttr(),
1541 ArrayRef<NamedAttribute>(), globalExpressionAttrs);
1542 globalInsertionOp = globalOp;
1544 if (globalVar->hasInitializer() && !valueAttr) {
1546 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1547 setConstantInsertionPointToStart(block);
1548 FailureOr<Value> initializer =
1549 convertConstantExpr(globalVar->getInitializer());
1552 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1554 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1555 globalOp.setUnnamedAddr(
1556 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1558 if (globalVar->hasSection())
1559 globalOp.setSection(globalVar->getSection());
1560 globalOp.setVisibility_(
1561 convertVisibilityFromLLVM(globalVar->getVisibility()));
1563 if (globalVar->hasComdat())
1564 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1572ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1573 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1575 llvm::Constant *initializer = globalVar->getInitializer();
1577 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1578 isa<llvm::ConstantAggregateZero>(initializer);
1585 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1586 if (caz->getElementCount().getFixedValue() != 0)
1590 SmallVector<Attribute> funcs;
1591 SmallVector<int32_t> priorities;
1592 SmallVector<Attribute> dataList;
1593 for (llvm::Value *operand : initializer->operands()) {
1594 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1595 if (!aggregate || aggregate->getNumOperands() != 3)
1598 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1599 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1600 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1601 if (!priority || !func || !data)
1604 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1608 else if (data->isNullValue())
1609 dataAttr = ZeroAttr::get(context);
1614 priorities.push_back(priority->getValue().getZExtValue());
1615 dataList.push_back(dataAttr);
1619 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1622 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1623 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1624 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1627 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1628 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1629 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1634ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1636 if (valueMapping.contains(constant))
1645 workList.insert(constant);
1646 while (!workList.empty()) {
1647 llvm::Constant *current = workList.back();
1650 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1651 orderedSet.insert(current);
1652 workList.pop_back();
1658 auto [adjacencyIt,
inserted] = adjacencyLists.try_emplace(current);
1662 for (llvm::Value *operand : current->operands())
1663 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1664 adjacencyIt->getSecond().push_back(constDependency);
1667 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1668 unsigned numElements = constAgg->getElementCount().getFixedValue();
1669 for (
unsigned i = 0, e = numElements; i != e; ++i)
1670 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1676 if (adjacencyIt->getSecond().empty()) {
1677 orderedSet.insert(current);
1678 workList.pop_back();
1686 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1687 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1688 orderedSet.contains(dependency))
1690 workList.insert(dependency);
1696FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1697 Location loc = UnknownLoc::get(context);
1700 if (Attribute attr = getConstantAsAttr(constant)) {
1702 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1703 return AddressOfOp::create(builder, loc, type, symbolRef.getValue())
1706 return ConstantOp::create(builder, loc, type, attr).getResult();
1710 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1712 return ZeroOp::create(builder, loc, type).getResult();
1716 if (isa<llvm::ConstantTokenNone>(constant)) {
1717 return NoneTokenOp::create(builder, loc).getResult();
1721 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1723 return PoisonOp::create(builder, loc, type).getResult();
1727 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1729 return UndefOp::create(builder, loc, type).getResult();
1733 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1734 Type type =
convertType(dsoLocalEquivalent->getType());
1735 return DSOLocalEquivalentOp::create(
1738 builder.getContext(),
1739 dsoLocalEquivalent->getGlobalValue()->getName()))
1744 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1746 StringRef globalName = globalObj->getName();
1747 FlatSymbolRefAttr symbolRef;
1749 if (globalName.empty())
1751 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1754 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1758 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1759 Type type =
convertType(globalAliasObj->getType());
1760 StringRef aliaseeName = globalAliasObj->getName();
1762 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1766 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1772 llvm::Instruction *inst = constExpr->getAsInstruction();
1773 llvm::scope_exit guard([&]() {
1774 assert(!noResultOpMapping.contains(inst) &&
1775 "expected constant expression to return a result");
1776 valueMapping.erase(inst);
1777 inst->deleteValue();
1781 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1782 return valueMapping.contains(value);
1784 if (
failed(processInstruction(inst)))
1790 if (
auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1791 Type type =
convertType(aggregateZero->getType());
1792 return ZeroOp::create(builder, loc, type).getResult();
1796 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1798 SmallVector<Value> elementValues;
1800 elementValues.reserve(constAgg->getNumOperands());
1801 for (llvm::Value *operand : constAgg->operands())
1804 assert(llvm::count(elementValues,
nullptr) == 0 &&
1805 "expected all elements have been converted before");
1809 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1811 "unrecognized aggregate type");
1812 Value root = UndefOp::create(builder, loc, rootType);
1813 for (
const auto &it : llvm::enumerate(elementValues)) {
1814 if (isArrayOrStruct) {
1816 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1818 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1820 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1821 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1828 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1829 LLVMTargetExtType targetExtType =
1830 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1831 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1832 "target extension type does not support zero-initialization");
1835 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1838 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1842 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1843 return BlockAddressOp::create(
1845 BlockAddressAttr::get(context, fnSym, blockTag))
1849 StringRef error =
"";
1851 if (isa<llvm::ConstantPtrAuth>(constant))
1852 error =
" since ptrauth(...) is unsupported";
1854 if (isa<llvm::NoCFIValue>(constant))
1855 error =
" since no_cfi is unsupported";
1857 if (isa<llvm::GlobalValue>(constant))
1858 error =
" since global value is unsupported";
1860 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1863FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1867 assert(!valueMapping.contains(constant) &&
1868 "expected constant has not been converted before");
1869 assert(constantInsertionBlock &&
1870 "expected the constant insertion block to be non-null");
1873 OpBuilder::InsertionGuard guard(builder);
1874 if (!constantInsertionOp)
1875 builder.setInsertionPointToStart(constantInsertionBlock);
1877 builder.setInsertionPointAfter(constantInsertionOp);
1881 getConstantsToConvert(constant);
1882 for (llvm::Constant *constantToConvert : constantsToConvert) {
1883 FailureOr<Value> converted = convertConstant(constantToConvert);
1886 mapValue(constantToConvert, *converted);
1891 constantInsertionOp =
result.getDefiningOp();
1896 assert(!isa<llvm::MetadataAsValue>(value) &&
1897 "expected value to not be metadata");
1900 auto it = valueMapping.find(value);
1901 if (it != valueMapping.end())
1902 return it->getSecond();
1905 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1906 return convertConstantExpr(constant);
1908 Location loc = UnknownLoc::get(context);
1909 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1911 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1917 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1920 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1923 value = node->getValue();
1926 auto it = valueMapping.find(value);
1927 if (it != valueMapping.end())
1928 return it->getSecond();
1931 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1932 return convertConstantExpr(constant);
1936FailureOr<SmallVector<Value>>
1939 remapped.reserve(values.size());
1940 for (llvm::Value *value : values) {
1942 if (failed(converted))
1944 remapped.push_back(*converted);
1954 assert(immArgPositions.size() == immArgAttrNames.size() &&
1955 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1959 for (
auto [immArgPos, immArgName] :
1960 llvm::zip(immArgPositions, immArgAttrNames)) {
1961 auto &value = operands[immArgPos];
1962 auto *constant = llvm::cast<llvm::Constant>(value);
1964 assert(attr && attr.getType().isIntOrFloat() &&
1965 "expected immarg to be float or integer constant");
1966 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1967 attrsOut.push_back({nameAttr, attr});
1972 for (llvm::Value *value : operands) {
1976 if (failed(mlirValue))
1978 valuesOut.push_back(*mlirValue);
1983 if (requiresOpBundles) {
1984 opBundleSizes.reserve(opBundles.size());
1985 opBundleTagAttrs.reserve(opBundles.size());
1987 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1988 opBundleSizes.push_back(bundle.Inputs.size());
1989 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
1991 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1992 auto operandMlirValue =
convertValue(opBundleOperand.get());
1993 if (failed(operandMlirValue))
1995 valuesOut.push_back(*operandMlirValue);
2000 auto opBundleSizesAttrNameAttr =
2001 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
2002 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
2004 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
2005 auto opBundleTagsAttrNameAttr =
2006 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
2007 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
2014 IntegerAttr integerAttr;
2016 bool success = succeeded(converted) &&
2018 assert(
success &&
"expected a constant integer value");
2024 FloatAttr floatAttr;
2028 assert(
success &&
"expected a constant float value");
2035 llvm::DILocalVariable *node =
nullptr;
2036 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2037 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2038 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2040 node = cast<llvm::DILocalVariable *>(valOrVariable);
2042 return debugImporter->translate(node);
2046 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2047 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2048 return debugImporter->translate(node);
2051FPExceptionBehaviorAttr
2053 auto *metadata = cast<llvm::MetadataAsValue>(value);
2054 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2055 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2056 llvm::convertStrToExceptionBehavior(mdstr->getString());
2057 assert(optLLVM &&
"Expecting FP exception behavior");
2058 return builder.getAttr<FPExceptionBehaviorAttr>(
2059 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2063 auto *metadata = cast<llvm::MetadataAsValue>(value);
2064 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2065 std::optional<llvm::RoundingMode> optLLVM =
2066 llvm::convertStrToRoundingMode(mdstr->getString());
2067 assert(optLLVM &&
"Expecting rounding mode");
2068 return builder.getAttr<RoundingModeAttr>(
2069 convertRoundingModeFromLLVM(*optLLVM));
2072FailureOr<SmallVector<AliasScopeAttr>>
2074 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2075 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2080 return debugImporter->translateLoc(loc);
2084ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2085 llvm::BasicBlock *
target,
2087 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2088 auto *phiInst = cast<llvm::PHINode>(&*inst);
2089 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2091 if (failed(converted))
2093 blockArguments.push_back(*converted);
2098FailureOr<SmallVector<Value>>
2099ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2100 bool allowInlineAsm) {
2101 bool isInlineAsm = callInst->isInlineAsm();
2102 if (isInlineAsm && !allowInlineAsm)
2112 llvm::Value *calleeOperand = callInst->getCalledOperand();
2113 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2117 operands.push_back(*called);
2120 SmallVector<llvm::Value *> args(callInst->args());
2121 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2125 llvm::append_range(operands, *arguments);
2133 LLVMFunctionType calleeType) {
2134 if (callType.getReturnType() != calleeType.getReturnType())
2137 if (calleeType.isVarArg()) {
2140 if (callType.getNumParams() < calleeType.getNumParams())
2145 if (callType.getNumParams() != calleeType.getNumParams())
2150 for (
auto [operandType, argumentType] :
2151 llvm::zip(callType.getParams(), calleeType.getParams()))
2152 if (operandType != argumentType)
2158FailureOr<LLVMFunctionType>
2159ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2160 bool &isIncompatibleCall) {
2161 isIncompatibleCall =
false;
2162 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2163 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2169 llvm::Value *calledOperand = callInst->getCalledOperand();
2170 FailureOr<LLVMFunctionType> callType =
2171 castOrFailure(
convertType(callInst->getFunctionType()));
2174 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2176 llvm::FunctionType *origCalleeType =
nullptr;
2178 origCalleeType = callee->getFunctionType();
2179 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2180 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2184 if (!origCalleeType)
2187 FailureOr<LLVMFunctionType> calleeType =
2195 isIncompatibleCall =
true;
2197 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2198 <<
" and " << *calleeType;
2205FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2206 llvm::Value *calledOperand = callInst->getCalledOperand();
2207 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2208 return SymbolRefAttr::get(context, calledOperand->getName());
2212LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2213 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2217 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2221ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2222 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2223 unsigned argIdx = 0;
2224 SmallVector<mlir::Attribute> opAttrs;
2225 bool hasIndirect =
false;
2227 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2229 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2234 if (ci.isIndirect) {
2235 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2236 SmallVector<mlir::NamedAttribute> attrs;
2237 attrs.push_back(builder.getNamedAttr(
2238 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2240 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2244 opAttrs.push_back(builder.getDictionaryAttr({}));
2250 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2254LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2257 if (inst->getOpcode() == llvm::Instruction::Br) {
2258 auto *brInst = cast<llvm::BranchInst>(inst);
2260 SmallVector<Block *> succBlocks;
2261 SmallVector<SmallVector<Value>> succBlockArgs;
2262 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2263 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2264 SmallVector<Value> blockArgs;
2265 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2268 succBlockArgs.push_back(blockArgs);
2271 if (!brInst->isConditional()) {
2272 auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),
2273 succBlocks.front());
2277 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2280 auto condBrOp = LLVM::CondBrOp::create(
2281 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2282 succBlocks.back(), succBlockArgs.back());
2286 if (inst->getOpcode() == llvm::Instruction::Switch) {
2287 auto *swInst = cast<llvm::SwitchInst>(inst);
2289 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2292 SmallVector<Value> defaultBlockArgs;
2294 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2295 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2299 unsigned numCases = swInst->getNumCases();
2300 SmallVector<SmallVector<Value>> caseOperands(numCases);
2301 SmallVector<ValueRange> caseOperandRefs(numCases);
2302 SmallVector<APInt> caseValues(numCases);
2303 SmallVector<Block *> caseBlocks(numCases);
2304 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2305 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2306 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2307 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2309 caseOperandRefs[it.index()] = caseOperands[it.index()];
2310 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2314 auto switchOp = SwitchOp::create(builder, loc, *condition,
2316 caseValues, caseBlocks, caseOperandRefs);
2320 if (inst->getOpcode() == llvm::Instruction::PHI) {
2322 mapValue(inst, builder.getInsertionBlock()->addArgument(
2326 if (inst->getOpcode() == llvm::Instruction::Call) {
2327 auto *callInst = cast<llvm::CallInst>(inst);
2328 llvm::Value *calledOperand = callInst->getCalledOperand();
2330 FailureOr<SmallVector<Value>> operands =
2331 convertCallOperands(callInst,
true);
2335 auto callOp = [&]() -> FailureOr<Operation *> {
2336 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2340 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2341 return InlineAsmOp::create(
2342 builder, loc, resultTy, *operands,
2343 builder.getStringAttr(asmI->getAsmString()),
2344 builder.getStringAttr(asmI->getConstraintString()),
2345 asmI->hasSideEffects(), asmI->isAlignStack(),
2346 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2347 AsmDialectAttr::get(
2348 mlirModule.getContext(),
2349 convertAsmDialectFromLLVM(asmI->getDialect())),
2353 bool isIncompatibleCall;
2354 FailureOr<LLVMFunctionType> funcTy =
2355 convertFunctionType(callInst, isIncompatibleCall);
2359 FlatSymbolRefAttr callee =
nullptr;
2360 if (isIncompatibleCall) {
2364 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2365 Value indirectCallVal = LLVM::AddressOfOp::create(
2366 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2367 operands->insert(operands->begin(), indirectCallVal);
2370 callee = convertCalleeName(callInst);
2372 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2374 if (
failed(convertCallAttributes(callInst, callOp)))
2379 if (!isIncompatibleCall)
2381 return callOp.getOperation();
2387 if (!callInst->getType()->isVoidTy())
2388 mapValue(inst, (*callOp)->getResult(0));
2393 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2394 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2396 SmallVector<Value> operands;
2397 operands.reserve(lpInst->getNumClauses());
2398 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2399 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2402 operands.push_back(*operand);
2407 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2411 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2412 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2414 if (invokeInst->isInlineAsm())
2415 return emitError(loc) <<
"invoke of inline assembly is not supported";
2417 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2423 bool invokeResultUsedInPhi = llvm::any_of(
2424 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2425 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2430 Block *directNormalDest = normalDest;
2431 if (invokeResultUsedInPhi) {
2436 OpBuilder::InsertionGuard g(builder);
2437 directNormalDest = builder.createBlock(normalDest);
2440 SmallVector<Value> unwindArgs;
2441 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2445 bool isIncompatibleInvoke;
2446 FailureOr<LLVMFunctionType> funcTy =
2447 convertFunctionType(invokeInst, isIncompatibleInvoke);
2451 FlatSymbolRefAttr calleeName =
nullptr;
2452 if (isIncompatibleInvoke) {
2456 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2457 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2458 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2459 operands->insert(operands->begin(), indirectInvokeVal);
2462 calleeName = convertCalleeName(invokeInst);
2467 auto invokeOp = InvokeOp::create(
2468 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2471 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2476 if (!isIncompatibleInvoke)
2479 if (!invokeInst->getType()->isVoidTy())
2480 mapValue(inst, invokeOp.getResults().front());
2484 SmallVector<Value> normalArgs;
2485 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2489 if (invokeResultUsedInPhi) {
2493 OpBuilder::InsertionGuard g(builder);
2494 builder.setInsertionPointToStart(directNormalDest);
2495 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2499 assert(llvm::none_of(
2501 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2502 "An llvm.invoke operation cannot pass its result as a block "
2504 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2509 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2510 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2511 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2512 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2521 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2529 auto gepOp = GEPOp::create(
2530 builder, loc, type, sourceElementType, *basePtr,
indices,
2531 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2536 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2537 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2539 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2543 SmallVector<Block *> succBlocks;
2544 SmallVector<SmallVector<Value>> succBlockArgs;
2545 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2546 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2547 SmallVector<Value> blockArgs;
2548 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2551 succBlockArgs.push_back(blockArgs);
2553 SmallVector<ValueRange> succBlockArgsRange =
2554 llvm::to_vector_of<ValueRange>(succBlockArgs);
2556 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2557 succBlockArgsRange, succBlocks);
2567 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2570LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2577 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2578 return convertIntrinsic(intrinsic);
2583 if (inst->DebugMarker) {
2584 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2586 if (
auto *dbgVariableRecord =
2587 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2592 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2593 if (!emitExpensiveWarnings)
2596 llvm::raw_string_ostream optionsStream(
options);
2597 dbgRecord.print(optionsStream);
2598 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2602 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2603 DILabelAttr labelAttr =
2604 debugImporter->translate(dbgLabelRecord->getLabel());
2606 return emitUnsupportedWarning();
2607 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2611 return emitUnsupportedWarning();
2616 return convertInstruction(inst);
2619FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2620 if (!f->hasPersonalityFn())
2623 llvm::Constant *pf = f->getPersonalityFn();
2627 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2631 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2632 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2633 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2634 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2635 return SymbolRefAttr::get(builder.getContext(), func->getName());
2638 return FlatSymbolRefAttr();
2642 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2644 auto othermem = convertModRefInfoFromLLVM(
2645 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2646 auto argMem = convertModRefInfoFromLLVM(
2647 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2648 auto inaccessibleMem = convertModRefInfoFromLLVM(
2649 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2650 auto errnoMem = convertModRefInfoFromLLVM(
2651 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2652 auto targetMem0 = convertModRefInfoFromLLVM(
2653 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2654 auto targetMem1 = convertModRefInfoFromLLVM(
2655 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2657 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2658 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2660 if (memAttr.isReadWrite())
2662 funcOp.setMemoryEffectsAttr(memAttr);
2666 llvm::DenormalFPEnv denormalFpEnv =
func->getDenormalFPEnv();
2668 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2671 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2672 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2674 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2675 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2676 convertDenormalModeKindFromLLVM(defaultMode.Input),
2677 convertDenormalModeKindFromLLVM(floatMode.Output),
2678 convertDenormalModeKindFromLLVM(floatMode.Input));
2679 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2685 StringLiteral(
"aarch64_in_za"),
2686 StringLiteral(
"aarch64_inout_za"),
2687 StringLiteral(
"aarch64_new_za"),
2688 StringLiteral(
"aarch64_out_za"),
2689 StringLiteral(
"aarch64_preserves_za"),
2690 StringLiteral(
"aarch64_pstate_sm_body"),
2691 StringLiteral(
"aarch64_pstate_sm_compatible"),
2692 StringLiteral(
"aarch64_pstate_sm_enabled"),
2693 StringLiteral(
"allocsize"),
2694 StringLiteral(
"alwaysinline"),
2695 StringLiteral(
"cold"),
2696 StringLiteral(
"convergent"),
2697 StringLiteral(
"fp-contract"),
2698 StringLiteral(
"frame-pointer"),
2699 StringLiteral(
"hot"),
2700 StringLiteral(
"inlinehint"),
2701 StringLiteral(
"instrument-function-entry"),
2702 StringLiteral(
"instrument-function-exit"),
2703 StringLiteral(
"modular-format"),
2704 StringLiteral(
"memory"),
2705 StringLiteral(
"minsize"),
2706 StringLiteral(
"no_caller_saved_registers"),
2707 StringLiteral(
"no-nans-fp-math"),
2708 StringLiteral(
"no-signed-zeros-fp-math"),
2709 StringLiteral(
"no-builtins"),
2710 StringLiteral(
"nocallback"),
2711 StringLiteral(
"noduplicate"),
2712 StringLiteral(
"noinline"),
2713 StringLiteral(
"noreturn"),
2714 StringLiteral(
"nounwind"),
2715 StringLiteral(
"optnone"),
2716 StringLiteral(
"optsize"),
2717 StringLiteral(
"returns_twice"),
2718 StringLiteral(
"save-reg-params"),
2719 StringLiteral(
"target-features"),
2720 StringLiteral(
"trap-func-name"),
2721 StringLiteral(
"tune-cpu"),
2722 StringLiteral(
"uwtable"),
2723 StringLiteral(
"vscale_range"),
2724 StringLiteral(
"willreturn"),
2725 StringLiteral(
"zero-call-used-regs"),
2726 StringLiteral(
"denormal_fpenv"),
2732 StringLiteral(
"no-builtin-"),
2735template <
typename OpTy>
2737 const llvm::AttributeSet &attrs,
2740 if (attrs.hasAttribute(
"no-builtins")) {
2741 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2746 for (llvm::Attribute attr : attrs) {
2749 if (attr.hasKindAsEnum())
2752 StringRef val = attr.getKindAsString();
2754 if (val.starts_with(
"no-builtin-"))
2756 StringAttr::get(ctx, val.drop_front(
sizeof(
"no-builtin-") - 1)));
2759 if (!nbAttrs.empty())
2760 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2763template <
typename OpTy>
2765 const llvm::AttributeSet &attrs, OpTy
target) {
2766 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2767 if (!attr.isValid())
2770 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2774 static_cast<int32_t
>(*numElems)}));
2785 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2786 llvm::AttributeList::AttrIndex::FunctionIndex);
2788 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2790 if (!passthroughAttr.empty())
2791 funcOp.setPassthroughAttr(passthroughAttr);
2795 LLVMFuncOp funcOp) {
2800 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
2801 funcOp.setNoInline(
true);
2802 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2803 funcOp.setAlwaysInline(
true);
2804 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
2805 funcOp.setInlineHint(
true);
2806 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2807 funcOp.setOptimizeNone(
true);
2808 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
2809 funcOp.setConvergent(
true);
2810 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
2811 funcOp.setNoUnwind(
true);
2812 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
2813 funcOp.setWillReturn(
true);
2814 if (
func->hasFnAttribute(llvm::Attribute::NoReturn))
2815 funcOp.setNoreturn(
true);
2816 if (
func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
2817 funcOp.setOptsize(
true);
2818 if (
func->hasFnAttribute(
"save-reg-params"))
2819 funcOp.setSaveRegParams(
true);
2820 if (
func->hasFnAttribute(llvm::Attribute::MinSize))
2821 funcOp.setMinsize(
true);
2822 if (
func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
2823 funcOp.setReturnsTwice(
true);
2824 if (
func->hasFnAttribute(llvm::Attribute::Cold))
2825 funcOp.setCold(
true);
2826 if (
func->hasFnAttribute(llvm::Attribute::Hot))
2827 funcOp.setHot(
true);
2828 if (
func->hasFnAttribute(llvm::Attribute::NoDuplicate))
2829 funcOp.setNoduplicate(
true);
2830 if (
func->hasFnAttribute(
"no_caller_saved_registers"))
2831 funcOp.setNoCallerSavedRegisters(
true);
2832 if (
func->hasFnAttribute(llvm::Attribute::NoCallback))
2833 funcOp.setNocallback(
true);
2834 if (llvm::Attribute attr =
func->getFnAttribute(
"modular-format");
2835 attr.isStringAttribute())
2836 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
2837 if (llvm::Attribute attr =
func->getFnAttribute(
"zero-call-used-regs");
2838 attr.isStringAttribute())
2839 funcOp.setZeroCallUsedRegsAttr(
2840 StringAttr::get(context, attr.getValueAsString()));
2842 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2843 funcOp.setArmStreaming(
true);
2844 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2845 funcOp.setArmLocallyStreaming(
true);
2846 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2847 funcOp.setArmStreamingCompatible(
true);
2849 if (
func->hasFnAttribute(
"aarch64_new_za"))
2850 funcOp.setArmNewZa(
true);
2851 else if (
func->hasFnAttribute(
"aarch64_in_za"))
2852 funcOp.setArmInZa(
true);
2853 else if (
func->hasFnAttribute(
"aarch64_out_za"))
2854 funcOp.setArmOutZa(
true);
2855 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
2856 funcOp.setArmInoutZa(
true);
2857 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
2858 funcOp.setArmPreservesZa(
true);
2863 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
2864 if (attr.isValid()) {
2866 auto intTy = IntegerType::get(context, 32);
2867 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2868 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2869 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2873 if (
func->hasFnAttribute(
"frame-pointer")) {
2874 StringRef stringRefFramePointerKind =
2875 func->getFnAttribute(
"frame-pointer").getValueAsString();
2876 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2877 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2878 stringRefFramePointerKind)
2882 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
2883 attr.isStringAttribute())
2884 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2886 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
2887 attr.isStringAttribute())
2888 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2890 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
2891 attr.isStringAttribute())
2892 funcOp.setTargetFeaturesAttr(
2893 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2895 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
2896 attr.isStringAttribute())
2897 funcOp.setReciprocalEstimatesAttr(
2898 StringAttr::get(context, attr.getValueAsString()));
2900 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
2901 attr.isStringAttribute())
2902 funcOp.setPreferVectorWidth(attr.getValueAsString());
2904 if (llvm::Attribute attr =
func->getFnAttribute(
"no-nans-fp-math");
2905 attr.isStringAttribute())
2906 funcOp.setNoNansFpMath(attr.getValueAsBool());
2908 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
2909 attr.isStringAttribute())
2910 funcOp.setInstrumentFunctionEntry(
2911 StringAttr::get(context, attr.getValueAsString()));
2913 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
2914 attr.isStringAttribute())
2915 funcOp.setInstrumentFunctionExit(
2916 StringAttr::get(context, attr.getValueAsString()));
2918 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
2919 attr.isStringAttribute())
2920 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2922 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
2923 attr.isStringAttribute())
2924 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2926 if (
func->hasUWTable()) {
2927 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
2928 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2929 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2934ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2937 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2939 if (!llvmAttr.isValid())
2944 if (llvmAttr.hasKindAsEnum() &&
2945 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2946 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2947 paramAttrs.push_back(
2953 if (llvmAttr.isTypeAttribute())
2954 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
2955 else if (llvmAttr.isIntAttribute())
2957 else if (llvmAttr.isEnumAttribute())
2959 else if (llvmAttr.isConstantRangeAttribute()) {
2960 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2961 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2964 llvm_unreachable(
"unexpected parameter attribute kind");
2966 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2969 return builder.getDictionaryAttr(paramAttrs);
2973 LLVMFuncOp funcOp) {
2974 auto llvmAttrs = func->getAttributes();
2975 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2976 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2977 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2981 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2982 if (!llvmResAttr.hasAttributes())
2984 funcOp.setResAttrsAttr(
2985 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2989 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2992 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2993 immArgPositions.end());
2995 llvm::AttributeList llvmAttrs = call->getAttributes();
2997 bool anyArgAttrs =
false;
2998 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
3000 if (immArgPositionsSet.contains(i))
3002 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3003 if (llvmArgAttrsSet.back().hasAttributes())
3008 for (
auto &dict : dictAttrs)
3009 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3010 return builder.getArrayAttr(attrs);
3014 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
3015 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3016 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3020 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3021 if (!llvmResAttr.hasAttributes())
3023 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3024 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3027template <
typename Op>
3029 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3033LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3038LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3044 llvm::AttributeList callAttrs = inst->getAttributes();
3046 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3047 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3048 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3049 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3050 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3052 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3053 op.setSaveRegParams(callAttrs.getFnAttr(
"save-reg-params").isValid());
3054 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3055 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3058 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3059 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3060 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3062 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3063 op.setNoCallerSavedRegisters(
3064 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3065 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3067 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3068 attr.isStringAttribute())
3069 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3070 if (llvm::Attribute attr = callAttrs.getFnAttr(
"zero-call-used-regs");
3071 attr.isStringAttribute())
3072 op.setZeroCallUsedRegsAttr(
3073 StringAttr::get(context, attr.getValueAsString()));
3074 if (llvm::Attribute attr = callAttrs.getFnAttr(
"trap-func-name");
3075 attr.isStringAttribute())
3076 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3077 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3079 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3080 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3082 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3083 ModRefInfo othermem = convertModRefInfoFromLLVM(
3084 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3085 ModRefInfo argMem = convertModRefInfoFromLLVM(
3086 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3087 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3088 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3089 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3090 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3091 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3092 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3093 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3094 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3096 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3097 errnoMem, targetMem0, targetMem1);
3099 if (!memAttr.isReadWrite())
3100 op.setMemoryEffectsAttr(memAttr);
3113 if (
func->isIntrinsic() &&
3114 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3117 bool dsoLocal =
func->isDSOLocal();
3118 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3122 builder.setInsertionPointToEnd(mlirModule.getBody());
3124 Location loc = debugImporter->translateFuncLocation(
func);
3125 LLVMFuncOp funcOp = LLVMFuncOp::create(
3126 builder, loc,
func->getName(), functionType,
3127 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3132 funcOp.setPersonalityAttr(personality);
3133 else if (
func->hasPersonalityFn())
3134 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3137 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3139 if (
func->hasAtLeastLocalUnnamedAddr())
3140 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3142 if (
func->hasSection())
3143 funcOp.setSection(StringRef(
func->getSection()));
3145 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3147 if (
func->hasComdat())
3148 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3150 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3151 funcOp.setAlignment(maybeAlign->value());
3158 func->getAllMetadata(allMetadata);
3159 for (
auto &[kind, node] : allMetadata) {
3160 if (!iface.isConvertibleMetadata(kind))
3162 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *
this))) {
3164 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
3169 if (
func->isDeclaration())
3178 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3179 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3184 for (llvm::BasicBlock &basicBlock : *
func) {
3186 if (!reachable.contains(&basicBlock)) {
3187 if (basicBlock.hasAddressTaken())
3189 <<
"unreachable block '" << basicBlock.getName()
3190 <<
"' with address taken";
3193 Region &body = funcOp.getBody();
3194 Block *block = builder.createBlock(&body, body.
end());
3196 reachableBasicBlocks.push_back(&basicBlock);
3200 for (
const auto &it : llvm::enumerate(
func->args())) {
3201 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3202 functionType.getParamType(it.index()), funcOp.getLoc());
3211 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3212 for (llvm::BasicBlock *basicBlock : blocks)
3213 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3218 if (failed(processDebugIntrinsics()))
3223 if (failed(processDebugRecords()))
3232 if (!dbgIntr->isKillLocation())
3234 llvm::Value *value = dbgIntr->getArgOperand(0);
3235 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3238 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3250 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3253 if (dominatedBlocks.empty())
3257 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3260 Value insertPt = argOperand;
3261 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3267 if (!insertionBlock->
empty() &&
3268 isa<LandingpadOp>(insertionBlock->
front()))
3269 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3277std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3278ModuleImport::processDebugOpArgumentsAndInsertionPt(
3280 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3281 llvm::Value *address,
3282 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3283 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3289 FailureOr<Value> argOperand = convertArgOperandToValue();
3290 if (
failed(argOperand)) {
3291 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3299 return {localVarAttr, debugImporter->translateExpression(expression),
3304ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3305 DominanceInfo &domInfo) {
3307 auto emitUnsupportedWarning = [&]() {
3308 if (emitExpensiveWarnings)
3313 OpBuilder::InsertionGuard guard(builder);
3314 auto convertArgOperandToValue = [&]() {
3320 if (dbgIntr->hasArgList())
3321 return emitUnsupportedWarning();
3328 return emitUnsupportedWarning();
3330 auto [localVariableAttr, locationExprAttr, locVal] =
3331 processDebugOpArgumentsAndInsertionPt(
3332 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3333 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3335 if (!localVariableAttr)
3336 return emitUnsupportedWarning();
3341 Operation *op =
nullptr;
3342 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3343 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3345 else if (isa<llvm::DbgValueInst>(dbgIntr))
3346 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3349 return emitUnsupportedWarning();
3352 setNonDebugMetadataAttrs(dbgIntr, op);
3357ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3358 DominanceInfo &domInfo) {
3359 OpBuilder::InsertionGuard guard(builder);
3361 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3362 if (!emitExpensiveWarnings)
3365 llvm::raw_string_ostream optionsStream(
options);
3366 dbgRecord.print(optionsStream);
3367 emitWarning(loc) <<
"unhandled debug variable record "
3368 << optionsStream.str();
3374 if (dbgRecord.hasArgList())
3375 return emitUnsupportedWarning();
3380 if (!dbgRecord.getAddress())
3381 return emitUnsupportedWarning();
3383 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3384 llvm::Value *value = dbgRecord.getAddress();
3387 auto it = valueMapping.find(value);
3388 if (it != valueMapping.end())
3389 return it->getSecond();
3392 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3393 return convertConstantExpr(constant);
3397 auto [localVariableAttr, locationExprAttr, locVal] =
3398 processDebugOpArgumentsAndInsertionPt(
3399 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3400 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3402 if (!localVariableAttr)
3403 return emitUnsupportedWarning();
3408 if (dbgRecord.isDbgDeclare())
3409 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3411 else if (dbgRecord.isDbgValue())
3412 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3415 return emitUnsupportedWarning();
3420LogicalResult ModuleImport::processDebugIntrinsics() {
3421 DominanceInfo domInfo;
3422 for (llvm::Instruction *inst : debugIntrinsics) {
3423 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3424 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3430LogicalResult ModuleImport::processDebugRecords() {
3431 DominanceInfo domInfo;
3432 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3433 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3439LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3441 builder.setInsertionPointToStart(block);
3442 for (llvm::Instruction &inst : *bb) {
3443 if (
failed(processInstruction(&inst)))
3448 if (debugIntrinsics.contains(&inst))
3455 setNonDebugMetadataAttrs(&inst, op);
3456 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3457 if (emitExpensiveWarnings) {
3458 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3464 if (bb->hasAddressTaken()) {
3465 OpBuilder::InsertionGuard guard(builder);
3466 builder.setInsertionPointToStart(block);
3468 BlockTagAttr::get(context, bb->getNumber()));
3473FailureOr<SmallVector<AccessGroupAttr>>
3475 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3481 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3484FailureOr<DereferenceableAttr>
3487 Location loc = mlirModule.getLoc();
3491 if (node->getNumOperands() != 1)
3492 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3493 <<
diagMD(node, llvmModule.get());
3495 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3496 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3497 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3498 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3499 "non-negative constant integer: "
3500 <<
diagMD(node, llvmModule.get());
3502 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3503 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3504 numBytesCst->getZExtValue(), mayBeNull);
3510 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3511 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3512 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3513 bool importStructsAsLiterals) {
3520 LLVMDialect::getDialectNamespace()));
3522 DLTIDialect::getDialectNamespace()));
3523 if (loadAllDialects)
3526 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3530 emitExpensiveWarnings, dropDICompositeTypeElements,
3531 preferUnregisteredIntrinsics,
3532 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.