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/Operator.h"
45#include "llvm/Support/LogicalResult.h"
46#include "llvm/Support/ModRef.h"
53#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
58static std::string
diag(
const llvm::Value &value) {
60 llvm::raw_string_ostream os(str);
68static std::string
diagMD(
const llvm::Metadata *node,
69 const llvm::Module *module) {
71 llvm::raw_string_ostream os(str);
72 node->print(os, module,
true);
78 return "llvm.global_ctors";
83 return "mlir.llvm.nameless_global";
88 return "llvm.global_dtors";
94 return "__llvm_global_comdat";
103 std::optional<llvm::SyncScope::ID> syncScopeID =
104 llvm::getAtomicSyncScopeID(inst);
111 llvm::LLVMContext &llvmContext = inst->getContext();
112 llvmContext.getSyncScopeNames(syncScopeName);
113 auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {
114 return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);
116 if (it != syncScopeName.end())
118 llvm_unreachable(
"incorrect sync scope identifier");
124 llvm::append_range(position,
indices);
135 llvm::Instruction *inst,
148#include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"
154ModuleImport::getMetadataGlobalValueSymbolRef(llvm::GlobalValue *global) {
155 if (
auto *globalVar = dyn_cast<llvm::GlobalVariable>(global)) {
156 StringRef name = globalVar->getName();
158 return getOrCreateNamelessSymbolName(globalVar);
163 if (
auto *func = dyn_cast<llvm::Function>(global)) {
166 if (func->isIntrinsic() &&
167 iface.isConvertibleIntrinsic(func->getIntrinsicID()))
171 if (global->getName().empty())
177ModuleImport::getMetadataOperandSymbolRef(
const llvm::Metadata *md) {
178 auto *valueAsMD = dyn_cast_or_null<llvm::ValueAsMetadata>(md);
181 llvm::Value *value = valueAsMD->getValue();
182 llvm::GlobalValue *gv = dyn_cast<llvm::GlobalValue>(value);
184 gv = dyn_cast<llvm::GlobalValue>(value->stripPointerCastsAndAliases());
187 return getMetadataGlobalValueSymbolRef(gv);
199Attribute ModuleImport::convertMetadataToAttrImpl(
200 const llvm::Metadata *md, SmallPtrSetImpl<const llvm::Metadata *> &path,
204 if (
auto *mdStr = dyn_cast<llvm::MDString>(md))
205 return MDStringAttr::get(context,
206 StringAttr::get(context, mdStr->getString()));
207 if (
auto *cam = dyn_cast<llvm::ConstantAsMetadata>(md)) {
208 llvm::Constant *constant = cam->getValue();
209 if (
auto *global = dyn_cast<llvm::GlobalValue>(constant)) {
210 if (FlatSymbolRefAttr symbolRef = getMetadataGlobalValueSymbolRef(global))
211 return MDGlobalValueAttr::get(context, symbolRef);
213 if (
auto *ci = dyn_cast<llvm::ConstantInt>(constant)) {
214 auto intType = IntegerType::get(context, ci->getBitWidth());
215 return MDConstantAttr::get(context,
216 IntegerAttr::get(intType, ci->getValue()));
218 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant))
219 return MDNullAttr::get(context,
220 nullPtr->getType()->getPointerAddressSpace());
221 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
224 if (constExpr->getOpcode() != llvm::Instruction::AddrSpaceCast)
226 Attribute argAttr = convertMetadataToAttrImpl(
227 llvm::ConstantAsMetadata::get(constExpr->getOperand(0)), path,
231 return MDAddrSpaceCastAttr::get(
232 context, argAttr, constExpr->getType()->getPointerAddressSpace());
236 if (
auto *node = dyn_cast<llvm::MDNode>(md)) {
238 if (node->isDistinct())
240 if (Attribute cached = attrMap.lookup(node))
244 if (!path.insert(node).second)
246 SmallVector<Attribute> operands;
247 operands.reserve(node->getNumOperands());
248 for (
const llvm::MDOperand &op : node->operands()) {
249 Attribute opAttr = convertMetadataToAttrImpl(op.get(), path, attrMap);
252 operands.push_back(opAttr);
255 Attribute nodeAttr = MDNodeAttr::get(context, operands);
256 attrMap.try_emplace(node, nodeAttr);
267Attribute ModuleImport::convertMetadataToAttr(
const llvm::Metadata *md) {
268 SmallPtrSet<const llvm::Metadata *, 8> path;
270 return convertMetadataToAttrImpl(md, path, attrMap);
277 for (llvm::BasicBlock *basicBlock : basicBlocks) {
278 if (!blocks.contains(basicBlock)) {
279 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
280 blocks.insert_range(traversal);
283 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
288 std::unique_ptr<llvm::Module> llvmModule,
289 bool emitExpensiveWarnings,
290 bool importEmptyDICompositeTypes,
291 bool preferUnregisteredIntrinsics,
292 bool importStructsAsLiterals)
294 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
296 typeTranslator(*mlirModule->
getContext(), importStructsAsLiterals),
298 mlirModule, importEmptyDICompositeTypes)),
299 loopAnnotationImporter(
301 emitExpensiveWarnings(emitExpensiveWarnings),
302 preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
303 builder.setInsertionPointToStart(mlirModule.getBody());
306ComdatOp ModuleImport::getGlobalComdatOp() {
308 return globalComdatOp;
314 globalInsertionOp = globalComdatOp;
315 return globalComdatOp;
318LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
323 auto getIdentityIfRootNode =
324 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
328 if (node->getNumOperands() > 1)
331 if (node->getNumOperands() == 1)
332 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
333 return std::optional<StringRef>{op0->getString()};
334 return std::optional<StringRef>{};
344 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
345 StringRef *identity =
nullptr,
346 SmallVectorImpl<TBAAMemberAttr> *members =
347 nullptr) -> std::optional<bool> {
348 unsigned numOperands = node->getNumOperands();
357 const auto *identityNode =
358 dyn_cast<const llvm::MDString>(node->getOperand(0));
364 *identity = identityNode->getString();
366 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
367 const auto *memberNode =
368 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
370 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
371 <<
diagMD(node, llvmModule.get());
375 if (2 * pairNum + 2 >= numOperands) {
377 if (numOperands != 2) {
378 emitError(loc) <<
"missing member offset: "
379 <<
diagMD(node, llvmModule.get());
383 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
384 node->getOperand(2 * pairNum + 2));
386 emitError(loc) <<
"operand '" << 2 * pairNum + 2
387 <<
"' must be ConstantInt: "
388 <<
diagMD(node, llvmModule.get());
391 offset = offsetCI->getZExtValue();
395 members->push_back(TBAAMemberAttr::get(
396 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
409 auto isTagNode = [&](
const llvm::MDNode *node,
410 TBAATypeDescriptorAttr *baseAttr =
nullptr,
411 TBAATypeDescriptorAttr *accessAttr =
nullptr,
412 int64_t *offset =
nullptr,
413 bool *isConstant =
nullptr) -> std::optional<bool> {
421 unsigned numOperands = node->getNumOperands();
422 if (numOperands != 3 && numOperands != 4)
424 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
425 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
427 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
428 if (!baseMD || !accessMD || !offsetCI)
435 if (accessMD->getNumOperands() < 1 ||
436 !isa<llvm::MDString>(accessMD->getOperand(0)))
438 bool isConst =
false;
439 if (numOperands == 4) {
441 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
443 emitError(loc) <<
"operand '3' must be ConstantInt: "
444 <<
diagMD(node, llvmModule.get());
447 isConst = isConstantCI->getValue()[0];
450 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
452 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
454 *offset = offsetCI->getZExtValue();
456 *isConstant = isConst;
464 SmallVector<const llvm::MDNode *> workList;
465 workList.push_back(node);
466 while (!workList.empty()) {
467 const llvm::MDNode *current = workList.back();
468 if (tbaaMapping.contains(current)) {
477 bool anyChildNotConverted =
false;
478 for (
const llvm::MDOperand &operand : current->operands())
479 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
480 if (!tbaaMapping.contains(childNode)) {
481 workList.push_back(childNode);
482 anyChildNotConverted =
true;
485 if (anyChildNotConverted) {
490 if (!seen.insert(current).second)
491 return emitError(loc) <<
"has cycle in TBAA graph: "
492 <<
diagMD(current, llvmModule.get());
500 FailureOr<std::optional<StringRef>> rootNodeIdentity =
501 getIdentityIfRootNode(current);
502 if (succeeded(rootNodeIdentity)) {
503 StringAttr stringAttr = *rootNodeIdentity
504 ? builder.getStringAttr(**rootNodeIdentity)
508 tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)});
513 SmallVector<TBAAMemberAttr> members;
514 if (std::optional<bool> isValid =
515 isTypeDescriptorNode(current, &identity, &members)) {
516 assert(isValid.value() &&
"type descriptor node must be valid");
518 tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>(
519 identity, members)});
523 TBAATypeDescriptorAttr baseAttr, accessAttr;
526 if (std::optional<bool> isValid =
527 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
528 assert(isValid.value() &&
"access tag node must be valid");
530 {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
535 return emitError(loc) <<
"unsupported TBAA node format: "
536 <<
diagMD(current, llvmModule.get());
542ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
543 Location loc = mlirModule.getLoc();
544 if (
failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
545 return emitError(loc) <<
"unsupported access group node: "
546 <<
diagMD(node, llvmModule.get());
551ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
552 Location loc = mlirModule.getLoc();
554 auto verifySelfRef = [](
const llvm::MDNode *node) {
555 return node->getNumOperands() != 0 &&
556 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
558 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
559 return node->getNumOperands() != 0 &&
560 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
561 isa<llvm::MDString>(node->getOperand(0)));
564 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
565 return idx >= node->getNumOperands() ||
566 isa<llvm::MDString>(node->getOperand(idx));
569 auto getIdAttr = [&](
const llvm::MDNode *node) -> Attribute {
570 if (verifySelfRef(node))
573 auto *name = cast<llvm::MDString>(node->getOperand(0));
574 return builder.getStringAttr(name->getString());
578 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
579 StringAttr description =
nullptr;
580 if (aliasDomain->getNumOperands() >= 2)
581 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
582 description = builder.getStringAttr(operand->getString());
583 Attribute idAttr = getIdAttr(aliasDomain);
584 return builder.getAttr<AliasScopeDomainAttr>(idAttr, description);
588 for (
const llvm::MDOperand &operand : node->operands()) {
589 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
590 llvm::AliasScopeNode aliasScope(scope);
591 const llvm::MDNode *domain = aliasScope.getDomain();
597 if (!verifySelfRefOrString(scope) || !domain ||
598 !verifyDescription(scope, 2))
599 return emitError(loc) <<
"unsupported alias scope node: "
600 <<
diagMD(scope, llvmModule.get());
601 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
602 return emitError(loc) <<
"unsupported alias domain node: "
603 <<
diagMD(domain, llvmModule.get());
605 if (aliasScopeMapping.contains(scope))
609 auto it = aliasScopeMapping.find(aliasScope.getDomain());
610 if (it == aliasScopeMapping.end()) {
611 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
612 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
616 StringAttr description =
nullptr;
617 if (!aliasScope.getName().empty())
618 description = builder.getStringAttr(aliasScope.getName());
619 Attribute idAttr = getIdAttr(scope);
620 auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(
621 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
623 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
629FailureOr<SmallVector<AliasScopeAttr>>
632 aliasScopes.reserve(node->getNumOperands());
633 for (
const llvm::MDOperand &operand : node->operands()) {
634 auto *node = cast<llvm::MDNode>(operand.get());
635 aliasScopes.push_back(
636 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
639 if (llvm::is_contained(aliasScopes,
nullptr))
645 debugIntrinsics.insert(intrinsic);
649 if (!dbgRecords.contains(dbgRecord))
650 dbgRecords.insert(dbgRecord);
654 llvm::MDTuple *mdTuple) {
655 auto getLLVMFunction =
656 [&](
const llvm::MDOperand &funcMDO) -> llvm::Function * {
657 auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);
661 auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());
667 for (
unsigned i = 0; i < mdTuple->getNumOperands(); i++) {
668 const llvm::MDOperand &mdo = mdTuple->getOperand(i);
669 auto *cgEntry = cast<llvm::MDNode>(mdo);
670 llvm::Constant *llvmConstant =
671 cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();
672 uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();
673 auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));
674 auto *toFn = getLLVMFunction(cgEntry->getOperand(1));
676 cgProfile.push_back(ModuleFlagCGProfileEntryAttr::get(
677 mlirModule->getContext(),
685 return ArrayAttr::get(mlirModule->getContext(), cgProfile);
691 const llvm::Module *llvmModule,
692 const llvm::MDOperand &md) {
693 auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
694 if (!tupleEntry || tupleEntry->getNumOperands() != 2)
696 <<
"expected 2-element tuple metadata: " <<
diagMD(md, llvmModule);
704 ModuleOp mlirModule,
const llvm::Module *llvmModule,
705 const llvm::MDOperand &md, StringRef matchKey,
bool optional =
false) {
709 auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
710 if (!keyMD || keyMD->getString() != matchKey) {
713 <<
"expected '" << matchKey <<
"' key, but found: "
714 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
718 return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));
724static FailureOr<uint64_t>
726 const llvm::Module *llvmModule,
727 const llvm::MDOperand &md, StringRef matchKey) {
728 llvm::ConstantAsMetadata *valMD =
733 if (
auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))
734 return cstInt->getZExtValue();
737 <<
"expected integer metadata value for key '" << matchKey
738 <<
"': " <<
diagMD(md, llvmModule);
742static std::optional<ProfileSummaryFormatKind>
744 const llvm::MDOperand &formatMD) {
749 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
750 if (!keyMD || keyMD->getString() !=
"ProfileFormat") {
752 <<
"expected 'ProfileFormat' key: "
753 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
757 llvm::Metadata *valueMD = tupleEntry->getOperand(1).get();
760 <<
"expected string metadata value for key 'ProfileFormat': null";
764 llvm::MDString *valMD = dyn_cast<llvm::MDString>(valueMD);
767 <<
"expected string metadata value for key 'ProfileFormat': "
768 <<
diagMD(valueMD, llvmModule);
771 std::optional<ProfileSummaryFormatKind> fmtKind =
772 symbolizeProfileSummaryFormatKind(valMD->getString());
775 <<
"expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
777 <<
diagMD(valMD, llvmModule);
784static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
786 const llvm::Module *llvmModule,
787 const llvm::MDOperand &summaryMD) {
792 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
793 if (!keyMD || keyMD->getString() !=
"DetailedSummary") {
795 <<
"expected 'DetailedSummary' key: "
796 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
800 llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
803 <<
"expected tuple value for 'DetailedSummary' key: "
804 <<
diagMD(tupleEntry->getOperand(1), llvmModule);
809 for (
auto &&entry : entriesMD->operands()) {
810 llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
811 if (!entryMD || entryMD->getNumOperands() != 3) {
813 <<
"'DetailedSummary' entry expects 3 operands: "
814 <<
diagMD(entry, llvmModule);
818 auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
819 auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
820 auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
821 if (!op0 || !op1 || !op2) {
823 <<
"expected only integer entries in 'DetailedSummary': "
824 <<
diagMD(entry, llvmModule);
828 auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get(
829 mlirModule->getContext(),
830 cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
831 cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
832 cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
833 detailedSummary.push_back(detaildSummaryEntry);
835 return detailedSummary;
840 const llvm::Module *llvmModule,
841 llvm::MDTuple *mdTuple) {
842 unsigned profileNumEntries = mdTuple->getNumOperands();
843 if (profileNumEntries < 8) {
845 <<
"expected at 8 entries in 'ProfileSummary': "
846 <<
diagMD(mdTuple, llvmModule);
850 unsigned summayIdx = 0;
851 auto checkOptionalPosition = [&](
const llvm::MDOperand &md,
852 StringRef matchKey) -> LogicalResult {
856 if (summayIdx + 1 >= profileNumEntries) {
858 <<
"the last summary entry is '" << matchKey
859 <<
"', expected 'DetailedSummary': " <<
diagMD(md, llvmModule);
866 auto getOptIntValue =
867 [&](
const llvm::MDOperand &md,
868 StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
871 return FailureOr<std::optional<uint64_t>>(std::nullopt);
872 if (checkOptionalPosition(md, matchKey).failed())
874 FailureOr<uint64_t> val =
881 auto getOptDoubleValue = [&](
const llvm::MDOperand &md,
882 StringRef matchKey) -> FailureOr<FloatAttr> {
887 if (
auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
888 if (checkOptionalPosition(md, matchKey).failed())
890 return FloatAttr::get(Float64Type::get(mlirModule.getContext()),
891 cstFP->getValueAPF());
894 <<
"expected double metadata value for key '" << matchKey
895 <<
"': " <<
diagMD(md, llvmModule);
902 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
903 if (!format.has_value())
907 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"TotalCount");
908 if (failed(totalCount))
912 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"MaxCount");
913 if (failed(maxCount))
917 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
919 if (failed(maxInternalCount))
923 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
925 if (failed(maxFunctionCount))
929 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumCounts");
930 if (failed(numCounts))
934 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumFunctions");
935 if (failed(numFunctions))
939 FailureOr<std::optional<uint64_t>> isPartialProfile =
940 getOptIntValue(mdTuple->getOperand(summayIdx),
"IsPartialProfile");
941 if (failed(isPartialProfile))
943 if (isPartialProfile->has_value())
946 FailureOr<FloatAttr> partialProfileRatio =
947 getOptDoubleValue(mdTuple->getOperand(summayIdx),
"PartialProfileRatio");
948 if (failed(partialProfileRatio))
950 if (*partialProfileRatio)
954 FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
956 mdTuple->getOperand(summayIdx));
957 if (failed(detailed))
961 return ModuleFlagProfileSummaryAttr::get(
962 mlirModule->getContext(), *format, *totalCount, *maxCount,
963 *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,
964 *isPartialProfile, *partialProfileRatio, *detailed);
971 const llvm::Module *llvmModule, StringRef key,
972 llvm::MDTuple *mdTuple) {
973 if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
975 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
980 Builder builder(mlirModule->getContext());
982 strings.reserve(mdTuple->getNumOperands());
983 for (
const llvm::MDOperand &operand : mdTuple->operands()) {
984 auto *mdString = dyn_cast_if_present<llvm::MDString>(operand.get());
987 strings.push_back(builder.
getStringAttr(mdString->getString()));
994 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
997 for (
const auto [behavior, key, val] : llvmModuleFlags) {
999 if (
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
1000 valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
1001 }
else if (
auto *mdString = dyn_cast<llvm::MDString>(val)) {
1002 valAttr = builder.getStringAttr(mdString->getString());
1003 }
else if (
auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
1005 key->getString(), mdTuple);
1010 <<
"unsupported module flag value for key '" << key->getString()
1011 <<
"' : " <<
diagMD(val, llvmModule.get());
1015 moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
1016 convertModFlagBehaviorFromLLVM(behavior),
1017 builder.getStringAttr(key->getString()), valAttr));
1020 if (!moduleFlags.empty())
1021 LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),
1022 builder.getArrayAttr(moduleFlags));
1028 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1029 if (named.getName() !=
"llvm.linker.options")
1032 for (
const llvm::MDNode *node : named.operands()) {
1034 options.reserve(node->getNumOperands());
1035 for (
const llvm::MDOperand &option : node->operands())
1036 options.push_back(cast<llvm::MDString>(option)->getString());
1037 LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),
1038 builder.getStrArrayAttr(
options));
1045 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1046 if (named.getName() !=
"llvm.dependent-libraries")
1049 for (
const llvm::MDNode *node : named.operands()) {
1050 if (node->getNumOperands() == 1)
1051 if (
auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
1052 libraries.push_back(mdString->getString());
1054 if (!libraries.empty())
1055 mlirModule->setDiscardableAttr(
1056 LLVM::LLVMDialect::getDependentLibrariesAttrName(),
1057 builder.getStrArrayAttr(libraries));
1063 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1066 if (named.getName() != LLVMDialect::getIdentAttrName())
1069 if (named.getNumOperands() == 1)
1070 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
1071 if (md->getNumOperands() == 1)
1072 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
1073 mlirModule->setDiscardableAttr(
1074 LLVMDialect::getIdentAttrName(),
1075 builder.getStringAttr(mdStr->getString()));
1081 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
1084 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
1087 if (nmd.getNumOperands() == 1)
1088 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
1089 if (md->getNumOperands() == 1)
1090 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
1091 mlirModule->setDiscardableAttr(
1092 LLVMDialect::getCommandlineAttrName(),
1093 builder.getStringAttr(mdStr->getString()));
1100 builder.setInsertionPointToEnd(mlirModule.getBody());
1101 for (
const llvm::Function &
func : llvmModule->functions()) {
1102 for (
const llvm::Instruction &inst : llvm::instructions(
func)) {
1104 if (llvm::MDNode *node =
1105 inst.getMetadata(llvm::LLVMContext::MD_access_group))
1106 if (failed(processAccessGroupMetadata(node)))
1110 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
1111 if (!aliasAnalysisNodes)
1113 if (aliasAnalysisNodes.TBAA)
1114 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
1116 if (aliasAnalysisNodes.Scope)
1117 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
1119 if (aliasAnalysisNodes.NoAlias)
1120 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
1137void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
1138 if (comdatMapping.contains(comdat))
1141 ComdatOp comdatOp = getGlobalComdatOp();
1144 auto selectorOp = ComdatSelectorOp::create(
1145 builder, mlirModule.getLoc(), comdat->getName(),
1146 convertComdatFromLLVM(comdat->getSelectionKind()),
1151 comdatMapping.try_emplace(comdat, symbolRef);
1155 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1156 if (globalVar.hasComdat())
1157 processComdat(globalVar.getComdat());
1158 for (llvm::Function &
func : llvmModule->functions())
1159 if (
func.hasComdat())
1160 processComdat(
func.getComdat());
1165 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1168 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1169 return emitError(UnknownLoc::get(context))
1170 <<
"unhandled global variable: " <<
diag(globalVar);
1174 if (failed(convertGlobal(&globalVar))) {
1175 return emitError(UnknownLoc::get(context))
1176 <<
"unhandled global variable: " <<
diag(globalVar);
1183 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1184 if (failed(convertAlias(&alias))) {
1185 return emitError(UnknownLoc::get(context))
1186 <<
"unhandled global alias: " <<
diag(alias);
1193 for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1194 if (failed(convertIFunc(&ifunc))) {
1195 return emitError(UnknownLoc::get(context))
1196 <<
"unhandled global ifunc: " <<
diag(ifunc);
1203 Location loc = mlirModule.getLoc();
1205 context, llvmModule->getDataLayout().getStringRepresentation());
1207 return emitError(loc,
"cannot translate data layout: ")
1211 emitWarning(loc,
"unhandled data layout token: ") << token;
1213 mlirModule->setDiscardableAttr(DLTIDialect::kDataLayoutAttrName,
1219 mlirModule->setDiscardableAttr(
1220 LLVM::LLVMDialect::getTargetTripleAttrName(),
1221 builder.getStringAttr(llvmModule->getTargetTriple().str()));
1227 for (
const llvm::Module::GlobalAsmFragment &Frag :
1228 llvmModule->getModuleInlineAsm()) {
1230 for (llvm::StringRef line : llvm::split(Frag.Asm,
'\n'))
1232 asmArrayAttr.push_back(builder.getStringAttr(line));
1235 mlirModule->setDiscardableAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1236 builder.getArrayAttr(asmArrayAttr));
1240 for (llvm::Function &
func : llvmModule->functions())
1246void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1249 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1250 for (
auto &[kind, node] : allMetadata) {
1254 if (emitExpensiveWarnings) {
1255 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1257 <<
diagMD(node, llvmModule.get()) <<
" on "
1266 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1268 IntegerOverflowFlags value = {};
1269 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1271 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1273 iface.setOverflowFlags(value);
1277 auto iface = cast<ExactFlagInterface>(op);
1279 iface.setIsExact(inst->isExact());
1284 auto iface = cast<DisjointFlagInterface>(op);
1285 auto *instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1287 iface.setIsDisjoint(instDisjoint->isDisjoint());
1291 auto iface = cast<NonNegFlagInterface>(op);
1293 iface.setNonNeg(inst->hasNonNeg());
1298 auto iface = cast<FastmathFlagsInterface>(op);
1304 if (!isa<llvm::FPMathOperator>(inst))
1306 llvm::FastMathFlags flags = inst->getFastMathFlags();
1309 FastmathFlags value = {};
1310 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1311 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1312 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1313 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1314 value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
1315 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1316 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1317 FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
1318 iface.setFastmathAttr(attr);
1330 if (numElements.isScalable()) {
1332 <<
"scalable vectors not supported";
1337 Type elementType = cast<VectorType>(type).getElementType();
1341 SmallVector<int64_t> shape(arrayShape);
1342 shape.push_back(numElements.getKnownMinValue());
1343 return VectorType::get(shape, elementType);
1346Type ModuleImport::getBuiltinTypeForAttr(Type type) {
1360 SmallVector<int64_t> arrayShape;
1361 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1362 arrayShape.push_back(arrayType.getNumElements());
1363 type = arrayType.getElementType();
1366 return RankedTensorType::get(arrayShape, type);
1373 llvm::Constant *constScalar) {
1376 if (constScalar->getType()->isVectorTy())
1380 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1382 IntegerType::get(context, constInt->getBitWidth()),
1383 constInt->getValue());
1387 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1388 llvm::Type *type = constFloat->getType();
1389 FloatType floatType =
1391 ? BFloat16Type::get(context)
1395 <<
"unexpected floating-point type";
1398 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1405static SmallVector<Attribute>
1407 llvm::ConstantDataSequential *constSequence) {
1409 elementAttrs.reserve(constSequence->getNumElements());
1410 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1411 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1414 return elementAttrs;
1417Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1423 auto getConstantShape = [&](llvm::Type *type) {
1424 return llvm::dyn_cast_if_present<ShapedType>(
1429 if (isa<llvm::ConstantInt, llvm::ConstantFP>(constant)) {
1430 assert(constant->getType()->isVectorTy() &&
"expected a vector splat");
1431 auto shape = getConstantShape(constant->getType());
1434 Attribute splatAttr =
1441 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1442 if (constArray->isString())
1443 return builder.getStringAttr(constArray->getAsString());
1444 auto shape = getConstantShape(constArray->getType());
1448 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1449 if (constVector && constVector->isSplat()) {
1452 builder, constVector->getElementAsConstant(0));
1456 SmallVector<Attribute> elementAttrs =
1463 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1464 auto shape = getConstantShape(constAggregate->getType());
1468 SmallVector<Attribute> elementAttrs;
1469 SmallVector<llvm::Constant *> workList = {constAggregate};
1470 while (!workList.empty()) {
1471 llvm::Constant *current = workList.pop_back_val();
1474 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1476 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1477 workList.push_back(constAggregate->getAggregateElement(idx));
1482 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1483 SmallVector<Attribute> attrs =
1485 elementAttrs.append(attrs.begin(), attrs.end());
1491 elementAttrs.push_back(scalarAttr);
1502 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1503 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1504 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1508 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1509 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1516ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1517 assert(globalVar->getName().empty() &&
1518 "expected to work with a nameless global");
1519 auto [it,
success] = namelessGlobals.try_emplace(globalVar);
1526 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1529 it->getSecond() = symbolRef;
1533OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1534 OpBuilder::InsertionGuard guard(builder);
1535 if (globalInsertionOp)
1536 builder.setInsertionPointAfter(globalInsertionOp);
1538 builder.setInsertionPointToStart(mlirModule.getBody());
1542LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1544 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1547 AliasOp aliasOp = AliasOp::create(
1548 builder, mlirModule.getLoc(), type,
1549 convertLinkageFromLLVM(alias->getLinkage()), alias->getName(),
1550 alias->isDSOLocal(),
1551 convertThreadLocalModeFromLLVM(alias->getThreadLocalMode()),
1552 ArrayRef<NamedAttribute>());
1553 globalInsertionOp = aliasOp;
1556 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1557 setConstantInsertionPointToStart(block);
1558 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1561 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1563 if (alias->hasAtLeastLocalUnnamedAddr())
1564 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1565 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1570LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1571 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1574 llvm::Constant *resolver = ifunc->getResolver();
1575 Type resolverType =
convertType(resolver->getType());
1576 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1577 resolver->getName(), resolverType,
1578 convertLinkageFromLLVM(ifunc->getLinkage()),
1579 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1580 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1581 convertVisibilityFromLLVM(ifunc->getVisibility()),
1592 ArrayRef<StringLiteral> attributePrefixesToSkip = {}) {
1593 SmallVector<Attribute> mlirAttributes;
1594 for (llvm::Attribute attr : attributes) {
1596 if (attr.isStringAttribute())
1597 attrName = attr.getKindAsString();
1599 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1600 if (llvm::is_contained(attributesToSkip, attrName))
1603 auto attrNameStartsWith = [attrName](StringLiteral sl) {
1604 return attrName.starts_with(sl);
1606 if (attributePrefixesToSkip.end() !=
1607 llvm::find_if(attributePrefixesToSkip, attrNameStartsWith))
1610 auto keyAttr = StringAttr::get(context, attrName);
1611 if (attr.isStringAttribute()) {
1612 StringRef val = attr.getValueAsString();
1615 mlirAttributes.push_back(keyAttr);
1619 mlirAttributes.push_back(
1620 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1623 if (attr.isIntAttribute()) {
1626 auto val = std::to_string(attr.getValueAsInt());
1627 mlirAttributes.push_back(
1628 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1631 if (attr.isEnumAttribute()) {
1633 mlirAttributes.push_back(keyAttr);
1639 <<
"' attribute is invalid on current operation, skipping it";
1641 return ArrayAttr::get(context, mlirAttributes);
1647 GlobalOp globalOp) {
1649 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1650 if (!targetSpecificAttrs.empty())
1651 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1654LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1656 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1658 Attribute valueAttr;
1659 if (globalVar->hasInitializer())
1660 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1661 Type type =
convertType(globalVar->getValueType());
1663 uint64_t alignment = 0;
1664 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1665 if (maybeAlign.has_value()) {
1666 llvm::Align align = *maybeAlign;
1667 alignment = align.value();
1672 SmallVector<Attribute> globalExpressionAttrs;
1673 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1674 globalVar->getDebugInfo(globalExpressions);
1676 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1677 DIGlobalVariableExpressionAttr globalExpressionAttr =
1678 debugImporter->translateGlobalVariableExpression(expr);
1679 globalExpressionAttrs.push_back(globalExpressionAttr);
1684 StringRef globalName = globalVar->getName();
1685 if (globalName.empty())
1686 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1688 GlobalOp globalOp = GlobalOp::create(
1689 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1690 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1691 valueAttr, alignment, globalVar->getAddressSpace(),
1692 globalVar->isDSOLocal(),
1693 convertThreadLocalModeFromLLVM(globalVar->getThreadLocalMode()),
1695 ArrayRef<NamedAttribute>(), globalExpressionAttrs);
1696 globalInsertionOp = globalOp;
1698 if (globalVar->hasInitializer() && !valueAttr) {
1700 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1701 setConstantInsertionPointToStart(block);
1702 FailureOr<Value> initializer =
1703 convertConstantExpr(globalVar->getInitializer());
1706 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1708 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1709 globalOp.setUnnamedAddr(
1710 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1712 if (globalVar->hasSection())
1713 globalOp.setSection(globalVar->getSection());
1714 globalOp.setVisibility_(
1715 convertVisibilityFromLLVM(globalVar->getVisibility()));
1717 if (globalVar->hasComdat())
1718 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1720 if (llvm::MDNode *associatedMD =
1721 globalVar->getMetadata(llvm::LLVMContext::MD_associated)) {
1722 FlatSymbolRefAttr symbolRef;
1723 if (associatedMD->getNumOperands() == 1)
1725 getMetadataOperandSymbolRef(associatedMD->getOperand(0).get());
1727 emitWarning(globalOp.getLoc()) <<
"unhandled associated metadata: "
1728 <<
diagMD(associatedMD, llvmModule.get())
1729 <<
" on " <<
diag(*globalVar);
1731 globalOp.setAssociatedAttr(symbolRef);
1735 if (llvm::MDNode *absSymMD =
1736 globalVar->getMetadata(llvm::LLVMContext::MD_absolute_symbol)) {
1737 unsigned numOps = absSymMD->getNumOperands();
1738 if (numOps >= 2 && numOps % 2 == 0) {
1739 SmallVector<Attribute> rangeAttrs;
1740 rangeAttrs.reserve(numOps);
1742 for (
const llvm::MDOperand &op : absSymMD->operands()) {
1743 auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(op);
1747 auto intType = IntegerType::get(context, constInt->getBitWidth());
1748 rangeAttrs.push_back(IntegerAttr::get(intType, constInt->getValue()));
1751 if (rangeAttrs.size() == numOps)
1752 globalOp.setAbsoluteSymbolAttr(ArrayAttr::get(context, rangeAttrs));
1762ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1763 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1765 llvm::Constant *initializer = globalVar->getInitializer();
1767 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1768 isa<llvm::ConstantAggregateZero>(initializer);
1775 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1776 if (caz->getElementCount().getFixedValue() != 0)
1780 SmallVector<Attribute> funcs;
1781 SmallVector<int32_t> priorities;
1782 SmallVector<Attribute> dataList;
1783 for (llvm::Value *operand : initializer->operands()) {
1784 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1785 if (!aggregate || aggregate->getNumOperands() != 3)
1788 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1789 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1790 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1791 if (!priority || !func || !data)
1794 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1798 else if (data->isNullValue())
1799 dataAttr = ZeroAttr::get(context);
1804 priorities.push_back(priority->getValue().getZExtValue());
1805 dataList.push_back(dataAttr);
1809 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1812 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1813 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1814 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1817 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1818 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1819 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1824ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1826 if (valueMapping.contains(constant))
1835 workList.insert(constant);
1836 while (!workList.empty()) {
1837 llvm::Constant *current = workList.back();
1840 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1841 orderedSet.insert(current);
1842 workList.pop_back();
1848 auto [adjacencyIt,
inserted] = adjacencyLists.try_emplace(current);
1852 for (llvm::Value *operand : current->operands())
1853 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1854 adjacencyIt->getSecond().push_back(constDependency);
1857 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1858 unsigned numElements = constAgg->getElementCount().getFixedValue();
1859 for (
unsigned i = 0, e = numElements; i != e; ++i)
1860 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1866 if (adjacencyIt->getSecond().empty()) {
1867 orderedSet.insert(current);
1868 workList.pop_back();
1876 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1877 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1878 orderedSet.contains(dependency))
1880 workList.insert(dependency);
1886FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1887 Location loc = UnknownLoc::get(context);
1890 if (Attribute attr = getConstantAsAttr(constant)) {
1892 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1893 return AddressOfOp::create(builder, loc, type, symbolRef.
getValue())
1896 return ConstantOp::create(builder, loc, type, attr).getResult();
1900 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1902 return ZeroOp::create(builder, loc, type).getResult();
1906 if (isa<llvm::ConstantTokenNone>(constant)) {
1907 return NoneTokenOp::create(builder, loc).getResult();
1911 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1913 return PoisonOp::create(builder, loc, type).getResult();
1917 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1919 return UndefOp::create(builder, loc, type).getResult();
1923 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1924 Type type =
convertType(dsoLocalEquivalent->getType());
1925 return DSOLocalEquivalentOp::create(
1928 builder.getContext(),
1929 dsoLocalEquivalent->getGlobalValue()->getName()))
1934 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1936 StringRef globalName = globalObj->getName();
1937 FlatSymbolRefAttr symbolRef;
1939 if (globalName.empty())
1941 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1944 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1948 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1949 Type type =
convertType(globalAliasObj->getType());
1950 StringRef aliaseeName = globalAliasObj->getName();
1952 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1956 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1962 llvm::Instruction *inst = constExpr->getAsInstruction();
1963 llvm::scope_exit guard([&]() {
1964 assert(!noResultOpMapping.contains(inst) &&
1965 "expected constant expression to return a result");
1966 valueMapping.erase(inst);
1967 inst->deleteValue();
1971 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1972 return valueMapping.contains(value);
1974 if (
failed(processInstruction(inst)))
1980 if (
auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1981 Type type =
convertType(aggregateZero->getType());
1982 return ZeroOp::create(builder, loc, type).getResult();
1986 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1988 SmallVector<Value> elementValues;
1990 elementValues.reserve(constAgg->getNumOperands());
1991 for (llvm::Value *operand : constAgg->operands())
1994 assert(llvm::count(elementValues,
nullptr) == 0 &&
1995 "expected all elements have been converted before");
1999 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
2001 "unrecognized aggregate type");
2002 Value root = UndefOp::create(builder, loc, rootType);
2003 for (
const auto &it : llvm::enumerate(elementValues)) {
2004 if (isArrayOrStruct) {
2006 InsertValueOp::create(builder, loc, root, it.value(), it.index());
2008 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
2010 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
2011 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
2018 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
2019 LLVMTargetExtType targetExtType =
2020 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
2021 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
2022 "target extension type does not support zero-initialization");
2025 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
2028 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
2032 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
2033 return BlockAddressOp::create(
2035 BlockAddressAttr::get(context, fnSym, blockTag))
2039 StringRef error =
"";
2041 if (isa<llvm::ConstantPtrAuth>(constant))
2042 error =
" since ptrauth(...) is unsupported";
2044 if (isa<llvm::NoCFIValue>(constant))
2045 error =
" since no_cfi is unsupported";
2047 if (isa<llvm::GlobalValue>(constant))
2048 error =
" since global value is unsupported";
2050 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
2053FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
2057 assert(!valueMapping.contains(constant) &&
2058 "expected constant has not been converted before");
2059 assert(constantInsertionBlock &&
2060 "expected the constant insertion block to be non-null");
2063 OpBuilder::InsertionGuard guard(builder);
2064 if (!constantInsertionOp)
2065 builder.setInsertionPointToStart(constantInsertionBlock);
2067 builder.setInsertionPointAfter(constantInsertionOp);
2071 getConstantsToConvert(constant);
2072 for (llvm::Constant *constantToConvert : constantsToConvert) {
2073 FailureOr<Value> converted = convertConstant(constantToConvert);
2076 mapValue(constantToConvert, *converted);
2081 constantInsertionOp =
result.getDefiningOp();
2087 auto it = valueMapping.find(value);
2088 if (it != valueMapping.end())
2089 return it->getSecond();
2096 if (
auto *mdAsVal = dyn_cast<llvm::MetadataAsValue>(value)) {
2097 llvm::Metadata *md = mdAsVal->getMetadata();
2098 Attribute mdAttr = convertMetadataToAttr(md);
2101 <<
"unsupported metadata: " <<
diagMD(md, llvmModule.get());
2103 MetadataAsValueOp::create(builder, UnknownLoc::get(context), mdAttr)
2110 if (
auto *constant = dyn_cast<llvm::Constant>(value))
2111 return convertConstantExpr(constant);
2113 Location loc = UnknownLoc::get(context);
2114 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
2116 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
2122 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2125 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2128 value = node->getValue();
2131 auto it = valueMapping.find(value);
2132 if (it != valueMapping.end())
2133 return it->getSecond();
2136 if (
auto *constant = dyn_cast<llvm::Constant>(value))
2137 return convertConstantExpr(constant);
2141FailureOr<SmallVector<Value>>
2144 remapped.reserve(values.size());
2145 for (llvm::Value *value : values) {
2147 if (failed(converted))
2149 remapped.push_back(*converted);
2159 assert(immArgPositions.size() == immArgAttrNames.size() &&
2160 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
2164 for (
auto [immArgPos, immArgName] :
2165 llvm::zip(immArgPositions, immArgAttrNames)) {
2166 auto &value = operands[immArgPos];
2167 auto *constant = llvm::cast<llvm::Constant>(value);
2169 assert(attr && attr.getType().isIntOrFloat() &&
2170 "expected immarg to be float or integer constant");
2171 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
2172 attrsOut.push_back({nameAttr, attr});
2177 for (llvm::Value *value : operands) {
2181 if (failed(mlirValue))
2183 valuesOut.push_back(*mlirValue);
2188 if (requiresOpBundles) {
2189 opBundleSizes.reserve(opBundles.size());
2190 opBundleTagAttrs.reserve(opBundles.size());
2192 for (
const llvm::OperandBundleUse &bundle : opBundles) {
2193 opBundleSizes.push_back(bundle.Inputs.size());
2194 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
2196 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
2197 auto operandMlirValue =
convertValue(opBundleOperand.get());
2198 if (failed(operandMlirValue))
2200 valuesOut.push_back(*operandMlirValue);
2205 auto opBundleSizesAttrNameAttr =
2206 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
2207 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
2209 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
2210 auto opBundleTagsAttrNameAttr =
2211 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
2212 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
2219 IntegerAttr integerAttr;
2221 bool success = succeeded(converted) &&
2223 assert(
success &&
"expected a constant integer value");
2229 FloatAttr floatAttr;
2233 assert(
success &&
"expected a constant float value");
2240 llvm::DILocalVariable *node =
nullptr;
2241 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2242 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2243 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2245 node = cast<llvm::DILocalVariable *>(valOrVariable);
2247 return debugImporter->translate(node);
2251 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2252 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2253 return debugImporter->translate(node);
2256FPExceptionBehaviorAttr
2258 auto *metadata = cast<llvm::MetadataAsValue>(value);
2259 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2260 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2261 llvm::convertStrToExceptionBehavior(mdstr->getString());
2262 assert(optLLVM &&
"Expecting FP exception behavior");
2263 return builder.getAttr<FPExceptionBehaviorAttr>(
2264 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2268 auto *metadata = cast<llvm::MetadataAsValue>(value);
2269 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2270 std::optional<llvm::RoundingMode> optLLVM =
2271 llvm::convertStrToRoundingMode(mdstr->getString());
2272 assert(optLLVM &&
"Expecting rounding mode");
2273 return builder.getAttr<RoundingModeAttr>(
2274 convertRoundingModeFromLLVM(*optLLVM));
2277FailureOr<SmallVector<AliasScopeAttr>>
2279 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2280 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2285 return debugImporter->translateLoc(loc);
2289ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2290 llvm::BasicBlock *
target,
2292 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2293 auto *phiInst = cast<llvm::PHINode>(&*inst);
2294 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2296 if (failed(converted))
2298 blockArguments.push_back(*converted);
2303FailureOr<SmallVector<Value>>
2304ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2305 bool allowInlineAsm) {
2306 bool isInlineAsm = callInst->isInlineAsm();
2307 if (isInlineAsm && !allowInlineAsm)
2317 llvm::Value *calleeOperand = callInst->getCalledOperand();
2318 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2322 operands.push_back(*called);
2325 SmallVector<llvm::Value *> args(callInst->args());
2326 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2330 llvm::append_range(operands, *arguments);
2338 LLVMFunctionType calleeType) {
2339 if (callType.getReturnType() != calleeType.getReturnType())
2342 if (calleeType.isVarArg()) {
2345 if (callType.getNumParams() < calleeType.getNumParams())
2350 if (callType.getNumParams() != calleeType.getNumParams())
2355 for (
auto [operandType, argumentType] :
2356 llvm::zip(callType.getParams(), calleeType.getParams()))
2357 if (operandType != argumentType)
2363FailureOr<LLVMFunctionType>
2364ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2365 bool &isIncompatibleCall) {
2366 isIncompatibleCall =
false;
2367 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2368 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2374 llvm::Value *calledOperand = callInst->getCalledOperand();
2375 FailureOr<LLVMFunctionType> callType =
2376 castOrFailure(
convertType(callInst->getFunctionType()));
2379 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2381 llvm::FunctionType *origCalleeType =
nullptr;
2383 origCalleeType = callee->getFunctionType();
2384 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2385 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2389 if (!origCalleeType)
2392 FailureOr<LLVMFunctionType> calleeType =
2400 isIncompatibleCall =
true;
2402 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2403 <<
" and " << *calleeType;
2410FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2411 llvm::Value *calledOperand = callInst->getCalledOperand();
2412 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2413 return SymbolRefAttr::get(context, calledOperand->getName());
2417LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2418 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2422 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2426ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2427 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2428 unsigned argIdx = 0;
2429 SmallVector<mlir::Attribute> opAttrs;
2430 bool hasIndirect =
false;
2432 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2434 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2439 if (ci.isIndirect) {
2440 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2441 SmallVector<mlir::NamedAttribute> attrs;
2442 attrs.push_back(builder.getNamedAttr(
2443 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2445 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2449 opAttrs.push_back(builder.getDictionaryAttr({}));
2455 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2459LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2462 if (
auto *brInst = dyn_cast<llvm::UncondBrInst>(inst)) {
2463 llvm::BasicBlock *succ = brInst->getSuccessor();
2464 SmallVector<Value> blockArgs;
2465 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2468 auto brOp = LLVM::BrOp::create(builder, loc, blockArgs,
lookupBlock(succ));
2472 if (
auto *brInst = dyn_cast<llvm::CondBrInst>(inst)) {
2473 SmallVector<Block *> succBlocks;
2474 SmallVector<SmallVector<Value>> succBlockArgs;
2475 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2476 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2477 SmallVector<Value> blockArgs;
2478 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2481 succBlockArgs.push_back(blockArgs);
2484 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2487 auto condBrOp = LLVM::CondBrOp::create(
2488 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2489 succBlocks.back(), succBlockArgs.back());
2493 if (inst->getOpcode() == llvm::Instruction::Switch) {
2494 auto *swInst = cast<llvm::SwitchInst>(inst);
2496 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2499 SmallVector<Value> defaultBlockArgs;
2501 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2502 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2506 unsigned numCases = swInst->getNumCases();
2507 SmallVector<SmallVector<Value>> caseOperands(numCases);
2508 SmallVector<ValueRange> caseOperandRefs(numCases);
2509 SmallVector<APInt> caseValues(numCases);
2510 SmallVector<Block *> caseBlocks(numCases);
2511 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2512 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2513 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2514 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2516 caseOperandRefs[it.index()] = caseOperands[it.index()];
2517 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2521 auto switchOp = SwitchOp::create(builder, loc, *condition,
2523 caseValues, caseBlocks, caseOperandRefs);
2527 if (inst->getOpcode() == llvm::Instruction::PHI) {
2529 mapValue(inst, builder.getInsertionBlock()->addArgument(
2533 if (inst->getOpcode() == llvm::Instruction::Call) {
2534 auto *callInst = cast<llvm::CallInst>(inst);
2535 llvm::Value *calledOperand = callInst->getCalledOperand();
2537 FailureOr<SmallVector<Value>> operands =
2538 convertCallOperands(callInst,
true);
2542 auto callOp = [&]() -> FailureOr<Operation *> {
2543 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2547 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2548 return InlineAsmOp::create(
2549 builder, loc, resultTy, *operands,
2550 builder.getStringAttr(asmI->getAsmString()),
2551 builder.getStringAttr(asmI->getConstraintString()),
2552 asmI->hasSideEffects(), asmI->isAlignStack(),
2553 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2554 AsmDialectAttr::get(
2555 mlirModule.getContext(),
2556 convertAsmDialectFromLLVM(asmI->getDialect())),
2560 bool isIncompatibleCall;
2561 FailureOr<LLVMFunctionType> funcTy =
2562 convertFunctionType(callInst, isIncompatibleCall);
2566 FlatSymbolRefAttr callee =
nullptr;
2567 if (isIncompatibleCall) {
2571 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2572 Value indirectCallVal = LLVM::AddressOfOp::create(
2573 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2574 operands->insert(operands->begin(), indirectCallVal);
2577 callee = convertCalleeName(callInst);
2579 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2581 if (
failed(convertCallAttributes(callInst, callOp)))
2586 if (!isIncompatibleCall)
2588 return callOp.getOperation();
2594 if (!callInst->getType()->isVoidTy())
2595 mapValue(inst, (*callOp)->getResult(0));
2600 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2601 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2603 SmallVector<Value> operands;
2604 operands.reserve(lpInst->getNumClauses());
2605 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2606 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2609 operands.push_back(*operand);
2614 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2618 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2619 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2621 if (invokeInst->isInlineAsm())
2622 return emitError(loc) <<
"invoke of inline assembly is not supported";
2624 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2630 bool invokeResultUsedInPhi = llvm::any_of(
2631 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2632 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2637 Block *directNormalDest = normalDest;
2638 if (invokeResultUsedInPhi) {
2643 OpBuilder::InsertionGuard g(builder);
2644 directNormalDest = builder.createBlock(normalDest);
2647 SmallVector<Value> unwindArgs;
2648 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2652 bool isIncompatibleInvoke;
2653 FailureOr<LLVMFunctionType> funcTy =
2654 convertFunctionType(invokeInst, isIncompatibleInvoke);
2658 FlatSymbolRefAttr calleeName =
nullptr;
2659 if (isIncompatibleInvoke) {
2663 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2664 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2665 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2666 operands->insert(operands->begin(), indirectInvokeVal);
2669 calleeName = convertCalleeName(invokeInst);
2674 auto invokeOp = InvokeOp::create(
2675 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2678 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2683 if (!isIncompatibleInvoke)
2686 if (!invokeInst->getType()->isVoidTy())
2687 mapValue(inst, invokeOp.getResults().front());
2691 SmallVector<Value> normalArgs;
2692 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2696 if (invokeResultUsedInPhi) {
2700 OpBuilder::InsertionGuard g(builder);
2701 builder.setInsertionPointToStart(directNormalDest);
2702 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2706 assert(llvm::none_of(
2708 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2709 "An llvm.invoke operation cannot pass its result as a block "
2711 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2716 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2717 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2718 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2719 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2728 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2736 auto gepOp = GEPOp::create(
2737 builder, loc, type, sourceElementType, *basePtr,
indices,
2738 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2743 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2744 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2746 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2750 SmallVector<Block *> succBlocks;
2751 SmallVector<SmallVector<Value>> succBlockArgs;
2752 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2753 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2754 SmallVector<Value> blockArgs;
2755 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2758 succBlockArgs.push_back(blockArgs);
2760 SmallVector<ValueRange> succBlockArgsRange =
2761 llvm::to_vector_of<ValueRange>(succBlockArgs);
2763 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2764 succBlockArgsRange, succBlocks);
2774 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2777LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2784 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2785 return convertIntrinsic(intrinsic);
2790 if (inst->DebugMarker) {
2791 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2793 if (
auto *dbgVariableRecord =
2794 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2799 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2800 if (!emitExpensiveWarnings)
2803 llvm::raw_string_ostream optionsStream(
options);
2804 dbgRecord.print(optionsStream);
2805 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2809 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2810 DILabelAttr labelAttr =
2811 debugImporter->translate(dbgLabelRecord->getLabel());
2813 return emitUnsupportedWarning();
2814 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2818 return emitUnsupportedWarning();
2823 return convertInstruction(inst);
2826FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2827 if (!f->hasPersonalityFn())
2830 llvm::Constant *pf = f->getPersonalityFn();
2834 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2838 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2839 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2840 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2841 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2842 return SymbolRefAttr::get(builder.getContext(), func->getName());
2845 return FlatSymbolRefAttr();
2849 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2851 auto othermem = convertModRefInfoFromLLVM(
2852 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2853 auto argMem = convertModRefInfoFromLLVM(
2854 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2855 auto inaccessibleMem = convertModRefInfoFromLLVM(
2856 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2857 auto errnoMem = convertModRefInfoFromLLVM(
2858 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2859 auto targetMem0 = convertModRefInfoFromLLVM(
2860 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2861 auto targetMem1 = convertModRefInfoFromLLVM(
2862 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2864 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2865 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2867 if (memAttr.isReadWrite())
2869 funcOp.setMemoryEffectsAttr(memAttr);
2873 llvm::DenormalFPEnv denormalFpEnv =
func->getDenormalFPEnv();
2875 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2878 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2879 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2881 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2882 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2883 convertDenormalModeKindFromLLVM(defaultMode.Input),
2884 convertDenormalModeKindFromLLVM(floatMode.Output),
2885 convertDenormalModeKindFromLLVM(floatMode.Input));
2886 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2892 StringLiteral(
"aarch64_in_za"),
2893 StringLiteral(
"aarch64_inout_za"),
2894 StringLiteral(
"aarch64_new_za"),
2895 StringLiteral(
"aarch64_out_za"),
2896 StringLiteral(
"aarch64_preserves_za"),
2897 StringLiteral(
"aarch64_pstate_sm_body"),
2898 StringLiteral(
"aarch64_pstate_sm_compatible"),
2899 StringLiteral(
"aarch64_pstate_sm_enabled"),
2900 StringLiteral(
"allocsize"),
2901 StringLiteral(
"alwaysinline"),
2902 StringLiteral(
"cold"),
2903 StringLiteral(
"convergent"),
2904 StringLiteral(
"fp-contract"),
2905 StringLiteral(
"frame-pointer"),
2906 StringLiteral(
"hot"),
2907 StringLiteral(
"inlinehint"),
2908 StringLiteral(
"instrument-function-entry"),
2909 StringLiteral(
"instrument-function-exit"),
2910 StringLiteral(
"modular-format"),
2911 StringLiteral(
"memory"),
2912 StringLiteral(
"minsize"),
2913 StringLiteral(
"no_caller_saved_registers"),
2914 StringLiteral(
"no-signed-zeros-fp-math"),
2915 StringLiteral(
"no-builtins"),
2916 StringLiteral(
"nocallback"),
2917 StringLiteral(
"noduplicate"),
2918 StringLiteral(
"noinline"),
2919 StringLiteral(
"noreturn"),
2920 StringLiteral(
"nounwind"),
2921 StringLiteral(
"optnone"),
2922 StringLiteral(
"optsize"),
2923 StringLiteral(
"returns_twice"),
2924 StringLiteral(
"save-reg-params"),
2925 StringLiteral(
"target-features"),
2926 StringLiteral(
"trap-func-name"),
2927 StringLiteral(
"tune-cpu"),
2928 StringLiteral(
"uniform-work-group-size"),
2929 StringLiteral(
"uwtable"),
2930 StringLiteral(
"vscale_range"),
2931 StringLiteral(
"willreturn"),
2932 StringLiteral(
"zero-call-used-regs"),
2933 StringLiteral(
"denormal_fpenv"),
2939 StringLiteral(
"no-builtin-"),
2942template <
typename OpTy>
2944 const llvm::AttributeSet &attrs,
2947 if (attrs.hasAttribute(
"no-builtins")) {
2948 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2953 for (llvm::Attribute attr : attrs) {
2956 if (attr.hasKindAsEnum())
2959 StringRef val = attr.getKindAsString();
2961 if (val.starts_with(
"no-builtin-"))
2963 StringAttr::get(ctx, val.drop_front(
sizeof(
"no-builtin-") - 1)));
2966 if (!nbAttrs.empty())
2967 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2970template <
typename OpTy>
2972 const llvm::AttributeSet &attrs, OpTy
target) {
2973 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2974 if (!attr.isValid())
2977 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2981 static_cast<int32_t
>(*numElems)}));
2992 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2993 llvm::AttributeList::AttrIndex::FunctionIndex);
2995 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2997 if (!passthroughAttr.empty())
2998 funcOp.setPassthroughAttr(passthroughAttr);
3002 LLVMFuncOp funcOp) {
3007 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
3008 funcOp.setNoInline(
true);
3009 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
3010 funcOp.setAlwaysInline(
true);
3011 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
3012 funcOp.setInlineHint(
true);
3013 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
3014 funcOp.setOptimizeNone(
true);
3015 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
3016 funcOp.setConvergent(
true);
3017 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
3018 funcOp.setNoUnwind(
true);
3019 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
3020 funcOp.setWillReturn(
true);
3021 if (
func->hasFnAttribute(llvm::Attribute::NoReturn))
3022 funcOp.setNoreturn(
true);
3023 if (
func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
3024 funcOp.setOptsize(
true);
3025 if (
func->hasFnAttribute(
"save-reg-params"))
3026 funcOp.setSaveRegParams(
true);
3027 if (
func->hasFnAttribute(
"uniform-work-group-size"))
3028 funcOp.setUniformWorkGroupSize(
true);
3029 if (
func->hasFnAttribute(llvm::Attribute::MinSize))
3030 funcOp.setMinsize(
true);
3031 if (
func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
3032 funcOp.setReturnsTwice(
true);
3033 if (
func->hasFnAttribute(llvm::Attribute::Cold))
3034 funcOp.setCold(
true);
3035 if (
func->hasFnAttribute(llvm::Attribute::Hot))
3036 funcOp.setHot(
true);
3037 if (
func->hasFnAttribute(llvm::Attribute::NoDuplicate))
3038 funcOp.setNoduplicate(
true);
3039 if (
func->hasFnAttribute(
"no_caller_saved_registers"))
3040 funcOp.setNoCallerSavedRegisters(
true);
3041 if (
func->hasFnAttribute(llvm::Attribute::NoCallback))
3042 funcOp.setNocallback(
true);
3043 if (llvm::Attribute attr =
func->getFnAttribute(
"modular-format");
3044 attr.isStringAttribute())
3045 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3046 if (llvm::Attribute attr =
func->getFnAttribute(
"zero-call-used-regs");
3047 attr.isStringAttribute())
3048 funcOp.setZeroCallUsedRegsAttr(
3049 StringAttr::get(context, attr.getValueAsString()));
3051 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
3052 funcOp.setArmStreaming(
true);
3053 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
3054 funcOp.setArmLocallyStreaming(
true);
3055 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
3056 funcOp.setArmStreamingCompatible(
true);
3058 if (
func->hasFnAttribute(
"aarch64_new_za"))
3059 funcOp.setArmNewZa(
true);
3060 else if (
func->hasFnAttribute(
"aarch64_in_za"))
3061 funcOp.setArmInZa(
true);
3062 else if (
func->hasFnAttribute(
"aarch64_out_za"))
3063 funcOp.setArmOutZa(
true);
3064 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
3065 funcOp.setArmInoutZa(
true);
3066 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
3067 funcOp.setArmPreservesZa(
true);
3072 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
3073 if (attr.isValid()) {
3075 auto intTy = IntegerType::get(context, 32);
3076 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
3077 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
3078 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
3082 if (
func->hasFnAttribute(
"frame-pointer")) {
3083 StringRef stringRefFramePointerKind =
3084 func->getFnAttribute(
"frame-pointer").getValueAsString();
3085 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
3086 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
3087 stringRefFramePointerKind)
3091 if (
func->hasFnAttribute(
"use-sample-profile"))
3092 funcOp.setUseSampleProfile(
true);
3094 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
3095 attr.isStringAttribute())
3096 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3098 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
3099 attr.isStringAttribute())
3100 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3102 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
3103 attr.isStringAttribute())
3104 funcOp.setTargetFeaturesAttr(
3105 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
3107 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
3108 attr.isStringAttribute())
3109 funcOp.setReciprocalEstimatesAttr(
3110 StringAttr::get(context, attr.getValueAsString()));
3112 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
3113 attr.isStringAttribute())
3114 funcOp.setPreferVectorWidth(attr.getValueAsString());
3116 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
3117 attr.isStringAttribute())
3118 funcOp.setInstrumentFunctionEntry(
3119 StringAttr::get(context, attr.getValueAsString()));
3121 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
3122 attr.isStringAttribute())
3123 funcOp.setInstrumentFunctionExit(
3124 StringAttr::get(context, attr.getValueAsString()));
3126 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
3127 attr.isStringAttribute())
3128 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
3130 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
3131 attr.isStringAttribute())
3132 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
3134 if (
func->hasUWTable()) {
3135 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
3136 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
3137 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
3142ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
3145 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
3147 if (!llvmAttr.isValid())
3152 if (llvmAttr.hasKindAsEnum() &&
3153 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
3154 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
3155 paramAttrs.push_back(
3161 if (llvmAttr.isTypeAttribute())
3162 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
3163 else if (llvmAttr.isIntAttribute())
3165 else if (llvmAttr.isEnumAttribute())
3167 else if (llvmAttr.isConstantRangeAttribute()) {
3168 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
3169 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
3172 llvm_unreachable(
"unexpected parameter attribute kind");
3174 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
3177 return builder.getDictionaryAttr(paramAttrs);
3181 LLVMFuncOp funcOp) {
3182 auto llvmAttrs = func->getAttributes();
3183 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
3184 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
3185 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
3189 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3190 if (!llvmResAttr.hasAttributes())
3192 funcOp.setResAttrsAttr(
3193 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
3197 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
3200 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
3201 immArgPositions.end());
3203 llvm::AttributeList llvmAttrs = call->getAttributes();
3205 bool anyArgAttrs =
false;
3206 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
3208 if (immArgPositionsSet.contains(i))
3210 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3211 if (llvmArgAttrsSet.back().hasAttributes())
3216 for (
auto &dict : dictAttrs)
3217 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3218 return builder.getArrayAttr(attrs);
3222 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
3223 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3224 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3228 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3229 if (!llvmResAttr.hasAttributes())
3231 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3232 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3235template <
typename Op>
3237 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3241LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3243 llvm::AttributeList invokeAttrs = inst->getAttributes();
3244 op.setUniformWorkGroupSize(
3245 invokeAttrs.getFnAttr(
"uniform-work-group-size").isValid());
3249LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3255 llvm::AttributeList callAttrs = inst->getAttributes();
3257 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3258 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3259 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3260 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3261 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3263 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3264 op.setSaveRegParams(callAttrs.getFnAttr(
"save-reg-params").isValid());
3265 op.setUniformWorkGroupSize(
3266 callAttrs.getFnAttr(
"uniform-work-group-size").isValid());
3267 op.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3268 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3269 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3272 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3273 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3274 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3276 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3277 op.setNoCallerSavedRegisters(
3278 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3279 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3281 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3282 attr.isStringAttribute())
3283 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3284 if (llvm::Attribute attr = callAttrs.getFnAttr(
"zero-call-used-regs");
3285 attr.isStringAttribute())
3286 op.setZeroCallUsedRegsAttr(
3287 StringAttr::get(context, attr.getValueAsString()));
3288 if (llvm::Attribute attr = callAttrs.getFnAttr(
"trap-func-name");
3289 attr.isStringAttribute())
3290 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3291 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3293 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3294 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3296 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3297 ModRefInfo othermem = convertModRefInfoFromLLVM(
3298 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3299 ModRefInfo argMem = convertModRefInfoFromLLVM(
3300 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3301 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3302 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3303 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3304 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3305 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3306 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3307 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3308 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3310 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3311 errnoMem, targetMem0, targetMem1);
3313 if (!memAttr.isReadWrite())
3314 op.setMemoryEffectsAttr(memAttr);
3327 if (
func->isIntrinsic() &&
3328 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3331 bool dsoLocal =
func->isDSOLocal();
3332 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3336 builder.setInsertionPointToEnd(mlirModule.getBody());
3338 Location loc = debugImporter->translateFuncLocation(
func);
3339 LLVMFuncOp funcOp = LLVMFuncOp::create(
3340 builder, loc,
func->getName(), functionType,
3341 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3346 funcOp.setPersonalityAttr(personality);
3347 else if (
func->hasPersonalityFn())
3348 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3351 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3353 if (
func->hasAtLeastLocalUnnamedAddr())
3354 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3356 if (
func->hasSection())
3357 funcOp.setSection(StringRef(
func->getSection()));
3359 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3361 if (
func->hasComdat())
3362 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3364 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3365 funcOp.setAlignment(maybeAlign->value());
3374 func->getAllMetadata(allMetadata);
3376 llvmModule->getMDKindNames(metadataNames);
3378 for (
auto &[kind, node] : allMetadata) {
3379 if (kind == llvm::LLVMContext::MD_dbg)
3382 llvm::MDNode *metadataNode = node;
3383 auto emitUnhandledFunctionMetadataWarning = [&]() {
3385 <<
"unhandled function metadata: "
3386 <<
diagMD(metadataNode, llvmModule.get()) <<
" on " <<
diag(*
func);
3389 if (iface.isConvertibleMetadata(kind)) {
3390 if (succeeded(iface.setMetadataAttrs(builder, kind, metadataNode, funcOp,
3393 emitUnhandledFunctionMetadataWarning();
3397 Attribute nodeAttr = convertMetadataToAttr(metadataNode);
3398 auto mdNodeAttr = dyn_cast_if_present<LLVM::MDNodeAttr>(nodeAttr);
3399 if (!mdNodeAttr || kind >= metadataNames.size()) {
3400 emitUnhandledFunctionMetadataWarning();
3404 functionMetadata.push_back(LLVM::FunctionMetadataAttr::get(
3405 context, builder.getStringAttr(metadataNames[kind]), mdNodeAttr));
3407 if (!functionMetadata.empty())
3408 funcOp.setFunctionMetadataAttr(builder.getArrayAttr(functionMetadata));
3410 if (
func->isDeclaration())
3419 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3420 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3425 for (llvm::BasicBlock &basicBlock : *
func) {
3427 if (!reachable.contains(&basicBlock)) {
3428 if (basicBlock.hasAddressTaken())
3430 <<
"unreachable block '" << basicBlock.getName()
3431 <<
"' with address taken";
3434 Region &body = funcOp.getBody();
3435 Block *block = builder.createBlock(&body, body.
end());
3437 reachableBasicBlocks.push_back(&basicBlock);
3441 for (
const auto &it : llvm::enumerate(
func->args())) {
3442 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3443 functionType.getParamType(it.index()), funcOp.getLoc());
3452 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3453 for (llvm::BasicBlock *basicBlock : blocks)
3454 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3459 if (failed(processDebugIntrinsics()))
3464 if (failed(processDebugRecords()))
3473 if (!dbgIntr->isKillLocation())
3475 llvm::Value *value = dbgIntr->getArgOperand(0);
3476 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3479 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3491 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3494 if (dominatedBlocks.empty())
3498 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3501 Value insertPt = argOperand;
3502 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3508 if (!insertionBlock->
empty() &&
3509 isa<LandingpadOp>(insertionBlock->
front()))
3510 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3518std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3519ModuleImport::processDebugOpArgumentsAndInsertionPt(
3521 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3522 llvm::Value *address,
3523 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3524 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3530 FailureOr<Value> argOperand = convertArgOperandToValue();
3531 if (
failed(argOperand)) {
3532 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3540 return {localVarAttr, debugImporter->translateExpression(expression),
3545ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3546 DominanceInfo &domInfo) {
3548 auto emitUnsupportedWarning = [&]() {
3549 if (emitExpensiveWarnings)
3554 OpBuilder::InsertionGuard guard(builder);
3555 auto convertArgOperandToValue = [&]() {
3561 if (dbgIntr->hasArgList())
3562 return emitUnsupportedWarning();
3569 return emitUnsupportedWarning();
3571 auto [localVariableAttr, locationExprAttr, locVal] =
3572 processDebugOpArgumentsAndInsertionPt(
3573 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3574 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3576 if (!localVariableAttr)
3577 return emitUnsupportedWarning();
3582 Operation *op =
nullptr;
3583 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3584 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3586 else if (isa<llvm::DbgValueInst>(dbgIntr))
3587 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3590 return emitUnsupportedWarning();
3593 setNonDebugMetadataAttrs(dbgIntr, op);
3598ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3599 DominanceInfo &domInfo) {
3600 OpBuilder::InsertionGuard guard(builder);
3602 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3603 if (!emitExpensiveWarnings)
3606 llvm::raw_string_ostream optionsStream(
options);
3607 dbgRecord.print(optionsStream);
3608 emitWarning(loc) <<
"unhandled debug variable record "
3609 << optionsStream.str();
3615 if (dbgRecord.hasArgList())
3616 return emitUnsupportedWarning();
3621 if (!dbgRecord.getAddress())
3622 return emitUnsupportedWarning();
3624 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3625 llvm::Value *value = dbgRecord.getAddress();
3628 auto it = valueMapping.find(value);
3629 if (it != valueMapping.end())
3630 return it->getSecond();
3633 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3634 return convertConstantExpr(constant);
3638 auto [localVariableAttr, locationExprAttr, locVal] =
3639 processDebugOpArgumentsAndInsertionPt(
3640 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3641 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3643 if (!localVariableAttr)
3644 return emitUnsupportedWarning();
3649 if (dbgRecord.isDbgDeclare())
3650 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3652 else if (dbgRecord.isDbgValue())
3653 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3656 return emitUnsupportedWarning();
3661LogicalResult ModuleImport::processDebugIntrinsics() {
3662 DominanceInfo domInfo;
3663 for (llvm::Instruction *inst : debugIntrinsics) {
3664 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3665 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3671LogicalResult ModuleImport::processDebugRecords() {
3672 DominanceInfo domInfo;
3673 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3674 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3680LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3682 builder.setInsertionPointToStart(block);
3683 for (llvm::Instruction &inst : *bb) {
3684 if (
failed(processInstruction(&inst)))
3689 if (debugIntrinsics.contains(&inst))
3696 setNonDebugMetadataAttrs(&inst, op);
3697 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3698 if (emitExpensiveWarnings) {
3699 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3705 if (bb->hasAddressTaken()) {
3706 OpBuilder::InsertionGuard guard(builder);
3707 builder.setInsertionPointToStart(block);
3709 BlockTagAttr::get(context, bb->getNumber()));
3714FailureOr<SmallVector<AccessGroupAttr>>
3716 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3722 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3725FailureOr<DereferenceableAttr>
3728 Location loc = mlirModule.getLoc();
3732 if (node->getNumOperands() != 1)
3733 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3734 <<
diagMD(node, llvmModule.get());
3736 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3737 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3738 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3739 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3740 "non-negative constant integer: "
3741 <<
diagMD(node, llvmModule.get());
3743 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3744 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3745 numBytesCst->getZExtValue(), mayBeNull);
3751 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3752 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3753 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3754 bool importStructsAsLiterals) {
3761 LLVMDialect::getDialectNamespace()));
3763 DLTIDialect::getDialectNamespace()));
3764 if (loadAllDialects)
3767 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3771 emitExpensiveWarnings, dropDICompositeTypeElements,
3772 preferUnregisteredIntrinsics,
3773 importStructsAsLiterals);
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be inserted(the insertion happens right before the *insertion point). Since `begin` can itself be invalidated due to the memref *rewriting done from this method
static ArrayAttr convertLLVMAttributesToMLIR(Location loc, MLIRContext *context, llvm::AttributeSet attributes, ArrayRef< StringLiteral > attributesToSkip={}, ArrayRef< StringLiteral > attributePrefixesToSkip={})
Converts LLVM string, integer, and enum attributes into MLIR attributes, skipping those in attributes...
static StringRef getLLVMSyncScope(llvm::Instruction *inst)
Converts the sync scope identifier of inst to the string representation necessary to build an atomic ...
static std::string diag(const llvm::Value &value)
static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp)
Converts LLVM attributes from func into MLIR attributes and adds them to funcOp as passthrough attrib...
static SmallVector< Attribute > getSequenceConstantAsAttrs(OpBuilder &builder, llvm::ConstantDataSequential *constSequence)
Returns an integer or float attribute array for the provided constant sequence constSequence or nullp...
static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op)
static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp)
static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule, llvm::MDTuple *mdTuple)
static constexpr std::array kExplicitLLVMFuncOpAttributePrefixes
static constexpr StringRef getGlobalDtorsVarName()
Returns the name of the global_dtors global variables.
static Type getVectorTypeForAttr(Type type, ArrayRef< int64_t > arrayShape={})
Returns type if it is a builtin integer or floating-point vector type that can be used to create an a...
static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder, llvm::Instruction *inst, ModuleImport &moduleImport, LLVMImportInterface &iface)
Converts the LLVM instructions that have a generated MLIR builder.
static constexpr StringRef getNamelessGlobalPrefix()
Prefix used for symbols of nameless llvm globals.
static Attribute convertModuleFlagValueFromMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, StringRef key, llvm::MDTuple *mdTuple)
Invoke specific handlers for each known module flag value, returns nullptr if the key is unknown or u...
static constexpr std::array kExplicitLLVMFuncOpAttributes
static constexpr StringRef getGlobalComdatOpName()
Returns the symbol name for the module-level comdat operation.
static void convertNoBuiltinAttrs(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static SmallVector< int64_t > getPositionFromIndices(ArrayRef< unsigned > indices)
Converts an array of unsigned indices to a signed integer position array.
static LogicalResult setDebugIntrinsicBuilderInsertionPoint(mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand)
Ensure that the debug intrinsic is inserted right after the operand definition.
static LogicalResult checkFunctionTypeCompatibility(LLVMFunctionType callType, LLVMFunctionType calleeType)
Checks if callType and calleeType are compatible and can be represented in MLIR.
static void processDenormalFPEnv(llvm::Function *func, LLVMFuncOp funcOp)
static std::optional< ProfileSummaryFormatKind > convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &formatMD)
static constexpr StringRef getGlobalCtorsVarName()
Returns the name of the global_ctors global variables.
static FailureOr< uint64_t > convertInt64FromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey)
Extract an integer value from a two element tuple (<key, value>).
static void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar, GlobalOp globalOp)
Converts LLVM attributes from globalVar into MLIR attributes and adds them to globalOp as target-spec...
static Attribute convertProfileSummaryModuleFlagValue(ModuleOp mlirModule, const llvm::Module *llvmModule, llvm::MDTuple *mdTuple)
static llvm::MDTuple * getTwoElementMDTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md)
Extract a two element MDTuple from a MDOperand.
static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr)
Checks if dbgIntr is a kill location that holds metadata instead of an SSA value.
static TypedAttr getScalarConstantAsAttr(OpBuilder &builder, llvm::Constant *constScalar)
Returns an integer or float attribute for the provided scalar constant constScalar or nullptr if the ...
static void convertAllocsizeAttr(MLIRContext *ctx, const llvm::AttributeSet &attrs, OpTy target)
static std::string diagMD(const llvm::Metadata *node, const llvm::Module *module)
static llvm::ConstantAsMetadata * getConstantMDFromKeyValueTuple(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &md, StringRef matchKey, bool optional=false)
Extract a constant metadata value from a two element tuple (<key, value>).
static FailureOr< SmallVector< ModuleFlagProfileSummaryDetailedAttr > > convertProfileSummaryDetailed(ModuleOp mlirModule, const llvm::Module *llvmModule, const llvm::MDOperand &summaryMD)
static SetVector< llvm::BasicBlock * > getTopologicallySortedBlocks(ArrayRef< llvm::BasicBlock * > basicBlocks)
Get a topologically sorted list of blocks for the given basic blocks.
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block represents an ordered list of Operations.
Operation * getTerminator()
Get the terminator operation of this block.
Operation * getParentOp()
Returns the closest surrounding operation that contains this block.
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.