30#include "llvm/ADT/DepthFirstIterator.h"
31#include "llvm/ADT/PostOrderIterator.h"
32#include "llvm/ADT/ScopeExit.h"
33#include "llvm/ADT/StringExtras.h"
34#include "llvm/ADT/TypeSwitch.h"
35#include "llvm/IR/Comdat.h"
36#include "llvm/IR/Constants.h"
37#include "llvm/IR/DebugProgramInstruction.h"
38#include "llvm/IR/InlineAsm.h"
39#include "llvm/IR/InstIterator.h"
40#include "llvm/IR/Instructions.h"
41#include "llvm/IR/IntrinsicInst.h"
42#include "llvm/IR/Metadata.h"
43#include "llvm/IR/Operator.h"
44#include "llvm/Support/LogicalResult.h"
45#include "llvm/Support/ModRef.h"
52#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
57static std::string
diag(
const llvm::Value &value) {
59 llvm::raw_string_ostream os(str);
67static std::string
diagMD(
const llvm::Metadata *node,
68 const llvm::Module *module) {
70 llvm::raw_string_ostream os(str);
71 node->print(os, module,
true);
77 return "llvm.global_ctors";
82 return "mlir.llvm.nameless_global";
87 return "llvm.global_dtors";
93 return "__llvm_global_comdat";
102 std::optional<llvm::SyncScope::ID> syncScopeID =
103 llvm::getAtomicSyncScopeID(inst);
110 llvm::LLVMContext &llvmContext = inst->getContext();
111 llvmContext.getSyncScopeNames(syncScopeName);
112 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
113 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
115 if (it != syncScopeName.end())
117 llvm_unreachable(
"incorrect sync scope identifier");
123 llvm::append_range(position,
indices);
134 llvm::Instruction *inst,
147#include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
156 for (llvm::BasicBlock *basicBlock : basicBlocks) {
157 if (!blocks.contains(basicBlock)) {
158 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
159 blocks.insert_range(traversal);
162 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
167 std::unique_ptr<llvm::Module> llvmModule,
168 bool emitExpensiveWarnings,
169 bool importEmptyDICompositeTypes,
170 bool preferUnregisteredIntrinsics,
171 bool importStructsAsLiterals)
173 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
175 typeTranslator(*mlirModule->
getContext(), importStructsAsLiterals),
177 mlirModule, importEmptyDICompositeTypes)),
178 loopAnnotationImporter(
180 emitExpensiveWarnings(emitExpensiveWarnings),
181 preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
182 builder.setInsertionPointToStart(mlirModule.getBody());
185ComdatOp ModuleImport::getGlobalComdatOp() {
187 return globalComdatOp;
193 globalInsertionOp = globalComdatOp;
194 return globalComdatOp;
197LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
202 auto getIdentityIfRootNode =
203 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
207 if (node->getNumOperands() > 1)
210 if (node->getNumOperands() == 1)
211 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
212 return std::optional<StringRef>{op0->getString()};
213 return std::optional<StringRef>{};
223 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
224 StringRef *identity =
nullptr,
225 SmallVectorImpl<TBAAMemberAttr> *members =
226 nullptr) -> std::optional<bool> {
227 unsigned numOperands = node->getNumOperands();
236 const auto *identityNode =
237 dyn_cast<const llvm::MDString>(node->getOperand(0));
243 *identity = identityNode->getString();
245 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
246 const auto *memberNode =
247 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
249 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
250 <<
diagMD(node, llvmModule.get());
254 if (2 * pairNum + 2 >= numOperands) {
256 if (numOperands != 2) {
257 emitError(loc) <<
"missing member offset: "
258 <<
diagMD(node, llvmModule.get());
262 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
263 node->getOperand(2 * pairNum + 2));
265 emitError(loc) <<
"operand '" << 2 * pairNum + 2
266 <<
"' must be ConstantInt: "
267 <<
diagMD(node, llvmModule.get());
270 offset = offsetCI->getZExtValue();
274 members->push_back(TBAAMemberAttr::get(
275 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
288 auto isTagNode = [&](
const llvm::MDNode *node,
289 TBAATypeDescriptorAttr *baseAttr =
nullptr,
290 TBAATypeDescriptorAttr *accessAttr =
nullptr,
291 int64_t *offset =
nullptr,
292 bool *isConstant =
nullptr) -> std::optional<bool> {
300 unsigned numOperands = node->getNumOperands();
301 if (numOperands != 3 && numOperands != 4)
303 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
304 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
306 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
307 if (!baseMD || !accessMD || !offsetCI)
314 if (accessMD->getNumOperands() < 1 ||
315 !isa<llvm::MDString>(accessMD->getOperand(0)))
317 bool isConst =
false;
318 if (numOperands == 4) {
320 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
322 emitError(loc) <<
"operand '3' must be ConstantInt: "
323 <<
diagMD(node, llvmModule.get());
326 isConst = isConstantCI->getValue()[0];
329 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
331 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
333 *offset = offsetCI->getZExtValue();
335 *isConstant = isConst;
343 SmallVector<const llvm::MDNode *> workList;
344 workList.push_back(node);
345 while (!workList.empty()) {
346 const llvm::MDNode *current = workList.back();
347 if (tbaaMapping.contains(current)) {
356 bool anyChildNotConverted =
false;
357 for (
const llvm::MDOperand &operand : current->operands())
358 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
359 if (!tbaaMapping.contains(childNode)) {
360 workList.push_back(childNode);
361 anyChildNotConverted =
true;
364 if (anyChildNotConverted) {
369 if (!seen.insert(current).second)
370 return emitError(loc) <<
"has cycle in TBAA graph: "
371 <<
diagMD(current, llvmModule.get());
379 FailureOr<std::optional<StringRef>> rootNodeIdentity =
380 getIdentityIfRootNode(current);
381 if (succeeded(rootNodeIdentity)) {
382 StringAttr stringAttr = *rootNodeIdentity
383 ? builder.getStringAttr(**rootNodeIdentity)
387 tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)});
392 SmallVector<TBAAMemberAttr> members;
393 if (std::optional<bool> isValid =
394 isTypeDescriptorNode(current, &identity, &members)) {
395 assert(isValid.value() &&
"type descriptor node must be valid");
397 tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>(
398 identity, members)});
402 TBAATypeDescriptorAttr baseAttr, accessAttr;
405 if (std::optional<bool> isValid =
406 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
407 assert(isValid.value() &&
"access tag node must be valid");
409 {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
414 return emitError(loc) <<
"unsupported TBAA node format: "
415 <<
diagMD(current, llvmModule.get());
421ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
422 Location loc = mlirModule.getLoc();
423 if (
failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
424 return emitError(loc) <<
"unsupported access group node: "
425 <<
diagMD(node, llvmModule.get());
430ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
431 Location loc = mlirModule.getLoc();
433 auto verifySelfRef = [](
const llvm::MDNode *node) {
434 return node->getNumOperands() != 0 &&
435 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
437 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
438 return node->getNumOperands() != 0 &&
439 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
440 isa<llvm::MDString>(node->getOperand(0)));
443 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
444 return idx >= node->getNumOperands() ||
445 isa<llvm::MDString>(node->getOperand(idx));
448 auto getIdAttr = [&](
const llvm::MDNode *node) -> Attribute {
449 if (verifySelfRef(node))
452 auto *name = cast<llvm::MDString>(node->getOperand(0));
453 return builder.getStringAttr(name->getString());
457 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
458 StringAttr description =
nullptr;
459 if (aliasDomain->getNumOperands() >= 2)
460 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
461 description = builder.getStringAttr(operand->getString());
462 Attribute idAttr = getIdAttr(aliasDomain);
463 return builder.getAttr<AliasScopeDomainAttr>(idAttr, description);
467 for (
const llvm::MDOperand &operand : node->operands()) {
468 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
469 llvm::AliasScopeNode aliasScope(scope);
470 const llvm::MDNode *domain = aliasScope.getDomain();
476 if (!verifySelfRefOrString(scope) || !domain ||
477 !verifyDescription(scope, 2))
478 return emitError(loc) <<
"unsupported alias scope node: "
479 <<
diagMD(scope, llvmModule.get());
480 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
481 return emitError(loc) <<
"unsupported alias domain node: "
482 <<
diagMD(domain, llvmModule.get());
484 if (aliasScopeMapping.contains(scope))
488 auto it = aliasScopeMapping.find(aliasScope.getDomain());
489 if (it == aliasScopeMapping.end()) {
490 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
491 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
495 StringAttr description =
nullptr;
496 if (!aliasScope.getName().empty())
497 description = builder.getStringAttr(aliasScope.getName());
498 Attribute idAttr = getIdAttr(scope);
499 auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(
500 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
502 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
508FailureOr<SmallVector<AliasScopeAttr>>
511 aliasScopes.reserve(node->getNumOperands());
512 for (
const llvm::MDOperand &operand : node->operands()) {
513 auto *node = cast<llvm::MDNode>(operand.get());
514 aliasScopes.push_back(
515 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
518 if (llvm::is_contained(aliasScopes,
nullptr))
524 debugIntrinsics.insert(intrinsic);
528 if (!dbgRecords.contains(dbgRecord))
529 dbgRecords.insert(dbgRecord);
533 llvm::MDTuple *mdTuple) {
534 auto getLLVMFunction =
535 [&](
const llvm::MDOperand &funcMDO) -> llvm::Function * {
536 auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);
540 auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());
546 for (
unsigned i = 0; i < mdTuple->getNumOperands(); i++) {
547 const llvm::MDOperand &mdo = mdTuple->getOperand(i);
548 auto *cgEntry = cast<llvm::MDNode>(mdo);
549 llvm::Constant *llvmConstant =
550 cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();
551 uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();
552 auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));
553 auto *toFn = getLLVMFunction(cgEntry->getOperand(1));
555 cgProfile.push_back(ModuleFlagCGProfileEntryAttr::get(
556 mlirModule->getContext(),
564 return ArrayAttr::get(mlirModule->getContext(), cgProfile);
570 const llvm::Module *llvmModule,
571 const llvm::MDOperand &md) {
572 auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
573 if (!tupleEntry || tupleEntry->getNumOperands() != 2)
575 <<
"expected 2-element tuple metadata: " <<
diagMD(md, llvmModule);
583 ModuleOp mlirModule,
const llvm::Module *llvmModule,
584 const llvm::MDOperand &md, StringRef matchKey,
bool optional =
false) {
588 auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
589 if (!keyMD || keyMD->getString() != matchKey) {
592 <<
"expected '" << matchKey <<
"' key, but found: "
593 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
597 return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));
603static FailureOr<uint64_t>
605 const llvm::Module *llvmModule,
606 const llvm::MDOperand &md, StringRef matchKey) {
607 llvm::ConstantAsMetadata *valMD =
612 if (
auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))
613 return cstInt->getZExtValue();
616 <<
"expected integer metadata value for key '" << matchKey
617 <<
"': " <<
diagMD(md, llvmModule);
621static std::optional<ProfileSummaryFormatKind>
623 const llvm::MDOperand &formatMD) {
628 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
629 if (!keyMD || keyMD->getString() !=
"ProfileFormat") {
631 <<
"expected 'ProfileFormat' key: "
632 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
636 llvm::MDString *valMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(1));
637 std::optional<ProfileSummaryFormatKind> fmtKind =
638 symbolizeProfileSummaryFormatKind(valMD->getString());
641 <<
"expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
643 <<
diagMD(valMD, llvmModule);
650static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
652 const llvm::Module *llvmModule,
653 const llvm::MDOperand &summaryMD) {
658 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
659 if (!keyMD || keyMD->getString() !=
"DetailedSummary") {
661 <<
"expected 'DetailedSummary' key: "
662 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
666 llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
669 <<
"expected tuple value for 'DetailedSummary' key: "
670 <<
diagMD(tupleEntry->getOperand(1), llvmModule);
675 for (
auto &&entry : entriesMD->operands()) {
676 llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
677 if (!entryMD || entryMD->getNumOperands() != 3) {
679 <<
"'DetailedSummary' entry expects 3 operands: "
680 <<
diagMD(entry, llvmModule);
684 auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
685 auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
686 auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
687 if (!op0 || !op1 || !op2) {
689 <<
"expected only integer entries in 'DetailedSummary': "
690 <<
diagMD(entry, llvmModule);
694 auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get(
695 mlirModule->getContext(),
696 cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
697 cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
698 cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
699 detailedSummary.push_back(detaildSummaryEntry);
701 return detailedSummary;
706 const llvm::Module *llvmModule,
707 llvm::MDTuple *mdTuple) {
708 unsigned profileNumEntries = mdTuple->getNumOperands();
709 if (profileNumEntries < 8) {
711 <<
"expected at 8 entries in 'ProfileSummary': "
712 <<
diagMD(mdTuple, llvmModule);
716 unsigned summayIdx = 0;
717 auto checkOptionalPosition = [&](
const llvm::MDOperand &md,
718 StringRef matchKey) -> LogicalResult {
722 if (summayIdx + 1 >= profileNumEntries) {
724 <<
"the last summary entry is '" << matchKey
725 <<
"', expected 'DetailedSummary': " <<
diagMD(md, llvmModule);
732 auto getOptIntValue =
733 [&](
const llvm::MDOperand &md,
734 StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
737 return FailureOr<std::optional<uint64_t>>(std::nullopt);
738 if (checkOptionalPosition(md, matchKey).failed())
740 FailureOr<uint64_t> val =
747 auto getOptDoubleValue = [&](
const llvm::MDOperand &md,
748 StringRef matchKey) -> FailureOr<FloatAttr> {
753 if (
auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
754 if (checkOptionalPosition(md, matchKey).failed())
756 return FloatAttr::get(Float64Type::get(mlirModule.getContext()),
757 cstFP->getValueAPF());
760 <<
"expected double metadata value for key '" << matchKey
761 <<
"': " <<
diagMD(md, llvmModule);
768 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
769 if (!format.has_value())
773 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"TotalCount");
774 if (failed(totalCount))
778 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"MaxCount");
779 if (failed(maxCount))
783 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
785 if (failed(maxInternalCount))
789 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
791 if (failed(maxFunctionCount))
795 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumCounts");
796 if (failed(numCounts))
800 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumFunctions");
801 if (failed(numFunctions))
805 FailureOr<std::optional<uint64_t>> isPartialProfile =
806 getOptIntValue(mdTuple->getOperand(summayIdx),
"IsPartialProfile");
807 if (failed(isPartialProfile))
809 if (isPartialProfile->has_value())
812 FailureOr<FloatAttr> partialProfileRatio =
813 getOptDoubleValue(mdTuple->getOperand(summayIdx),
"PartialProfileRatio");
814 if (failed(partialProfileRatio))
816 if (*partialProfileRatio)
820 FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
822 mdTuple->getOperand(summayIdx));
823 if (failed(detailed))
827 return ModuleFlagProfileSummaryAttr::get(
828 mlirModule->getContext(), *format, *totalCount, *maxCount,
829 *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,
830 *isPartialProfile, *partialProfileRatio, *detailed);
837 const llvm::Module *llvmModule, StringRef key,
838 llvm::MDTuple *mdTuple) {
839 if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
841 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
849 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
852 for (
const auto [behavior, key, val] : llvmModuleFlags) {
854 if (
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
855 valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
856 }
else if (
auto *mdString = dyn_cast<llvm::MDString>(val)) {
857 valAttr = builder.getStringAttr(mdString->getString());
858 }
else if (
auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
860 key->getString(), mdTuple);
865 <<
"unsupported module flag value for key '" << key->getString()
866 <<
"' : " <<
diagMD(val, llvmModule.get());
870 moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
871 convertModFlagBehaviorFromLLVM(behavior),
872 builder.getStringAttr(key->getString()), valAttr));
875 if (!moduleFlags.empty())
876 LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),
877 builder.getArrayAttr(moduleFlags));
883 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
884 if (named.getName() !=
"llvm.linker.options")
887 for (
const llvm::MDNode *node : named.operands()) {
889 options.reserve(node->getNumOperands());
890 for (
const llvm::MDOperand &option : node->operands())
891 options.push_back(cast<llvm::MDString>(option)->getString());
892 LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),
893 builder.getStrArrayAttr(
options));
900 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
901 if (named.getName() !=
"llvm.dependent-libraries")
904 for (
const llvm::MDNode *node : named.operands()) {
905 if (node->getNumOperands() == 1)
906 if (
auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
907 libraries.push_back(mdString->getString());
909 if (!libraries.empty())
910 mlirModule->setAttr(LLVM::LLVMDialect::getDependentLibrariesAttrName(),
911 builder.getStrArrayAttr(libraries));
917 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
920 if (named.getName() != LLVMDialect::getIdentAttrName())
923 if (named.getNumOperands() == 1)
924 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
925 if (md->getNumOperands() == 1)
926 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
927 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
928 builder.getStringAttr(mdStr->getString()));
934 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
937 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
940 if (nmd.getNumOperands() == 1)
941 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
942 if (md->getNumOperands() == 1)
943 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
944 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
945 builder.getStringAttr(mdStr->getString()));
952 builder.setInsertionPointToEnd(mlirModule.getBody());
953 for (
const llvm::Function &
func : llvmModule->functions()) {
954 for (
const llvm::Instruction &inst : llvm::instructions(
func)) {
956 if (llvm::MDNode *node =
957 inst.getMetadata(llvm::LLVMContext::MD_access_group))
958 if (failed(processAccessGroupMetadata(node)))
962 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
963 if (!aliasAnalysisNodes)
965 if (aliasAnalysisNodes.TBAA)
966 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
968 if (aliasAnalysisNodes.Scope)
969 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
971 if (aliasAnalysisNodes.NoAlias)
972 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
989void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
990 if (comdatMapping.contains(comdat))
993 ComdatOp comdatOp = getGlobalComdatOp();
996 auto selectorOp = ComdatSelectorOp::create(
997 builder, mlirModule.getLoc(), comdat->getName(),
998 convertComdatFromLLVM(comdat->getSelectionKind()));
1002 comdatMapping.try_emplace(comdat, symbolRef);
1006 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1007 if (globalVar.hasComdat())
1008 processComdat(globalVar.getComdat());
1009 for (llvm::Function &
func : llvmModule->functions())
1010 if (
func.hasComdat())
1011 processComdat(
func.getComdat());
1016 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1019 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1020 return emitError(UnknownLoc::get(context))
1021 <<
"unhandled global variable: " <<
diag(globalVar);
1025 if (failed(convertGlobal(&globalVar))) {
1026 return emitError(UnknownLoc::get(context))
1027 <<
"unhandled global variable: " <<
diag(globalVar);
1034 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1035 if (failed(convertAlias(&alias))) {
1036 return emitError(UnknownLoc::get(context))
1037 <<
"unhandled global alias: " <<
diag(alias);
1044 for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1045 if (failed(convertIFunc(&ifunc))) {
1046 return emitError(UnknownLoc::get(context))
1047 <<
"unhandled global ifunc: " <<
diag(ifunc);
1054 Location loc = mlirModule.getLoc();
1056 context, llvmModule->getDataLayout().getStringRepresentation());
1058 return emitError(loc,
"cannot translate data layout: ")
1062 emitWarning(loc,
"unhandled data layout token: ") << token;
1064 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
1070 mlirModule->setAttr(
1071 LLVM::LLVMDialect::getTargetTripleAttrName(),
1072 builder.getStringAttr(llvmModule->getTargetTriple().str()));
1076 llvm::StringRef asmStr = llvmModule->getModuleInlineAsm();
1079 for (llvm::StringRef line : llvm::split(asmStr,
'\n'))
1081 asmArrayAttr.push_back(builder.getStringAttr(line));
1083 mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1084 builder.getArrayAttr(asmArrayAttr));
1088 for (llvm::Function &
func : llvmModule->functions())
1094void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1097 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1098 for (
auto &[kind, node] : allMetadata) {
1102 if (emitExpensiveWarnings) {
1103 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1105 <<
diagMD(node, llvmModule.get()) <<
" on "
1114 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1116 IntegerOverflowFlags value = {};
1117 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1119 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1121 iface.setOverflowFlags(value);
1125 auto iface = cast<ExactFlagInterface>(op);
1127 iface.setIsExact(inst->isExact());
1132 auto iface = cast<DisjointFlagInterface>(op);
1133 auto *instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1135 iface.setIsDisjoint(instDisjoint->isDisjoint());
1139 auto iface = cast<NonNegFlagInterface>(op);
1141 iface.setNonNeg(inst->hasNonNeg());
1146 auto iface = cast<FastmathFlagsInterface>(op);
1152 if (!isa<llvm::FPMathOperator>(inst))
1154 llvm::FastMathFlags flags = inst->getFastMathFlags();
1157 FastmathFlags value = {};
1158 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1159 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1160 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1161 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1162 value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
1163 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1164 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1165 FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
1166 iface->setAttr(iface.getFastmathAttrName(), attr);
1178 if (numElements.isScalable()) {
1180 <<
"scalable vectors not supported";
1185 Type elementType = cast<VectorType>(type).getElementType();
1189 SmallVector<int64_t> shape(arrayShape);
1190 shape.push_back(numElements.getKnownMinValue());
1191 return VectorType::get(shape, elementType);
1194Type ModuleImport::getBuiltinTypeForAttr(Type type) {
1208 SmallVector<int64_t> arrayShape;
1209 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1210 arrayShape.push_back(arrayType.getNumElements());
1211 type = arrayType.getElementType();
1214 return RankedTensorType::get(arrayShape, type);
1221 llvm::Constant *constScalar) {
1225 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1227 IntegerType::get(context, constInt->getBitWidth()),
1228 constInt->getValue());
1232 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1233 llvm::Type *type = constFloat->getType();
1234 FloatType floatType =
1236 ? BFloat16Type::get(context)
1240 <<
"unexpected floating-point type";
1243 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1250static SmallVector<Attribute>
1252 llvm::ConstantDataSequential *constSequence) {
1254 elementAttrs.reserve(constSequence->getNumElements());
1255 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1256 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1259 return elementAttrs;
1262Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1268 auto getConstantShape = [&](llvm::Type *type) {
1269 return llvm::dyn_cast_if_present<ShapedType>(
1275 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1276 if (constArray->isString())
1277 return builder.getStringAttr(constArray->getAsString());
1278 auto shape = getConstantShape(constArray->getType());
1282 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1283 if (constVector && constVector->isSplat()) {
1286 builder, constVector->getElementAsConstant(0));
1290 SmallVector<Attribute> elementAttrs =
1297 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1298 auto shape = getConstantShape(constAggregate->getType());
1302 SmallVector<Attribute> elementAttrs;
1303 SmallVector<llvm::Constant *> workList = {constAggregate};
1304 while (!workList.empty()) {
1305 llvm::Constant *current = workList.pop_back_val();
1308 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1310 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1311 workList.push_back(constAggregate->getAggregateElement(idx));
1316 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1317 SmallVector<Attribute> attrs =
1319 elementAttrs.append(attrs.begin(), attrs.end());
1325 elementAttrs.push_back(scalarAttr);
1336 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1337 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1338 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1342 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1343 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1350ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1351 assert(globalVar->getName().empty() &&
1352 "expected to work with a nameless global");
1353 auto [it,
success] = namelessGlobals.try_emplace(globalVar);
1360 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1363 it->getSecond() = symbolRef;
1367OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1368 OpBuilder::InsertionGuard guard(builder);
1369 if (globalInsertionOp)
1370 builder.setInsertionPointAfter(globalInsertionOp);
1372 builder.setInsertionPointToStart(mlirModule.getBody());
1376LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1378 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1381 AliasOp aliasOp = AliasOp::create(builder, mlirModule.getLoc(), type,
1382 convertLinkageFromLLVM(alias->getLinkage()),
1384 alias->isDSOLocal(),
1385 alias->isThreadLocal(),
1386 ArrayRef<NamedAttribute>());
1387 globalInsertionOp = aliasOp;
1390 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1391 setConstantInsertionPointToStart(block);
1392 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1395 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1397 if (alias->hasAtLeastLocalUnnamedAddr())
1398 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1399 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1404LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1405 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1408 llvm::Constant *resolver = ifunc->getResolver();
1409 Type resolverType =
convertType(resolver->getType());
1410 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1411 resolver->getName(), resolverType,
1412 convertLinkageFromLLVM(ifunc->getLinkage()),
1413 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1414 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1415 convertVisibilityFromLLVM(ifunc->getVisibility()));
1424 llvm::AttributeSet attributes,
1426 SmallVector<Attribute> mlirAttributes;
1427 for (llvm::Attribute attr : attributes) {
1429 if (attr.isStringAttribute())
1430 attrName = attr.getKindAsString();
1432 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1433 if (llvm::is_contained(attributesToSkip, attrName))
1436 auto keyAttr = StringAttr::get(context, attrName);
1437 if (attr.isStringAttribute()) {
1438 StringRef val = attr.getValueAsString();
1441 mlirAttributes.push_back(keyAttr);
1445 mlirAttributes.push_back(
1446 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1449 if (attr.isIntAttribute()) {
1452 auto val = std::to_string(attr.getValueAsInt());
1453 mlirAttributes.push_back(
1454 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1457 if (attr.isEnumAttribute()) {
1459 mlirAttributes.push_back(keyAttr);
1465 <<
"' attribute is invalid on current operation, skipping it";
1467 return ArrayAttr::get(context, mlirAttributes);
1473 GlobalOp globalOp) {
1475 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1476 if (!targetSpecificAttrs.empty())
1477 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1480LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1482 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1484 Attribute valueAttr;
1485 if (globalVar->hasInitializer())
1486 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1487 Type type =
convertType(globalVar->getValueType());
1489 uint64_t alignment = 0;
1490 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1491 if (maybeAlign.has_value()) {
1492 llvm::Align align = *maybeAlign;
1493 alignment = align.value();
1498 SmallVector<Attribute> globalExpressionAttrs;
1499 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1500 globalVar->getDebugInfo(globalExpressions);
1502 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1503 DIGlobalVariableExpressionAttr globalExpressionAttr =
1504 debugImporter->translateGlobalVariableExpression(expr);
1505 globalExpressionAttrs.push_back(globalExpressionAttr);
1510 StringRef globalName = globalVar->getName();
1511 if (globalName.empty())
1512 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1514 GlobalOp globalOp = GlobalOp::create(
1515 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1516 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1517 valueAttr, alignment, globalVar->getAddressSpace(),
1518 globalVar->isDSOLocal(),
1519 globalVar->isThreadLocal(), SymbolRefAttr(),
1520 ArrayRef<NamedAttribute>(), globalExpressionAttrs);
1521 globalInsertionOp = globalOp;
1523 if (globalVar->hasInitializer() && !valueAttr) {
1525 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1526 setConstantInsertionPointToStart(block);
1527 FailureOr<Value> initializer =
1528 convertConstantExpr(globalVar->getInitializer());
1531 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1533 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1534 globalOp.setUnnamedAddr(
1535 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1537 if (globalVar->hasSection())
1538 globalOp.setSection(globalVar->getSection());
1539 globalOp.setVisibility_(
1540 convertVisibilityFromLLVM(globalVar->getVisibility()));
1542 if (globalVar->hasComdat())
1543 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1551ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1552 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1554 llvm::Constant *initializer = globalVar->getInitializer();
1556 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1557 isa<llvm::ConstantAggregateZero>(initializer);
1564 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1565 if (caz->getElementCount().getFixedValue() != 0)
1569 SmallVector<Attribute> funcs;
1570 SmallVector<int32_t> priorities;
1571 SmallVector<Attribute> dataList;
1572 for (llvm::Value *operand : initializer->operands()) {
1573 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1574 if (!aggregate || aggregate->getNumOperands() != 3)
1577 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1578 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1579 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1580 if (!priority || !func || !data)
1583 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1587 else if (data->isNullValue())
1588 dataAttr = ZeroAttr::get(context);
1593 priorities.push_back(priority->getValue().getZExtValue());
1594 dataList.push_back(dataAttr);
1598 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1601 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1602 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1603 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1606 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1607 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1608 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1613ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1615 if (valueMapping.contains(constant))
1624 workList.insert(constant);
1625 while (!workList.empty()) {
1626 llvm::Constant *current = workList.back();
1629 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1630 orderedSet.insert(current);
1631 workList.pop_back();
1637 auto [adjacencyIt,
inserted] = adjacencyLists.try_emplace(current);
1641 for (llvm::Value *operand : current->operands())
1642 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1643 adjacencyIt->getSecond().push_back(constDependency);
1646 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1647 unsigned numElements = constAgg->getElementCount().getFixedValue();
1648 for (
unsigned i = 0, e = numElements; i != e; ++i)
1649 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1655 if (adjacencyIt->getSecond().empty()) {
1656 orderedSet.insert(current);
1657 workList.pop_back();
1665 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1666 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1667 orderedSet.contains(dependency))
1669 workList.insert(dependency);
1675FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1676 Location loc = UnknownLoc::get(context);
1679 if (Attribute attr = getConstantAsAttr(constant)) {
1681 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1682 return AddressOfOp::create(builder, loc, type, symbolRef.getValue())
1685 return ConstantOp::create(builder, loc, type, attr).getResult();
1689 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1691 return ZeroOp::create(builder, loc, type).getResult();
1695 if (isa<llvm::ConstantTokenNone>(constant)) {
1696 return NoneTokenOp::create(builder, loc).getResult();
1700 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1702 return PoisonOp::create(builder, loc, type).getResult();
1706 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1708 return UndefOp::create(builder, loc, type).getResult();
1712 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1713 Type type =
convertType(dsoLocalEquivalent->getType());
1714 return DSOLocalEquivalentOp::create(
1717 builder.getContext(),
1718 dsoLocalEquivalent->getGlobalValue()->getName()))
1723 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1725 StringRef globalName = globalObj->getName();
1726 FlatSymbolRefAttr symbolRef;
1728 if (globalName.empty())
1730 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1733 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1737 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1738 Type type =
convertType(globalAliasObj->getType());
1739 StringRef aliaseeName = globalAliasObj->getName();
1741 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1745 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1751 llvm::Instruction *inst = constExpr->getAsInstruction();
1752 auto guard = llvm::make_scope_exit([&]() {
1753 assert(!noResultOpMapping.contains(inst) &&
1754 "expected constant expression to return a result");
1755 valueMapping.erase(inst);
1756 inst->deleteValue();
1760 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1761 return valueMapping.contains(value);
1763 if (
failed(processInstruction(inst)))
1769 if (
auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1770 Type type =
convertType(aggregateZero->getType());
1771 return ZeroOp::create(builder, loc, type).getResult();
1775 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1777 SmallVector<Value> elementValues;
1779 elementValues.reserve(constAgg->getNumOperands());
1780 for (llvm::Value *operand : constAgg->operands())
1783 assert(llvm::count(elementValues,
nullptr) == 0 &&
1784 "expected all elements have been converted before");
1788 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1790 "unrecognized aggregate type");
1791 Value root = UndefOp::create(builder, loc, rootType);
1792 for (
const auto &it : llvm::enumerate(elementValues)) {
1793 if (isArrayOrStruct) {
1795 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1797 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1799 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1800 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1807 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1808 LLVMTargetExtType targetExtType =
1809 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1810 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1811 "target extension type does not support zero-initialization");
1814 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1817 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1821 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1822 return BlockAddressOp::create(
1824 BlockAddressAttr::get(context, fnSym, blockTag))
1828 StringRef error =
"";
1830 if (isa<llvm::ConstantPtrAuth>(constant))
1831 error =
" since ptrauth(...) is unsupported";
1833 if (isa<llvm::NoCFIValue>(constant))
1834 error =
" since no_cfi is unsupported";
1836 if (isa<llvm::GlobalValue>(constant))
1837 error =
" since global value is unsupported";
1839 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1842FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1846 assert(!valueMapping.contains(constant) &&
1847 "expected constant has not been converted before");
1848 assert(constantInsertionBlock &&
1849 "expected the constant insertion block to be non-null");
1852 OpBuilder::InsertionGuard guard(builder);
1853 if (!constantInsertionOp)
1854 builder.setInsertionPointToStart(constantInsertionBlock);
1856 builder.setInsertionPointAfter(constantInsertionOp);
1860 getConstantsToConvert(constant);
1861 for (llvm::Constant *constantToConvert : constantsToConvert) {
1862 FailureOr<Value> converted = convertConstant(constantToConvert);
1865 mapValue(constantToConvert, *converted);
1870 constantInsertionOp =
result.getDefiningOp();
1875 assert(!isa<llvm::MetadataAsValue>(value) &&
1876 "expected value to not be metadata");
1879 auto it = valueMapping.find(value);
1880 if (it != valueMapping.end())
1881 return it->getSecond();
1884 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1885 return convertConstantExpr(constant);
1887 Location loc = UnknownLoc::get(context);
1888 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1890 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1896 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1899 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1902 value = node->getValue();
1905 auto it = valueMapping.find(value);
1906 if (it != valueMapping.end())
1907 return it->getSecond();
1910 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1911 return convertConstantExpr(constant);
1915FailureOr<SmallVector<Value>>
1918 remapped.reserve(values.size());
1919 for (llvm::Value *value : values) {
1921 if (failed(converted))
1923 remapped.push_back(*converted);
1933 assert(immArgPositions.size() == immArgAttrNames.size() &&
1934 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1938 for (
auto [immArgPos, immArgName] :
1939 llvm::zip(immArgPositions, immArgAttrNames)) {
1940 auto &value = operands[immArgPos];
1941 auto *constant = llvm::cast<llvm::Constant>(value);
1943 assert(attr && attr.getType().isIntOrFloat() &&
1944 "expected immarg to be float or integer constant");
1945 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1946 attrsOut.push_back({nameAttr, attr});
1951 for (llvm::Value *value : operands) {
1955 if (failed(mlirValue))
1957 valuesOut.push_back(*mlirValue);
1962 if (requiresOpBundles) {
1963 opBundleSizes.reserve(opBundles.size());
1964 opBundleTagAttrs.reserve(opBundles.size());
1966 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1967 opBundleSizes.push_back(bundle.Inputs.size());
1968 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
1970 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1971 auto operandMlirValue =
convertValue(opBundleOperand.get());
1972 if (failed(operandMlirValue))
1974 valuesOut.push_back(*operandMlirValue);
1979 auto opBundleSizesAttrNameAttr =
1980 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
1981 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1983 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
1984 auto opBundleTagsAttrNameAttr =
1985 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
1986 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1993 IntegerAttr integerAttr;
1995 bool success = succeeded(converted) &&
1997 assert(
success &&
"expected a constant integer value");
2003 FloatAttr floatAttr;
2007 assert(
success &&
"expected a constant float value");
2014 llvm::DILocalVariable *node =
nullptr;
2015 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2016 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2017 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2019 node = cast<llvm::DILocalVariable *>(valOrVariable);
2021 return debugImporter->translate(node);
2025 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2026 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2027 return debugImporter->translate(node);
2030FPExceptionBehaviorAttr
2032 auto *metadata = cast<llvm::MetadataAsValue>(value);
2033 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2034 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2035 llvm::convertStrToExceptionBehavior(mdstr->getString());
2036 assert(optLLVM &&
"Expecting FP exception behavior");
2037 return builder.getAttr<FPExceptionBehaviorAttr>(
2038 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2042 auto *metadata = cast<llvm::MetadataAsValue>(value);
2043 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2044 std::optional<llvm::RoundingMode> optLLVM =
2045 llvm::convertStrToRoundingMode(mdstr->getString());
2046 assert(optLLVM &&
"Expecting rounding mode");
2047 return builder.getAttr<RoundingModeAttr>(
2048 convertRoundingModeFromLLVM(*optLLVM));
2051FailureOr<SmallVector<AliasScopeAttr>>
2053 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2054 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2059 return debugImporter->translateLoc(loc);
2063ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2064 llvm::BasicBlock *
target,
2066 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2067 auto *phiInst = cast<llvm::PHINode>(&*inst);
2068 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2070 if (failed(converted))
2072 blockArguments.push_back(*converted);
2077FailureOr<SmallVector<Value>>
2078ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2079 bool allowInlineAsm) {
2080 bool isInlineAsm = callInst->isInlineAsm();
2081 if (isInlineAsm && !allowInlineAsm)
2091 llvm::Value *calleeOperand = callInst->getCalledOperand();
2092 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2096 operands.push_back(*called);
2099 SmallVector<llvm::Value *> args(callInst->args());
2100 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2104 llvm::append_range(operands, *arguments);
2112 LLVMFunctionType calleeType) {
2113 if (callType.getReturnType() != calleeType.getReturnType())
2116 if (calleeType.isVarArg()) {
2119 if (callType.getNumParams() < calleeType.getNumParams())
2124 if (callType.getNumParams() != calleeType.getNumParams())
2129 for (
auto [operandType, argumentType] :
2130 llvm::zip(callType.getParams(), calleeType.getParams()))
2131 if (operandType != argumentType)
2137FailureOr<LLVMFunctionType>
2138ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2139 bool &isIncompatibleCall) {
2140 isIncompatibleCall =
false;
2141 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2142 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2148 llvm::Value *calledOperand = callInst->getCalledOperand();
2149 FailureOr<LLVMFunctionType> callType =
2150 castOrFailure(
convertType(callInst->getFunctionType()));
2153 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2155 llvm::FunctionType *origCalleeType =
nullptr;
2157 origCalleeType = callee->getFunctionType();
2158 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2159 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2163 if (!origCalleeType)
2166 FailureOr<LLVMFunctionType> calleeType =
2174 isIncompatibleCall =
true;
2176 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2177 <<
" and " << *calleeType;
2184FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2185 llvm::Value *calledOperand = callInst->getCalledOperand();
2186 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2187 return SymbolRefAttr::get(context, calledOperand->getName());
2191LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2192 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2196 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2200ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2201 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2202 unsigned argIdx = 0;
2203 SmallVector<mlir::Attribute> opAttrs;
2204 bool hasIndirect =
false;
2206 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2208 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2213 if (ci.isIndirect) {
2214 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2215 SmallVector<mlir::NamedAttribute> attrs;
2216 attrs.push_back(builder.getNamedAttr(
2217 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2219 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2223 opAttrs.push_back(builder.getDictionaryAttr({}));
2229 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2233LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2236 if (inst->getOpcode() == llvm::Instruction::Br) {
2237 auto *brInst = cast<llvm::BranchInst>(inst);
2239 SmallVector<Block *> succBlocks;
2240 SmallVector<SmallVector<Value>> succBlockArgs;
2241 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2242 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2243 SmallVector<Value> blockArgs;
2244 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2247 succBlockArgs.push_back(blockArgs);
2250 if (!brInst->isConditional()) {
2251 auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),
2252 succBlocks.front());
2256 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2259 auto condBrOp = LLVM::CondBrOp::create(
2260 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2261 succBlocks.back(), succBlockArgs.back());
2265 if (inst->getOpcode() == llvm::Instruction::Switch) {
2266 auto *swInst = cast<llvm::SwitchInst>(inst);
2268 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2271 SmallVector<Value> defaultBlockArgs;
2273 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2274 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2278 unsigned numCases = swInst->getNumCases();
2279 SmallVector<SmallVector<Value>> caseOperands(numCases);
2280 SmallVector<ValueRange> caseOperandRefs(numCases);
2281 SmallVector<APInt> caseValues(numCases);
2282 SmallVector<Block *> caseBlocks(numCases);
2283 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2284 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2285 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2286 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2288 caseOperandRefs[it.index()] = caseOperands[it.index()];
2289 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2293 auto switchOp = SwitchOp::create(builder, loc, *condition,
2295 caseValues, caseBlocks, caseOperandRefs);
2299 if (inst->getOpcode() == llvm::Instruction::PHI) {
2301 mapValue(inst, builder.getInsertionBlock()->addArgument(
2305 if (inst->getOpcode() == llvm::Instruction::Call) {
2306 auto *callInst = cast<llvm::CallInst>(inst);
2307 llvm::Value *calledOperand = callInst->getCalledOperand();
2309 FailureOr<SmallVector<Value>> operands =
2310 convertCallOperands(callInst,
true);
2314 auto callOp = [&]() -> FailureOr<Operation *> {
2315 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2319 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2320 return InlineAsmOp::create(
2321 builder, loc, resultTy, *operands,
2322 builder.getStringAttr(asmI->getAsmString()),
2323 builder.getStringAttr(asmI->getConstraintString()),
2324 asmI->hasSideEffects(), asmI->isAlignStack(),
2325 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2326 AsmDialectAttr::get(
2327 mlirModule.getContext(),
2328 convertAsmDialectFromLLVM(asmI->getDialect())),
2332 bool isIncompatibleCall;
2333 FailureOr<LLVMFunctionType> funcTy =
2334 convertFunctionType(callInst, isIncompatibleCall);
2338 FlatSymbolRefAttr callee =
nullptr;
2339 if (isIncompatibleCall) {
2343 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2344 Value indirectCallVal = LLVM::AddressOfOp::create(
2345 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2346 operands->insert(operands->begin(), indirectCallVal);
2349 callee = convertCalleeName(callInst);
2351 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2353 if (
failed(convertCallAttributes(callInst, callOp)))
2358 if (!isIncompatibleCall)
2360 return callOp.getOperation();
2366 if (!callInst->getType()->isVoidTy())
2367 mapValue(inst, (*callOp)->getResult(0));
2372 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2373 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2375 SmallVector<Value> operands;
2376 operands.reserve(lpInst->getNumClauses());
2377 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2378 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2381 operands.push_back(*operand);
2386 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2390 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2391 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2393 if (invokeInst->isInlineAsm())
2394 return emitError(loc) <<
"invoke of inline assembly is not supported";
2396 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2402 bool invokeResultUsedInPhi = llvm::any_of(
2403 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2404 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2409 Block *directNormalDest = normalDest;
2410 if (invokeResultUsedInPhi) {
2415 OpBuilder::InsertionGuard g(builder);
2416 directNormalDest = builder.createBlock(normalDest);
2419 SmallVector<Value> unwindArgs;
2420 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2424 bool isIncompatibleInvoke;
2425 FailureOr<LLVMFunctionType> funcTy =
2426 convertFunctionType(invokeInst, isIncompatibleInvoke);
2430 FlatSymbolRefAttr calleeName =
nullptr;
2431 if (isIncompatibleInvoke) {
2435 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2436 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2437 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2438 operands->insert(operands->begin(), indirectInvokeVal);
2441 calleeName = convertCalleeName(invokeInst);
2446 auto invokeOp = InvokeOp::create(
2447 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2450 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2455 if (!isIncompatibleInvoke)
2458 if (!invokeInst->getType()->isVoidTy())
2459 mapValue(inst, invokeOp.getResults().front());
2463 SmallVector<Value> normalArgs;
2464 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2468 if (invokeResultUsedInPhi) {
2472 OpBuilder::InsertionGuard g(builder);
2473 builder.setInsertionPointToStart(directNormalDest);
2474 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2478 assert(llvm::none_of(
2480 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2481 "An llvm.invoke operation cannot pass its result as a block "
2483 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2488 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2489 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2490 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2491 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2500 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2508 auto gepOp = GEPOp::create(
2509 builder, loc, type, sourceElementType, *basePtr,
indices,
2510 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2515 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2516 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2518 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2522 SmallVector<Block *> succBlocks;
2523 SmallVector<SmallVector<Value>> succBlockArgs;
2524 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2525 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2526 SmallVector<Value> blockArgs;
2527 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2530 succBlockArgs.push_back(blockArgs);
2532 SmallVector<ValueRange> succBlockArgsRange =
2533 llvm::to_vector_of<ValueRange>(succBlockArgs);
2535 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2536 succBlockArgsRange, succBlocks);
2546 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2549LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2556 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2557 return convertIntrinsic(intrinsic);
2562 if (inst->DebugMarker) {
2563 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2565 if (
auto *dbgVariableRecord =
2566 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2571 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2572 if (!emitExpensiveWarnings)
2575 llvm::raw_string_ostream optionsStream(
options);
2576 dbgRecord.print(optionsStream);
2577 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2581 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2582 DILabelAttr labelAttr =
2583 debugImporter->translate(dbgLabelRecord->getLabel());
2585 return emitUnsupportedWarning();
2586 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2590 return emitUnsupportedWarning();
2595 return convertInstruction(inst);
2598FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2599 if (!f->hasPersonalityFn())
2602 llvm::Constant *pf = f->getPersonalityFn();
2606 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2610 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2611 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2612 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2613 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2614 return SymbolRefAttr::get(builder.getContext(), func->getName());
2617 return FlatSymbolRefAttr();
2621 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2623 auto othermem = convertModRefInfoFromLLVM(
2624 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2625 auto argMem = convertModRefInfoFromLLVM(
2626 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2627 auto inaccessibleMem = convertModRefInfoFromLLVM(
2628 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2629 auto errnoMem = convertModRefInfoFromLLVM(
2630 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2631 auto targetMem0 = convertModRefInfoFromLLVM(
2632 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2633 auto targetMem1 = convertModRefInfoFromLLVM(
2634 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2636 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2637 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2639 if (memAttr.isReadWrite())
2641 funcOp.setMemoryEffectsAttr(memAttr);
2647 StringLiteral(
"aarch64_in_za"),
2648 StringLiteral(
"aarch64_inout_za"),
2649 StringLiteral(
"aarch64_new_za"),
2650 StringLiteral(
"aarch64_out_za"),
2651 StringLiteral(
"aarch64_preserves_za"),
2652 StringLiteral(
"aarch64_pstate_sm_body"),
2653 StringLiteral(
"aarch64_pstate_sm_compatible"),
2654 StringLiteral(
"aarch64_pstate_sm_enabled"),
2655 StringLiteral(
"alwaysinline"),
2656 StringLiteral(
"convergent"),
2657 StringLiteral(
"denormal-fp-math"),
2658 StringLiteral(
"denormal-fp-math-f32"),
2659 StringLiteral(
"fp-contract"),
2660 StringLiteral(
"frame-pointer"),
2661 StringLiteral(
"inlinehint"),
2662 StringLiteral(
"instrument-function-entry"),
2663 StringLiteral(
"instrument-function-exit"),
2664 StringLiteral(
"memory"),
2665 StringLiteral(
"no-infs-fp-math"),
2666 StringLiteral(
"no-nans-fp-math"),
2667 StringLiteral(
"no-signed-zeros-fp-math"),
2668 StringLiteral(
"noinline"),
2669 StringLiteral(
"nounwind"),
2670 StringLiteral(
"optnone"),
2671 StringLiteral(
"target-features"),
2672 StringLiteral(
"tune-cpu"),
2673 StringLiteral(
"uwtable"),
2674 StringLiteral(
"vscale_range"),
2675 StringLiteral(
"willreturn"),
2682 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2683 llvm::AttributeList::AttrIndex::FunctionIndex);
2687 if (!passthroughAttr.empty())
2688 funcOp.setPassthroughAttr(passthroughAttr);
2692 LLVMFuncOp funcOp) {
2696 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
2697 funcOp.setNoInline(
true);
2698 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2699 funcOp.setAlwaysInline(
true);
2700 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
2701 funcOp.setInlineHint(
true);
2702 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2703 funcOp.setOptimizeNone(
true);
2704 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
2705 funcOp.setConvergent(
true);
2706 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
2707 funcOp.setNoUnwind(
true);
2708 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
2709 funcOp.setWillReturn(
true);
2711 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2712 funcOp.setArmStreaming(
true);
2713 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2714 funcOp.setArmLocallyStreaming(
true);
2715 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2716 funcOp.setArmStreamingCompatible(
true);
2718 if (
func->hasFnAttribute(
"aarch64_new_za"))
2719 funcOp.setArmNewZa(
true);
2720 else if (
func->hasFnAttribute(
"aarch64_in_za"))
2721 funcOp.setArmInZa(
true);
2722 else if (
func->hasFnAttribute(
"aarch64_out_za"))
2723 funcOp.setArmOutZa(
true);
2724 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
2725 funcOp.setArmInoutZa(
true);
2726 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
2727 funcOp.setArmPreservesZa(
true);
2729 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
2730 if (attr.isValid()) {
2732 auto intTy = IntegerType::get(context, 32);
2733 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2734 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2735 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2739 if (
func->hasFnAttribute(
"frame-pointer")) {
2740 StringRef stringRefFramePointerKind =
2741 func->getFnAttribute(
"frame-pointer").getValueAsString();
2742 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2743 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2744 stringRefFramePointerKind)
2748 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
2749 attr.isStringAttribute())
2750 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2752 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
2753 attr.isStringAttribute())
2754 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2756 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
2757 attr.isStringAttribute())
2758 funcOp.setTargetFeaturesAttr(
2759 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2761 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
2762 attr.isStringAttribute())
2763 funcOp.setReciprocalEstimatesAttr(
2764 StringAttr::get(context, attr.getValueAsString()));
2766 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
2767 attr.isStringAttribute())
2768 funcOp.setPreferVectorWidth(attr.getValueAsString());
2770 if (llvm::Attribute attr =
func->getFnAttribute(
"no-infs-fp-math");
2771 attr.isStringAttribute())
2772 funcOp.setNoInfsFpMath(attr.getValueAsBool());
2774 if (llvm::Attribute attr =
func->getFnAttribute(
"no-nans-fp-math");
2775 attr.isStringAttribute())
2776 funcOp.setNoNansFpMath(attr.getValueAsBool());
2778 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
2779 attr.isStringAttribute())
2780 funcOp.setInstrumentFunctionEntry(
2781 StringAttr::get(context, attr.getValueAsString()));
2783 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
2784 attr.isStringAttribute())
2785 funcOp.setInstrumentFunctionExit(
2786 StringAttr::get(context, attr.getValueAsString()));
2788 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
2789 attr.isStringAttribute())
2790 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2792 if (llvm::Attribute attr =
func->getFnAttribute(
"denormal-fp-math");
2793 attr.isStringAttribute())
2794 funcOp.setDenormalFpMathAttr(
2795 StringAttr::get(context, attr.getValueAsString()));
2797 if (llvm::Attribute attr =
func->getFnAttribute(
"denormal-fp-math-f32");
2798 attr.isStringAttribute())
2799 funcOp.setDenormalFpMathF32Attr(
2800 StringAttr::get(context, attr.getValueAsString()));
2802 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
2803 attr.isStringAttribute())
2804 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2806 if (
func->hasUWTable()) {
2807 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
2808 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2809 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2814ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2817 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2819 if (!llvmAttr.isValid())
2824 if (llvmAttr.hasKindAsEnum() &&
2825 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2826 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2827 paramAttrs.push_back(
2833 if (llvmAttr.isTypeAttribute())
2834 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
2835 else if (llvmAttr.isIntAttribute())
2837 else if (llvmAttr.isEnumAttribute())
2839 else if (llvmAttr.isConstantRangeAttribute()) {
2840 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2841 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2844 llvm_unreachable(
"unexpected parameter attribute kind");
2846 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2849 return builder.getDictionaryAttr(paramAttrs);
2853 LLVMFuncOp funcOp) {
2854 auto llvmAttrs = func->getAttributes();
2855 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2856 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2857 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2861 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2862 if (!llvmResAttr.hasAttributes())
2864 funcOp.setResAttrsAttr(
2865 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2869 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2872 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2873 immArgPositions.end());
2875 llvm::AttributeList llvmAttrs = call->getAttributes();
2877 bool anyArgAttrs =
false;
2878 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
2880 if (immArgPositionsSet.contains(i))
2882 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
2883 if (llvmArgAttrsSet.back().hasAttributes())
2888 for (
auto &dict : dictAttrs)
2889 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
2890 return builder.getArrayAttr(attrs);
2894 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
2895 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
2896 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
2900 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2901 if (!llvmResAttr.hasAttributes())
2903 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
2904 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
2907template <
typename Op>
2909 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
2913LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
2918LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
2924 llvm::AttributeList callAttrs = inst->getAttributes();
2926 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
2927 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
2928 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
2929 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
2930 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
2932 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
2933 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
2935 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
2936 ModRefInfo othermem = convertModRefInfoFromLLVM(
2937 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2938 ModRefInfo argMem = convertModRefInfoFromLLVM(
2939 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2940 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
2941 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2942 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
2943 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2944 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
2945 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2946 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
2947 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2949 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
2950 errnoMem, targetMem0, targetMem1);
2952 if (!memAttr.isReadWrite())
2953 op.setMemoryEffectsAttr(memAttr);
2963 if (
func->isIntrinsic() &&
2964 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
2967 bool dsoLocal =
func->isDSOLocal();
2968 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
2972 builder.setInsertionPointToEnd(mlirModule.getBody());
2974 Location loc = debugImporter->translateFuncLocation(
func);
2975 LLVMFuncOp funcOp = LLVMFuncOp::create(
2976 builder, loc,
func->getName(), functionType,
2977 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
2982 funcOp.setPersonalityAttr(personality);
2983 else if (
func->hasPersonalityFn())
2984 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
2987 funcOp.setGarbageCollector(StringRef(
func->getGC()));
2989 if (
func->hasAtLeastLocalUnnamedAddr())
2990 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
2992 if (
func->hasSection())
2993 funcOp.setSection(StringRef(
func->getSection()));
2995 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
2997 if (
func->hasComdat())
2998 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3000 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3001 funcOp.setAlignment(maybeAlign->value());
3008 func->getAllMetadata(allMetadata);
3009 for (
auto &[kind, node] : allMetadata) {
3010 if (!iface.isConvertibleMetadata(kind))
3012 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *
this))) {
3014 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
3019 if (
func->isDeclaration())
3028 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3029 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3034 for (llvm::BasicBlock &basicBlock : *
func) {
3036 if (!reachable.contains(&basicBlock)) {
3037 if (basicBlock.hasAddressTaken())
3039 <<
"unreachable block '" << basicBlock.getName()
3040 <<
"' with address taken";
3043 Region &body = funcOp.getBody();
3044 Block *block = builder.createBlock(&body, body.
end());
3046 reachableBasicBlocks.push_back(&basicBlock);
3050 for (
const auto &it : llvm::enumerate(
func->args())) {
3051 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3052 functionType.getParamType(it.index()), funcOp.getLoc());
3061 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3062 for (llvm::BasicBlock *basicBlock : blocks)
3063 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3068 if (failed(processDebugIntrinsics()))
3073 if (failed(processDebugRecords()))
3082 if (!dbgIntr->isKillLocation())
3084 llvm::Value *value = dbgIntr->getArgOperand(0);
3085 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3088 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3100 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3103 if (dominatedBlocks.empty())
3107 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3110 Value insertPt = argOperand;
3111 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3117 if (!insertionBlock->
empty() &&
3118 isa<LandingpadOp>(insertionBlock->
front()))
3119 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3127std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3128ModuleImport::processDebugOpArgumentsAndInsertionPt(
3130 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3131 llvm::Value *address,
3132 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3133 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3139 FailureOr<Value> argOperand = convertArgOperandToValue();
3140 if (
failed(argOperand)) {
3141 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3149 return {localVarAttr, debugImporter->translateExpression(expression),
3154ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3155 DominanceInfo &domInfo) {
3157 auto emitUnsupportedWarning = [&]() {
3158 if (emitExpensiveWarnings)
3163 OpBuilder::InsertionGuard guard(builder);
3164 auto convertArgOperandToValue = [&]() {
3170 if (dbgIntr->hasArgList())
3171 return emitUnsupportedWarning();
3178 return emitUnsupportedWarning();
3180 auto [localVariableAttr, locationExprAttr, locVal] =
3181 processDebugOpArgumentsAndInsertionPt(
3182 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3183 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3185 if (!localVariableAttr)
3186 return emitUnsupportedWarning();
3191 Operation *op =
nullptr;
3192 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3193 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3195 else if (isa<llvm::DbgValueInst>(dbgIntr))
3196 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3199 return emitUnsupportedWarning();
3202 setNonDebugMetadataAttrs(dbgIntr, op);
3207ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3208 DominanceInfo &domInfo) {
3209 OpBuilder::InsertionGuard guard(builder);
3211 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3212 if (!emitExpensiveWarnings)
3215 llvm::raw_string_ostream optionsStream(
options);
3216 dbgRecord.print(optionsStream);
3217 emitWarning(loc) <<
"unhandled debug variable record "
3218 << optionsStream.str();
3224 if (dbgRecord.hasArgList())
3225 return emitUnsupportedWarning();
3230 if (!dbgRecord.getAddress())
3231 return emitUnsupportedWarning();
3233 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3234 llvm::Value *value = dbgRecord.getAddress();
3237 auto it = valueMapping.find(value);
3238 if (it != valueMapping.end())
3239 return it->getSecond();
3242 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3243 return convertConstantExpr(constant);
3247 auto [localVariableAttr, locationExprAttr, locVal] =
3248 processDebugOpArgumentsAndInsertionPt(
3249 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3250 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3252 if (!localVariableAttr)
3253 return emitUnsupportedWarning();
3258 if (dbgRecord.isDbgDeclare())
3259 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3261 else if (dbgRecord.isDbgValue())
3262 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3265 return emitUnsupportedWarning();
3270LogicalResult ModuleImport::processDebugIntrinsics() {
3271 DominanceInfo domInfo;
3272 for (llvm::Instruction *inst : debugIntrinsics) {
3273 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3274 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3280LogicalResult ModuleImport::processDebugRecords() {
3281 DominanceInfo domInfo;
3282 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3283 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3289LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3291 builder.setInsertionPointToStart(block);
3292 for (llvm::Instruction &inst : *bb) {
3293 if (
failed(processInstruction(&inst)))
3298 if (debugIntrinsics.contains(&inst))
3305 setNonDebugMetadataAttrs(&inst, op);
3306 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3307 if (emitExpensiveWarnings) {
3308 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3314 if (bb->hasAddressTaken()) {
3315 OpBuilder::InsertionGuard guard(builder);
3316 builder.setInsertionPointToStart(block);
3318 BlockTagAttr::get(context, bb->getNumber()));
3323FailureOr<SmallVector<AccessGroupAttr>>
3325 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3331 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3334FailureOr<DereferenceableAttr>
3337 Location loc = mlirModule.getLoc();
3341 if (node->getNumOperands() != 1)
3342 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3343 <<
diagMD(node, llvmModule.get());
3345 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3346 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3347 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3348 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3349 "non-negative constant integer: "
3350 <<
diagMD(node, llvmModule.get());
3352 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3353 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3354 numBytesCst->getZExtValue(), mayBeNull);
3360 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3361 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3362 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3363 bool importStructsAsLiterals) {
3370 LLVMDialect::getDialectNamespace()));
3372 DLTIDialect::getDialectNamespace()));
3373 if (loadAllDialects)
3376 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3380 emitExpensiveWarnings, dropDICompositeTypeElements,
3381 preferUnregisteredIntrinsics,
3382 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 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 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 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 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 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 ArrayAttr convertLLVMAttributesToMLIR(Location loc, MLIRContext *context, llvm::AttributeSet attributes, ArrayRef< StringLiteral > attributesToSkip={})
Converts LLVM string, integer, and enum attributes into MLIR attributes, skipping those in attributes...
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.