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