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 (
auto *brInst = dyn_cast<llvm::UncondBrInst>(inst)) {
2258 llvm::BasicBlock *succ = brInst->getSuccessor();
2259 SmallVector<Value> blockArgs;
2260 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2263 auto brOp = LLVM::BrOp::create(builder, loc, blockArgs,
lookupBlock(succ));
2267 if (
auto *brInst = dyn_cast<llvm::CondBrInst>(inst)) {
2268 SmallVector<Block *> succBlocks;
2269 SmallVector<SmallVector<Value>> succBlockArgs;
2270 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2271 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2272 SmallVector<Value> blockArgs;
2273 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2276 succBlockArgs.push_back(blockArgs);
2279 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2282 auto condBrOp = LLVM::CondBrOp::create(
2283 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2284 succBlocks.back(), succBlockArgs.back());
2288 if (inst->getOpcode() == llvm::Instruction::Switch) {
2289 auto *swInst = cast<llvm::SwitchInst>(inst);
2291 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2294 SmallVector<Value> defaultBlockArgs;
2296 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2297 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2301 unsigned numCases = swInst->getNumCases();
2302 SmallVector<SmallVector<Value>> caseOperands(numCases);
2303 SmallVector<ValueRange> caseOperandRefs(numCases);
2304 SmallVector<APInt> caseValues(numCases);
2305 SmallVector<Block *> caseBlocks(numCases);
2306 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2307 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2308 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2309 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2311 caseOperandRefs[it.index()] = caseOperands[it.index()];
2312 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2316 auto switchOp = SwitchOp::create(builder, loc, *condition,
2318 caseValues, caseBlocks, caseOperandRefs);
2322 if (inst->getOpcode() == llvm::Instruction::PHI) {
2324 mapValue(inst, builder.getInsertionBlock()->addArgument(
2328 if (inst->getOpcode() == llvm::Instruction::Call) {
2329 auto *callInst = cast<llvm::CallInst>(inst);
2330 llvm::Value *calledOperand = callInst->getCalledOperand();
2332 FailureOr<SmallVector<Value>> operands =
2333 convertCallOperands(callInst,
true);
2337 auto callOp = [&]() -> FailureOr<Operation *> {
2338 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2342 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2343 return InlineAsmOp::create(
2344 builder, loc, resultTy, *operands,
2345 builder.getStringAttr(asmI->getAsmString()),
2346 builder.getStringAttr(asmI->getConstraintString()),
2347 asmI->hasSideEffects(), asmI->isAlignStack(),
2348 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2349 AsmDialectAttr::get(
2350 mlirModule.getContext(),
2351 convertAsmDialectFromLLVM(asmI->getDialect())),
2355 bool isIncompatibleCall;
2356 FailureOr<LLVMFunctionType> funcTy =
2357 convertFunctionType(callInst, isIncompatibleCall);
2361 FlatSymbolRefAttr callee =
nullptr;
2362 if (isIncompatibleCall) {
2366 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2367 Value indirectCallVal = LLVM::AddressOfOp::create(
2368 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2369 operands->insert(operands->begin(), indirectCallVal);
2372 callee = convertCalleeName(callInst);
2374 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2376 if (
failed(convertCallAttributes(callInst, callOp)))
2381 if (!isIncompatibleCall)
2383 return callOp.getOperation();
2389 if (!callInst->getType()->isVoidTy())
2390 mapValue(inst, (*callOp)->getResult(0));
2395 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2396 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2398 SmallVector<Value> operands;
2399 operands.reserve(lpInst->getNumClauses());
2400 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2401 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2404 operands.push_back(*operand);
2409 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2413 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2414 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2416 if (invokeInst->isInlineAsm())
2417 return emitError(loc) <<
"invoke of inline assembly is not supported";
2419 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2425 bool invokeResultUsedInPhi = llvm::any_of(
2426 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2427 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2432 Block *directNormalDest = normalDest;
2433 if (invokeResultUsedInPhi) {
2438 OpBuilder::InsertionGuard g(builder);
2439 directNormalDest = builder.createBlock(normalDest);
2442 SmallVector<Value> unwindArgs;
2443 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2447 bool isIncompatibleInvoke;
2448 FailureOr<LLVMFunctionType> funcTy =
2449 convertFunctionType(invokeInst, isIncompatibleInvoke);
2453 FlatSymbolRefAttr calleeName =
nullptr;
2454 if (isIncompatibleInvoke) {
2458 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2459 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2460 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2461 operands->insert(operands->begin(), indirectInvokeVal);
2464 calleeName = convertCalleeName(invokeInst);
2469 auto invokeOp = InvokeOp::create(
2470 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2473 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2478 if (!isIncompatibleInvoke)
2481 if (!invokeInst->getType()->isVoidTy())
2482 mapValue(inst, invokeOp.getResults().front());
2486 SmallVector<Value> normalArgs;
2487 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2491 if (invokeResultUsedInPhi) {
2495 OpBuilder::InsertionGuard g(builder);
2496 builder.setInsertionPointToStart(directNormalDest);
2497 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2501 assert(llvm::none_of(
2503 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2504 "An llvm.invoke operation cannot pass its result as a block "
2506 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2511 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2512 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2513 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2514 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2523 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2531 auto gepOp = GEPOp::create(
2532 builder, loc, type, sourceElementType, *basePtr,
indices,
2533 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2538 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2539 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2541 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2545 SmallVector<Block *> succBlocks;
2546 SmallVector<SmallVector<Value>> succBlockArgs;
2547 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2548 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2549 SmallVector<Value> blockArgs;
2550 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2553 succBlockArgs.push_back(blockArgs);
2555 SmallVector<ValueRange> succBlockArgsRange =
2556 llvm::to_vector_of<ValueRange>(succBlockArgs);
2558 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2559 succBlockArgsRange, succBlocks);
2569 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2572LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2579 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2580 return convertIntrinsic(intrinsic);
2585 if (inst->DebugMarker) {
2586 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2588 if (
auto *dbgVariableRecord =
2589 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2594 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2595 if (!emitExpensiveWarnings)
2598 llvm::raw_string_ostream optionsStream(
options);
2599 dbgRecord.print(optionsStream);
2600 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2604 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2605 DILabelAttr labelAttr =
2606 debugImporter->translate(dbgLabelRecord->getLabel());
2608 return emitUnsupportedWarning();
2609 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2613 return emitUnsupportedWarning();
2618 return convertInstruction(inst);
2621FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2622 if (!f->hasPersonalityFn())
2625 llvm::Constant *pf = f->getPersonalityFn();
2629 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2633 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2634 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2635 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2636 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2637 return SymbolRefAttr::get(builder.getContext(), func->getName());
2640 return FlatSymbolRefAttr();
2644 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2646 auto othermem = convertModRefInfoFromLLVM(
2647 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2648 auto argMem = convertModRefInfoFromLLVM(
2649 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2650 auto inaccessibleMem = convertModRefInfoFromLLVM(
2651 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2652 auto errnoMem = convertModRefInfoFromLLVM(
2653 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2654 auto targetMem0 = convertModRefInfoFromLLVM(
2655 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2656 auto targetMem1 = convertModRefInfoFromLLVM(
2657 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2659 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2660 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2662 if (memAttr.isReadWrite())
2664 funcOp.setMemoryEffectsAttr(memAttr);
2668 llvm::DenormalFPEnv denormalFpEnv =
func->getDenormalFPEnv();
2670 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2673 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2674 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2676 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2677 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2678 convertDenormalModeKindFromLLVM(defaultMode.Input),
2679 convertDenormalModeKindFromLLVM(floatMode.Output),
2680 convertDenormalModeKindFromLLVM(floatMode.Input));
2681 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2687 StringLiteral(
"aarch64_in_za"),
2688 StringLiteral(
"aarch64_inout_za"),
2689 StringLiteral(
"aarch64_new_za"),
2690 StringLiteral(
"aarch64_out_za"),
2691 StringLiteral(
"aarch64_preserves_za"),
2692 StringLiteral(
"aarch64_pstate_sm_body"),
2693 StringLiteral(
"aarch64_pstate_sm_compatible"),
2694 StringLiteral(
"aarch64_pstate_sm_enabled"),
2695 StringLiteral(
"allocsize"),
2696 StringLiteral(
"alwaysinline"),
2697 StringLiteral(
"cold"),
2698 StringLiteral(
"convergent"),
2699 StringLiteral(
"fp-contract"),
2700 StringLiteral(
"frame-pointer"),
2701 StringLiteral(
"hot"),
2702 StringLiteral(
"inlinehint"),
2703 StringLiteral(
"instrument-function-entry"),
2704 StringLiteral(
"instrument-function-exit"),
2705 StringLiteral(
"modular-format"),
2706 StringLiteral(
"memory"),
2707 StringLiteral(
"minsize"),
2708 StringLiteral(
"no_caller_saved_registers"),
2709 StringLiteral(
"no-signed-zeros-fp-math"),
2710 StringLiteral(
"no-builtins"),
2711 StringLiteral(
"nocallback"),
2712 StringLiteral(
"noduplicate"),
2713 StringLiteral(
"noinline"),
2714 StringLiteral(
"noreturn"),
2715 StringLiteral(
"nounwind"),
2716 StringLiteral(
"optnone"),
2717 StringLiteral(
"optsize"),
2718 StringLiteral(
"returns_twice"),
2719 StringLiteral(
"save-reg-params"),
2720 StringLiteral(
"target-features"),
2721 StringLiteral(
"trap-func-name"),
2722 StringLiteral(
"tune-cpu"),
2723 StringLiteral(
"uwtable"),
2724 StringLiteral(
"vscale_range"),
2725 StringLiteral(
"willreturn"),
2726 StringLiteral(
"zero-call-used-regs"),
2727 StringLiteral(
"denormal_fpenv"),
2733 StringLiteral(
"no-builtin-"),
2736template <
typename OpTy>
2738 const llvm::AttributeSet &attrs,
2741 if (attrs.hasAttribute(
"no-builtins")) {
2742 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2747 for (llvm::Attribute attr : attrs) {
2750 if (attr.hasKindAsEnum())
2753 StringRef val = attr.getKindAsString();
2755 if (val.starts_with(
"no-builtin-"))
2757 StringAttr::get(ctx, val.drop_front(
sizeof(
"no-builtin-") - 1)));
2760 if (!nbAttrs.empty())
2761 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2764template <
typename OpTy>
2766 const llvm::AttributeSet &attrs, OpTy
target) {
2767 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2768 if (!attr.isValid())
2771 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2775 static_cast<int32_t
>(*numElems)}));
2786 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2787 llvm::AttributeList::AttrIndex::FunctionIndex);
2789 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2791 if (!passthroughAttr.empty())
2792 funcOp.setPassthroughAttr(passthroughAttr);
2796 LLVMFuncOp funcOp) {
2801 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
2802 funcOp.setNoInline(
true);
2803 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2804 funcOp.setAlwaysInline(
true);
2805 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
2806 funcOp.setInlineHint(
true);
2807 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2808 funcOp.setOptimizeNone(
true);
2809 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
2810 funcOp.setConvergent(
true);
2811 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
2812 funcOp.setNoUnwind(
true);
2813 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
2814 funcOp.setWillReturn(
true);
2815 if (
func->hasFnAttribute(llvm::Attribute::NoReturn))
2816 funcOp.setNoreturn(
true);
2817 if (
func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
2818 funcOp.setOptsize(
true);
2819 if (
func->hasFnAttribute(
"save-reg-params"))
2820 funcOp.setSaveRegParams(
true);
2821 if (
func->hasFnAttribute(llvm::Attribute::MinSize))
2822 funcOp.setMinsize(
true);
2823 if (
func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
2824 funcOp.setReturnsTwice(
true);
2825 if (
func->hasFnAttribute(llvm::Attribute::Cold))
2826 funcOp.setCold(
true);
2827 if (
func->hasFnAttribute(llvm::Attribute::Hot))
2828 funcOp.setHot(
true);
2829 if (
func->hasFnAttribute(llvm::Attribute::NoDuplicate))
2830 funcOp.setNoduplicate(
true);
2831 if (
func->hasFnAttribute(
"no_caller_saved_registers"))
2832 funcOp.setNoCallerSavedRegisters(
true);
2833 if (
func->hasFnAttribute(llvm::Attribute::NoCallback))
2834 funcOp.setNocallback(
true);
2835 if (llvm::Attribute attr =
func->getFnAttribute(
"modular-format");
2836 attr.isStringAttribute())
2837 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
2838 if (llvm::Attribute attr =
func->getFnAttribute(
"zero-call-used-regs");
2839 attr.isStringAttribute())
2840 funcOp.setZeroCallUsedRegsAttr(
2841 StringAttr::get(context, attr.getValueAsString()));
2843 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2844 funcOp.setArmStreaming(
true);
2845 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2846 funcOp.setArmLocallyStreaming(
true);
2847 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2848 funcOp.setArmStreamingCompatible(
true);
2850 if (
func->hasFnAttribute(
"aarch64_new_za"))
2851 funcOp.setArmNewZa(
true);
2852 else if (
func->hasFnAttribute(
"aarch64_in_za"))
2853 funcOp.setArmInZa(
true);
2854 else if (
func->hasFnAttribute(
"aarch64_out_za"))
2855 funcOp.setArmOutZa(
true);
2856 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
2857 funcOp.setArmInoutZa(
true);
2858 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
2859 funcOp.setArmPreservesZa(
true);
2864 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
2865 if (attr.isValid()) {
2867 auto intTy = IntegerType::get(context, 32);
2868 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2869 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2870 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2874 if (
func->hasFnAttribute(
"frame-pointer")) {
2875 StringRef stringRefFramePointerKind =
2876 func->getFnAttribute(
"frame-pointer").getValueAsString();
2877 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2878 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2879 stringRefFramePointerKind)
2883 if (
func->hasFnAttribute(
"use-sample-profile"))
2884 funcOp.setUseSampleProfile(
true);
2886 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
2887 attr.isStringAttribute())
2888 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2890 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
2891 attr.isStringAttribute())
2892 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2894 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
2895 attr.isStringAttribute())
2896 funcOp.setTargetFeaturesAttr(
2897 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2899 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
2900 attr.isStringAttribute())
2901 funcOp.setReciprocalEstimatesAttr(
2902 StringAttr::get(context, attr.getValueAsString()));
2904 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
2905 attr.isStringAttribute())
2906 funcOp.setPreferVectorWidth(attr.getValueAsString());
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.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3055 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3056 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3059 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3060 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3061 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3063 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3064 op.setNoCallerSavedRegisters(
3065 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3066 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3068 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3069 attr.isStringAttribute())
3070 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3071 if (llvm::Attribute attr = callAttrs.getFnAttr(
"zero-call-used-regs");
3072 attr.isStringAttribute())
3073 op.setZeroCallUsedRegsAttr(
3074 StringAttr::get(context, attr.getValueAsString()));
3075 if (llvm::Attribute attr = callAttrs.getFnAttr(
"trap-func-name");
3076 attr.isStringAttribute())
3077 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3078 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3080 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3081 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3083 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3084 ModRefInfo othermem = convertModRefInfoFromLLVM(
3085 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3086 ModRefInfo argMem = convertModRefInfoFromLLVM(
3087 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3088 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3089 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3090 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3091 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3092 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3093 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3094 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3095 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3097 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3098 errnoMem, targetMem0, targetMem1);
3100 if (!memAttr.isReadWrite())
3101 op.setMemoryEffectsAttr(memAttr);
3114 if (
func->isIntrinsic() &&
3115 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3118 bool dsoLocal =
func->isDSOLocal();
3119 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3123 builder.setInsertionPointToEnd(mlirModule.getBody());
3125 Location loc = debugImporter->translateFuncLocation(
func);
3126 LLVMFuncOp funcOp = LLVMFuncOp::create(
3127 builder, loc,
func->getName(), functionType,
3128 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3133 funcOp.setPersonalityAttr(personality);
3134 else if (
func->hasPersonalityFn())
3135 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3138 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3140 if (
func->hasAtLeastLocalUnnamedAddr())
3141 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3143 if (
func->hasSection())
3144 funcOp.setSection(StringRef(
func->getSection()));
3146 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3148 if (
func->hasComdat())
3149 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3151 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3152 funcOp.setAlignment(maybeAlign->value());
3159 func->getAllMetadata(allMetadata);
3160 for (
auto &[kind, node] : allMetadata) {
3161 if (!iface.isConvertibleMetadata(kind))
3163 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *
this))) {
3165 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
3170 if (
func->isDeclaration())
3179 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3180 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3185 for (llvm::BasicBlock &basicBlock : *
func) {
3187 if (!reachable.contains(&basicBlock)) {
3188 if (basicBlock.hasAddressTaken())
3190 <<
"unreachable block '" << basicBlock.getName()
3191 <<
"' with address taken";
3194 Region &body = funcOp.getBody();
3195 Block *block = builder.createBlock(&body, body.
end());
3197 reachableBasicBlocks.push_back(&basicBlock);
3201 for (
const auto &it : llvm::enumerate(
func->args())) {
3202 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3203 functionType.getParamType(it.index()), funcOp.getLoc());
3212 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3213 for (llvm::BasicBlock *basicBlock : blocks)
3214 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3219 if (failed(processDebugIntrinsics()))
3224 if (failed(processDebugRecords()))
3233 if (!dbgIntr->isKillLocation())
3235 llvm::Value *value = dbgIntr->getArgOperand(0);
3236 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3239 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3251 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3254 if (dominatedBlocks.empty())
3258 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3261 Value insertPt = argOperand;
3262 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3268 if (!insertionBlock->
empty() &&
3269 isa<LandingpadOp>(insertionBlock->
front()))
3270 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3278std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3279ModuleImport::processDebugOpArgumentsAndInsertionPt(
3281 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3282 llvm::Value *address,
3283 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3284 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3290 FailureOr<Value> argOperand = convertArgOperandToValue();
3291 if (
failed(argOperand)) {
3292 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3300 return {localVarAttr, debugImporter->translateExpression(expression),
3305ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3306 DominanceInfo &domInfo) {
3308 auto emitUnsupportedWarning = [&]() {
3309 if (emitExpensiveWarnings)
3314 OpBuilder::InsertionGuard guard(builder);
3315 auto convertArgOperandToValue = [&]() {
3321 if (dbgIntr->hasArgList())
3322 return emitUnsupportedWarning();
3329 return emitUnsupportedWarning();
3331 auto [localVariableAttr, locationExprAttr, locVal] =
3332 processDebugOpArgumentsAndInsertionPt(
3333 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3334 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3336 if (!localVariableAttr)
3337 return emitUnsupportedWarning();
3342 Operation *op =
nullptr;
3343 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3344 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3346 else if (isa<llvm::DbgValueInst>(dbgIntr))
3347 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3350 return emitUnsupportedWarning();
3353 setNonDebugMetadataAttrs(dbgIntr, op);
3358ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3359 DominanceInfo &domInfo) {
3360 OpBuilder::InsertionGuard guard(builder);
3362 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3363 if (!emitExpensiveWarnings)
3366 llvm::raw_string_ostream optionsStream(
options);
3367 dbgRecord.print(optionsStream);
3368 emitWarning(loc) <<
"unhandled debug variable record "
3369 << optionsStream.str();
3375 if (dbgRecord.hasArgList())
3376 return emitUnsupportedWarning();
3381 if (!dbgRecord.getAddress())
3382 return emitUnsupportedWarning();
3384 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3385 llvm::Value *value = dbgRecord.getAddress();
3388 auto it = valueMapping.find(value);
3389 if (it != valueMapping.end())
3390 return it->getSecond();
3393 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3394 return convertConstantExpr(constant);
3398 auto [localVariableAttr, locationExprAttr, locVal] =
3399 processDebugOpArgumentsAndInsertionPt(
3400 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3401 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3403 if (!localVariableAttr)
3404 return emitUnsupportedWarning();
3409 if (dbgRecord.isDbgDeclare())
3410 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3412 else if (dbgRecord.isDbgValue())
3413 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3416 return emitUnsupportedWarning();
3421LogicalResult ModuleImport::processDebugIntrinsics() {
3422 DominanceInfo domInfo;
3423 for (llvm::Instruction *inst : debugIntrinsics) {
3424 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3425 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3431LogicalResult ModuleImport::processDebugRecords() {
3432 DominanceInfo domInfo;
3433 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3434 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3440LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3442 builder.setInsertionPointToStart(block);
3443 for (llvm::Instruction &inst : *bb) {
3444 if (
failed(processInstruction(&inst)))
3449 if (debugIntrinsics.contains(&inst))
3456 setNonDebugMetadataAttrs(&inst, op);
3457 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3458 if (emitExpensiveWarnings) {
3459 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3465 if (bb->hasAddressTaken()) {
3466 OpBuilder::InsertionGuard guard(builder);
3467 builder.setInsertionPointToStart(block);
3469 BlockTagAttr::get(context, bb->getNumber()));
3474FailureOr<SmallVector<AccessGroupAttr>>
3476 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3482 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3485FailureOr<DereferenceableAttr>
3488 Location loc = mlirModule.getLoc();
3492 if (node->getNumOperands() != 1)
3493 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3494 <<
diagMD(node, llvmModule.get());
3496 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3497 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3498 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3499 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3500 "non-negative constant integer: "
3501 <<
diagMD(node, llvmModule.get());
3503 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3504 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3505 numBytesCst->getZExtValue(), mayBeNull);
3511 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3512 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3513 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3514 bool importStructsAsLiterals) {
3521 LLVMDialect::getDialectNamespace()));
3523 DLTIDialect::getDialectNamespace()));
3524 if (loadAllDialects)
3527 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3531 emitExpensiveWarnings, dropDICompositeTypeElements,
3532 preferUnregisteredIntrinsics,
3533 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.