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 (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
2884 attr.isStringAttribute())
2885 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2887 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
2888 attr.isStringAttribute())
2889 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2891 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
2892 attr.isStringAttribute())
2893 funcOp.setTargetFeaturesAttr(
2894 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2896 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
2897 attr.isStringAttribute())
2898 funcOp.setReciprocalEstimatesAttr(
2899 StringAttr::get(context, attr.getValueAsString()));
2901 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
2902 attr.isStringAttribute())
2903 funcOp.setPreferVectorWidth(attr.getValueAsString());
2905 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
2906 attr.isStringAttribute())
2907 funcOp.setInstrumentFunctionEntry(
2908 StringAttr::get(context, attr.getValueAsString()));
2910 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
2911 attr.isStringAttribute())
2912 funcOp.setInstrumentFunctionExit(
2913 StringAttr::get(context, attr.getValueAsString()));
2915 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
2916 attr.isStringAttribute())
2917 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2919 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
2920 attr.isStringAttribute())
2921 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2923 if (
func->hasUWTable()) {
2924 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
2925 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2926 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2931ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2934 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2936 if (!llvmAttr.isValid())
2941 if (llvmAttr.hasKindAsEnum() &&
2942 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2943 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2944 paramAttrs.push_back(
2950 if (llvmAttr.isTypeAttribute())
2951 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
2952 else if (llvmAttr.isIntAttribute())
2954 else if (llvmAttr.isEnumAttribute())
2956 else if (llvmAttr.isConstantRangeAttribute()) {
2957 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2958 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2961 llvm_unreachable(
"unexpected parameter attribute kind");
2963 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2966 return builder.getDictionaryAttr(paramAttrs);
2970 LLVMFuncOp funcOp) {
2971 auto llvmAttrs = func->getAttributes();
2972 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2973 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2974 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2978 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2979 if (!llvmResAttr.hasAttributes())
2981 funcOp.setResAttrsAttr(
2982 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2986 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2989 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2990 immArgPositions.end());
2992 llvm::AttributeList llvmAttrs = call->getAttributes();
2994 bool anyArgAttrs =
false;
2995 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
2997 if (immArgPositionsSet.contains(i))
2999 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3000 if (llvmArgAttrsSet.back().hasAttributes())
3005 for (
auto &dict : dictAttrs)
3006 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3007 return builder.getArrayAttr(attrs);
3011 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
3012 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3013 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3017 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3018 if (!llvmResAttr.hasAttributes())
3020 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3021 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3024template <
typename Op>
3026 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3030LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3035LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3041 llvm::AttributeList callAttrs = inst->getAttributes();
3043 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3044 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3045 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3046 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3047 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3049 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3050 op.setSaveRegParams(callAttrs.getFnAttr(
"save-reg-params").isValid());
3051 op.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3052 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3053 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3056 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3057 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3058 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3060 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3061 op.setNoCallerSavedRegisters(
3062 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3063 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3065 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3066 attr.isStringAttribute())
3067 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3068 if (llvm::Attribute attr = callAttrs.getFnAttr(
"zero-call-used-regs");
3069 attr.isStringAttribute())
3070 op.setZeroCallUsedRegsAttr(
3071 StringAttr::get(context, attr.getValueAsString()));
3072 if (llvm::Attribute attr = callAttrs.getFnAttr(
"trap-func-name");
3073 attr.isStringAttribute())
3074 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3075 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3077 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3078 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3080 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3081 ModRefInfo othermem = convertModRefInfoFromLLVM(
3082 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3083 ModRefInfo argMem = convertModRefInfoFromLLVM(
3084 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3085 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3086 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3087 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3088 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3089 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3090 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3091 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3092 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3094 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3095 errnoMem, targetMem0, targetMem1);
3097 if (!memAttr.isReadWrite())
3098 op.setMemoryEffectsAttr(memAttr);
3111 if (
func->isIntrinsic() &&
3112 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3115 bool dsoLocal =
func->isDSOLocal();
3116 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3120 builder.setInsertionPointToEnd(mlirModule.getBody());
3122 Location loc = debugImporter->translateFuncLocation(
func);
3123 LLVMFuncOp funcOp = LLVMFuncOp::create(
3124 builder, loc,
func->getName(), functionType,
3125 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3130 funcOp.setPersonalityAttr(personality);
3131 else if (
func->hasPersonalityFn())
3132 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3135 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3137 if (
func->hasAtLeastLocalUnnamedAddr())
3138 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3140 if (
func->hasSection())
3141 funcOp.setSection(StringRef(
func->getSection()));
3143 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3145 if (
func->hasComdat())
3146 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3148 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3149 funcOp.setAlignment(maybeAlign->value());
3156 func->getAllMetadata(allMetadata);
3157 for (
auto &[kind, node] : allMetadata) {
3158 if (!iface.isConvertibleMetadata(kind))
3160 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *
this))) {
3162 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
3167 if (
func->isDeclaration())
3176 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3177 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3182 for (llvm::BasicBlock &basicBlock : *
func) {
3184 if (!reachable.contains(&basicBlock)) {
3185 if (basicBlock.hasAddressTaken())
3187 <<
"unreachable block '" << basicBlock.getName()
3188 <<
"' with address taken";
3191 Region &body = funcOp.getBody();
3192 Block *block = builder.createBlock(&body, body.
end());
3194 reachableBasicBlocks.push_back(&basicBlock);
3198 for (
const auto &it : llvm::enumerate(
func->args())) {
3199 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3200 functionType.getParamType(it.index()), funcOp.getLoc());
3209 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3210 for (llvm::BasicBlock *basicBlock : blocks)
3211 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3216 if (failed(processDebugIntrinsics()))
3221 if (failed(processDebugRecords()))
3230 if (!dbgIntr->isKillLocation())
3232 llvm::Value *value = dbgIntr->getArgOperand(0);
3233 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3236 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3248 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3251 if (dominatedBlocks.empty())
3255 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3258 Value insertPt = argOperand;
3259 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3265 if (!insertionBlock->
empty() &&
3266 isa<LandingpadOp>(insertionBlock->
front()))
3267 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3275std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3276ModuleImport::processDebugOpArgumentsAndInsertionPt(
3278 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3279 llvm::Value *address,
3280 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3281 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3287 FailureOr<Value> argOperand = convertArgOperandToValue();
3288 if (
failed(argOperand)) {
3289 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3297 return {localVarAttr, debugImporter->translateExpression(expression),
3302ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3303 DominanceInfo &domInfo) {
3305 auto emitUnsupportedWarning = [&]() {
3306 if (emitExpensiveWarnings)
3311 OpBuilder::InsertionGuard guard(builder);
3312 auto convertArgOperandToValue = [&]() {
3318 if (dbgIntr->hasArgList())
3319 return emitUnsupportedWarning();
3326 return emitUnsupportedWarning();
3328 auto [localVariableAttr, locationExprAttr, locVal] =
3329 processDebugOpArgumentsAndInsertionPt(
3330 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3331 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3333 if (!localVariableAttr)
3334 return emitUnsupportedWarning();
3339 Operation *op =
nullptr;
3340 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3341 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3343 else if (isa<llvm::DbgValueInst>(dbgIntr))
3344 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3347 return emitUnsupportedWarning();
3350 setNonDebugMetadataAttrs(dbgIntr, op);
3355ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3356 DominanceInfo &domInfo) {
3357 OpBuilder::InsertionGuard guard(builder);
3359 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3360 if (!emitExpensiveWarnings)
3363 llvm::raw_string_ostream optionsStream(
options);
3364 dbgRecord.print(optionsStream);
3365 emitWarning(loc) <<
"unhandled debug variable record "
3366 << optionsStream.str();
3372 if (dbgRecord.hasArgList())
3373 return emitUnsupportedWarning();
3378 if (!dbgRecord.getAddress())
3379 return emitUnsupportedWarning();
3381 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3382 llvm::Value *value = dbgRecord.getAddress();
3385 auto it = valueMapping.find(value);
3386 if (it != valueMapping.end())
3387 return it->getSecond();
3390 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3391 return convertConstantExpr(constant);
3395 auto [localVariableAttr, locationExprAttr, locVal] =
3396 processDebugOpArgumentsAndInsertionPt(
3397 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3398 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3400 if (!localVariableAttr)
3401 return emitUnsupportedWarning();
3406 if (dbgRecord.isDbgDeclare())
3407 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3409 else if (dbgRecord.isDbgValue())
3410 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3413 return emitUnsupportedWarning();
3418LogicalResult ModuleImport::processDebugIntrinsics() {
3419 DominanceInfo domInfo;
3420 for (llvm::Instruction *inst : debugIntrinsics) {
3421 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3422 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3428LogicalResult ModuleImport::processDebugRecords() {
3429 DominanceInfo domInfo;
3430 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3431 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3437LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3439 builder.setInsertionPointToStart(block);
3440 for (llvm::Instruction &inst : *bb) {
3441 if (
failed(processInstruction(&inst)))
3446 if (debugIntrinsics.contains(&inst))
3453 setNonDebugMetadataAttrs(&inst, op);
3454 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3455 if (emitExpensiveWarnings) {
3456 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3462 if (bb->hasAddressTaken()) {
3463 OpBuilder::InsertionGuard guard(builder);
3464 builder.setInsertionPointToStart(block);
3466 BlockTagAttr::get(context, bb->getNumber()));
3471FailureOr<SmallVector<AccessGroupAttr>>
3473 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3479 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3482FailureOr<DereferenceableAttr>
3485 Location loc = mlirModule.getLoc();
3489 if (node->getNumOperands() != 1)
3490 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3491 <<
diagMD(node, llvmModule.get());
3493 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3494 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3495 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3496 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3497 "non-negative constant integer: "
3498 <<
diagMD(node, llvmModule.get());
3500 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3501 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3502 numBytesCst->getZExtValue(), mayBeNull);
3508 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3509 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3510 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3511 bool importStructsAsLiterals) {
3518 LLVMDialect::getDialectNamespace()));
3520 DLTIDialect::getDialectNamespace()));
3521 if (loadAllDialects)
3524 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3528 emitExpensiveWarnings, dropDICompositeTypeElements,
3529 preferUnregisteredIntrinsics,
3530 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.