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 (isa<llvm::ConstantAggregate>(constant) ||
1770 isa<llvm::ConstantAggregateZero>(constant)) {
1772 SmallVector<Value> elementValues;
1773 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1774 elementValues.reserve(constAgg->getNumOperands());
1775 for (llvm::Value *operand : constAgg->operands())
1778 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1779 unsigned numElements = constAgg->getElementCount().getFixedValue();
1780 elementValues.reserve(numElements);
1781 for (
unsigned i = 0, e = numElements; i != e; ++i)
1782 elementValues.push_back(
lookupValue(constAgg->getElementValue(i)));
1784 assert(llvm::count(elementValues,
nullptr) == 0 &&
1785 "expected all elements have been converted before");
1789 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1791 "unrecognized aggregate type");
1792 Value root = UndefOp::create(builder, loc, rootType);
1793 for (
const auto &it : llvm::enumerate(elementValues)) {
1794 if (isArrayOrStruct) {
1796 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1798 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1800 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1801 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1808 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1809 LLVMTargetExtType targetExtType =
1810 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1811 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1812 "target extension type does not support zero-initialization");
1815 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1818 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1822 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1823 return BlockAddressOp::create(
1825 BlockAddressAttr::get(context, fnSym, blockTag))
1829 StringRef error =
"";
1831 if (isa<llvm::ConstantPtrAuth>(constant))
1832 error =
" since ptrauth(...) is unsupported";
1834 if (isa<llvm::NoCFIValue>(constant))
1835 error =
" since no_cfi is unsupported";
1837 if (isa<llvm::GlobalValue>(constant))
1838 error =
" since global value is unsupported";
1840 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1843FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1847 assert(!valueMapping.contains(constant) &&
1848 "expected constant has not been converted before");
1849 assert(constantInsertionBlock &&
1850 "expected the constant insertion block to be non-null");
1853 OpBuilder::InsertionGuard guard(builder);
1854 if (!constantInsertionOp)
1855 builder.setInsertionPointToStart(constantInsertionBlock);
1857 builder.setInsertionPointAfter(constantInsertionOp);
1861 getConstantsToConvert(constant);
1862 for (llvm::Constant *constantToConvert : constantsToConvert) {
1863 FailureOr<Value> converted = convertConstant(constantToConvert);
1866 mapValue(constantToConvert, *converted);
1871 constantInsertionOp =
result.getDefiningOp();
1876 assert(!isa<llvm::MetadataAsValue>(value) &&
1877 "expected value to not be metadata");
1880 auto it = valueMapping.find(value);
1881 if (it != valueMapping.end())
1882 return it->getSecond();
1885 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1886 return convertConstantExpr(constant);
1888 Location loc = UnknownLoc::get(context);
1889 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
1891 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
1897 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
1900 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
1903 value = node->getValue();
1906 auto it = valueMapping.find(value);
1907 if (it != valueMapping.end())
1908 return it->getSecond();
1911 if (
auto *constant = dyn_cast<llvm::Constant>(value))
1912 return convertConstantExpr(constant);
1916FailureOr<SmallVector<Value>>
1919 remapped.reserve(values.size());
1920 for (llvm::Value *value : values) {
1922 if (failed(converted))
1924 remapped.push_back(*converted);
1934 assert(immArgPositions.size() == immArgAttrNames.size() &&
1935 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
1939 for (
auto [immArgPos, immArgName] :
1940 llvm::zip(immArgPositions, immArgAttrNames)) {
1941 auto &value = operands[immArgPos];
1942 auto *constant = llvm::cast<llvm::Constant>(value);
1944 assert(attr && attr.getType().isIntOrFloat() &&
1945 "expected immarg to be float or integer constant");
1946 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
1947 attrsOut.push_back({nameAttr, attr});
1952 for (llvm::Value *value : operands) {
1956 if (failed(mlirValue))
1958 valuesOut.push_back(*mlirValue);
1963 if (requiresOpBundles) {
1964 opBundleSizes.reserve(opBundles.size());
1965 opBundleTagAttrs.reserve(opBundles.size());
1967 for (
const llvm::OperandBundleUse &bundle : opBundles) {
1968 opBundleSizes.push_back(bundle.Inputs.size());
1969 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
1971 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
1972 auto operandMlirValue =
convertValue(opBundleOperand.get());
1973 if (failed(operandMlirValue))
1975 valuesOut.push_back(*operandMlirValue);
1980 auto opBundleSizesAttrNameAttr =
1981 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
1982 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
1984 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
1985 auto opBundleTagsAttrNameAttr =
1986 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
1987 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
1994 IntegerAttr integerAttr;
1996 bool success = succeeded(converted) &&
1998 assert(
success &&
"expected a constant integer value");
2004 FloatAttr floatAttr;
2008 assert(
success &&
"expected a constant float value");
2015 llvm::DILocalVariable *node =
nullptr;
2016 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2017 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2018 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2020 node = cast<llvm::DILocalVariable *>(valOrVariable);
2022 return debugImporter->translate(node);
2026 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2027 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2028 return debugImporter->translate(node);
2031FPExceptionBehaviorAttr
2033 auto *metadata = cast<llvm::MetadataAsValue>(value);
2034 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2035 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2036 llvm::convertStrToExceptionBehavior(mdstr->getString());
2037 assert(optLLVM &&
"Expecting FP exception behavior");
2038 return builder.getAttr<FPExceptionBehaviorAttr>(
2039 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2043 auto *metadata = cast<llvm::MetadataAsValue>(value);
2044 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2045 std::optional<llvm::RoundingMode> optLLVM =
2046 llvm::convertStrToRoundingMode(mdstr->getString());
2047 assert(optLLVM &&
"Expecting rounding mode");
2048 return builder.getAttr<RoundingModeAttr>(
2049 convertRoundingModeFromLLVM(*optLLVM));
2052FailureOr<SmallVector<AliasScopeAttr>>
2054 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2055 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2060 return debugImporter->translateLoc(loc);
2064ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2065 llvm::BasicBlock *
target,
2067 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2068 auto *phiInst = cast<llvm::PHINode>(&*inst);
2069 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2071 if (failed(converted))
2073 blockArguments.push_back(*converted);
2078FailureOr<SmallVector<Value>>
2079ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2080 bool allowInlineAsm) {
2081 bool isInlineAsm = callInst->isInlineAsm();
2082 if (isInlineAsm && !allowInlineAsm)
2092 llvm::Value *calleeOperand = callInst->getCalledOperand();
2093 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2097 operands.push_back(*called);
2100 SmallVector<llvm::Value *> args(callInst->args());
2101 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2105 llvm::append_range(operands, *arguments);
2113 LLVMFunctionType calleeType) {
2114 if (callType.getReturnType() != calleeType.getReturnType())
2117 if (calleeType.isVarArg()) {
2120 if (callType.getNumParams() < calleeType.getNumParams())
2125 if (callType.getNumParams() != calleeType.getNumParams())
2130 for (
auto [operandType, argumentType] :
2131 llvm::zip(callType.getParams(), calleeType.getParams()))
2132 if (operandType != argumentType)
2138FailureOr<LLVMFunctionType>
2139ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2140 bool &isIncompatibleCall) {
2141 isIncompatibleCall =
false;
2142 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2143 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2149 llvm::Value *calledOperand = callInst->getCalledOperand();
2150 FailureOr<LLVMFunctionType> callType =
2151 castOrFailure(
convertType(callInst->getFunctionType()));
2154 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2156 llvm::FunctionType *origCalleeType =
nullptr;
2158 origCalleeType = callee->getFunctionType();
2159 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2160 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2164 if (!origCalleeType)
2167 FailureOr<LLVMFunctionType> calleeType =
2175 isIncompatibleCall =
true;
2177 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2178 <<
" and " << *calleeType;
2185FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2186 llvm::Value *calledOperand = callInst->getCalledOperand();
2187 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2188 return SymbolRefAttr::get(context, calledOperand->getName());
2192LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2193 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2197 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2201ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2202 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2203 unsigned argIdx = 0;
2204 SmallVector<mlir::Attribute> opAttrs;
2205 bool hasIndirect =
false;
2207 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2209 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2214 if (ci.isIndirect) {
2215 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2216 SmallVector<mlir::NamedAttribute> attrs;
2217 attrs.push_back(builder.getNamedAttr(
2218 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2220 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2224 opAttrs.push_back(builder.getDictionaryAttr({}));
2230 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2234LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2237 if (inst->getOpcode() == llvm::Instruction::Br) {
2238 auto *brInst = cast<llvm::BranchInst>(inst);
2240 SmallVector<Block *> succBlocks;
2241 SmallVector<SmallVector<Value>> succBlockArgs;
2242 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2243 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2244 SmallVector<Value> blockArgs;
2245 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2248 succBlockArgs.push_back(blockArgs);
2251 if (!brInst->isConditional()) {
2252 auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),
2253 succBlocks.front());
2257 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2260 auto condBrOp = LLVM::CondBrOp::create(
2261 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2262 succBlocks.back(), succBlockArgs.back());
2266 if (inst->getOpcode() == llvm::Instruction::Switch) {
2267 auto *swInst = cast<llvm::SwitchInst>(inst);
2269 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2272 SmallVector<Value> defaultBlockArgs;
2274 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2275 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2279 unsigned numCases = swInst->getNumCases();
2280 SmallVector<SmallVector<Value>> caseOperands(numCases);
2281 SmallVector<ValueRange> caseOperandRefs(numCases);
2282 SmallVector<APInt> caseValues(numCases);
2283 SmallVector<Block *> caseBlocks(numCases);
2284 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2285 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2286 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2287 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2289 caseOperandRefs[it.index()] = caseOperands[it.index()];
2290 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2294 auto switchOp = SwitchOp::create(builder, loc, *condition,
2296 caseValues, caseBlocks, caseOperandRefs);
2300 if (inst->getOpcode() == llvm::Instruction::PHI) {
2302 mapValue(inst, builder.getInsertionBlock()->addArgument(
2306 if (inst->getOpcode() == llvm::Instruction::Call) {
2307 auto *callInst = cast<llvm::CallInst>(inst);
2308 llvm::Value *calledOperand = callInst->getCalledOperand();
2310 FailureOr<SmallVector<Value>> operands =
2311 convertCallOperands(callInst,
true);
2315 auto callOp = [&]() -> FailureOr<Operation *> {
2316 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2320 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2321 return InlineAsmOp::create(
2322 builder, loc, resultTy, *operands,
2323 builder.getStringAttr(asmI->getAsmString()),
2324 builder.getStringAttr(asmI->getConstraintString()),
2325 asmI->hasSideEffects(), asmI->isAlignStack(),
2326 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2327 AsmDialectAttr::get(
2328 mlirModule.getContext(),
2329 convertAsmDialectFromLLVM(asmI->getDialect())),
2333 bool isIncompatibleCall;
2334 FailureOr<LLVMFunctionType> funcTy =
2335 convertFunctionType(callInst, isIncompatibleCall);
2339 FlatSymbolRefAttr callee =
nullptr;
2340 if (isIncompatibleCall) {
2344 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2345 Value indirectCallVal = LLVM::AddressOfOp::create(
2346 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2347 operands->insert(operands->begin(), indirectCallVal);
2350 callee = convertCalleeName(callInst);
2352 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2354 if (
failed(convertCallAttributes(callInst, callOp)))
2359 if (!isIncompatibleCall)
2361 return callOp.getOperation();
2367 if (!callInst->getType()->isVoidTy())
2368 mapValue(inst, (*callOp)->getResult(0));
2373 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2374 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2376 SmallVector<Value> operands;
2377 operands.reserve(lpInst->getNumClauses());
2378 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2379 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2382 operands.push_back(*operand);
2387 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2391 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2392 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2394 if (invokeInst->isInlineAsm())
2395 return emitError(loc) <<
"invoke of inline assembly is not supported";
2397 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2403 bool invokeResultUsedInPhi = llvm::any_of(
2404 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2405 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2410 Block *directNormalDest = normalDest;
2411 if (invokeResultUsedInPhi) {
2416 OpBuilder::InsertionGuard g(builder);
2417 directNormalDest = builder.createBlock(normalDest);
2420 SmallVector<Value> unwindArgs;
2421 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2425 bool isIncompatibleInvoke;
2426 FailureOr<LLVMFunctionType> funcTy =
2427 convertFunctionType(invokeInst, isIncompatibleInvoke);
2431 FlatSymbolRefAttr calleeName =
nullptr;
2432 if (isIncompatibleInvoke) {
2436 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2437 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2438 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2439 operands->insert(operands->begin(), indirectInvokeVal);
2442 calleeName = convertCalleeName(invokeInst);
2447 auto invokeOp = InvokeOp::create(
2448 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2451 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2456 if (!isIncompatibleInvoke)
2459 if (!invokeInst->getType()->isVoidTy())
2460 mapValue(inst, invokeOp.getResults().front());
2464 SmallVector<Value> normalArgs;
2465 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2469 if (invokeResultUsedInPhi) {
2473 OpBuilder::InsertionGuard g(builder);
2474 builder.setInsertionPointToStart(directNormalDest);
2475 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2479 assert(llvm::none_of(
2481 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2482 "An llvm.invoke operation cannot pass its result as a block "
2484 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2489 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2490 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2491 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2492 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2501 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2509 auto gepOp = GEPOp::create(
2510 builder, loc, type, sourceElementType, *basePtr,
indices,
2511 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2516 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2517 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2519 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2523 SmallVector<Block *> succBlocks;
2524 SmallVector<SmallVector<Value>> succBlockArgs;
2525 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2526 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2527 SmallVector<Value> blockArgs;
2528 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2531 succBlockArgs.push_back(blockArgs);
2533 SmallVector<ValueRange> succBlockArgsRange =
2534 llvm::to_vector_of<ValueRange>(succBlockArgs);
2536 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2537 succBlockArgsRange, succBlocks);
2547 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2550LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2557 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2558 return convertIntrinsic(intrinsic);
2563 if (inst->DebugMarker) {
2564 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2566 if (
auto *dbgVariableRecord =
2567 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2572 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2573 if (!emitExpensiveWarnings)
2576 llvm::raw_string_ostream optionsStream(
options);
2577 dbgRecord.print(optionsStream);
2578 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2582 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2583 DILabelAttr labelAttr =
2584 debugImporter->translate(dbgLabelRecord->getLabel());
2586 return emitUnsupportedWarning();
2587 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2591 return emitUnsupportedWarning();
2596 return convertInstruction(inst);
2599FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2600 if (!f->hasPersonalityFn())
2603 llvm::Constant *pf = f->getPersonalityFn();
2607 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2611 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2612 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2613 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2614 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2615 return SymbolRefAttr::get(builder.getContext(), func->getName());
2618 return FlatSymbolRefAttr();
2622 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2624 auto othermem = convertModRefInfoFromLLVM(
2625 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2626 auto argMem = convertModRefInfoFromLLVM(
2627 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2628 auto inaccessibleMem = convertModRefInfoFromLLVM(
2629 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2630 auto errnoMem = convertModRefInfoFromLLVM(
2631 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2632 auto targetMem0 = convertModRefInfoFromLLVM(
2633 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2634 auto targetMem1 = convertModRefInfoFromLLVM(
2635 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2637 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2638 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2640 if (memAttr.isReadWrite())
2642 funcOp.setMemoryEffectsAttr(memAttr);
2648 StringLiteral(
"aarch64_in_za"),
2649 StringLiteral(
"aarch64_inout_za"),
2650 StringLiteral(
"aarch64_new_za"),
2651 StringLiteral(
"aarch64_out_za"),
2652 StringLiteral(
"aarch64_preserves_za"),
2653 StringLiteral(
"aarch64_pstate_sm_body"),
2654 StringLiteral(
"aarch64_pstate_sm_compatible"),
2655 StringLiteral(
"aarch64_pstate_sm_enabled"),
2656 StringLiteral(
"alwaysinline"),
2657 StringLiteral(
"convergent"),
2658 StringLiteral(
"denormal-fp-math"),
2659 StringLiteral(
"denormal-fp-math-f32"),
2660 StringLiteral(
"fp-contract"),
2661 StringLiteral(
"frame-pointer"),
2662 StringLiteral(
"inlinehint"),
2663 StringLiteral(
"instrument-function-entry"),
2664 StringLiteral(
"instrument-function-exit"),
2665 StringLiteral(
"memory"),
2666 StringLiteral(
"no-infs-fp-math"),
2667 StringLiteral(
"no-nans-fp-math"),
2668 StringLiteral(
"no-signed-zeros-fp-math"),
2669 StringLiteral(
"noinline"),
2670 StringLiteral(
"nounwind"),
2671 StringLiteral(
"optnone"),
2672 StringLiteral(
"target-features"),
2673 StringLiteral(
"tune-cpu"),
2674 StringLiteral(
"uwtable"),
2675 StringLiteral(
"vscale_range"),
2676 StringLiteral(
"willreturn"),
2683 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2684 llvm::AttributeList::AttrIndex::FunctionIndex);
2688 if (!passthroughAttr.empty())
2689 funcOp.setPassthroughAttr(passthroughAttr);
2693 LLVMFuncOp funcOp) {
2697 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
2698 funcOp.setNoInline(
true);
2699 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2700 funcOp.setAlwaysInline(
true);
2701 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
2702 funcOp.setInlineHint(
true);
2703 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2704 funcOp.setOptimizeNone(
true);
2705 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
2706 funcOp.setConvergent(
true);
2707 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
2708 funcOp.setNoUnwind(
true);
2709 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
2710 funcOp.setWillReturn(
true);
2712 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2713 funcOp.setArmStreaming(
true);
2714 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2715 funcOp.setArmLocallyStreaming(
true);
2716 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2717 funcOp.setArmStreamingCompatible(
true);
2719 if (
func->hasFnAttribute(
"aarch64_new_za"))
2720 funcOp.setArmNewZa(
true);
2721 else if (
func->hasFnAttribute(
"aarch64_in_za"))
2722 funcOp.setArmInZa(
true);
2723 else if (
func->hasFnAttribute(
"aarch64_out_za"))
2724 funcOp.setArmOutZa(
true);
2725 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
2726 funcOp.setArmInoutZa(
true);
2727 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
2728 funcOp.setArmPreservesZa(
true);
2730 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
2731 if (attr.isValid()) {
2733 auto intTy = IntegerType::get(context, 32);
2734 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2735 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2736 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2740 if (
func->hasFnAttribute(
"frame-pointer")) {
2741 StringRef stringRefFramePointerKind =
2742 func->getFnAttribute(
"frame-pointer").getValueAsString();
2743 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2744 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
2745 stringRefFramePointerKind)
2749 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
2750 attr.isStringAttribute())
2751 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2753 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
2754 attr.isStringAttribute())
2755 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
2757 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
2758 attr.isStringAttribute())
2759 funcOp.setTargetFeaturesAttr(
2760 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
2762 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
2763 attr.isStringAttribute())
2764 funcOp.setReciprocalEstimatesAttr(
2765 StringAttr::get(context, attr.getValueAsString()));
2767 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
2768 attr.isStringAttribute())
2769 funcOp.setPreferVectorWidth(attr.getValueAsString());
2771 if (llvm::Attribute attr =
func->getFnAttribute(
"no-infs-fp-math");
2772 attr.isStringAttribute())
2773 funcOp.setNoInfsFpMath(attr.getValueAsBool());
2775 if (llvm::Attribute attr =
func->getFnAttribute(
"no-nans-fp-math");
2776 attr.isStringAttribute())
2777 funcOp.setNoNansFpMath(attr.getValueAsBool());
2779 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
2780 attr.isStringAttribute())
2781 funcOp.setInstrumentFunctionEntry(
2782 StringAttr::get(context, attr.getValueAsString()));
2784 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
2785 attr.isStringAttribute())
2786 funcOp.setInstrumentFunctionExit(
2787 StringAttr::get(context, attr.getValueAsString()));
2789 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
2790 attr.isStringAttribute())
2791 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
2793 if (llvm::Attribute attr =
func->getFnAttribute(
"denormal-fp-math");
2794 attr.isStringAttribute())
2795 funcOp.setDenormalFpMathAttr(
2796 StringAttr::get(context, attr.getValueAsString()));
2798 if (llvm::Attribute attr =
func->getFnAttribute(
"denormal-fp-math-f32");
2799 attr.isStringAttribute())
2800 funcOp.setDenormalFpMathF32Attr(
2801 StringAttr::get(context, attr.getValueAsString()));
2803 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
2804 attr.isStringAttribute())
2805 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
2807 if (
func->hasUWTable()) {
2808 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
2809 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
2810 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
2815ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
2818 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
2820 if (!llvmAttr.isValid())
2825 if (llvmAttr.hasKindAsEnum() &&
2826 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
2827 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
2828 paramAttrs.push_back(
2834 if (llvmAttr.isTypeAttribute())
2835 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
2836 else if (llvmAttr.isIntAttribute())
2838 else if (llvmAttr.isEnumAttribute())
2840 else if (llvmAttr.isConstantRangeAttribute()) {
2841 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
2842 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
2845 llvm_unreachable(
"unexpected parameter attribute kind");
2847 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
2850 return builder.getDictionaryAttr(paramAttrs);
2854 LLVMFuncOp funcOp) {
2855 auto llvmAttrs = func->getAttributes();
2856 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
2857 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
2858 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
2862 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2863 if (!llvmResAttr.hasAttributes())
2865 funcOp.setResAttrsAttr(
2866 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
2870 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
2873 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
2874 immArgPositions.end());
2876 llvm::AttributeList llvmAttrs = call->getAttributes();
2878 bool anyArgAttrs =
false;
2879 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
2881 if (immArgPositionsSet.contains(i))
2883 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
2884 if (llvmArgAttrsSet.back().hasAttributes())
2889 for (
auto &dict : dictAttrs)
2890 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
2891 return builder.getArrayAttr(attrs);
2895 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
2896 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
2897 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
2901 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
2902 if (!llvmResAttr.hasAttributes())
2904 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
2905 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
2908template <
typename Op>
2910 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
2914LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
2919LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
2925 llvm::AttributeList callAttrs = inst->getAttributes();
2927 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
2928 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
2929 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
2930 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
2931 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
2933 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
2934 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
2936 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
2937 ModRefInfo othermem = convertModRefInfoFromLLVM(
2938 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2939 ModRefInfo argMem = convertModRefInfoFromLLVM(
2940 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2941 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
2942 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2943 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
2944 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2945 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
2946 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2947 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
2948 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2950 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
2951 errnoMem, targetMem0, targetMem1);
2953 if (!memAttr.isReadWrite())
2954 op.setMemoryEffectsAttr(memAttr);
2964 if (
func->isIntrinsic() &&
2965 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
2968 bool dsoLocal =
func->isDSOLocal();
2969 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
2973 builder.setInsertionPointToEnd(mlirModule.getBody());
2975 Location loc = debugImporter->translateFuncLocation(
func);
2976 LLVMFuncOp funcOp = LLVMFuncOp::create(
2977 builder, loc,
func->getName(), functionType,
2978 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
2983 funcOp.setPersonalityAttr(personality);
2984 else if (
func->hasPersonalityFn())
2985 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
2988 funcOp.setGarbageCollector(StringRef(
func->getGC()));
2990 if (
func->hasAtLeastLocalUnnamedAddr())
2991 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
2993 if (
func->hasSection())
2994 funcOp.setSection(StringRef(
func->getSection()));
2996 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
2998 if (
func->hasComdat())
2999 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3001 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3002 funcOp.setAlignment(maybeAlign->value());
3009 func->getAllMetadata(allMetadata);
3010 for (
auto &[kind, node] : allMetadata) {
3011 if (!iface.isConvertibleMetadata(kind))
3013 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *
this))) {
3015 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
3020 if (
func->isDeclaration())
3029 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3030 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3035 for (llvm::BasicBlock &basicBlock : *
func) {
3037 if (!reachable.contains(&basicBlock)) {
3038 if (basicBlock.hasAddressTaken())
3040 <<
"unreachable block '" << basicBlock.getName()
3041 <<
"' with address taken";
3044 Region &body = funcOp.getBody();
3045 Block *block = builder.createBlock(&body, body.
end());
3047 reachableBasicBlocks.push_back(&basicBlock);
3051 for (
const auto &it : llvm::enumerate(
func->args())) {
3052 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3053 functionType.getParamType(it.index()), funcOp.getLoc());
3062 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3063 for (llvm::BasicBlock *basicBlock : blocks)
3064 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3069 if (failed(processDebugIntrinsics()))
3074 if (failed(processDebugRecords()))
3083 if (!dbgIntr->isKillLocation())
3085 llvm::Value *value = dbgIntr->getArgOperand(0);
3086 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3089 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3101 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3104 if (dominatedBlocks.empty())
3108 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3111 Value insertPt = argOperand;
3112 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3118 if (!insertionBlock->
empty() &&
3119 isa<LandingpadOp>(insertionBlock->
front()))
3120 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3128std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3129ModuleImport::processDebugOpArgumentsAndInsertionPt(
3131 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3132 llvm::Value *address,
3133 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3134 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3140 FailureOr<Value> argOperand = convertArgOperandToValue();
3141 if (
failed(argOperand)) {
3142 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3150 return {localVarAttr, debugImporter->translateExpression(expression),
3155ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3156 DominanceInfo &domInfo) {
3158 auto emitUnsupportedWarning = [&]() {
3159 if (emitExpensiveWarnings)
3164 OpBuilder::InsertionGuard guard(builder);
3165 auto convertArgOperandToValue = [&]() {
3171 if (dbgIntr->hasArgList())
3172 return emitUnsupportedWarning();
3179 return emitUnsupportedWarning();
3181 auto [localVariableAttr, locationExprAttr, locVal] =
3182 processDebugOpArgumentsAndInsertionPt(
3183 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3184 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3186 if (!localVariableAttr)
3187 return emitUnsupportedWarning();
3192 Operation *op =
nullptr;
3193 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3194 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3196 else if (isa<llvm::DbgValueInst>(dbgIntr))
3197 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3200 return emitUnsupportedWarning();
3203 setNonDebugMetadataAttrs(dbgIntr, op);
3208ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3209 DominanceInfo &domInfo) {
3210 OpBuilder::InsertionGuard guard(builder);
3212 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3213 if (!emitExpensiveWarnings)
3216 llvm::raw_string_ostream optionsStream(
options);
3217 dbgRecord.print(optionsStream);
3218 emitWarning(loc) <<
"unhandled debug variable record "
3219 << optionsStream.str();
3225 if (dbgRecord.hasArgList())
3226 return emitUnsupportedWarning();
3231 if (!dbgRecord.getAddress())
3232 return emitUnsupportedWarning();
3234 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3235 llvm::Value *value = dbgRecord.getAddress();
3238 auto it = valueMapping.find(value);
3239 if (it != valueMapping.end())
3240 return it->getSecond();
3243 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3244 return convertConstantExpr(constant);
3248 auto [localVariableAttr, locationExprAttr, locVal] =
3249 processDebugOpArgumentsAndInsertionPt(
3250 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3251 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3253 if (!localVariableAttr)
3254 return emitUnsupportedWarning();
3259 if (dbgRecord.isDbgDeclare())
3260 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3262 else if (dbgRecord.isDbgValue())
3263 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3266 return emitUnsupportedWarning();
3271LogicalResult ModuleImport::processDebugIntrinsics() {
3272 DominanceInfo domInfo;
3273 for (llvm::Instruction *inst : debugIntrinsics) {
3274 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3275 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3281LogicalResult ModuleImport::processDebugRecords() {
3282 DominanceInfo domInfo;
3283 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3284 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3290LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3292 builder.setInsertionPointToStart(block);
3293 for (llvm::Instruction &inst : *bb) {
3294 if (
failed(processInstruction(&inst)))
3299 if (debugIntrinsics.contains(&inst))
3306 setNonDebugMetadataAttrs(&inst, op);
3307 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3308 if (emitExpensiveWarnings) {
3309 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3315 if (bb->hasAddressTaken()) {
3316 OpBuilder::InsertionGuard guard(builder);
3317 builder.setInsertionPointToStart(block);
3319 BlockTagAttr::get(context, bb->getNumber()));
3324FailureOr<SmallVector<AccessGroupAttr>>
3326 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3332 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3335FailureOr<DereferenceableAttr>
3338 Location loc = mlirModule.getLoc();
3342 if (node->getNumOperands() != 1)
3343 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3344 <<
diagMD(node, llvmModule.get());
3346 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3347 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3348 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3349 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3350 "non-negative constant integer: "
3351 <<
diagMD(node, llvmModule.get());
3353 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3354 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3355 numBytesCst->getZExtValue(), mayBeNull);
3361 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3362 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3363 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3364 bool importStructsAsLiterals) {
3371 LLVMDialect::getDialectNamespace()));
3373 DLTIDialect::getDialectNamespace()));
3374 if (loadAllDialects)
3377 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3381 emitExpensiveWarnings, dropDICompositeTypeElements,
3382 preferUnregisteredIntrinsics,
3383 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.