30#include "llvm/ADT/DepthFirstIterator.h"
31#include "llvm/ADT/PostOrderIterator.h"
32#include "llvm/ADT/ScopeExit.h"
33#include "llvm/ADT/SmallPtrSet.h"
34#include "llvm/ADT/StringExtras.h"
35#include "llvm/ADT/TypeSwitch.h"
36#include "llvm/IR/Comdat.h"
37#include "llvm/IR/Constants.h"
38#include "llvm/IR/DebugProgramInstruction.h"
39#include "llvm/IR/InlineAsm.h"
40#include "llvm/IR/InstIterator.h"
41#include "llvm/IR/Instructions.h"
42#include "llvm/IR/IntrinsicInst.h"
43#include "llvm/IR/Metadata.h"
44#include "llvm/IR/ModuleSlotTracker.h"
45#include "llvm/IR/Operator.h"
46#include "llvm/Support/LogicalResult.h"
47#include "llvm/Support/ModRef.h"
54#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
69 str +=
"... <truncated>";
76 llvm::ModuleSlotTracker &tracker,
77 const llvm::Module *module) {
79 llvm::raw_string_ostream os(str);
80 node->print(os, tracker, module,
true);
84llvm::ModuleSlotTracker &ModuleImport::getDiagSlotTracker() {
91 std::make_unique<llvm::ModuleSlotTracker>(llvmModule.get());
92 return *diagSlotTracker;
95std::string ModuleImport::renderValue(
const llvm::Value &value) {
97 llvm::raw_string_ostream os(str);
100 if (
const auto *global = llvm::dyn_cast<llvm::GlobalValue>(&value)) {
101 global->printAsOperand(os,
false, getDiagSlotTracker());
104 value.print(os, getDiagSlotTracker());
108std::string ModuleImport::renderMetadata(
const llvm::Metadata *node) {
115 return "llvm.global_ctors";
120 return "mlir.llvm.nameless_global";
125 return "llvm.global_dtors";
131 return "__llvm_global_comdat";
140 std::optional<llvm::SyncScope::ID> syncScopeID =
141 llvm::getAtomicSyncScopeID(inst);
148 llvm::LLVMContext &llvmContext = inst->getContext();
149 llvmContext.getSyncScopeNames(syncScopeName);
150 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
151 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
153 if (it != syncScopeName.end())
155 llvm_unreachable(
"incorrect sync scope identifier");
161 llvm::append_range(position,
indices);
172 llvm::Instruction *inst,
185#include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
191ModuleImport::getMetadataGlobalValueSymbolRef(llvm::GlobalValue *global) {
192 if (
auto *globalVar = dyn_cast<llvm::GlobalVariable>(global)) {
193 StringRef name = globalVar->getName();
195 return getOrCreateNamelessSymbolName(globalVar);
200 if (
auto *func = dyn_cast<llvm::Function>(global)) {
203 if (func->isIntrinsic() &&
204 iface.isConvertibleIntrinsic(func->getIntrinsicID()))
208 if (global->getName().empty())
214ModuleImport::getMetadataOperandSymbolRef(
const llvm::Metadata *md) {
215 auto *valueAsMD = dyn_cast_or_null<llvm::ValueAsMetadata>(md);
218 llvm::Value *value = valueAsMD->getValue();
219 llvm::GlobalValue *gv = dyn_cast<llvm::GlobalValue>(value);
221 gv = dyn_cast<llvm::GlobalValue>(value->stripPointerCastsAndAliases());
224 return getMetadataGlobalValueSymbolRef(gv);
236Attribute ModuleImport::convertMetadataToAttrImpl(
237 const llvm::Metadata *md, SmallPtrSetImpl<const llvm::Metadata *> &path,
241 if (
auto *mdStr = dyn_cast<llvm::MDString>(md))
242 return MDStringAttr::get(context,
243 StringAttr::get(context, mdStr->getString()));
244 if (
auto *cam = dyn_cast<llvm::ConstantAsMetadata>(md)) {
245 llvm::Constant *constant = cam->getValue();
246 if (
auto *global = dyn_cast<llvm::GlobalValue>(constant)) {
247 if (FlatSymbolRefAttr symbolRef = getMetadataGlobalValueSymbolRef(global))
248 return MDGlobalValueAttr::get(context, symbolRef);
250 if (
auto *ci = dyn_cast<llvm::ConstantInt>(constant)) {
251 auto intType = IntegerType::get(context, ci->getBitWidth());
252 return MDConstantAttr::get(context,
253 IntegerAttr::get(intType, ci->getValue()));
255 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant))
256 return MDNullAttr::get(context,
257 nullPtr->getType()->getPointerAddressSpace());
258 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
261 if (constExpr->getOpcode() != llvm::Instruction::AddrSpaceCast)
263 Attribute argAttr = convertMetadataToAttrImpl(
264 llvm::ConstantAsMetadata::get(constExpr->getOperand(0)), path,
268 return MDAddrSpaceCastAttr::get(
269 context, argAttr, constExpr->getType()->getPointerAddressSpace());
273 if (
auto *node = dyn_cast<llvm::MDNode>(md)) {
275 if (node->isDistinct())
277 if (Attribute cached = attrMap.lookup(node))
281 if (!path.insert(node).second)
283 SmallVector<Attribute> operands;
284 operands.reserve(node->getNumOperands());
285 for (
const llvm::MDOperand &op : node->operands()) {
286 Attribute opAttr = convertMetadataToAttrImpl(op.get(), path, attrMap);
289 operands.push_back(opAttr);
292 Attribute nodeAttr = MDNodeAttr::get(context, operands);
293 attrMap.try_emplace(node, nodeAttr);
304Attribute ModuleImport::convertMetadataToAttr(
const llvm::Metadata *md) {
305 SmallPtrSet<const llvm::Metadata *, 8> path;
307 return convertMetadataToAttrImpl(md, path, attrMap);
314 for (llvm::BasicBlock *basicBlock : basicBlocks) {
315 if (!blocks.contains(basicBlock)) {
316 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
317 blocks.insert_range(traversal);
320 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
327 std::unique_ptr<llvm::Module> llvmModule,
328 bool emitExpensiveWarnings,
329 bool importEmptyDICompositeTypes,
330 bool preferUnregisteredIntrinsics,
331 bool importStructsAsLiterals)
333 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
335 typeTranslator(*mlirModule->
getContext(), importStructsAsLiterals),
337 mlirModule, importEmptyDICompositeTypes)),
338 loopAnnotationImporter(
340 emitExpensiveWarnings(emitExpensiveWarnings),
341 preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
342 builder.setInsertionPointToStart(mlirModule.getBody());
345ComdatOp ModuleImport::getGlobalComdatOp() {
347 return globalComdatOp;
353 globalInsertionOp = globalComdatOp;
354 return globalComdatOp;
357LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
362 auto getIdentityIfRootNode =
363 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
367 if (node->getNumOperands() > 1)
370 if (node->getNumOperands() == 1)
371 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
372 return std::optional<StringRef>{op0->getString()};
373 return std::optional<StringRef>{};
383 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
384 StringRef *identity =
nullptr,
385 SmallVectorImpl<TBAAMemberAttr> *members =
386 nullptr) -> std::optional<bool> {
387 unsigned numOperands = node->getNumOperands();
396 const auto *identityNode =
397 dyn_cast<const llvm::MDString>(node->getOperand(0));
403 *identity = identityNode->getString();
405 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
406 const auto *memberNode =
407 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
409 emitError(loc) <<
"operand '" << 2 * pairNum + 1
410 <<
"' must be MDNode: " << renderMetadata(node);
414 if (2 * pairNum + 2 >= numOperands) {
416 if (numOperands != 2) {
417 emitError(loc) <<
"missing member offset: " << renderMetadata(node);
421 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
422 node->getOperand(2 * pairNum + 2));
424 emitError(loc) <<
"operand '" << 2 * pairNum + 2
425 <<
"' must be ConstantInt: " << renderMetadata(node);
428 offset = offsetCI->getZExtValue();
432 members->push_back(TBAAMemberAttr::get(
433 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
446 auto isTagNode = [&](
const llvm::MDNode *node,
447 TBAATypeDescriptorAttr *baseAttr =
nullptr,
448 TBAATypeDescriptorAttr *accessAttr =
nullptr,
449 int64_t *offset =
nullptr,
450 bool *isConstant =
nullptr) -> std::optional<bool> {
458 unsigned numOperands = node->getNumOperands();
459 if (numOperands != 3 && numOperands != 4)
461 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
462 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
464 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
465 if (!baseMD || !accessMD || !offsetCI)
472 if (accessMD->getNumOperands() < 1 ||
473 !isa<llvm::MDString>(accessMD->getOperand(0)))
475 bool isConst =
false;
476 if (numOperands == 4) {
478 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
480 emitError(loc) <<
"operand '3' must be ConstantInt: "
481 << renderMetadata(node);
484 isConst = isConstantCI->getValue()[0];
487 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
489 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
491 *offset = offsetCI->getZExtValue();
493 *isConstant = isConst;
501 SmallVector<const llvm::MDNode *> workList;
502 workList.push_back(node);
503 while (!workList.empty()) {
504 const llvm::MDNode *current = workList.back();
505 if (tbaaMapping.contains(current)) {
514 bool anyChildNotConverted =
false;
515 for (
const llvm::MDOperand &operand : current->operands())
516 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
517 if (!tbaaMapping.contains(childNode)) {
518 workList.push_back(childNode);
519 anyChildNotConverted =
true;
522 if (anyChildNotConverted) {
527 if (!seen.insert(current).second)
529 <<
"has cycle in TBAA graph: " << renderMetadata(current);
537 FailureOr<std::optional<StringRef>> rootNodeIdentity =
538 getIdentityIfRootNode(current);
539 if (succeeded(rootNodeIdentity)) {
540 StringAttr stringAttr = *rootNodeIdentity
541 ? builder.getStringAttr(**rootNodeIdentity)
545 tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)});
550 SmallVector<TBAAMemberAttr> members;
551 if (std::optional<bool> isValid =
552 isTypeDescriptorNode(current, &identity, &members)) {
553 assert(isValid.value() &&
"type descriptor node must be valid");
555 tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>(
556 identity, members)});
560 TBAATypeDescriptorAttr baseAttr, accessAttr;
563 if (std::optional<bool> isValid =
564 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
565 assert(isValid.value() &&
"access tag node must be valid");
567 {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
572 return emitError(loc) <<
"unsupported TBAA node format: "
573 << renderMetadata(current);
579ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
580 Location loc = mlirModule.getLoc();
581 if (
failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
582 return emitError(loc) <<
"unsupported access group node: "
583 << renderMetadata(node);
588ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
589 Location loc = mlirModule.getLoc();
591 auto verifySelfRef = [](
const llvm::MDNode *node) {
592 return node->getNumOperands() != 0 &&
593 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
595 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
596 return node->getNumOperands() != 0 &&
597 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
598 isa<llvm::MDString>(node->getOperand(0)));
601 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
602 return idx >= node->getNumOperands() ||
603 isa<llvm::MDString>(node->getOperand(idx));
606 auto getIdAttr = [&](
const llvm::MDNode *node) -> Attribute {
607 if (verifySelfRef(node))
610 auto *name = cast<llvm::MDString>(node->getOperand(0));
611 return builder.getStringAttr(name->getString());
615 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
616 StringAttr description =
nullptr;
617 StringRef descriptionStr =
618 llvm::AliasScopeDomainNode(aliasDomain).getDescription();
619 if (!descriptionStr.empty())
620 description = builder.getStringAttr(descriptionStr);
621 Attribute idAttr = getIdAttr(aliasDomain);
622 return builder.getAttr<AliasScopeDomainAttr>(idAttr, description);
626 for (
const llvm::MDOperand &operand : node->operands()) {
627 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
628 llvm::AliasScopeNode aliasScope(scope);
629 const llvm::MDNode *domain = aliasScope.getDomain();
635 if (!verifySelfRefOrString(scope) || !domain ||
636 !verifyDescription(scope, 2))
638 <<
"unsupported alias scope node: " << renderMetadata(scope);
639 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 2))
641 <<
"unsupported alias domain node: " << renderMetadata(domain);
643 if (aliasScopeMapping.contains(scope))
647 auto it = aliasScopeMapping.find(aliasScope.getDomain());
648 if (it == aliasScopeMapping.end()) {
649 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
650 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
654 StringAttr description =
nullptr;
655 if (!aliasScope.getName().empty())
656 description = builder.getStringAttr(aliasScope.getName());
657 Attribute idAttr = getIdAttr(scope);
658 auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(
659 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
661 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
667FailureOr<SmallVector<AliasScopeAttr>>
670 aliasScopes.reserve(node->getNumOperands());
671 for (
const llvm::MDOperand &operand : node->operands()) {
672 auto *node = cast<llvm::MDNode>(operand.get());
673 aliasScopes.push_back(
674 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
677 if (llvm::is_contained(aliasScopes,
nullptr))
683 debugIntrinsics.insert(intrinsic);
687 if (!dbgRecords.contains(dbgRecord))
688 dbgRecords.insert(dbgRecord);
692 llvm::MDTuple *mdTuple) {
693 auto getLLVMFunction =
694 [&](
const llvm::MDOperand &funcMDO) -> llvm::Function * {
695 auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);
699 auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());
705 for (
unsigned i = 0; i < mdTuple->getNumOperands(); i++) {
706 const llvm::MDOperand &mdo = mdTuple->getOperand(i);
707 auto *cgEntry = cast<llvm::MDNode>(mdo);
708 llvm::Constant *llvmConstant =
709 cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();
710 uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();
711 auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));
712 auto *toFn = getLLVMFunction(cgEntry->getOperand(1));
714 cgProfile.push_back(ModuleFlagCGProfileEntryAttr::get(
715 mlirModule->getContext(),
723 return ArrayAttr::get(mlirModule->getContext(), cgProfile);
729 const llvm::Module *llvmModule,
730 const llvm::MDOperand &md,
731 llvm::ModuleSlotTracker &tracker) {
732 auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
733 if (!tupleEntry || tupleEntry->getNumOperands() != 2)
735 <<
"expected 2-element tuple metadata: "
744 ModuleOp mlirModule,
const llvm::Module *llvmModule,
745 const llvm::MDOperand &md, StringRef matchKey,
746 llvm::ModuleSlotTracker &tracker,
bool optional =
false) {
747 llvm::MDTuple *tupleEntry =
751 auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
752 if (!keyMD || keyMD->getString() != matchKey) {
755 <<
"expected '" << matchKey <<
"' key, but found: "
761 return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));
767static FailureOr<uint64_t>
769 const llvm::Module *llvmModule,
770 const llvm::MDOperand &md, StringRef matchKey,
771 llvm::ModuleSlotTracker &tracker) {
773 mlirModule, llvmModule, md, matchKey, tracker);
777 if (
auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))
778 return cstInt->getZExtValue();
781 <<
"expected integer metadata value for key '" << matchKey
786static std::optional<ProfileSummaryFormatKind>
788 const llvm::MDOperand &formatMD,
789 llvm::ModuleSlotTracker &tracker) {
795 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
796 if (!keyMD || keyMD->getString() !=
"ProfileFormat") {
798 <<
"expected 'ProfileFormat' key: "
804 llvm::Metadata *valueMD = tupleEntry->getOperand(1).get();
807 <<
"expected string metadata value for key 'ProfileFormat': null";
811 llvm::MDString *valMD = dyn_cast<llvm::MDString>(valueMD);
814 <<
"expected string metadata value for key 'ProfileFormat': "
818 std::optional<ProfileSummaryFormatKind> fmtKind =
819 symbolizeProfileSummaryFormatKind(valMD->getString());
822 <<
"expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
831static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
833 const llvm::Module *llvmModule,
834 const llvm::MDOperand &summaryMD,
835 llvm::ModuleSlotTracker &tracker) {
841 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
842 if (!keyMD || keyMD->getString() !=
"DetailedSummary") {
844 <<
"expected 'DetailedSummary' key: "
850 llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
853 <<
"expected tuple value for 'DetailedSummary' key: "
860 for (
auto &&entry : entriesMD->operands()) {
861 llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
862 if (!entryMD || entryMD->getNumOperands() != 3) {
864 <<
"'DetailedSummary' entry expects 3 operands: "
869 auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
870 auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
871 auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
872 if (!op0 || !op1 || !op2) {
874 <<
"expected only integer entries in 'DetailedSummary': "
879 auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get(
880 mlirModule->getContext(),
881 cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
882 cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
883 cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
884 detailedSummary.push_back(detaildSummaryEntry);
886 return detailedSummary;
890 ModuleOp mlirModule,
const llvm::Module *llvmModule, llvm::MDTuple *mdTuple,
891 llvm::ModuleSlotTracker &tracker) {
892 unsigned profileNumEntries = mdTuple->getNumOperands();
893 if (profileNumEntries < 8) {
895 <<
"expected at 8 entries in 'ProfileSummary': "
900 unsigned summayIdx = 0;
901 auto checkOptionalPosition = [&](
const llvm::MDOperand &md,
902 StringRef matchKey) -> LogicalResult {
906 if (summayIdx + 1 >= profileNumEntries) {
908 <<
"the last summary entry is '" << matchKey
909 <<
"', expected 'DetailedSummary': "
917 auto getOptIntValue =
918 [&](
const llvm::MDOperand &md,
919 StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
923 return FailureOr<std::optional<uint64_t>>(std::nullopt);
924 if (checkOptionalPosition(md, matchKey).failed())
927 mlirModule, llvmModule, md, matchKey, tracker);
933 auto getOptDoubleValue = [&](
const llvm::MDOperand &md,
934 StringRef matchKey) -> FailureOr<FloatAttr> {
940 if (
auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
941 if (checkOptionalPosition(md, matchKey).failed())
943 return FloatAttr::get(Float64Type::get(mlirModule.getContext()),
944 cstFP->getValueAPF());
947 <<
"expected double metadata value for key '" << matchKey
955 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), tracker);
956 if (!format.has_value())
960 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"TotalCount",
962 if (failed(totalCount))
966 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"MaxCount",
968 if (failed(maxCount))
972 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
973 "MaxInternalCount", tracker);
974 if (failed(maxInternalCount))
978 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
979 "MaxFunctionCount", tracker);
980 if (failed(maxFunctionCount))
984 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumCounts",
986 if (failed(numCounts))
990 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumFunctions",
992 if (failed(numFunctions))
996 FailureOr<std::optional<uint64_t>> isPartialProfile =
997 getOptIntValue(mdTuple->getOperand(summayIdx),
"IsPartialProfile");
998 if (failed(isPartialProfile))
1000 if (isPartialProfile->has_value())
1003 FailureOr<FloatAttr> partialProfileRatio =
1004 getOptDoubleValue(mdTuple->getOperand(summayIdx),
"PartialProfileRatio");
1005 if (failed(partialProfileRatio))
1007 if (*partialProfileRatio)
1011 FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
1013 mdTuple->getOperand(summayIdx), tracker);
1014 if (failed(detailed))
1018 return ModuleFlagProfileSummaryAttr::get(
1019 mlirModule->getContext(), *format, *totalCount, *maxCount,
1020 *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,
1021 *isPartialProfile, *partialProfileRatio, *detailed);
1027 ModuleOp mlirModule,
const llvm::Module *llvmModule, StringRef key,
1028 llvm::MDTuple *mdTuple, llvm::ModuleSlotTracker &tracker) {
1029 if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
1031 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
1036 Builder builder(mlirModule->getContext());
1038 strings.reserve(mdTuple->getNumOperands());
1039 for (
const llvm::MDOperand &operand : mdTuple->operands()) {
1040 auto *mdString = dyn_cast_if_present<llvm::MDString>(operand.get());
1043 strings.push_back(builder.
getStringAttr(mdString->getString()));
1050 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
1053 for (
const auto [behavior, key, val] : llvmModuleFlags) {
1055 if (
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
1056 valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
1057 }
else if (
auto *mdString = dyn_cast<llvm::MDString>(val)) {
1058 valAttr = builder.getStringAttr(mdString->getString());
1059 }
else if (
auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
1061 key->getString(), mdTuple,
1062 getDiagSlotTracker());
1067 <<
"unsupported module flag value for key '" << key->getString()
1068 <<
"' : " << renderMetadata(val);
1072 moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
1073 convertModFlagBehaviorFromLLVM(behavior),
1074 builder.getStringAttr(key->getString()), valAttr));
1077 if (!moduleFlags.empty())
1078 LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),
1079 builder.getArrayAttr(moduleFlags));
1085 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1086 if (named.getName() !=
"llvm.linker.options")
1089 for (
const llvm::MDNode *node : named.operands()) {
1091 options.reserve(node->getNumOperands());
1092 for (
const llvm::MDOperand &option : node->operands())
1093 options.push_back(cast<llvm::MDString>(option)->getString());
1094 LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),
1095 builder.getStrArrayAttr(
options));
1102 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1103 if (named.getName() !=
"llvm.dependent-libraries")
1106 for (
const llvm::MDNode *node : named.operands()) {
1107 if (node->getNumOperands() == 1)
1108 if (
auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
1109 libraries.push_back(mdString->getString());
1111 if (!libraries.empty())
1112 mlirModule->setDiscardableAttr(
1113 LLVM::LLVMDialect::getDependentLibrariesAttrName(),
1114 builder.getStrArrayAttr(libraries));
1120 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1123 if (named.getName() != LLVMDialect::getIdentAttrName())
1126 if (named.getNumOperands() == 1)
1127 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
1128 if (md->getNumOperands() == 1)
1129 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
1130 mlirModule->setDiscardableAttr(
1131 LLVMDialect::getIdentAttrName(),
1132 builder.getStringAttr(mdStr->getString()));
1138 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
1141 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
1144 if (nmd.getNumOperands() == 1)
1145 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
1146 if (md->getNumOperands() == 1)
1147 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
1148 mlirModule->setDiscardableAttr(
1149 LLVMDialect::getCommandlineAttrName(),
1150 builder.getStringAttr(mdStr->getString()));
1157 builder.setInsertionPointToEnd(mlirModule.getBody());
1158 for (
const llvm::Function &
func : llvmModule->functions()) {
1159 for (
const llvm::Instruction &inst : llvm::instructions(
func)) {
1161 if (llvm::MDNode *node =
1162 inst.getMetadata(llvm::LLVMContext::MD_access_group))
1163 if (failed(processAccessGroupMetadata(node)))
1167 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
1168 if (!aliasAnalysisNodes)
1170 if (aliasAnalysisNodes.TBAA)
1171 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
1173 if (aliasAnalysisNodes.Scope)
1174 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
1176 if (aliasAnalysisNodes.NoAlias)
1177 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
1194void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
1195 if (comdatMapping.contains(comdat))
1198 ComdatOp comdatOp = getGlobalComdatOp();
1201 auto selectorOp = ComdatSelectorOp::create(
1202 builder, mlirModule.getLoc(), comdat->getName(),
1203 convertComdatFromLLVM(comdat->getSelectionKind()),
1208 comdatMapping.try_emplace(comdat, symbolRef);
1212 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1213 if (globalVar.hasComdat())
1214 processComdat(globalVar.getComdat());
1215 for (llvm::Function &
func : llvmModule->functions())
1216 if (
func.hasComdat())
1217 processComdat(
func.getComdat());
1222 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1225 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1226 return emitError(UnknownLoc::get(context))
1227 <<
"unhandled global variable: " << renderValue(globalVar);
1231 if (failed(convertGlobal(&globalVar))) {
1232 return emitError(UnknownLoc::get(context))
1233 <<
"unhandled global variable: " << renderValue(globalVar);
1240 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1241 if (failed(convertAlias(&alias))) {
1242 return emitError(UnknownLoc::get(context))
1243 <<
"unhandled global alias: " << renderValue(alias);
1250 for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1251 if (failed(convertIFunc(&ifunc))) {
1252 return emitError(UnknownLoc::get(context))
1253 <<
"unhandled global ifunc: " << renderValue(ifunc);
1260 Location loc = mlirModule.getLoc();
1262 context, llvmModule->getDataLayout().getStringRepresentation());
1264 return emitError(loc,
"cannot translate data layout: ")
1268 emitWarning(loc,
"unhandled data layout token: ") << token;
1270 mlirModule->setDiscardableAttr(DLTIDialect::kDataLayoutAttrName,
1276 mlirModule->setDiscardableAttr(
1277 LLVM::LLVMDialect::getTargetTripleAttrName(),
1278 builder.getStringAttr(llvmModule->getTargetTriple().str()));
1284 for (
const llvm::Module::GlobalAsmFragment &Frag :
1285 llvmModule->getModuleInlineAsm()) {
1287 for (llvm::StringRef line : llvm::split(Frag.Asm,
'\n'))
1289 asmArrayAttr.push_back(builder.getStringAttr(line));
1292 mlirModule->setDiscardableAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1293 builder.getArrayAttr(asmArrayAttr));
1297 for (llvm::Function &
func : llvmModule->functions())
1303void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1306 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1307 for (
auto &[kind, node] : allMetadata) {
1311 if (emitExpensiveWarnings) {
1312 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1313 emitWarning(loc) <<
"unhandled metadata: " << renderMetadata(node)
1314 <<
" on " << renderValue(*inst);
1322 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1324 IntegerOverflowFlags value = {};
1325 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1327 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1329 iface.setOverflowFlags(value);
1333 auto iface = cast<ExactFlagInterface>(op);
1335 iface.setIsExact(inst->isExact());
1340 auto iface = cast<DisjointFlagInterface>(op);
1341 auto *instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1343 iface.setIsDisjoint(instDisjoint->isDisjoint());
1347 auto iface = cast<NonNegFlagInterface>(op);
1349 iface.setNonNeg(inst->hasNonNeg());
1354 auto iface = cast<FastmathFlagsInterface>(op);
1360 if (!isa<llvm::FPMathOperator>(inst))
1362 llvm::FastMathFlags flags = inst->getFastMathFlags();
1365 FastmathFlags value = {};
1366 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1367 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1368 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1369 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1370 value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
1371 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1372 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1373 FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
1374 iface.setFastmathAttr(attr);
1386 if (numElements.isScalable()) {
1388 <<
"scalable vectors not supported";
1393 Type elementType = cast<VectorType>(type).getElementType();
1397 SmallVector<int64_t> shape(arrayShape);
1398 shape.push_back(numElements.getKnownMinValue());
1399 return VectorType::get(shape, elementType);
1402Type ModuleImport::getBuiltinTypeForAttr(Type type) {
1416 SmallVector<int64_t> arrayShape;
1417 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1418 arrayShape.push_back(arrayType.getNumElements());
1419 type = arrayType.getElementType();
1422 return RankedTensorType::get(arrayShape, type);
1429 llvm::Constant *constScalar) {
1432 if (constScalar->getType()->isVectorTy())
1436 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1438 IntegerType::get(context, constInt->getBitWidth()),
1439 constInt->getValue());
1443 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1444 llvm::Type *type = constFloat->getType();
1445 FloatType floatType =
1447 ? BFloat16Type::get(context)
1451 <<
"unexpected floating-point type";
1454 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1461static SmallVector<Attribute>
1463 llvm::ConstantDataSequential *constSequence) {
1465 elementAttrs.reserve(constSequence->getNumElements());
1466 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1467 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1470 return elementAttrs;
1473Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1479 auto getConstantShape = [&](llvm::Type *type) {
1480 return llvm::dyn_cast_if_present<ShapedType>(
1485 if (isa<llvm::ConstantInt, llvm::ConstantFP>(constant)) {
1486 assert(constant->getType()->isVectorTy() &&
"expected a vector splat");
1487 auto shape = getConstantShape(constant->getType());
1490 Attribute splatAttr =
1497 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1498 if (constArray->isString())
1499 return builder.getStringAttr(constArray->getAsString());
1500 auto shape = getConstantShape(constArray->getType());
1504 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1505 if (constVector && constVector->isSplat()) {
1508 builder, constVector->getElementAsConstant(0));
1512 SmallVector<Attribute> elementAttrs =
1519 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1520 auto shape = getConstantShape(constAggregate->getType());
1524 SmallVector<Attribute> elementAttrs;
1525 SmallVector<llvm::Constant *> workList = {constAggregate};
1526 while (!workList.empty()) {
1527 llvm::Constant *current = workList.pop_back_val();
1530 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1532 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1533 workList.push_back(constAggregate->getAggregateElement(idx));
1538 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1539 SmallVector<Attribute> attrs =
1541 elementAttrs.append(attrs.begin(), attrs.end());
1547 elementAttrs.push_back(scalarAttr);
1558 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1559 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1560 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1564 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1565 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1572ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1573 assert(globalVar->getName().empty() &&
1574 "expected to work with a nameless global");
1575 auto [it,
success] = namelessGlobals.try_emplace(globalVar);
1582 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1585 it->getSecond() = symbolRef;
1589OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1590 OpBuilder::InsertionGuard guard(builder);
1591 if (globalInsertionOp)
1592 builder.setInsertionPointAfter(globalInsertionOp);
1594 builder.setInsertionPointToStart(mlirModule.getBody());
1598LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1600 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1603 AliasOp aliasOp = AliasOp::create(
1604 builder, mlirModule.getLoc(), type,
1605 convertLinkageFromLLVM(alias->getLinkage()), alias->getName(),
1606 alias->isDSOLocal(),
1607 convertThreadLocalModeFromLLVM(alias->getThreadLocalMode()),
1608 ArrayRef<NamedAttribute>());
1609 globalInsertionOp = aliasOp;
1612 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1613 setConstantInsertionPointToStart(block);
1614 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1617 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1619 if (alias->hasAtLeastLocalUnnamedAddr())
1620 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1621 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1626LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1627 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1630 llvm::Constant *resolver = ifunc->getResolver();
1631 Type resolverType =
convertType(resolver->getType());
1632 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1633 resolver->getName(), resolverType,
1634 convertLinkageFromLLVM(ifunc->getLinkage()),
1635 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1636 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1637 convertVisibilityFromLLVM(ifunc->getVisibility()),
1648 ArrayRef<StringLiteral> attributePrefixesToSkip = {}) {
1649 SmallVector<Attribute> mlirAttributes;
1650 for (llvm::Attribute attr : attributes) {
1652 if (attr.isStringAttribute())
1653 attrName = attr.getKindAsString();
1655 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1656 if (llvm::is_contained(attributesToSkip, attrName))
1659 auto attrNameStartsWith = [attrName](StringLiteral sl) {
1660 return attrName.starts_with(sl);
1662 if (attributePrefixesToSkip.end() !=
1663 llvm::find_if(attributePrefixesToSkip, attrNameStartsWith))
1666 auto keyAttr = StringAttr::get(context, attrName);
1667 if (attr.isStringAttribute()) {
1668 StringRef val = attr.getValueAsString();
1671 mlirAttributes.push_back(keyAttr);
1675 mlirAttributes.push_back(
1676 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1679 if (attr.isIntAttribute()) {
1682 auto val = std::to_string(attr.getValueAsInt());
1683 mlirAttributes.push_back(
1684 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1687 if (attr.isEnumAttribute()) {
1689 mlirAttributes.push_back(keyAttr);
1695 <<
"' attribute is invalid on current operation, skipping it";
1697 return ArrayAttr::get(context, mlirAttributes);
1703 GlobalOp globalOp) {
1705 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1706 if (!targetSpecificAttrs.empty())
1707 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1710LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1712 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1714 Attribute valueAttr;
1715 if (globalVar->hasInitializer())
1716 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1717 Type type =
convertType(globalVar->getValueType());
1719 uint64_t alignment = 0;
1720 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1721 if (maybeAlign.has_value()) {
1722 llvm::Align align = *maybeAlign;
1723 alignment = align.value();
1728 SmallVector<Attribute> globalExpressionAttrs;
1729 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1730 globalVar->getDebugInfo(globalExpressions);
1732 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1733 DIGlobalVariableExpressionAttr globalExpressionAttr =
1734 debugImporter->translateGlobalVariableExpression(expr);
1735 globalExpressionAttrs.push_back(globalExpressionAttr);
1740 StringRef globalName = globalVar->getName();
1741 if (globalName.empty())
1742 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1744 GlobalOp globalOp = GlobalOp::create(
1745 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1746 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1747 valueAttr, alignment, globalVar->getAddressSpace(),
1748 globalVar->isDSOLocal(),
1749 convertThreadLocalModeFromLLVM(globalVar->getThreadLocalMode()),
1751 ArrayRef<NamedAttribute>(), globalExpressionAttrs);
1752 globalInsertionOp = globalOp;
1754 if (globalVar->hasInitializer() && !valueAttr) {
1756 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1757 setConstantInsertionPointToStart(block);
1758 FailureOr<Value> initializer =
1759 convertConstantExpr(globalVar->getInitializer());
1762 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1764 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1765 globalOp.setUnnamedAddr(
1766 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1768 if (globalVar->hasSection())
1769 globalOp.setSection(globalVar->getSection());
1770 globalOp.setVisibility_(
1771 convertVisibilityFromLLVM(globalVar->getVisibility()));
1773 if (globalVar->hasComdat())
1774 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1776 if (llvm::MDNode *associatedMD =
1777 globalVar->getMetadata(llvm::LLVMContext::MD_associated)) {
1778 FlatSymbolRefAttr symbolRef;
1779 if (associatedMD->getNumOperands() == 1)
1781 getMetadataOperandSymbolRef(associatedMD->getOperand(0).get());
1784 <<
"unhandled associated metadata: " << renderMetadata(associatedMD)
1785 <<
" on " << renderValue(*globalVar);
1787 globalOp.setAssociatedAttr(symbolRef);
1791 if (llvm::MDNode *absSymMD =
1792 globalVar->getMetadata(llvm::LLVMContext::MD_absolute_symbol)) {
1793 unsigned numOps = absSymMD->getNumOperands();
1794 if (numOps >= 2 && numOps % 2 == 0) {
1795 SmallVector<Attribute> rangeAttrs;
1796 rangeAttrs.reserve(numOps);
1798 for (
const llvm::MDOperand &op : absSymMD->operands()) {
1799 auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(op);
1803 auto intType = IntegerType::get(context, constInt->getBitWidth());
1804 rangeAttrs.push_back(IntegerAttr::get(intType, constInt->getValue()));
1807 if (rangeAttrs.size() == numOps)
1808 globalOp.setAbsoluteSymbolAttr(ArrayAttr::get(context, rangeAttrs));
1818ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1819 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1821 llvm::Constant *initializer = globalVar->getInitializer();
1823 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1824 isa<llvm::ConstantAggregateZero>(initializer);
1831 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1832 if (caz->getElementCount().getFixedValue() != 0)
1836 SmallVector<Attribute> funcs;
1837 SmallVector<int32_t> priorities;
1838 SmallVector<Attribute> dataList;
1839 for (llvm::Value *operand : initializer->operands()) {
1840 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1841 if (!aggregate || aggregate->getNumOperands() != 3)
1844 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1845 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1846 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1847 if (!priority || !func || !data)
1850 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1854 else if (data->isNullValue())
1855 dataAttr = ZeroAttr::get(context);
1860 priorities.push_back(priority->getValue().getZExtValue());
1861 dataList.push_back(dataAttr);
1865 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1868 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1869 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1870 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1873 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1874 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1875 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1880ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1882 if (valueMapping.contains(constant))
1891 workList.insert(constant);
1892 while (!workList.empty()) {
1893 llvm::Constant *current = workList.back();
1896 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1897 orderedSet.insert(current);
1898 workList.pop_back();
1904 auto [adjacencyIt,
inserted] = adjacencyLists.try_emplace(current);
1908 for (llvm::Value *operand : current->operands())
1909 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1910 adjacencyIt->getSecond().push_back(constDependency);
1913 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1914 unsigned numElements = constAgg->getElementCount().getFixedValue();
1915 for (
unsigned i = 0, e = numElements; i != e; ++i)
1916 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1922 if (adjacencyIt->getSecond().empty()) {
1923 orderedSet.insert(current);
1924 workList.pop_back();
1932 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1933 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1934 orderedSet.contains(dependency))
1936 workList.insert(dependency);
1942FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1943 Location loc = UnknownLoc::get(context);
1946 if (Attribute attr = getConstantAsAttr(constant)) {
1948 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1949 return AddressOfOp::create(builder, loc, type, symbolRef.
getValue())
1952 return ConstantOp::create(builder, loc, type, attr).getResult();
1956 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1958 return ZeroOp::create(builder, loc, type).getResult();
1962 if (isa<llvm::ConstantTokenNone>(constant)) {
1963 return NoneTokenOp::create(builder, loc).getResult();
1967 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1969 return PoisonOp::create(builder, loc, type).getResult();
1973 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1975 return UndefOp::create(builder, loc, type).getResult();
1979 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1980 Type type =
convertType(dsoLocalEquivalent->getType());
1981 return DSOLocalEquivalentOp::create(
1984 builder.getContext(),
1985 dsoLocalEquivalent->getGlobalValue()->getName()))
1990 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1992 StringRef globalName = globalObj->getName();
1993 FlatSymbolRefAttr symbolRef;
1995 if (globalName.empty())
1997 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
2000 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
2004 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
2005 Type type =
convertType(globalAliasObj->getType());
2006 StringRef aliaseeName = globalAliasObj->getName();
2008 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
2012 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
2018 llvm::Instruction *inst = constExpr->getAsInstruction();
2019 llvm::scope_exit guard([&]() {
2020 assert(!noResultOpMapping.contains(inst) &&
2021 "expected constant expression to return a result");
2022 valueMapping.erase(inst);
2023 inst->deleteValue();
2027 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
2028 return valueMapping.contains(value);
2030 if (
failed(processInstruction(inst)))
2035 if (constExpr->getOpcode() == llvm::Instruction::GetElementPtr) {
2036 auto *gepOperator = llvm::cast<llvm::GEPOperator>(constExpr);
2037 if (std::optional<llvm::ConstantRange> inRange =
2038 gepOperator->getInRange()) {
2039 auto gepOp =
result.getDefiningOp<GEPOp>();
2040 assert(gepOp &&
"expected GEPOp for getelementptr constexpr");
2044 unsigned indexWidth =
2045 llvmModule->getDataLayout().getIndexTypeSizeInBits(
2046 gepOperator->getPointerOperandType());
2047 gepOp.setInrangeAttr(LLVM::ConstantRangeAttr::get(
2048 context, inRange->getLower().sextOrTrunc(indexWidth),
2049 inRange->getUpper().sextOrTrunc(indexWidth)));
2056 if (
auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
2057 Type type =
convertType(aggregateZero->getType());
2058 return ZeroOp::create(builder, loc, type).getResult();
2062 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
2064 SmallVector<Value> elementValues;
2066 elementValues.reserve(constAgg->getNumOperands());
2067 for (llvm::Value *operand : constAgg->operands())
2070 assert(llvm::count(elementValues,
nullptr) == 0 &&
2071 "expected all elements have been converted before");
2075 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
2077 "unrecognized aggregate type");
2078 Value root = UndefOp::create(builder, loc, rootType);
2079 for (
const auto &it : llvm::enumerate(elementValues)) {
2080 if (isArrayOrStruct) {
2082 InsertValueOp::create(builder, loc, root, it.value(), it.index());
2084 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
2086 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
2087 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
2094 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
2095 LLVMTargetExtType targetExtType =
2096 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
2097 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
2098 "target extension type does not support zero-initialization");
2101 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
2104 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
2108 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
2109 return BlockAddressOp::create(
2111 BlockAddressAttr::get(context, fnSym, blockTag))
2115 StringRef error =
"";
2117 if (isa<llvm::ConstantPtrAuth>(constant))
2118 error =
" since ptrauth(...) is unsupported";
2120 if (isa<llvm::NoCFIValue>(constant))
2121 error =
" since no_cfi is unsupported";
2123 if (isa<llvm::GlobalValue>(constant))
2124 error =
" since global value is unsupported";
2126 return emitError(loc) <<
"unhandled constant: " << renderValue(*constant)
2130FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
2134 assert(!valueMapping.contains(constant) &&
2135 "expected constant has not been converted before");
2136 assert(constantInsertionBlock &&
2137 "expected the constant insertion block to be non-null");
2140 OpBuilder::InsertionGuard guard(builder);
2141 if (!constantInsertionOp)
2142 builder.setInsertionPointToStart(constantInsertionBlock);
2144 builder.setInsertionPointAfter(constantInsertionOp);
2148 getConstantsToConvert(constant);
2149 for (llvm::Constant *constantToConvert : constantsToConvert) {
2150 FailureOr<Value> converted = convertConstant(constantToConvert);
2153 mapValue(constantToConvert, *converted);
2158 constantInsertionOp =
result.getDefiningOp();
2164 auto it = valueMapping.find(value);
2165 if (it != valueMapping.end())
2166 return it->getSecond();
2173 if (
auto *mdAsVal = dyn_cast<llvm::MetadataAsValue>(value)) {
2174 llvm::Metadata *md = mdAsVal->getMetadata();
2175 Attribute mdAttr = convertMetadataToAttr(md);
2178 <<
"unsupported metadata: " << renderMetadata(md);
2180 MetadataAsValueOp::create(builder, UnknownLoc::get(context), mdAttr)
2187 if (
auto *constant = dyn_cast<llvm::Constant>(value))
2188 return convertConstantExpr(constant);
2190 Location loc = UnknownLoc::get(context);
2191 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
2193 return emitError(loc) <<
"unhandled value: " << renderValue(*value);
2199 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2202 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2205 value = node->getValue();
2208 auto it = valueMapping.find(value);
2209 if (it != valueMapping.end())
2210 return it->getSecond();
2213 if (
auto *constant = dyn_cast<llvm::Constant>(value))
2214 return convertConstantExpr(constant);
2218FailureOr<SmallVector<Value>>
2221 remapped.reserve(values.size());
2222 for (llvm::Value *value : values) {
2224 if (failed(converted))
2226 remapped.push_back(*converted);
2236 assert(immArgPositions.size() == immArgAttrNames.size() &&
2237 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
2241 for (
auto [immArgPos, immArgName] :
2242 llvm::zip(immArgPositions, immArgAttrNames)) {
2243 auto &value = operands[immArgPos];
2244 auto *constant = llvm::cast<llvm::Constant>(value);
2246 assert(attr && attr.getType().isIntOrFloat() &&
2247 "expected immarg to be float or integer constant");
2248 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
2249 attrsOut.push_back({nameAttr, attr});
2254 for (llvm::Value *value : operands) {
2258 if (failed(mlirValue))
2260 valuesOut.push_back(*mlirValue);
2265 if (requiresOpBundles) {
2266 opBundleSizes.reserve(opBundles.size());
2267 opBundleTagAttrs.reserve(opBundles.size());
2269 for (
const llvm::OperandBundleUse &bundle : opBundles) {
2270 opBundleSizes.push_back(bundle.Inputs.size());
2271 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
2273 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
2274 auto operandMlirValue =
convertValue(opBundleOperand.get());
2275 if (failed(operandMlirValue))
2277 valuesOut.push_back(*operandMlirValue);
2282 auto opBundleSizesAttrNameAttr =
2283 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
2284 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
2286 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
2287 auto opBundleTagsAttrNameAttr =
2288 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
2289 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
2296 IntegerAttr integerAttr;
2298 bool success = succeeded(converted) &&
2300 assert(
success &&
"expected a constant integer value");
2306 FloatAttr floatAttr;
2310 assert(
success &&
"expected a constant float value");
2317 llvm::DILocalVariable *node =
nullptr;
2318 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2319 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2320 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2322 node = cast<llvm::DILocalVariable *>(valOrVariable);
2324 return debugImporter->translate(node);
2328 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2329 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2330 return debugImporter->translate(node);
2333FPExceptionBehaviorAttr
2335 auto *metadata = cast<llvm::MetadataAsValue>(value);
2336 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2337 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2338 llvm::convertStrToExceptionBehavior(mdstr->getString());
2339 assert(optLLVM &&
"Expecting FP exception behavior");
2340 return builder.getAttr<FPExceptionBehaviorAttr>(
2341 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2345 auto *metadata = cast<llvm::MetadataAsValue>(value);
2346 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2347 std::optional<llvm::RoundingMode> optLLVM =
2348 llvm::convertStrToRoundingMode(mdstr->getString());
2349 assert(optLLVM &&
"Expecting rounding mode");
2350 return builder.getAttr<RoundingModeAttr>(
2351 convertRoundingModeFromLLVM(*optLLVM));
2354FailureOr<SmallVector<AliasScopeAttr>>
2356 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2357 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2362 return debugImporter->translateLoc(loc);
2366ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2367 llvm::BasicBlock *
target,
2369 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2370 auto *phiInst = cast<llvm::PHINode>(&*inst);
2371 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2373 if (failed(converted))
2375 blockArguments.push_back(*converted);
2380FailureOr<SmallVector<Value>>
2381ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2382 bool allowInlineAsm) {
2383 bool isInlineAsm = callInst->isInlineAsm();
2384 if (isInlineAsm && !allowInlineAsm)
2394 llvm::Value *calleeOperand = callInst->getCalledOperand();
2395 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2399 operands.push_back(*called);
2402 SmallVector<llvm::Value *> args(callInst->args());
2403 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2407 llvm::append_range(operands, *arguments);
2415 LLVMFunctionType calleeType) {
2416 if (callType.getReturnType() != calleeType.getReturnType())
2419 if (calleeType.isVarArg()) {
2422 if (callType.getNumParams() < calleeType.getNumParams())
2427 if (callType.getNumParams() != calleeType.getNumParams())
2432 for (
auto [operandType, argumentType] :
2433 llvm::zip(callType.getParams(), calleeType.getParams()))
2434 if (operandType != argumentType)
2440FailureOr<LLVMFunctionType>
2441ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2442 bool &isIncompatibleCall) {
2443 isIncompatibleCall =
false;
2444 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2445 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2451 llvm::Value *calledOperand = callInst->getCalledOperand();
2452 FailureOr<LLVMFunctionType> callType =
2453 castOrFailure(
convertType(callInst->getFunctionType()));
2456 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2458 llvm::FunctionType *origCalleeType =
nullptr;
2460 origCalleeType = callee->getFunctionType();
2461 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2462 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2466 if (!origCalleeType)
2469 FailureOr<LLVMFunctionType> calleeType =
2477 isIncompatibleCall =
true;
2479 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2480 <<
" and " << *calleeType;
2487FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2488 llvm::Value *calledOperand = callInst->getCalledOperand();
2489 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2490 return SymbolRefAttr::get(context, calledOperand->getName());
2494LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2495 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2499 return emitError(loc) <<
"unhandled intrinsic: " << renderValue(*inst);
2503ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2504 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2505 unsigned argIdx = 0;
2506 SmallVector<mlir::Attribute> opAttrs;
2507 bool hasIndirect =
false;
2509 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2511 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2516 if (ci.isIndirect) {
2517 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2518 SmallVector<mlir::NamedAttribute> attrs;
2519 attrs.push_back(builder.getNamedAttr(
2520 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2522 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2526 opAttrs.push_back(builder.getDictionaryAttr({}));
2532 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2536LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2539 if (
auto *brInst = dyn_cast<llvm::UncondBrInst>(inst)) {
2540 llvm::BasicBlock *succ = brInst->getSuccessor();
2541 SmallVector<Value> blockArgs;
2542 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2545 auto brOp = LLVM::BrOp::create(builder, loc, blockArgs,
lookupBlock(succ));
2549 if (
auto *brInst = dyn_cast<llvm::CondBrInst>(inst)) {
2550 SmallVector<Block *> succBlocks;
2551 SmallVector<SmallVector<Value>> succBlockArgs;
2552 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2553 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2554 SmallVector<Value> blockArgs;
2555 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2558 succBlockArgs.push_back(blockArgs);
2561 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2564 auto condBrOp = LLVM::CondBrOp::create(
2565 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2566 succBlocks.back(), succBlockArgs.back());
2570 if (inst->getOpcode() == llvm::Instruction::Switch) {
2571 auto *swInst = cast<llvm::SwitchInst>(inst);
2573 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2576 SmallVector<Value> defaultBlockArgs;
2578 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2579 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2583 unsigned numCases = swInst->getNumCases();
2584 SmallVector<SmallVector<Value>> caseOperands(numCases);
2585 SmallVector<ValueRange> caseOperandRefs(numCases);
2586 SmallVector<APInt> caseValues(numCases);
2587 SmallVector<Block *> caseBlocks(numCases);
2588 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2589 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2590 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2591 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2593 caseOperandRefs[it.index()] = caseOperands[it.index()];
2594 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2598 auto switchOp = SwitchOp::create(builder, loc, *condition,
2600 caseValues, caseBlocks, caseOperandRefs);
2604 if (inst->getOpcode() == llvm::Instruction::PHI) {
2606 mapValue(inst, builder.getInsertionBlock()->addArgument(
2610 if (inst->getOpcode() == llvm::Instruction::Call) {
2611 auto *callInst = cast<llvm::CallInst>(inst);
2612 llvm::Value *calledOperand = callInst->getCalledOperand();
2614 FailureOr<SmallVector<Value>> operands =
2615 convertCallOperands(callInst,
true);
2619 auto callOp = [&]() -> FailureOr<Operation *> {
2620 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2624 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2625 return InlineAsmOp::create(
2626 builder, loc, resultTy, *operands,
2627 builder.getStringAttr(asmI->getAsmString()),
2628 builder.getStringAttr(asmI->getConstraintString()),
2629 asmI->hasSideEffects(), asmI->isAlignStack(),
2630 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2631 callInst->hasFnAttr(llvm::Attribute::Convergent),
2632 AsmDialectAttr::get(
2633 mlirModule.getContext(),
2634 convertAsmDialectFromLLVM(asmI->getDialect())),
2638 bool isIncompatibleCall;
2639 FailureOr<LLVMFunctionType> funcTy =
2640 convertFunctionType(callInst, isIncompatibleCall);
2644 FlatSymbolRefAttr callee =
nullptr;
2645 if (isIncompatibleCall) {
2649 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2650 Value indirectCallVal = LLVM::AddressOfOp::create(
2651 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2652 operands->insert(operands->begin(), indirectCallVal);
2655 callee = convertCalleeName(callInst);
2657 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2659 if (
failed(convertCallAttributes(callInst, callOp)))
2664 if (!isIncompatibleCall)
2666 return callOp.getOperation();
2672 if (!callInst->getType()->isVoidTy())
2673 mapValue(inst, (*callOp)->getResult(0));
2678 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2679 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2681 SmallVector<Value> operands;
2682 operands.reserve(lpInst->getNumClauses());
2683 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2684 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2687 operands.push_back(*operand);
2692 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2696 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2697 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2699 if (invokeInst->isInlineAsm())
2700 return emitError(loc) <<
"invoke of inline assembly is not supported";
2702 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2708 bool invokeResultUsedInPhi = llvm::any_of(
2709 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2710 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2715 Block *directNormalDest = normalDest;
2716 if (invokeResultUsedInPhi) {
2721 OpBuilder::InsertionGuard g(builder);
2722 directNormalDest = builder.createBlock(normalDest);
2725 SmallVector<Value> unwindArgs;
2726 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2730 bool isIncompatibleInvoke;
2731 FailureOr<LLVMFunctionType> funcTy =
2732 convertFunctionType(invokeInst, isIncompatibleInvoke);
2736 FlatSymbolRefAttr calleeName =
nullptr;
2737 if (isIncompatibleInvoke) {
2741 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2742 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2743 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2744 operands->insert(operands->begin(), indirectInvokeVal);
2747 calleeName = convertCalleeName(invokeInst);
2752 auto invokeOp = InvokeOp::create(
2753 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2756 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2761 if (!isIncompatibleInvoke)
2764 if (!invokeInst->getType()->isVoidTy())
2765 mapValue(inst, invokeOp.getResults().front());
2769 SmallVector<Value> normalArgs;
2770 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2774 if (invokeResultUsedInPhi) {
2778 OpBuilder::InsertionGuard g(builder);
2779 builder.setInsertionPointToStart(directNormalDest);
2780 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2784 assert(llvm::none_of(
2786 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2787 "An llvm.invoke operation cannot pass its result as a block "
2789 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2794 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2795 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2796 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2797 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2806 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2814 auto gepOp = GEPOp::create(
2815 builder, loc, type, sourceElementType, *basePtr,
indices,
2816 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2821 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2822 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2824 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2828 SmallVector<Block *> succBlocks;
2829 SmallVector<SmallVector<Value>> succBlockArgs;
2830 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2831 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2832 SmallVector<Value> blockArgs;
2833 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2836 succBlockArgs.push_back(blockArgs);
2838 SmallVector<ValueRange> succBlockArgsRange =
2839 llvm::to_vector_of<ValueRange>(succBlockArgs);
2841 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2842 succBlockArgsRange, succBlocks);
2852 return emitError(loc) <<
"unhandled instruction: " << renderValue(*inst);
2855LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2862 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2863 return convertIntrinsic(intrinsic);
2868 if (inst->getDbgMarker()) {
2869 for (llvm::DbgRecord &dbgRecord :
2870 inst->getDbgMarker()->getDbgRecordRange()) {
2872 if (
auto *dbgVariableRecord =
2873 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2878 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2879 if (!emitExpensiveWarnings)
2882 llvm::raw_string_ostream optionsStream(
options);
2883 dbgRecord.print(optionsStream);
2884 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2888 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2889 DILabelAttr labelAttr =
2890 debugImporter->translate(dbgLabelRecord->getLabel());
2892 return emitUnsupportedWarning();
2893 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2897 return emitUnsupportedWarning();
2902 return convertInstruction(inst);
2905FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2906 if (!f->hasPersonalityFn())
2909 llvm::Constant *pf = f->getPersonalityFn();
2913 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2917 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2918 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2919 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2920 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2921 return SymbolRefAttr::get(builder.getContext(), func->getName());
2924 return FlatSymbolRefAttr();
2928 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2930 auto othermem = convertModRefInfoFromLLVM(
2931 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2932 auto argMem = convertModRefInfoFromLLVM(
2933 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2934 auto inaccessibleMem = convertModRefInfoFromLLVM(
2935 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2936 auto errnoMem = convertModRefInfoFromLLVM(
2937 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2938 auto targetMem0 = convertModRefInfoFromLLVM(
2939 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2940 auto targetMem1 = convertModRefInfoFromLLVM(
2941 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2943 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2944 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2946 if (memAttr.isReadWrite())
2948 funcOp.setMemoryEffectsAttr(memAttr);
2952 llvm::DenormalFPEnv denormalFpEnv =
func->getDenormalFPEnv();
2954 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2957 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2958 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2960 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2961 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2962 convertDenormalModeKindFromLLVM(defaultMode.Input),
2963 convertDenormalModeKindFromLLVM(floatMode.Output),
2964 convertDenormalModeKindFromLLVM(floatMode.Input));
2965 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2971 StringLiteral(
"aarch64_in_za"),
2972 StringLiteral(
"aarch64_inout_za"),
2973 StringLiteral(
"aarch64_new_za"),
2974 StringLiteral(
"aarch64_out_za"),
2975 StringLiteral(
"aarch64_preserves_za"),
2976 StringLiteral(
"aarch64_pstate_sm_body"),
2977 StringLiteral(
"aarch64_pstate_sm_compatible"),
2978 StringLiteral(
"aarch64_pstate_sm_enabled"),
2979 StringLiteral(
"allocsize"),
2980 StringLiteral(
"alwaysinline"),
2981 StringLiteral(
"cold"),
2982 StringLiteral(
"convergent"),
2983 StringLiteral(
"disable-tail-calls"),
2984 StringLiteral(
"fp-contract"),
2985 StringLiteral(
"frame-pointer"),
2986 StringLiteral(
"hot"),
2987 StringLiteral(
"inlinehint"),
2988 StringLiteral(
"instrument-function-entry"),
2989 StringLiteral(
"instrument-function-exit"),
2990 StringLiteral(
"modular-format"),
2991 StringLiteral(
"memory"),
2992 StringLiteral(
"minsize"),
2993 StringLiteral(
"no_caller_saved_registers"),
2994 StringLiteral(
"no-signed-zeros-fp-math"),
2995 StringLiteral(
"no-builtins"),
2996 StringLiteral(
"nocallback"),
2997 StringLiteral(
"noduplicate"),
2998 StringLiteral(
"noinline"),
2999 StringLiteral(
"noreturn"),
3000 StringLiteral(
"nounwind"),
3001 StringLiteral(
"optnone"),
3002 StringLiteral(
"optsize"),
3003 StringLiteral(
"returns_twice"),
3004 StringLiteral(
"save-reg-params"),
3005 StringLiteral(
"target-features"),
3006 StringLiteral(
"trap-func-name"),
3007 StringLiteral(
"sample-profile-suffix-elision-policy"),
3008 StringLiteral(
"tune-cpu"),
3009 StringLiteral(
"uniform-work-group-size"),
3010 StringLiteral(
"uwtable"),
3011 StringLiteral(
"vscale_range"),
3012 StringLiteral(
"willreturn"),
3013 StringLiteral(
"zero-call-used-regs"),
3014 StringLiteral(
"denormal_fpenv"),
3020 StringLiteral(
"no-builtin-"),
3023template <
typename OpTy>
3025 const llvm::AttributeSet &attrs,
3028 if (attrs.hasAttribute(
"no-builtins")) {
3029 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
3034 for (llvm::Attribute attr : attrs) {
3037 if (attr.hasKindAsEnum())
3040 StringRef val = attr.getKindAsString();
3042 if (val.starts_with(
"no-builtin-"))
3044 StringAttr::get(ctx, val.drop_front(
sizeof(
"no-builtin-") - 1)));
3047 if (!nbAttrs.empty())
3048 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
3051template <
typename OpTy>
3053 const llvm::AttributeSet &attrs, OpTy
target) {
3054 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
3055 if (!attr.isValid())
3058 auto [elemSize, numElems] = attr.getAllocSizeArgs();
3062 static_cast<int32_t
>(*numElems)}));
3073 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
3074 llvm::AttributeList::AttrIndex::FunctionIndex);
3076 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
3078 if (!passthroughAttr.empty())
3079 funcOp.setPassthroughAttr(passthroughAttr);
3083 LLVMFuncOp funcOp) {
3088 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
3089 funcOp.setNoInline(
true);
3090 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
3091 funcOp.setAlwaysInline(
true);
3092 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
3093 funcOp.setInlineHint(
true);
3094 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
3095 funcOp.setOptimizeNone(
true);
3096 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
3097 funcOp.setConvergent(
true);
3098 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
3099 funcOp.setNoUnwind(
true);
3100 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
3101 funcOp.setWillReturn(
true);
3102 if (
func->hasFnAttribute(llvm::Attribute::NoReturn))
3103 funcOp.setNoreturn(
true);
3104 if (
func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
3105 funcOp.setOptsize(
true);
3106 if (
func->hasFnAttribute(
"save-reg-params"))
3107 funcOp.setSaveRegParams(
true);
3108 if (
func->hasFnAttribute(
"uniform-work-group-size"))
3109 funcOp.setUniformWorkGroupSize(
true);
3110 if (
func->hasFnAttribute(llvm::Attribute::MinSize))
3111 funcOp.setMinsize(
true);
3112 if (
func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
3113 funcOp.setReturnsTwice(
true);
3114 if (
func->hasFnAttribute(llvm::Attribute::Cold))
3115 funcOp.setCold(
true);
3116 if (
func->hasFnAttribute(llvm::Attribute::Hot))
3117 funcOp.setHot(
true);
3118 if (
func->hasFnAttribute(llvm::Attribute::NoDuplicate))
3119 funcOp.setNoduplicate(
true);
3120 if (
func->hasFnAttribute(
"no_caller_saved_registers"))
3121 funcOp.setNoCallerSavedRegisters(
true);
3122 if (
func->hasFnAttribute(llvm::Attribute::NoCallback))
3123 funcOp.setNocallback(
true);
3124 if (llvm::Attribute attr =
func->getFnAttribute(
"modular-format");
3125 attr.isStringAttribute())
3126 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3127 if (llvm::Attribute attr =
func->getFnAttribute(
"zero-call-used-regs");
3128 attr.isStringAttribute())
3129 funcOp.setZeroCallUsedRegsAttr(
3130 StringAttr::get(context, attr.getValueAsString()));
3132 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
3133 funcOp.setArmStreaming(
true);
3134 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
3135 funcOp.setArmLocallyStreaming(
true);
3136 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
3137 funcOp.setArmStreamingCompatible(
true);
3139 if (
func->hasFnAttribute(
"aarch64_new_za"))
3140 funcOp.setArmNewZa(
true);
3141 else if (
func->hasFnAttribute(
"aarch64_in_za"))
3142 funcOp.setArmInZa(
true);
3143 else if (
func->hasFnAttribute(
"aarch64_out_za"))
3144 funcOp.setArmOutZa(
true);
3145 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
3146 funcOp.setArmInoutZa(
true);
3147 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
3148 funcOp.setArmPreservesZa(
true);
3153 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
3154 if (attr.isValid()) {
3156 auto intTy = IntegerType::get(context, 32);
3157 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
3158 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
3159 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
3163 if (
func->hasFnAttribute(
"frame-pointer")) {
3164 StringRef stringRefFramePointerKind =
3165 func->getFnAttribute(
"frame-pointer").getValueAsString();
3166 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
3167 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
3168 stringRefFramePointerKind)
3172 if (
func->hasFnAttribute(
"use-sample-profile"))
3173 funcOp.setUseSampleProfile(
true);
3175 if (llvm::Attribute attr =
func->getFnAttribute(
"disable-tail-calls");
3176 attr.isStringAttribute()) {
3177 StringRef val = attr.getValueAsString();
3179 funcOp.setDisableTailCalls(
true);
3180 else if (val !=
"false")
3182 <<
"unknown value '" << val <<
"' for 'disable-tail-calls' attribute";
3185 if (llvm::Attribute attr =
3186 func->getFnAttribute(
"sample-profile-suffix-elision-policy");
3187 attr.isStringAttribute())
3188 funcOp.setSampleProfileSuffixElisionPolicy(
3189 StringAttr::get(context, attr.getValueAsString()));
3191 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
3192 attr.isStringAttribute())
3193 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3195 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
3196 attr.isStringAttribute())
3197 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3199 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
3200 attr.isStringAttribute())
3201 funcOp.setTargetFeaturesAttr(
3202 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
3204 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
3205 attr.isStringAttribute())
3206 funcOp.setReciprocalEstimatesAttr(
3207 StringAttr::get(context, attr.getValueAsString()));
3209 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
3210 attr.isStringAttribute())
3211 funcOp.setPreferVectorWidth(attr.getValueAsString());
3213 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
3214 attr.isStringAttribute())
3215 funcOp.setInstrumentFunctionEntry(
3216 StringAttr::get(context, attr.getValueAsString()));
3218 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
3219 attr.isStringAttribute())
3220 funcOp.setInstrumentFunctionExit(
3221 StringAttr::get(context, attr.getValueAsString()));
3223 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
3224 attr.isStringAttribute())
3225 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
3227 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
3228 attr.isStringAttribute())
3229 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
3231 if (
func->hasUWTable()) {
3232 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
3233 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
3234 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
3239ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
3242 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
3244 if (!llvmAttr.isValid())
3249 if (llvmAttr.hasKindAsEnum() &&
3250 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
3251 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
3252 paramAttrs.push_back(
3258 if (llvmAttr.isTypeAttribute())
3259 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
3260 else if (llvmAttr.isIntAttribute())
3262 else if (llvmAttr.isEnumAttribute())
3264 else if (llvmAttr.isConstantRangeAttribute()) {
3265 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
3266 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
3269 llvm_unreachable(
"unexpected parameter attribute kind");
3271 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
3274 return builder.getDictionaryAttr(paramAttrs);
3278 LLVMFuncOp funcOp) {
3279 auto llvmAttrs = func->getAttributes();
3280 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
3281 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
3282 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
3286 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3287 if (!llvmResAttr.hasAttributes())
3289 funcOp.setResAttrsAttr(
3290 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
3294 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
3297 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
3298 immArgPositions.end());
3300 llvm::AttributeList llvmAttrs = call->getAttributes();
3302 bool anyArgAttrs =
false;
3303 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
3305 if (immArgPositionsSet.contains(i))
3307 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3308 if (llvmArgAttrsSet.back().hasAttributes())
3313 for (
auto &dict : dictAttrs)
3314 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3315 return builder.getArrayAttr(attrs);
3319 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
3320 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3321 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3325 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3326 if (!llvmResAttr.hasAttributes())
3328 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3329 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3332template <
typename Op>
3334 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3338LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3340 llvm::AttributeList invokeAttrs = inst->getAttributes();
3341 op.setUniformWorkGroupSize(
3342 invokeAttrs.getFnAttr(
"uniform-work-group-size").isValid());
3346LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3352 llvm::AttributeList callAttrs = inst->getAttributes();
3354 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3355 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3356 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3357 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3358 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3360 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3361 op.setSaveRegParams(callAttrs.getFnAttr(
"save-reg-params").isValid());
3362 op.setUniformWorkGroupSize(
3363 callAttrs.getFnAttr(
"uniform-work-group-size").isValid());
3364 op.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3365 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3366 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3369 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3370 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3371 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3373 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3374 op.setNoCallerSavedRegisters(
3375 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3376 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3378 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3379 attr.isStringAttribute())
3380 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3381 if (llvm::Attribute attr = callAttrs.getFnAttr(
"zero-call-used-regs");
3382 attr.isStringAttribute())
3383 op.setZeroCallUsedRegsAttr(
3384 StringAttr::get(context, attr.getValueAsString()));
3385 if (llvm::Attribute attr = callAttrs.getFnAttr(
"trap-func-name");
3386 attr.isStringAttribute())
3387 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3388 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3390 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3391 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3393 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3394 ModRefInfo othermem = convertModRefInfoFromLLVM(
3395 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3396 ModRefInfo argMem = convertModRefInfoFromLLVM(
3397 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3398 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3399 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3400 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3401 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3402 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3403 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3404 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3405 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3407 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3408 errnoMem, targetMem0, targetMem1);
3410 if (!memAttr.isReadWrite())
3411 op.setMemoryEffectsAttr(memAttr);
3424 if (
func->isIntrinsic() &&
3425 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3428 bool dsoLocal =
func->isDSOLocal();
3429 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3433 builder.setInsertionPointToEnd(mlirModule.getBody());
3435 Location loc = debugImporter->translateFuncLocation(
func);
3436 LLVMFuncOp funcOp = LLVMFuncOp::create(
3437 builder, loc,
func->getName(), functionType,
3438 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3443 funcOp.setPersonalityAttr(personality);
3444 else if (
func->hasPersonalityFn())
3445 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3448 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3450 if (
func->hasAtLeastLocalUnnamedAddr())
3451 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3453 if (
func->hasSection())
3454 funcOp.setSection(StringRef(
func->getSection()));
3456 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3458 if (
func->hasComdat())
3459 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3461 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3462 funcOp.setAlignment(maybeAlign->value());
3471 func->getAllMetadata(allMetadata);
3473 llvmModule->getMDKindNames(metadataNames);
3475 for (
auto &[kind, node] : allMetadata) {
3476 if (kind == llvm::LLVMContext::MD_dbg)
3479 llvm::MDNode *metadataNode = node;
3480 auto emitUnhandledFunctionMetadataWarning = [&]() {
3481 if (!emitExpensiveWarnings)
3484 <<
"unhandled function metadata: " << renderMetadata(metadataNode)
3485 <<
" on " << renderValue(*
func);
3488 if (iface.isConvertibleMetadata(kind)) {
3489 if (succeeded(iface.setMetadataAttrs(builder, kind, metadataNode, funcOp,
3492 emitUnhandledFunctionMetadataWarning();
3496 Attribute nodeAttr = convertMetadataToAttr(metadataNode);
3497 auto mdNodeAttr = dyn_cast_if_present<LLVM::MDNodeAttr>(nodeAttr);
3498 if (!mdNodeAttr || kind >= metadataNames.size()) {
3499 emitUnhandledFunctionMetadataWarning();
3503 functionMetadata.push_back(LLVM::FunctionMetadataAttr::get(
3504 context, builder.getStringAttr(metadataNames[kind]), mdNodeAttr));
3506 if (!functionMetadata.empty())
3507 funcOp.setFunctionMetadataAttr(builder.getArrayAttr(functionMetadata));
3509 if (
func->isDeclaration())
3518 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3519 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3524 for (llvm::BasicBlock &basicBlock : *
func) {
3526 if (!reachable.contains(&basicBlock)) {
3527 if (basicBlock.hasAddressTaken())
3529 <<
"unreachable block '" << basicBlock.getName()
3530 <<
"' with address taken";
3533 Region &body = funcOp.getBody();
3534 Block *block = builder.createBlock(&body, body.
end());
3536 reachableBasicBlocks.push_back(&basicBlock);
3540 for (
const auto &it : llvm::enumerate(
func->args())) {
3541 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3542 functionType.getParamType(it.index()), funcOp.getLoc());
3551 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3552 for (llvm::BasicBlock *basicBlock : blocks)
3553 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3558 if (failed(processDebugIntrinsics()))
3563 if (failed(processDebugRecords()))
3572 if (!dbgIntr->isKillLocation())
3574 llvm::Value *value = dbgIntr->getArgOperand(0);
3575 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3578 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3590 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3593 if (dominatedBlocks.empty())
3597 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3600 Value insertPt = argOperand;
3601 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3607 if (!insertionBlock->
empty() &&
3608 isa<LandingpadOp>(insertionBlock->
front()))
3609 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3617std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3618ModuleImport::processDebugOpArgumentsAndInsertionPt(
3620 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3621 llvm::Value *address,
3622 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3623 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3629 FailureOr<Value> argOperand = convertArgOperandToValue();
3630 if (
failed(argOperand)) {
3631 emitError(loc) <<
"failed to convert a debug operand: "
3632 << renderValue(*address);
3640 return {localVarAttr, debugImporter->translateExpression(expression),
3645ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3646 DominanceInfo &domInfo) {
3648 auto emitUnsupportedWarning = [&]() {
3649 if (emitExpensiveWarnings)
3650 emitWarning(loc) <<
"dropped intrinsic: " << renderValue(*dbgIntr);
3654 OpBuilder::InsertionGuard guard(builder);
3655 auto convertArgOperandToValue = [&]() {
3661 if (dbgIntr->hasArgList())
3662 return emitUnsupportedWarning();
3669 return emitUnsupportedWarning();
3671 auto [localVariableAttr, locationExprAttr, locVal] =
3672 processDebugOpArgumentsAndInsertionPt(
3673 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3674 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3676 if (!localVariableAttr)
3677 return emitUnsupportedWarning();
3682 Operation *op =
nullptr;
3683 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3684 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3686 else if (isa<llvm::DbgValueInst>(dbgIntr))
3687 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3690 return emitUnsupportedWarning();
3693 setNonDebugMetadataAttrs(dbgIntr, op);
3698ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3699 DominanceInfo &domInfo) {
3700 OpBuilder::InsertionGuard guard(builder);
3702 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3703 if (!emitExpensiveWarnings)
3706 llvm::raw_string_ostream optionsStream(
options);
3707 dbgRecord.print(optionsStream);
3708 emitWarning(loc) <<
"unhandled debug variable record "
3709 << optionsStream.str();
3715 if (dbgRecord.hasArgList())
3716 return emitUnsupportedWarning();
3721 if (!dbgRecord.getAddress())
3722 return emitUnsupportedWarning();
3724 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3725 llvm::Value *value = dbgRecord.getAddress();
3728 auto it = valueMapping.find(value);
3729 if (it != valueMapping.end())
3730 return it->getSecond();
3733 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3734 return convertConstantExpr(constant);
3738 auto [localVariableAttr, locationExprAttr, locVal] =
3739 processDebugOpArgumentsAndInsertionPt(
3740 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3741 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3743 if (!localVariableAttr)
3744 return emitUnsupportedWarning();
3749 if (dbgRecord.isDbgDeclare())
3750 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3752 else if (dbgRecord.isDbgValue())
3753 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3756 return emitUnsupportedWarning();
3761LogicalResult ModuleImport::processDebugIntrinsics() {
3762 DominanceInfo domInfo;
3763 for (llvm::Instruction *inst : debugIntrinsics) {
3764 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3765 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3771LogicalResult ModuleImport::processDebugRecords() {
3772 DominanceInfo domInfo;
3773 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3774 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3780LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3782 builder.setInsertionPointToStart(block);
3783 for (llvm::Instruction &inst : *bb) {
3784 if (
failed(processInstruction(&inst)))
3789 if (debugIntrinsics.contains(&inst))
3796 setNonDebugMetadataAttrs(&inst, op);
3797 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3798 if (emitExpensiveWarnings) {
3799 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3800 emitWarning(loc) <<
"dropped instruction: " << renderValue(inst);
3805 if (bb->hasAddressTaken()) {
3806 OpBuilder::InsertionGuard guard(builder);
3807 builder.setInsertionPointToStart(block);
3809 BlockTagAttr::get(context, bb->getNumber()));
3814FailureOr<SmallVector<AccessGroupAttr>>
3816 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3822 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3825FailureOr<DereferenceableAttr>
3828 Location loc = mlirModule.getLoc();
3832 if (node->getNumOperands() != 1)
3833 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3834 << renderMetadata(node);
3836 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3837 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3838 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3839 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3840 "non-negative constant integer: "
3841 << renderMetadata(node);
3843 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3844 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3845 numBytesCst->getZExtValue(), mayBeNull);
3851 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3852 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3853 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3854 bool importStructsAsLiterals) {
3861 LLVMDialect::getDialectNamespace()));
3863 DLTIDialect::getDialectNamespace()));
3864 if (loadAllDialects)
3867 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3871 emitExpensiveWarnings, dropDICompositeTypeElements,
3872 preferUnregisteredIntrinsics,
3873 importStructsAsLiterals);
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static ArrayAttr convertLLVMAttributesToMLIR(Location loc, MLIRContext *context, llvm::AttributeSet attributes, ArrayRef< StringLiteral > attributesToSkip={}, ArrayRef< StringLiteral > attributePrefixesToSkip={})
Converts LLVM string, integer, and enum attributes into MLIR attributes, skipping those in attributes...
static StringRef getLLVMSyncScope(llvm::Instruction *inst)
Converts the sync scope identifier of inst to the string representation necessary to build an atomic ...
static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp)
Converts LLVM attributes from func into MLIR attributes and adds them to funcOp as passthrough attrib...
static constexpr size_t kMaxDiagLength
Upper bound on the characters a diagnostic renders for an LLVM entity.
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 FailureOr< uint64_t > convertInt64FromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey, llvm::ModuleSlotTracker &tracker)
Extract an integer value from a two element tuple (<key, value>).
static constexpr std::array kExplicitLLVMFuncOpAttributePrefixes
static llvm::ConstantAsMetadata * getConstantMDFromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey, llvm::ModuleSlotTracker &tracker, bool optional=false)
Extract a constant metadata value from a two element tuple (<key, value>).
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 constexpr std::array kExplicitLLVMFuncOpAttributes
static constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static std::optional< ProfileSummaryFormatKind > convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &formatMD, llvm::ModuleSlotTracker &tracker)
static void convertNoBuiltinAttrs(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static LogicalResult setDebugIntrinsicBuilderInsertionPoint(mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand)
Ensure that the debug intrinsic is inserted right after the operand definition.
static LogicalResult checkFunctionTypeCompatibility(LLVMFunctionType callType, LLVMFunctionType calleeType)
Checks if callType and calleeType are compatible and can be represented in MLIR.
static void processDenormalFPEnv(llvm::Function *func, LLVMFuncOp funcOp)
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
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 llvm::MDTuple * getTwoElementMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, llvm::ModuleSlotTracker &tracker)
Extract a two element MDTuple from a MDOperand.
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
static TypedAttr getScalarConstantAsAttr(OpBuilder &builder, llvm::Constant *constScalar)
Returns an integer or float attribute for the provided scalar constant constScalar or nullptr if the ...
static void convertAllocsizeAttr(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static Attribute convertProfileSummaryModuleFlagValue(ModuleOp mlirModule, const llvm::Module *llvmModule, llvm::MDTuple *mdTuple, llvm::ModuleSlotTracker &tracker)
static std::string truncateDiag(std::string str)
static Attribute convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, StringRef key, llvm::MDTuple *mdTuple, llvm::ModuleSlotTracker &tracker)
Invoke specific handlers for each known module flag value, returns nullptr if the key is unknown or u...
static std::string renderMetadataWithTracker(const llvm::Metadata *node, llvm::ModuleSlotTracker &tracker, const llvm::Module *module)
Prints a metadata node through a caller-provided tracker so module-flag conversion shares the importe...
static FailureOr< SmallVector< ModuleFlagProfileSummaryDetailedAttr > > convertProfileSummaryDetailed(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &summaryMD, llvm::ModuleSlotTracker &tracker)
static SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(ArrayRef< llvm::BasicBlock * > basicBlocks)
Get a topologically sorted list of blocks for the given basic blocks.
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
Operation * getTerminator()
Get the terminator operation of this block.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
This class is a general helper class for creating context-global objects like types,...
IntegerAttr getIntegerAttr(Type type, int64_t value)
FloatAttr getFloatAttr(Type type, double value)
IntegerAttr getI64IntegerAttr(int64_t value)
StringAttr getStringAttr(const Twine &bytes)
ArrayAttr getArrayAttr(ArrayRef< Attribute > 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.
StringRef getValue() const
Returns the name of the held symbol reference.
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.