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::MDString *valMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(1));
758 std::optional<ProfileSummaryFormatKind> fmtKind =
759 symbolizeProfileSummaryFormatKind(valMD->getString());
762 <<
"expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
764 <<
diagMD(valMD, llvmModule);
771static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
773 const llvm::Module *llvmModule,
774 const llvm::MDOperand &summaryMD) {
779 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
780 if (!keyMD || keyMD->getString() !=
"DetailedSummary") {
782 <<
"expected 'DetailedSummary' key: "
783 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
787 llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
790 <<
"expected tuple value for 'DetailedSummary' key: "
791 <<
diagMD(tupleEntry->getOperand(1), llvmModule);
796 for (
auto &&entry : entriesMD->operands()) {
797 llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
798 if (!entryMD || entryMD->getNumOperands() != 3) {
800 <<
"'DetailedSummary' entry expects 3 operands: "
801 <<
diagMD(entry, llvmModule);
805 auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
806 auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
807 auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
808 if (!op0 || !op1 || !op2) {
810 <<
"expected only integer entries in 'DetailedSummary': "
811 <<
diagMD(entry, llvmModule);
815 auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get(
816 mlirModule->getContext(),
817 cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
818 cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
819 cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
820 detailedSummary.push_back(detaildSummaryEntry);
822 return detailedSummary;
827 const llvm::Module *llvmModule,
828 llvm::MDTuple *mdTuple) {
829 unsigned profileNumEntries = mdTuple->getNumOperands();
830 if (profileNumEntries < 8) {
832 <<
"expected at 8 entries in 'ProfileSummary': "
833 <<
diagMD(mdTuple, llvmModule);
837 unsigned summayIdx = 0;
838 auto checkOptionalPosition = [&](
const llvm::MDOperand &md,
839 StringRef matchKey) -> LogicalResult {
843 if (summayIdx + 1 >= profileNumEntries) {
845 <<
"the last summary entry is '" << matchKey
846 <<
"', expected 'DetailedSummary': " <<
diagMD(md, llvmModule);
853 auto getOptIntValue =
854 [&](
const llvm::MDOperand &md,
855 StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
858 return FailureOr<std::optional<uint64_t>>(std::nullopt);
859 if (checkOptionalPosition(md, matchKey).failed())
861 FailureOr<uint64_t> val =
868 auto getOptDoubleValue = [&](
const llvm::MDOperand &md,
869 StringRef matchKey) -> FailureOr<FloatAttr> {
874 if (
auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
875 if (checkOptionalPosition(md, matchKey).failed())
877 return FloatAttr::get(Float64Type::get(mlirModule.getContext()),
878 cstFP->getValueAPF());
881 <<
"expected double metadata value for key '" << matchKey
882 <<
"': " <<
diagMD(md, llvmModule);
889 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
890 if (!format.has_value())
894 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"TotalCount");
895 if (failed(totalCount))
899 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"MaxCount");
900 if (failed(maxCount))
904 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
906 if (failed(maxInternalCount))
910 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
912 if (failed(maxFunctionCount))
916 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumCounts");
917 if (failed(numCounts))
921 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumFunctions");
922 if (failed(numFunctions))
926 FailureOr<std::optional<uint64_t>> isPartialProfile =
927 getOptIntValue(mdTuple->getOperand(summayIdx),
"IsPartialProfile");
928 if (failed(isPartialProfile))
930 if (isPartialProfile->has_value())
933 FailureOr<FloatAttr> partialProfileRatio =
934 getOptDoubleValue(mdTuple->getOperand(summayIdx),
"PartialProfileRatio");
935 if (failed(partialProfileRatio))
937 if (*partialProfileRatio)
941 FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
943 mdTuple->getOperand(summayIdx));
944 if (failed(detailed))
948 return ModuleFlagProfileSummaryAttr::get(
949 mlirModule->getContext(), *format, *totalCount, *maxCount,
950 *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,
951 *isPartialProfile, *partialProfileRatio, *detailed);
958 const llvm::Module *llvmModule, StringRef key,
959 llvm::MDTuple *mdTuple) {
960 if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
962 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
967 Builder builder(mlirModule->getContext());
969 strings.reserve(mdTuple->getNumOperands());
970 for (
const llvm::MDOperand &operand : mdTuple->operands()) {
971 auto *mdString = dyn_cast_if_present<llvm::MDString>(operand.get());
974 strings.push_back(builder.
getStringAttr(mdString->getString()));
981 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
984 for (
const auto [behavior, key, val] : llvmModuleFlags) {
986 if (
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
987 valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
988 }
else if (
auto *mdString = dyn_cast<llvm::MDString>(val)) {
989 valAttr = builder.getStringAttr(mdString->getString());
990 }
else if (
auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
992 key->getString(), mdTuple);
997 <<
"unsupported module flag value for key '" << key->getString()
998 <<
"' : " <<
diagMD(val, llvmModule.get());
1002 moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
1003 convertModFlagBehaviorFromLLVM(behavior),
1004 builder.getStringAttr(key->getString()), valAttr));
1007 if (!moduleFlags.empty())
1008 LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),
1009 builder.getArrayAttr(moduleFlags));
1015 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1016 if (named.getName() !=
"llvm.linker.options")
1019 for (
const llvm::MDNode *node : named.operands()) {
1021 options.reserve(node->getNumOperands());
1022 for (
const llvm::MDOperand &option : node->operands())
1023 options.push_back(cast<llvm::MDString>(option)->getString());
1024 LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),
1025 builder.getStrArrayAttr(
options));
1032 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1033 if (named.getName() !=
"llvm.dependent-libraries")
1036 for (
const llvm::MDNode *node : named.operands()) {
1037 if (node->getNumOperands() == 1)
1038 if (
auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
1039 libraries.push_back(mdString->getString());
1041 if (!libraries.empty())
1042 mlirModule->setAttr(LLVM::LLVMDialect::getDependentLibrariesAttrName(),
1043 builder.getStrArrayAttr(libraries));
1049 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1052 if (named.getName() != LLVMDialect::getIdentAttrName())
1055 if (named.getNumOperands() == 1)
1056 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
1057 if (md->getNumOperands() == 1)
1058 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
1059 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
1060 builder.getStringAttr(mdStr->getString()));
1066 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
1069 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
1072 if (nmd.getNumOperands() == 1)
1073 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
1074 if (md->getNumOperands() == 1)
1075 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
1076 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
1077 builder.getStringAttr(mdStr->getString()));
1084 builder.setInsertionPointToEnd(mlirModule.getBody());
1085 for (
const llvm::Function &
func : llvmModule->functions()) {
1086 for (
const llvm::Instruction &inst : llvm::instructions(
func)) {
1088 if (llvm::MDNode *node =
1089 inst.getMetadata(llvm::LLVMContext::MD_access_group))
1090 if (failed(processAccessGroupMetadata(node)))
1094 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
1095 if (!aliasAnalysisNodes)
1097 if (aliasAnalysisNodes.TBAA)
1098 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
1100 if (aliasAnalysisNodes.Scope)
1101 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
1103 if (aliasAnalysisNodes.NoAlias)
1104 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
1121void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
1122 if (comdatMapping.contains(comdat))
1125 ComdatOp comdatOp = getGlobalComdatOp();
1128 auto selectorOp = ComdatSelectorOp::create(
1129 builder, mlirModule.getLoc(), comdat->getName(),
1130 convertComdatFromLLVM(comdat->getSelectionKind()),
1135 comdatMapping.try_emplace(comdat, symbolRef);
1139 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1140 if (globalVar.hasComdat())
1141 processComdat(globalVar.getComdat());
1142 for (llvm::Function &
func : llvmModule->functions())
1143 if (
func.hasComdat())
1144 processComdat(
func.getComdat());
1149 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1152 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1153 return emitError(UnknownLoc::get(context))
1154 <<
"unhandled global variable: " <<
diag(globalVar);
1158 if (failed(convertGlobal(&globalVar))) {
1159 return emitError(UnknownLoc::get(context))
1160 <<
"unhandled global variable: " <<
diag(globalVar);
1167 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1168 if (failed(convertAlias(&alias))) {
1169 return emitError(UnknownLoc::get(context))
1170 <<
"unhandled global alias: " <<
diag(alias);
1177 for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1178 if (failed(convertIFunc(&ifunc))) {
1179 return emitError(UnknownLoc::get(context))
1180 <<
"unhandled global ifunc: " <<
diag(ifunc);
1187 Location loc = mlirModule.getLoc();
1189 context, llvmModule->getDataLayout().getStringRepresentation());
1191 return emitError(loc,
"cannot translate data layout: ")
1195 emitWarning(loc,
"unhandled data layout token: ") << token;
1197 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
1203 mlirModule->setAttr(
1204 LLVM::LLVMDialect::getTargetTripleAttrName(),
1205 builder.getStringAttr(llvmModule->getTargetTriple().str()));
1211 for (
const llvm::Module::GlobalAsmFragment &Frag :
1212 llvmModule->getModuleInlineAsm()) {
1214 for (llvm::StringRef line : llvm::split(Frag.Asm,
'\n'))
1216 asmArrayAttr.push_back(builder.getStringAttr(line));
1219 mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1220 builder.getArrayAttr(asmArrayAttr));
1224 for (llvm::Function &
func : llvmModule->functions())
1230void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1233 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1234 for (
auto &[kind, node] : allMetadata) {
1238 if (emitExpensiveWarnings) {
1239 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1241 <<
diagMD(node, llvmModule.get()) <<
" on "
1250 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1252 IntegerOverflowFlags value = {};
1253 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1255 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1257 iface.setOverflowFlags(value);
1261 auto iface = cast<ExactFlagInterface>(op);
1263 iface.setIsExact(inst->isExact());
1268 auto iface = cast<DisjointFlagInterface>(op);
1269 auto *instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1271 iface.setIsDisjoint(instDisjoint->isDisjoint());
1275 auto iface = cast<NonNegFlagInterface>(op);
1277 iface.setNonNeg(inst->hasNonNeg());
1282 auto iface = cast<FastmathFlagsInterface>(op);
1288 if (!isa<llvm::FPMathOperator>(inst))
1290 llvm::FastMathFlags flags = inst->getFastMathFlags();
1293 FastmathFlags value = {};
1294 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1295 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1296 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1297 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1298 value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
1299 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1300 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1301 FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
1302 iface->setAttr(iface.getFastmathAttrName(), attr);
1314 if (numElements.isScalable()) {
1316 <<
"scalable vectors not supported";
1321 Type elementType = cast<VectorType>(type).getElementType();
1325 SmallVector<int64_t> shape(arrayShape);
1326 shape.push_back(numElements.getKnownMinValue());
1327 return VectorType::get(shape, elementType);
1330Type ModuleImport::getBuiltinTypeForAttr(Type type) {
1344 SmallVector<int64_t> arrayShape;
1345 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1346 arrayShape.push_back(arrayType.getNumElements());
1347 type = arrayType.getElementType();
1350 return RankedTensorType::get(arrayShape, type);
1357 llvm::Constant *constScalar) {
1360 if (constScalar->getType()->isVectorTy())
1364 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1366 IntegerType::get(context, constInt->getBitWidth()),
1367 constInt->getValue());
1371 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1372 llvm::Type *type = constFloat->getType();
1373 FloatType floatType =
1375 ? BFloat16Type::get(context)
1379 <<
"unexpected floating-point type";
1382 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1389static SmallVector<Attribute>
1391 llvm::ConstantDataSequential *constSequence) {
1393 elementAttrs.reserve(constSequence->getNumElements());
1394 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1395 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1398 return elementAttrs;
1401Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1407 auto getConstantShape = [&](llvm::Type *type) {
1408 return llvm::dyn_cast_if_present<ShapedType>(
1413 if (isa<llvm::ConstantInt, llvm::ConstantFP>(constant)) {
1414 assert(constant->getType()->isVectorTy() &&
"expected a vector splat");
1415 auto shape = getConstantShape(constant->getType());
1418 Attribute splatAttr =
1425 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1426 if (constArray->isString())
1427 return builder.getStringAttr(constArray->getAsString());
1428 auto shape = getConstantShape(constArray->getType());
1432 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1433 if (constVector && constVector->isSplat()) {
1436 builder, constVector->getElementAsConstant(0));
1440 SmallVector<Attribute> elementAttrs =
1447 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1448 auto shape = getConstantShape(constAggregate->getType());
1452 SmallVector<Attribute> elementAttrs;
1453 SmallVector<llvm::Constant *> workList = {constAggregate};
1454 while (!workList.empty()) {
1455 llvm::Constant *current = workList.pop_back_val();
1458 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1460 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1461 workList.push_back(constAggregate->getAggregateElement(idx));
1466 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1467 SmallVector<Attribute> attrs =
1469 elementAttrs.append(attrs.begin(), attrs.end());
1475 elementAttrs.push_back(scalarAttr);
1486 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1487 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1488 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1492 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1493 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1500ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1501 assert(globalVar->getName().empty() &&
1502 "expected to work with a nameless global");
1503 auto [it,
success] = namelessGlobals.try_emplace(globalVar);
1510 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1513 it->getSecond() = symbolRef;
1517OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1518 OpBuilder::InsertionGuard guard(builder);
1519 if (globalInsertionOp)
1520 builder.setInsertionPointAfter(globalInsertionOp);
1522 builder.setInsertionPointToStart(mlirModule.getBody());
1526LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1528 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1531 AliasOp aliasOp = AliasOp::create(
1532 builder, mlirModule.getLoc(), type,
1533 convertLinkageFromLLVM(alias->getLinkage()), alias->getName(),
1534 alias->isDSOLocal(),
1535 convertThreadLocalModeFromLLVM(alias->getThreadLocalMode()),
1536 ArrayRef<NamedAttribute>());
1537 globalInsertionOp = aliasOp;
1540 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1541 setConstantInsertionPointToStart(block);
1542 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1545 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1547 if (alias->hasAtLeastLocalUnnamedAddr())
1548 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1549 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1554LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1555 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1558 llvm::Constant *resolver = ifunc->getResolver();
1559 Type resolverType =
convertType(resolver->getType());
1560 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1561 resolver->getName(), resolverType,
1562 convertLinkageFromLLVM(ifunc->getLinkage()),
1563 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1564 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1565 convertVisibilityFromLLVM(ifunc->getVisibility()),
1576 ArrayRef<StringLiteral> attributePrefixesToSkip = {}) {
1577 SmallVector<Attribute> mlirAttributes;
1578 for (llvm::Attribute attr : attributes) {
1580 if (attr.isStringAttribute())
1581 attrName = attr.getKindAsString();
1583 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1584 if (llvm::is_contained(attributesToSkip, attrName))
1587 auto attrNameStartsWith = [attrName](StringLiteral sl) {
1588 return attrName.starts_with(sl);
1590 if (attributePrefixesToSkip.end() !=
1591 llvm::find_if(attributePrefixesToSkip, attrNameStartsWith))
1594 auto keyAttr = StringAttr::get(context, attrName);
1595 if (attr.isStringAttribute()) {
1596 StringRef val = attr.getValueAsString();
1599 mlirAttributes.push_back(keyAttr);
1603 mlirAttributes.push_back(
1604 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1607 if (attr.isIntAttribute()) {
1610 auto val = std::to_string(attr.getValueAsInt());
1611 mlirAttributes.push_back(
1612 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1615 if (attr.isEnumAttribute()) {
1617 mlirAttributes.push_back(keyAttr);
1623 <<
"' attribute is invalid on current operation, skipping it";
1625 return ArrayAttr::get(context, mlirAttributes);
1631 GlobalOp globalOp) {
1633 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1634 if (!targetSpecificAttrs.empty())
1635 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1638LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1640 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1642 Attribute valueAttr;
1643 if (globalVar->hasInitializer())
1644 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1645 Type type =
convertType(globalVar->getValueType());
1647 uint64_t alignment = 0;
1648 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1649 if (maybeAlign.has_value()) {
1650 llvm::Align align = *maybeAlign;
1651 alignment = align.value();
1656 SmallVector<Attribute> globalExpressionAttrs;
1657 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1658 globalVar->getDebugInfo(globalExpressions);
1660 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1661 DIGlobalVariableExpressionAttr globalExpressionAttr =
1662 debugImporter->translateGlobalVariableExpression(expr);
1663 globalExpressionAttrs.push_back(globalExpressionAttr);
1668 StringRef globalName = globalVar->getName();
1669 if (globalName.empty())
1670 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1672 GlobalOp globalOp = GlobalOp::create(
1673 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1674 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1675 valueAttr, alignment, globalVar->getAddressSpace(),
1676 globalVar->isDSOLocal(),
1677 convertThreadLocalModeFromLLVM(globalVar->getThreadLocalMode()),
1679 ArrayRef<NamedAttribute>(), globalExpressionAttrs);
1680 globalInsertionOp = globalOp;
1682 if (globalVar->hasInitializer() && !valueAttr) {
1684 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1685 setConstantInsertionPointToStart(block);
1686 FailureOr<Value> initializer =
1687 convertConstantExpr(globalVar->getInitializer());
1690 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1692 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1693 globalOp.setUnnamedAddr(
1694 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1696 if (globalVar->hasSection())
1697 globalOp.setSection(globalVar->getSection());
1698 globalOp.setVisibility_(
1699 convertVisibilityFromLLVM(globalVar->getVisibility()));
1701 if (globalVar->hasComdat())
1702 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1704 if (llvm::MDNode *associatedMD =
1705 globalVar->getMetadata(llvm::LLVMContext::MD_associated)) {
1706 FlatSymbolRefAttr symbolRef;
1707 if (associatedMD->getNumOperands() == 1)
1709 getMetadataOperandSymbolRef(associatedMD->getOperand(0).get());
1711 emitWarning(globalOp.getLoc()) <<
"unhandled associated metadata: "
1712 <<
diagMD(associatedMD, llvmModule.get())
1713 <<
" on " <<
diag(*globalVar);
1715 globalOp.setAssociatedAttr(symbolRef);
1719 if (llvm::MDNode *absSymMD =
1720 globalVar->getMetadata(llvm::LLVMContext::MD_absolute_symbol)) {
1721 unsigned numOps = absSymMD->getNumOperands();
1722 if (numOps >= 2 && numOps % 2 == 0) {
1723 SmallVector<Attribute> rangeAttrs;
1724 rangeAttrs.reserve(numOps);
1726 for (
const llvm::MDOperand &op : absSymMD->operands()) {
1727 auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(op);
1731 auto intType = IntegerType::get(context, constInt->getBitWidth());
1732 rangeAttrs.push_back(IntegerAttr::get(intType, constInt->getValue()));
1735 if (rangeAttrs.size() == numOps)
1736 globalOp.setAbsoluteSymbolAttr(ArrayAttr::get(context, rangeAttrs));
1746ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1747 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1749 llvm::Constant *initializer = globalVar->getInitializer();
1751 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1752 isa<llvm::ConstantAggregateZero>(initializer);
1759 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1760 if (caz->getElementCount().getFixedValue() != 0)
1764 SmallVector<Attribute> funcs;
1765 SmallVector<int32_t> priorities;
1766 SmallVector<Attribute> dataList;
1767 for (llvm::Value *operand : initializer->operands()) {
1768 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1769 if (!aggregate || aggregate->getNumOperands() != 3)
1772 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1773 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1774 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1775 if (!priority || !func || !data)
1778 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1782 else if (data->isNullValue())
1783 dataAttr = ZeroAttr::get(context);
1788 priorities.push_back(priority->getValue().getZExtValue());
1789 dataList.push_back(dataAttr);
1793 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1796 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1797 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1798 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1801 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1802 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1803 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1808ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1810 if (valueMapping.contains(constant))
1819 workList.insert(constant);
1820 while (!workList.empty()) {
1821 llvm::Constant *current = workList.back();
1824 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1825 orderedSet.insert(current);
1826 workList.pop_back();
1832 auto [adjacencyIt,
inserted] = adjacencyLists.try_emplace(current);
1836 for (llvm::Value *operand : current->operands())
1837 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1838 adjacencyIt->getSecond().push_back(constDependency);
1841 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1842 unsigned numElements = constAgg->getElementCount().getFixedValue();
1843 for (
unsigned i = 0, e = numElements; i != e; ++i)
1844 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1850 if (adjacencyIt->getSecond().empty()) {
1851 orderedSet.insert(current);
1852 workList.pop_back();
1860 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1861 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1862 orderedSet.contains(dependency))
1864 workList.insert(dependency);
1870FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1871 Location loc = UnknownLoc::get(context);
1874 if (Attribute attr = getConstantAsAttr(constant)) {
1876 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1877 return AddressOfOp::create(builder, loc, type, symbolRef.
getValue())
1880 return ConstantOp::create(builder, loc, type, attr).getResult();
1884 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1886 return ZeroOp::create(builder, loc, type).getResult();
1890 if (isa<llvm::ConstantTokenNone>(constant)) {
1891 return NoneTokenOp::create(builder, loc).getResult();
1895 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1897 return PoisonOp::create(builder, loc, type).getResult();
1901 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1903 return UndefOp::create(builder, loc, type).getResult();
1907 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1908 Type type =
convertType(dsoLocalEquivalent->getType());
1909 return DSOLocalEquivalentOp::create(
1912 builder.getContext(),
1913 dsoLocalEquivalent->getGlobalValue()->getName()))
1918 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1920 StringRef globalName = globalObj->getName();
1921 FlatSymbolRefAttr symbolRef;
1923 if (globalName.empty())
1925 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1928 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1932 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1933 Type type =
convertType(globalAliasObj->getType());
1934 StringRef aliaseeName = globalAliasObj->getName();
1936 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1940 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1946 llvm::Instruction *inst = constExpr->getAsInstruction();
1947 llvm::scope_exit guard([&]() {
1948 assert(!noResultOpMapping.contains(inst) &&
1949 "expected constant expression to return a result");
1950 valueMapping.erase(inst);
1951 inst->deleteValue();
1955 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1956 return valueMapping.contains(value);
1958 if (
failed(processInstruction(inst)))
1964 if (
auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1965 Type type =
convertType(aggregateZero->getType());
1966 return ZeroOp::create(builder, loc, type).getResult();
1970 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1972 SmallVector<Value> elementValues;
1974 elementValues.reserve(constAgg->getNumOperands());
1975 for (llvm::Value *operand : constAgg->operands())
1978 assert(llvm::count(elementValues,
nullptr) == 0 &&
1979 "expected all elements have been converted before");
1983 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1985 "unrecognized aggregate type");
1986 Value root = UndefOp::create(builder, loc, rootType);
1987 for (
const auto &it : llvm::enumerate(elementValues)) {
1988 if (isArrayOrStruct) {
1990 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1992 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1994 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1995 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
2002 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
2003 LLVMTargetExtType targetExtType =
2004 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
2005 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
2006 "target extension type does not support zero-initialization");
2009 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
2012 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
2016 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
2017 return BlockAddressOp::create(
2019 BlockAddressAttr::get(context, fnSym, blockTag))
2023 StringRef error =
"";
2025 if (isa<llvm::ConstantPtrAuth>(constant))
2026 error =
" since ptrauth(...) is unsupported";
2028 if (isa<llvm::NoCFIValue>(constant))
2029 error =
" since no_cfi is unsupported";
2031 if (isa<llvm::GlobalValue>(constant))
2032 error =
" since global value is unsupported";
2034 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
2037FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
2041 assert(!valueMapping.contains(constant) &&
2042 "expected constant has not been converted before");
2043 assert(constantInsertionBlock &&
2044 "expected the constant insertion block to be non-null");
2047 OpBuilder::InsertionGuard guard(builder);
2048 if (!constantInsertionOp)
2049 builder.setInsertionPointToStart(constantInsertionBlock);
2051 builder.setInsertionPointAfter(constantInsertionOp);
2055 getConstantsToConvert(constant);
2056 for (llvm::Constant *constantToConvert : constantsToConvert) {
2057 FailureOr<Value> converted = convertConstant(constantToConvert);
2060 mapValue(constantToConvert, *converted);
2065 constantInsertionOp =
result.getDefiningOp();
2071 auto it = valueMapping.find(value);
2072 if (it != valueMapping.end())
2073 return it->getSecond();
2080 if (
auto *mdAsVal = dyn_cast<llvm::MetadataAsValue>(value)) {
2081 llvm::Metadata *md = mdAsVal->getMetadata();
2082 Attribute mdAttr = convertMetadataToAttr(md);
2085 <<
"unsupported metadata: " <<
diagMD(md, llvmModule.get());
2087 MetadataAsValueOp::create(builder, UnknownLoc::get(context), mdAttr)
2094 if (
auto *constant = dyn_cast<llvm::Constant>(value))
2095 return convertConstantExpr(constant);
2097 Location loc = UnknownLoc::get(context);
2098 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
2100 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
2106 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2109 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2112 value = node->getValue();
2115 auto it = valueMapping.find(value);
2116 if (it != valueMapping.end())
2117 return it->getSecond();
2120 if (
auto *constant = dyn_cast<llvm::Constant>(value))
2121 return convertConstantExpr(constant);
2125FailureOr<SmallVector<Value>>
2128 remapped.reserve(values.size());
2129 for (llvm::Value *value : values) {
2131 if (failed(converted))
2133 remapped.push_back(*converted);
2143 assert(immArgPositions.size() == immArgAttrNames.size() &&
2144 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
2148 for (
auto [immArgPos, immArgName] :
2149 llvm::zip(immArgPositions, immArgAttrNames)) {
2150 auto &value = operands[immArgPos];
2151 auto *constant = llvm::cast<llvm::Constant>(value);
2153 assert(attr && attr.getType().isIntOrFloat() &&
2154 "expected immarg to be float or integer constant");
2155 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
2156 attrsOut.push_back({nameAttr, attr});
2161 for (llvm::Value *value : operands) {
2165 if (failed(mlirValue))
2167 valuesOut.push_back(*mlirValue);
2172 if (requiresOpBundles) {
2173 opBundleSizes.reserve(opBundles.size());
2174 opBundleTagAttrs.reserve(opBundles.size());
2176 for (
const llvm::OperandBundleUse &bundle : opBundles) {
2177 opBundleSizes.push_back(bundle.Inputs.size());
2178 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
2180 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
2181 auto operandMlirValue =
convertValue(opBundleOperand.get());
2182 if (failed(operandMlirValue))
2184 valuesOut.push_back(*operandMlirValue);
2189 auto opBundleSizesAttrNameAttr =
2190 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
2191 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
2193 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
2194 auto opBundleTagsAttrNameAttr =
2195 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
2196 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
2203 IntegerAttr integerAttr;
2205 bool success = succeeded(converted) &&
2207 assert(
success &&
"expected a constant integer value");
2213 FloatAttr floatAttr;
2217 assert(
success &&
"expected a constant float value");
2224 llvm::DILocalVariable *node =
nullptr;
2225 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2226 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2227 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2229 node = cast<llvm::DILocalVariable *>(valOrVariable);
2231 return debugImporter->translate(node);
2235 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2236 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2237 return debugImporter->translate(node);
2240FPExceptionBehaviorAttr
2242 auto *metadata = cast<llvm::MetadataAsValue>(value);
2243 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2244 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2245 llvm::convertStrToExceptionBehavior(mdstr->getString());
2246 assert(optLLVM &&
"Expecting FP exception behavior");
2247 return builder.getAttr<FPExceptionBehaviorAttr>(
2248 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2252 auto *metadata = cast<llvm::MetadataAsValue>(value);
2253 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2254 std::optional<llvm::RoundingMode> optLLVM =
2255 llvm::convertStrToRoundingMode(mdstr->getString());
2256 assert(optLLVM &&
"Expecting rounding mode");
2257 return builder.getAttr<RoundingModeAttr>(
2258 convertRoundingModeFromLLVM(*optLLVM));
2261FailureOr<SmallVector<AliasScopeAttr>>
2263 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2264 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2269 return debugImporter->translateLoc(loc);
2273ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2274 llvm::BasicBlock *
target,
2276 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2277 auto *phiInst = cast<llvm::PHINode>(&*inst);
2278 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2280 if (failed(converted))
2282 blockArguments.push_back(*converted);
2287FailureOr<SmallVector<Value>>
2288ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2289 bool allowInlineAsm) {
2290 bool isInlineAsm = callInst->isInlineAsm();
2291 if (isInlineAsm && !allowInlineAsm)
2301 llvm::Value *calleeOperand = callInst->getCalledOperand();
2302 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2306 operands.push_back(*called);
2309 SmallVector<llvm::Value *> args(callInst->args());
2310 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2314 llvm::append_range(operands, *arguments);
2322 LLVMFunctionType calleeType) {
2323 if (callType.getReturnType() != calleeType.getReturnType())
2326 if (calleeType.isVarArg()) {
2329 if (callType.getNumParams() < calleeType.getNumParams())
2334 if (callType.getNumParams() != calleeType.getNumParams())
2339 for (
auto [operandType, argumentType] :
2340 llvm::zip(callType.getParams(), calleeType.getParams()))
2341 if (operandType != argumentType)
2347FailureOr<LLVMFunctionType>
2348ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2349 bool &isIncompatibleCall) {
2350 isIncompatibleCall =
false;
2351 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2352 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2358 llvm::Value *calledOperand = callInst->getCalledOperand();
2359 FailureOr<LLVMFunctionType> callType =
2360 castOrFailure(
convertType(callInst->getFunctionType()));
2363 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2365 llvm::FunctionType *origCalleeType =
nullptr;
2367 origCalleeType = callee->getFunctionType();
2368 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2369 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2373 if (!origCalleeType)
2376 FailureOr<LLVMFunctionType> calleeType =
2384 isIncompatibleCall =
true;
2386 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2387 <<
" and " << *calleeType;
2394FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2395 llvm::Value *calledOperand = callInst->getCalledOperand();
2396 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2397 return SymbolRefAttr::get(context, calledOperand->getName());
2401LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2402 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2406 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2410ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2411 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2412 unsigned argIdx = 0;
2413 SmallVector<mlir::Attribute> opAttrs;
2414 bool hasIndirect =
false;
2416 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2418 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2423 if (ci.isIndirect) {
2424 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2425 SmallVector<mlir::NamedAttribute> attrs;
2426 attrs.push_back(builder.getNamedAttr(
2427 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2429 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2433 opAttrs.push_back(builder.getDictionaryAttr({}));
2439 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2443LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2446 if (
auto *brInst = dyn_cast<llvm::UncondBrInst>(inst)) {
2447 llvm::BasicBlock *succ = brInst->getSuccessor();
2448 SmallVector<Value> blockArgs;
2449 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2452 auto brOp = LLVM::BrOp::create(builder, loc, blockArgs,
lookupBlock(succ));
2456 if (
auto *brInst = dyn_cast<llvm::CondBrInst>(inst)) {
2457 SmallVector<Block *> succBlocks;
2458 SmallVector<SmallVector<Value>> succBlockArgs;
2459 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2460 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2461 SmallVector<Value> blockArgs;
2462 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2465 succBlockArgs.push_back(blockArgs);
2468 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2471 auto condBrOp = LLVM::CondBrOp::create(
2472 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2473 succBlocks.back(), succBlockArgs.back());
2477 if (inst->getOpcode() == llvm::Instruction::Switch) {
2478 auto *swInst = cast<llvm::SwitchInst>(inst);
2480 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2483 SmallVector<Value> defaultBlockArgs;
2485 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2486 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2490 unsigned numCases = swInst->getNumCases();
2491 SmallVector<SmallVector<Value>> caseOperands(numCases);
2492 SmallVector<ValueRange> caseOperandRefs(numCases);
2493 SmallVector<APInt> caseValues(numCases);
2494 SmallVector<Block *> caseBlocks(numCases);
2495 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2496 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2497 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2498 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2500 caseOperandRefs[it.index()] = caseOperands[it.index()];
2501 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2505 auto switchOp = SwitchOp::create(builder, loc, *condition,
2507 caseValues, caseBlocks, caseOperandRefs);
2511 if (inst->getOpcode() == llvm::Instruction::PHI) {
2513 mapValue(inst, builder.getInsertionBlock()->addArgument(
2517 if (inst->getOpcode() == llvm::Instruction::Call) {
2518 auto *callInst = cast<llvm::CallInst>(inst);
2519 llvm::Value *calledOperand = callInst->getCalledOperand();
2521 FailureOr<SmallVector<Value>> operands =
2522 convertCallOperands(callInst,
true);
2526 auto callOp = [&]() -> FailureOr<Operation *> {
2527 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2531 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2532 return InlineAsmOp::create(
2533 builder, loc, resultTy, *operands,
2534 builder.getStringAttr(asmI->getAsmString()),
2535 builder.getStringAttr(asmI->getConstraintString()),
2536 asmI->hasSideEffects(), asmI->isAlignStack(),
2537 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2538 AsmDialectAttr::get(
2539 mlirModule.getContext(),
2540 convertAsmDialectFromLLVM(asmI->getDialect())),
2544 bool isIncompatibleCall;
2545 FailureOr<LLVMFunctionType> funcTy =
2546 convertFunctionType(callInst, isIncompatibleCall);
2550 FlatSymbolRefAttr callee =
nullptr;
2551 if (isIncompatibleCall) {
2555 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2556 Value indirectCallVal = LLVM::AddressOfOp::create(
2557 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2558 operands->insert(operands->begin(), indirectCallVal);
2561 callee = convertCalleeName(callInst);
2563 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2565 if (
failed(convertCallAttributes(callInst, callOp)))
2570 if (!isIncompatibleCall)
2572 return callOp.getOperation();
2578 if (!callInst->getType()->isVoidTy())
2579 mapValue(inst, (*callOp)->getResult(0));
2584 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2585 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2587 SmallVector<Value> operands;
2588 operands.reserve(lpInst->getNumClauses());
2589 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2590 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2593 operands.push_back(*operand);
2598 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2602 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2603 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2605 if (invokeInst->isInlineAsm())
2606 return emitError(loc) <<
"invoke of inline assembly is not supported";
2608 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2614 bool invokeResultUsedInPhi = llvm::any_of(
2615 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2616 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2621 Block *directNormalDest = normalDest;
2622 if (invokeResultUsedInPhi) {
2627 OpBuilder::InsertionGuard g(builder);
2628 directNormalDest = builder.createBlock(normalDest);
2631 SmallVector<Value> unwindArgs;
2632 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2636 bool isIncompatibleInvoke;
2637 FailureOr<LLVMFunctionType> funcTy =
2638 convertFunctionType(invokeInst, isIncompatibleInvoke);
2642 FlatSymbolRefAttr calleeName =
nullptr;
2643 if (isIncompatibleInvoke) {
2647 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2648 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2649 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2650 operands->insert(operands->begin(), indirectInvokeVal);
2653 calleeName = convertCalleeName(invokeInst);
2658 auto invokeOp = InvokeOp::create(
2659 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2662 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2667 if (!isIncompatibleInvoke)
2670 if (!invokeInst->getType()->isVoidTy())
2671 mapValue(inst, invokeOp.getResults().front());
2675 SmallVector<Value> normalArgs;
2676 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2680 if (invokeResultUsedInPhi) {
2684 OpBuilder::InsertionGuard g(builder);
2685 builder.setInsertionPointToStart(directNormalDest);
2686 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2690 assert(llvm::none_of(
2692 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2693 "An llvm.invoke operation cannot pass its result as a block "
2695 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2700 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2701 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2702 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2703 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2712 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2720 auto gepOp = GEPOp::create(
2721 builder, loc, type, sourceElementType, *basePtr,
indices,
2722 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2727 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2728 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2730 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2734 SmallVector<Block *> succBlocks;
2735 SmallVector<SmallVector<Value>> succBlockArgs;
2736 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2737 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2738 SmallVector<Value> blockArgs;
2739 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2742 succBlockArgs.push_back(blockArgs);
2744 SmallVector<ValueRange> succBlockArgsRange =
2745 llvm::to_vector_of<ValueRange>(succBlockArgs);
2747 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2748 succBlockArgsRange, succBlocks);
2758 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2761LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2768 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2769 return convertIntrinsic(intrinsic);
2774 if (inst->DebugMarker) {
2775 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2777 if (
auto *dbgVariableRecord =
2778 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2783 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2784 if (!emitExpensiveWarnings)
2787 llvm::raw_string_ostream optionsStream(
options);
2788 dbgRecord.print(optionsStream);
2789 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2793 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2794 DILabelAttr labelAttr =
2795 debugImporter->translate(dbgLabelRecord->getLabel());
2797 return emitUnsupportedWarning();
2798 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2802 return emitUnsupportedWarning();
2807 return convertInstruction(inst);
2810FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2811 if (!f->hasPersonalityFn())
2814 llvm::Constant *pf = f->getPersonalityFn();
2818 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2822 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2823 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2824 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2825 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2826 return SymbolRefAttr::get(builder.getContext(), func->getName());
2829 return FlatSymbolRefAttr();
2833 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2835 auto othermem = convertModRefInfoFromLLVM(
2836 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2837 auto argMem = convertModRefInfoFromLLVM(
2838 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2839 auto inaccessibleMem = convertModRefInfoFromLLVM(
2840 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2841 auto errnoMem = convertModRefInfoFromLLVM(
2842 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2843 auto targetMem0 = convertModRefInfoFromLLVM(
2844 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2845 auto targetMem1 = convertModRefInfoFromLLVM(
2846 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2848 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2849 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2851 if (memAttr.isReadWrite())
2853 funcOp.setMemoryEffectsAttr(memAttr);
2857 llvm::DenormalFPEnv denormalFpEnv =
func->getDenormalFPEnv();
2859 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2862 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2863 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2865 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2866 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2867 convertDenormalModeKindFromLLVM(defaultMode.Input),
2868 convertDenormalModeKindFromLLVM(floatMode.Output),
2869 convertDenormalModeKindFromLLVM(floatMode.Input));
2870 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2876 StringLiteral(
"aarch64_in_za"),
2877 StringLiteral(
"aarch64_inout_za"),
2878 StringLiteral(
"aarch64_new_za"),
2879 StringLiteral(
"aarch64_out_za"),
2880 StringLiteral(
"aarch64_preserves_za"),
2881 StringLiteral(
"aarch64_pstate_sm_body"),
2882 StringLiteral(
"aarch64_pstate_sm_compatible"),
2883 StringLiteral(
"aarch64_pstate_sm_enabled"),
2884 StringLiteral(
"allocsize"),
2885 StringLiteral(
"alwaysinline"),
2886 StringLiteral(
"cold"),
2887 StringLiteral(
"convergent"),
2888 StringLiteral(
"fp-contract"),
2889 StringLiteral(
"frame-pointer"),
2890 StringLiteral(
"hot"),
2891 StringLiteral(
"inlinehint"),
2892 StringLiteral(
"instrument-function-entry"),
2893 StringLiteral(
"instrument-function-exit"),
2894 StringLiteral(
"modular-format"),
2895 StringLiteral(
"memory"),
2896 StringLiteral(
"minsize"),
2897 StringLiteral(
"no_caller_saved_registers"),
2898 StringLiteral(
"no-signed-zeros-fp-math"),
2899 StringLiteral(
"no-builtins"),
2900 StringLiteral(
"nocallback"),
2901 StringLiteral(
"noduplicate"),
2902 StringLiteral(
"noinline"),
2903 StringLiteral(
"noreturn"),
2904 StringLiteral(
"nounwind"),
2905 StringLiteral(
"optnone"),
2906 StringLiteral(
"optsize"),
2907 StringLiteral(
"returns_twice"),
2908 StringLiteral(
"save-reg-params"),
2909 StringLiteral(
"target-features"),
2910 StringLiteral(
"trap-func-name"),
2911 StringLiteral(
"tune-cpu"),
2912 StringLiteral(
"uwtable"),
2913 StringLiteral(
"vscale_range"),
2914 StringLiteral(
"willreturn"),
2915 StringLiteral(
"zero-call-used-regs"),
2916 StringLiteral(
"denormal_fpenv"),
2922 StringLiteral(
"no-builtin-"),
2925template <
typename OpTy>
2927 const llvm::AttributeSet &attrs,
2930 if (attrs.hasAttribute(
"no-builtins")) {
2931 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2936 for (llvm::Attribute attr : attrs) {
2939 if (attr.hasKindAsEnum())
2942 StringRef val = attr.getKindAsString();
2944 if (val.starts_with(
"no-builtin-"))
2946 StringAttr::get(ctx, val.drop_front(
sizeof(
"no-builtin-") - 1)));
2949 if (!nbAttrs.empty())
2950 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2953template <
typename OpTy>
2955 const llvm::AttributeSet &attrs, OpTy
target) {
2956 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2957 if (!attr.isValid())
2960 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2964 static_cast<int32_t
>(*numElems)}));
2975 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2976 llvm::AttributeList::AttrIndex::FunctionIndex);
2978 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2980 if (!passthroughAttr.empty())
2981 funcOp.setPassthroughAttr(passthroughAttr);
2985 LLVMFuncOp funcOp) {
2990 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
2991 funcOp.setNoInline(
true);
2992 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2993 funcOp.setAlwaysInline(
true);
2994 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
2995 funcOp.setInlineHint(
true);
2996 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2997 funcOp.setOptimizeNone(
true);
2998 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
2999 funcOp.setConvergent(
true);
3000 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
3001 funcOp.setNoUnwind(
true);
3002 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
3003 funcOp.setWillReturn(
true);
3004 if (
func->hasFnAttribute(llvm::Attribute::NoReturn))
3005 funcOp.setNoreturn(
true);
3006 if (
func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
3007 funcOp.setOptsize(
true);
3008 if (
func->hasFnAttribute(
"save-reg-params"))
3009 funcOp.setSaveRegParams(
true);
3010 if (
func->hasFnAttribute(llvm::Attribute::MinSize))
3011 funcOp.setMinsize(
true);
3012 if (
func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
3013 funcOp.setReturnsTwice(
true);
3014 if (
func->hasFnAttribute(llvm::Attribute::Cold))
3015 funcOp.setCold(
true);
3016 if (
func->hasFnAttribute(llvm::Attribute::Hot))
3017 funcOp.setHot(
true);
3018 if (
func->hasFnAttribute(llvm::Attribute::NoDuplicate))
3019 funcOp.setNoduplicate(
true);
3020 if (
func->hasFnAttribute(
"no_caller_saved_registers"))
3021 funcOp.setNoCallerSavedRegisters(
true);
3022 if (
func->hasFnAttribute(llvm::Attribute::NoCallback))
3023 funcOp.setNocallback(
true);
3024 if (llvm::Attribute attr =
func->getFnAttribute(
"modular-format");
3025 attr.isStringAttribute())
3026 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3027 if (llvm::Attribute attr =
func->getFnAttribute(
"zero-call-used-regs");
3028 attr.isStringAttribute())
3029 funcOp.setZeroCallUsedRegsAttr(
3030 StringAttr::get(context, attr.getValueAsString()));
3032 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
3033 funcOp.setArmStreaming(
true);
3034 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
3035 funcOp.setArmLocallyStreaming(
true);
3036 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
3037 funcOp.setArmStreamingCompatible(
true);
3039 if (
func->hasFnAttribute(
"aarch64_new_za"))
3040 funcOp.setArmNewZa(
true);
3041 else if (
func->hasFnAttribute(
"aarch64_in_za"))
3042 funcOp.setArmInZa(
true);
3043 else if (
func->hasFnAttribute(
"aarch64_out_za"))
3044 funcOp.setArmOutZa(
true);
3045 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
3046 funcOp.setArmInoutZa(
true);
3047 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
3048 funcOp.setArmPreservesZa(
true);
3053 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
3054 if (attr.isValid()) {
3056 auto intTy = IntegerType::get(context, 32);
3057 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
3058 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
3059 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
3063 if (
func->hasFnAttribute(
"frame-pointer")) {
3064 StringRef stringRefFramePointerKind =
3065 func->getFnAttribute(
"frame-pointer").getValueAsString();
3066 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
3067 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
3068 stringRefFramePointerKind)
3072 if (
func->hasFnAttribute(
"use-sample-profile"))
3073 funcOp.setUseSampleProfile(
true);
3075 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
3076 attr.isStringAttribute())
3077 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3079 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
3080 attr.isStringAttribute())
3081 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3083 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
3084 attr.isStringAttribute())
3085 funcOp.setTargetFeaturesAttr(
3086 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
3088 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
3089 attr.isStringAttribute())
3090 funcOp.setReciprocalEstimatesAttr(
3091 StringAttr::get(context, attr.getValueAsString()));
3093 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
3094 attr.isStringAttribute())
3095 funcOp.setPreferVectorWidth(attr.getValueAsString());
3097 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
3098 attr.isStringAttribute())
3099 funcOp.setInstrumentFunctionEntry(
3100 StringAttr::get(context, attr.getValueAsString()));
3102 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
3103 attr.isStringAttribute())
3104 funcOp.setInstrumentFunctionExit(
3105 StringAttr::get(context, attr.getValueAsString()));
3107 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
3108 attr.isStringAttribute())
3109 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
3111 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
3112 attr.isStringAttribute())
3113 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
3115 if (
func->hasUWTable()) {
3116 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
3117 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
3118 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
3123ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
3126 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
3128 if (!llvmAttr.isValid())
3133 if (llvmAttr.hasKindAsEnum() &&
3134 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
3135 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
3136 paramAttrs.push_back(
3142 if (llvmAttr.isTypeAttribute())
3143 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
3144 else if (llvmAttr.isIntAttribute())
3146 else if (llvmAttr.isEnumAttribute())
3148 else if (llvmAttr.isConstantRangeAttribute()) {
3149 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
3150 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
3153 llvm_unreachable(
"unexpected parameter attribute kind");
3155 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
3158 return builder.getDictionaryAttr(paramAttrs);
3162 LLVMFuncOp funcOp) {
3163 auto llvmAttrs = func->getAttributes();
3164 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
3165 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
3166 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
3170 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3171 if (!llvmResAttr.hasAttributes())
3173 funcOp.setResAttrsAttr(
3174 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
3178 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
3181 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
3182 immArgPositions.end());
3184 llvm::AttributeList llvmAttrs = call->getAttributes();
3186 bool anyArgAttrs =
false;
3187 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
3189 if (immArgPositionsSet.contains(i))
3191 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3192 if (llvmArgAttrsSet.back().hasAttributes())
3197 for (
auto &dict : dictAttrs)
3198 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3199 return builder.getArrayAttr(attrs);
3203 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
3204 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3205 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3209 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3210 if (!llvmResAttr.hasAttributes())
3212 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3213 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3216template <
typename Op>
3218 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3222LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3227LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3233 llvm::AttributeList callAttrs = inst->getAttributes();
3235 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3236 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3237 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3238 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3239 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3241 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3242 op.setSaveRegParams(callAttrs.getFnAttr(
"save-reg-params").isValid());
3243 op.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3244 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3245 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3248 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3249 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3250 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3252 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3253 op.setNoCallerSavedRegisters(
3254 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3255 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3257 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3258 attr.isStringAttribute())
3259 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3260 if (llvm::Attribute attr = callAttrs.getFnAttr(
"zero-call-used-regs");
3261 attr.isStringAttribute())
3262 op.setZeroCallUsedRegsAttr(
3263 StringAttr::get(context, attr.getValueAsString()));
3264 if (llvm::Attribute attr = callAttrs.getFnAttr(
"trap-func-name");
3265 attr.isStringAttribute())
3266 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3267 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3269 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3270 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3272 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3273 ModRefInfo othermem = convertModRefInfoFromLLVM(
3274 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3275 ModRefInfo argMem = convertModRefInfoFromLLVM(
3276 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3277 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3278 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3279 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3280 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3281 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3282 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3283 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3284 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3286 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3287 errnoMem, targetMem0, targetMem1);
3289 if (!memAttr.isReadWrite())
3290 op.setMemoryEffectsAttr(memAttr);
3303 if (
func->isIntrinsic() &&
3304 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3307 bool dsoLocal =
func->isDSOLocal();
3308 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3312 builder.setInsertionPointToEnd(mlirModule.getBody());
3314 Location loc = debugImporter->translateFuncLocation(
func);
3315 LLVMFuncOp funcOp = LLVMFuncOp::create(
3316 builder, loc,
func->getName(), functionType,
3317 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3322 funcOp.setPersonalityAttr(personality);
3323 else if (
func->hasPersonalityFn())
3324 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3327 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3329 if (
func->hasAtLeastLocalUnnamedAddr())
3330 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3332 if (
func->hasSection())
3333 funcOp.setSection(StringRef(
func->getSection()));
3335 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3337 if (
func->hasComdat())
3338 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3340 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3341 funcOp.setAlignment(maybeAlign->value());
3350 func->getAllMetadata(allMetadata);
3352 llvmModule->getMDKindNames(metadataNames);
3354 for (
auto &[kind, node] : allMetadata) {
3355 if (kind == llvm::LLVMContext::MD_dbg)
3358 llvm::MDNode *metadataNode = node;
3359 auto emitUnhandledFunctionMetadataWarning = [&]() {
3361 <<
"unhandled function metadata: "
3362 <<
diagMD(metadataNode, llvmModule.get()) <<
" on " <<
diag(*
func);
3365 if (iface.isConvertibleMetadata(kind)) {
3366 if (succeeded(iface.setMetadataAttrs(builder, kind, metadataNode, funcOp,
3369 emitUnhandledFunctionMetadataWarning();
3373 Attribute nodeAttr = convertMetadataToAttr(metadataNode);
3374 auto mdNodeAttr = dyn_cast_if_present<LLVM::MDNodeAttr>(nodeAttr);
3375 if (!mdNodeAttr || kind >= metadataNames.size()) {
3376 emitUnhandledFunctionMetadataWarning();
3380 functionMetadata.push_back(LLVM::FunctionMetadataAttr::get(
3381 context, builder.getStringAttr(metadataNames[kind]), mdNodeAttr));
3383 if (!functionMetadata.empty())
3384 funcOp.setFunctionMetadataAttr(builder.getArrayAttr(functionMetadata));
3386 if (
func->isDeclaration())
3395 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3396 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3401 for (llvm::BasicBlock &basicBlock : *
func) {
3403 if (!reachable.contains(&basicBlock)) {
3404 if (basicBlock.hasAddressTaken())
3406 <<
"unreachable block '" << basicBlock.getName()
3407 <<
"' with address taken";
3410 Region &body = funcOp.getBody();
3411 Block *block = builder.createBlock(&body, body.
end());
3413 reachableBasicBlocks.push_back(&basicBlock);
3417 for (
const auto &it : llvm::enumerate(
func->args())) {
3418 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3419 functionType.getParamType(it.index()), funcOp.getLoc());
3428 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3429 for (llvm::BasicBlock *basicBlock : blocks)
3430 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3435 if (failed(processDebugIntrinsics()))
3440 if (failed(processDebugRecords()))
3449 if (!dbgIntr->isKillLocation())
3451 llvm::Value *value = dbgIntr->getArgOperand(0);
3452 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3455 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3467 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3470 if (dominatedBlocks.empty())
3474 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3477 Value insertPt = argOperand;
3478 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3484 if (!insertionBlock->
empty() &&
3485 isa<LandingpadOp>(insertionBlock->
front()))
3486 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3494std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3495ModuleImport::processDebugOpArgumentsAndInsertionPt(
3497 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3498 llvm::Value *address,
3499 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3500 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3506 FailureOr<Value> argOperand = convertArgOperandToValue();
3507 if (
failed(argOperand)) {
3508 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3516 return {localVarAttr, debugImporter->translateExpression(expression),
3521ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3522 DominanceInfo &domInfo) {
3524 auto emitUnsupportedWarning = [&]() {
3525 if (emitExpensiveWarnings)
3530 OpBuilder::InsertionGuard guard(builder);
3531 auto convertArgOperandToValue = [&]() {
3537 if (dbgIntr->hasArgList())
3538 return emitUnsupportedWarning();
3545 return emitUnsupportedWarning();
3547 auto [localVariableAttr, locationExprAttr, locVal] =
3548 processDebugOpArgumentsAndInsertionPt(
3549 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3550 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3552 if (!localVariableAttr)
3553 return emitUnsupportedWarning();
3558 Operation *op =
nullptr;
3559 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3560 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3562 else if (isa<llvm::DbgValueInst>(dbgIntr))
3563 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3566 return emitUnsupportedWarning();
3569 setNonDebugMetadataAttrs(dbgIntr, op);
3574ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3575 DominanceInfo &domInfo) {
3576 OpBuilder::InsertionGuard guard(builder);
3578 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3579 if (!emitExpensiveWarnings)
3582 llvm::raw_string_ostream optionsStream(
options);
3583 dbgRecord.print(optionsStream);
3584 emitWarning(loc) <<
"unhandled debug variable record "
3585 << optionsStream.str();
3591 if (dbgRecord.hasArgList())
3592 return emitUnsupportedWarning();
3597 if (!dbgRecord.getAddress())
3598 return emitUnsupportedWarning();
3600 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3601 llvm::Value *value = dbgRecord.getAddress();
3604 auto it = valueMapping.find(value);
3605 if (it != valueMapping.end())
3606 return it->getSecond();
3609 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3610 return convertConstantExpr(constant);
3614 auto [localVariableAttr, locationExprAttr, locVal] =
3615 processDebugOpArgumentsAndInsertionPt(
3616 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3617 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3619 if (!localVariableAttr)
3620 return emitUnsupportedWarning();
3625 if (dbgRecord.isDbgDeclare())
3626 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3628 else if (dbgRecord.isDbgValue())
3629 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3632 return emitUnsupportedWarning();
3637LogicalResult ModuleImport::processDebugIntrinsics() {
3638 DominanceInfo domInfo;
3639 for (llvm::Instruction *inst : debugIntrinsics) {
3640 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3641 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3647LogicalResult ModuleImport::processDebugRecords() {
3648 DominanceInfo domInfo;
3649 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3650 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3656LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3658 builder.setInsertionPointToStart(block);
3659 for (llvm::Instruction &inst : *bb) {
3660 if (
failed(processInstruction(&inst)))
3665 if (debugIntrinsics.contains(&inst))
3672 setNonDebugMetadataAttrs(&inst, op);
3673 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3674 if (emitExpensiveWarnings) {
3675 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3681 if (bb->hasAddressTaken()) {
3682 OpBuilder::InsertionGuard guard(builder);
3683 builder.setInsertionPointToStart(block);
3685 BlockTagAttr::get(context, bb->getNumber()));
3690FailureOr<SmallVector<AccessGroupAttr>>
3692 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3698 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3701FailureOr<DereferenceableAttr>
3704 Location loc = mlirModule.getLoc();
3708 if (node->getNumOperands() != 1)
3709 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3710 <<
diagMD(node, llvmModule.get());
3712 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3713 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3714 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3715 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3716 "non-negative constant integer: "
3717 <<
diagMD(node, llvmModule.get());
3719 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3720 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3721 numBytesCst->getZExtValue(), mayBeNull);
3727 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3728 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3729 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3730 bool importStructsAsLiterals) {
3737 LLVMDialect::getDialectNamespace()));
3739 DLTIDialect::getDialectNamespace()));
3740 if (loadAllDialects)
3743 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3747 emitExpensiveWarnings, dropDICompositeTypeElements,
3748 preferUnregisteredIntrinsics,
3749 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.