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())
185Attribute ModuleImport::convertMetadataToAttrImpl(
186 const llvm::Metadata *md, SmallPtrSetImpl<const llvm::Metadata *> &path,
190 if (
auto *mdStr = dyn_cast<llvm::MDString>(md))
191 return MDStringAttr::get(context,
192 StringAttr::get(context, mdStr->getString()));
193 if (
auto *cam = dyn_cast<llvm::ConstantAsMetadata>(md)) {
194 llvm::Constant *constant = cam->getValue();
195 if (
auto *global = dyn_cast<llvm::GlobalValue>(constant)) {
196 if (FlatSymbolRefAttr symbolRef = getMetadataGlobalValueSymbolRef(global))
197 return MDGlobalValueAttr::get(context, symbolRef);
199 auto *ci = dyn_cast<llvm::ConstantInt>(constant);
202 auto intType = IntegerType::get(context, ci->getBitWidth());
203 return MDConstantAttr::get(context,
204 IntegerAttr::get(intType, ci->getValue()));
206 if (
auto *node = dyn_cast<llvm::MDNode>(md)) {
208 if (node->isDistinct())
210 if (Attribute cached = attrMap.lookup(node))
214 if (!path.insert(node).second)
216 SmallVector<Attribute> operands;
217 operands.reserve(node->getNumOperands());
218 for (
const llvm::MDOperand &op : node->operands()) {
219 Attribute opAttr = convertMetadataToAttrImpl(op.get(), path, attrMap);
222 operands.push_back(opAttr);
225 Attribute nodeAttr = MDNodeAttr::get(context, operands);
226 attrMap.try_emplace(node, nodeAttr);
237Attribute ModuleImport::convertMetadataToAttr(
const llvm::Metadata *md) {
238 SmallPtrSet<const llvm::Metadata *, 8> path;
240 return convertMetadataToAttrImpl(md, path, attrMap);
247 for (llvm::BasicBlock *basicBlock : basicBlocks) {
248 if (!blocks.contains(basicBlock)) {
249 llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);
250 blocks.insert_range(traversal);
253 assert(blocks.size() == basicBlocks.size() &&
"some blocks are not sorted");
258 std::unique_ptr<llvm::Module> llvmModule,
259 bool emitExpensiveWarnings,
260 bool importEmptyDICompositeTypes,
261 bool preferUnregisteredIntrinsics,
262 bool importStructsAsLiterals)
264 mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
266 typeTranslator(*mlirModule->
getContext(), importStructsAsLiterals),
268 mlirModule, importEmptyDICompositeTypes)),
269 loopAnnotationImporter(
271 emitExpensiveWarnings(emitExpensiveWarnings),
272 preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {
273 builder.setInsertionPointToStart(mlirModule.getBody());
276ComdatOp ModuleImport::getGlobalComdatOp() {
278 return globalComdatOp;
284 globalInsertionOp = globalComdatOp;
285 return globalComdatOp;
288LogicalResult ModuleImport::processTBAAMetadata(
const llvm::MDNode *node) {
293 auto getIdentityIfRootNode =
294 [&](
const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {
298 if (node->getNumOperands() > 1)
301 if (node->getNumOperands() == 1)
302 if (
const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))
303 return std::optional<StringRef>{op0->getString()};
304 return std::optional<StringRef>{};
314 auto isTypeDescriptorNode = [&](
const llvm::MDNode *node,
315 StringRef *identity =
nullptr,
316 SmallVectorImpl<TBAAMemberAttr> *members =
317 nullptr) -> std::optional<bool> {
318 unsigned numOperands = node->getNumOperands();
327 const auto *identityNode =
328 dyn_cast<const llvm::MDString>(node->getOperand(0));
334 *identity = identityNode->getString();
336 for (
unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {
337 const auto *memberNode =
338 dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));
340 emitError(loc) <<
"operand '" << 2 * pairNum + 1 <<
"' must be MDNode: "
341 <<
diagMD(node, llvmModule.get());
345 if (2 * pairNum + 2 >= numOperands) {
347 if (numOperands != 2) {
348 emitError(loc) <<
"missing member offset: "
349 <<
diagMD(node, llvmModule.get());
353 auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(
354 node->getOperand(2 * pairNum + 2));
356 emitError(loc) <<
"operand '" << 2 * pairNum + 2
357 <<
"' must be ConstantInt: "
358 <<
diagMD(node, llvmModule.get());
361 offset = offsetCI->getZExtValue();
365 members->push_back(TBAAMemberAttr::get(
366 cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));
379 auto isTagNode = [&](
const llvm::MDNode *node,
380 TBAATypeDescriptorAttr *baseAttr =
nullptr,
381 TBAATypeDescriptorAttr *accessAttr =
nullptr,
382 int64_t *offset =
nullptr,
383 bool *isConstant =
nullptr) -> std::optional<bool> {
391 unsigned numOperands = node->getNumOperands();
392 if (numOperands != 3 && numOperands != 4)
394 const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));
395 const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));
397 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));
398 if (!baseMD || !accessMD || !offsetCI)
405 if (accessMD->getNumOperands() < 1 ||
406 !isa<llvm::MDString>(accessMD->getOperand(0)))
408 bool isConst =
false;
409 if (numOperands == 4) {
411 llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));
413 emitError(loc) <<
"operand '3' must be ConstantInt: "
414 <<
diagMD(node, llvmModule.get());
417 isConst = isConstantCI->getValue()[0];
420 *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));
422 *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));
424 *offset = offsetCI->getZExtValue();
426 *isConstant = isConst;
434 SmallVector<const llvm::MDNode *> workList;
435 workList.push_back(node);
436 while (!workList.empty()) {
437 const llvm::MDNode *current = workList.back();
438 if (tbaaMapping.contains(current)) {
447 bool anyChildNotConverted =
false;
448 for (
const llvm::MDOperand &operand : current->operands())
449 if (
auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))
450 if (!tbaaMapping.contains(childNode)) {
451 workList.push_back(childNode);
452 anyChildNotConverted =
true;
455 if (anyChildNotConverted) {
460 if (!seen.insert(current).second)
461 return emitError(loc) <<
"has cycle in TBAA graph: "
462 <<
diagMD(current, llvmModule.get());
470 FailureOr<std::optional<StringRef>> rootNodeIdentity =
471 getIdentityIfRootNode(current);
472 if (succeeded(rootNodeIdentity)) {
473 StringAttr stringAttr = *rootNodeIdentity
474 ? builder.getStringAttr(**rootNodeIdentity)
478 tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)});
483 SmallVector<TBAAMemberAttr> members;
484 if (std::optional<bool> isValid =
485 isTypeDescriptorNode(current, &identity, &members)) {
486 assert(isValid.value() &&
"type descriptor node must be valid");
488 tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>(
489 identity, members)});
493 TBAATypeDescriptorAttr baseAttr, accessAttr;
496 if (std::optional<bool> isValid =
497 isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {
498 assert(isValid.value() &&
"access tag node must be valid");
500 {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,
505 return emitError(loc) <<
"unsupported TBAA node format: "
506 <<
diagMD(current, llvmModule.get());
512ModuleImport::processAccessGroupMetadata(
const llvm::MDNode *node) {
513 Location loc = mlirModule.getLoc();
514 if (
failed(loopAnnotationImporter->translateAccessGroup(node, loc)))
515 return emitError(loc) <<
"unsupported access group node: "
516 <<
diagMD(node, llvmModule.get());
521ModuleImport::processAliasScopeMetadata(
const llvm::MDNode *node) {
522 Location loc = mlirModule.getLoc();
524 auto verifySelfRef = [](
const llvm::MDNode *node) {
525 return node->getNumOperands() != 0 &&
526 node == dyn_cast<llvm::MDNode>(node->getOperand(0));
528 auto verifySelfRefOrString = [](
const llvm::MDNode *node) {
529 return node->getNumOperands() != 0 &&
530 (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||
531 isa<llvm::MDString>(node->getOperand(0)));
534 auto verifyDescription = [](
const llvm::MDNode *node,
unsigned idx) {
535 return idx >= node->getNumOperands() ||
536 isa<llvm::MDString>(node->getOperand(idx));
539 auto getIdAttr = [&](
const llvm::MDNode *node) -> Attribute {
540 if (verifySelfRef(node))
543 auto *name = cast<llvm::MDString>(node->getOperand(0));
544 return builder.getStringAttr(name->getString());
548 auto createAliasScopeDomainOp = [&](
const llvm::MDNode *aliasDomain) {
549 StringAttr description =
nullptr;
550 if (aliasDomain->getNumOperands() >= 2)
551 if (
auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))
552 description = builder.getStringAttr(operand->getString());
553 Attribute idAttr = getIdAttr(aliasDomain);
554 return builder.getAttr<AliasScopeDomainAttr>(idAttr, description);
558 for (
const llvm::MDOperand &operand : node->operands()) {
559 if (
const auto *scope = dyn_cast<llvm::MDNode>(operand)) {
560 llvm::AliasScopeNode aliasScope(scope);
561 const llvm::MDNode *domain = aliasScope.getDomain();
567 if (!verifySelfRefOrString(scope) || !domain ||
568 !verifyDescription(scope, 2))
569 return emitError(loc) <<
"unsupported alias scope node: "
570 <<
diagMD(scope, llvmModule.get());
571 if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))
572 return emitError(loc) <<
"unsupported alias domain node: "
573 <<
diagMD(domain, llvmModule.get());
575 if (aliasScopeMapping.contains(scope))
579 auto it = aliasScopeMapping.find(aliasScope.getDomain());
580 if (it == aliasScopeMapping.end()) {
581 auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);
582 it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;
586 StringAttr description =
nullptr;
587 if (!aliasScope.getName().empty())
588 description = builder.getStringAttr(aliasScope.getName());
589 Attribute idAttr = getIdAttr(scope);
590 auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(
591 idAttr, cast<AliasScopeDomainAttr>(it->second), description);
593 aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);
599FailureOr<SmallVector<AliasScopeAttr>>
602 aliasScopes.reserve(node->getNumOperands());
603 for (
const llvm::MDOperand &operand : node->operands()) {
604 auto *node = cast<llvm::MDNode>(operand.get());
605 aliasScopes.push_back(
606 dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));
609 if (llvm::is_contained(aliasScopes,
nullptr))
615 debugIntrinsics.insert(intrinsic);
619 if (!dbgRecords.contains(dbgRecord))
620 dbgRecords.insert(dbgRecord);
624 llvm::MDTuple *mdTuple) {
625 auto getLLVMFunction =
626 [&](
const llvm::MDOperand &funcMDO) -> llvm::Function * {
627 auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);
631 auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());
637 for (
unsigned i = 0; i < mdTuple->getNumOperands(); i++) {
638 const llvm::MDOperand &mdo = mdTuple->getOperand(i);
639 auto *cgEntry = cast<llvm::MDNode>(mdo);
640 llvm::Constant *llvmConstant =
641 cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();
642 uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();
643 auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));
644 auto *toFn = getLLVMFunction(cgEntry->getOperand(1));
646 cgProfile.push_back(ModuleFlagCGProfileEntryAttr::get(
647 mlirModule->getContext(),
655 return ArrayAttr::get(mlirModule->getContext(), cgProfile);
661 const llvm::Module *llvmModule,
662 const llvm::MDOperand &md) {
663 auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);
664 if (!tupleEntry || tupleEntry->getNumOperands() != 2)
666 <<
"expected 2-element tuple metadata: " <<
diagMD(md, llvmModule);
674 ModuleOp mlirModule,
const llvm::Module *llvmModule,
675 const llvm::MDOperand &md, StringRef matchKey,
bool optional =
false) {
679 auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
680 if (!keyMD || keyMD->getString() != matchKey) {
683 <<
"expected '" << matchKey <<
"' key, but found: "
684 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
688 return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));
694static FailureOr<uint64_t>
696 const llvm::Module *llvmModule,
697 const llvm::MDOperand &md, StringRef matchKey) {
698 llvm::ConstantAsMetadata *valMD =
703 if (
auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))
704 return cstInt->getZExtValue();
707 <<
"expected integer metadata value for key '" << matchKey
708 <<
"': " <<
diagMD(md, llvmModule);
712static std::optional<ProfileSummaryFormatKind>
714 const llvm::MDOperand &formatMD) {
719 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
720 if (!keyMD || keyMD->getString() !=
"ProfileFormat") {
722 <<
"expected 'ProfileFormat' key: "
723 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
727 llvm::MDString *valMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(1));
728 std::optional<ProfileSummaryFormatKind> fmtKind =
729 symbolizeProfileSummaryFormatKind(valMD->getString());
732 <<
"expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "
734 <<
diagMD(valMD, llvmModule);
741static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>
743 const llvm::Module *llvmModule,
744 const llvm::MDOperand &summaryMD) {
749 llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));
750 if (!keyMD || keyMD->getString() !=
"DetailedSummary") {
752 <<
"expected 'DetailedSummary' key: "
753 <<
diagMD(tupleEntry->getOperand(0), llvmModule);
757 llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));
760 <<
"expected tuple value for 'DetailedSummary' key: "
761 <<
diagMD(tupleEntry->getOperand(1), llvmModule);
766 for (
auto &&entry : entriesMD->operands()) {
767 llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);
768 if (!entryMD || entryMD->getNumOperands() != 3) {
770 <<
"'DetailedSummary' entry expects 3 operands: "
771 <<
diagMD(entry, llvmModule);
775 auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));
776 auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));
777 auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));
778 if (!op0 || !op1 || !op2) {
780 <<
"expected only integer entries in 'DetailedSummary': "
781 <<
diagMD(entry, llvmModule);
785 auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get(
786 mlirModule->getContext(),
787 cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),
788 cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),
789 cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());
790 detailedSummary.push_back(detaildSummaryEntry);
792 return detailedSummary;
797 const llvm::Module *llvmModule,
798 llvm::MDTuple *mdTuple) {
799 unsigned profileNumEntries = mdTuple->getNumOperands();
800 if (profileNumEntries < 8) {
802 <<
"expected at 8 entries in 'ProfileSummary': "
803 <<
diagMD(mdTuple, llvmModule);
807 unsigned summayIdx = 0;
808 auto checkOptionalPosition = [&](
const llvm::MDOperand &md,
809 StringRef matchKey) -> LogicalResult {
813 if (summayIdx + 1 >= profileNumEntries) {
815 <<
"the last summary entry is '" << matchKey
816 <<
"', expected 'DetailedSummary': " <<
diagMD(md, llvmModule);
823 auto getOptIntValue =
824 [&](
const llvm::MDOperand &md,
825 StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {
828 return FailureOr<std::optional<uint64_t>>(std::nullopt);
829 if (checkOptionalPosition(md, matchKey).failed())
831 FailureOr<uint64_t> val =
838 auto getOptDoubleValue = [&](
const llvm::MDOperand &md,
839 StringRef matchKey) -> FailureOr<FloatAttr> {
844 if (
auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {
845 if (checkOptionalPosition(md, matchKey).failed())
847 return FloatAttr::get(Float64Type::get(mlirModule.getContext()),
848 cstFP->getValueAPF());
851 <<
"expected double metadata value for key '" << matchKey
852 <<
"': " <<
diagMD(md, llvmModule);
859 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));
860 if (!format.has_value())
864 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"TotalCount");
865 if (failed(totalCount))
869 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"MaxCount");
870 if (failed(maxCount))
874 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
876 if (failed(maxInternalCount))
880 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
882 if (failed(maxFunctionCount))
886 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumCounts");
887 if (failed(numCounts))
891 mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),
"NumFunctions");
892 if (failed(numFunctions))
896 FailureOr<std::optional<uint64_t>> isPartialProfile =
897 getOptIntValue(mdTuple->getOperand(summayIdx),
"IsPartialProfile");
898 if (failed(isPartialProfile))
900 if (isPartialProfile->has_value())
903 FailureOr<FloatAttr> partialProfileRatio =
904 getOptDoubleValue(mdTuple->getOperand(summayIdx),
"PartialProfileRatio");
905 if (failed(partialProfileRatio))
907 if (*partialProfileRatio)
911 FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =
913 mdTuple->getOperand(summayIdx));
914 if (failed(detailed))
918 return ModuleFlagProfileSummaryAttr::get(
919 mlirModule->getContext(), *format, *totalCount, *maxCount,
920 *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,
921 *isPartialProfile, *partialProfileRatio, *detailed);
928 const llvm::Module *llvmModule, StringRef key,
929 llvm::MDTuple *mdTuple) {
930 if (key == LLVMDialect::getModuleFlagKeyCGProfileName())
932 if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())
937 Builder builder(mlirModule->getContext());
939 strings.reserve(mdTuple->getNumOperands());
940 for (
const llvm::MDOperand &operand : mdTuple->operands()) {
941 auto *mdString = dyn_cast_if_present<llvm::MDString>(operand.get());
944 strings.push_back(builder.
getStringAttr(mdString->getString()));
951 llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
954 for (
const auto [behavior, key, val] : llvmModuleFlags) {
956 if (
auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {
957 valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());
958 }
else if (
auto *mdString = dyn_cast<llvm::MDString>(val)) {
959 valAttr = builder.getStringAttr(mdString->getString());
960 }
else if (
auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {
962 key->getString(), mdTuple);
967 <<
"unsupported module flag value for key '" << key->getString()
968 <<
"' : " <<
diagMD(val, llvmModule.get());
972 moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
973 convertModFlagBehaviorFromLLVM(behavior),
974 builder.getStringAttr(key->getString()), valAttr));
977 if (!moduleFlags.empty())
978 LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),
979 builder.getArrayAttr(moduleFlags));
985 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
986 if (named.getName() !=
"llvm.linker.options")
989 for (
const llvm::MDNode *node : named.operands()) {
991 options.reserve(node->getNumOperands());
992 for (
const llvm::MDOperand &option : node->operands())
993 options.push_back(cast<llvm::MDString>(option)->getString());
994 LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),
995 builder.getStrArrayAttr(
options));
1002 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1003 if (named.getName() !=
"llvm.dependent-libraries")
1006 for (
const llvm::MDNode *node : named.operands()) {
1007 if (node->getNumOperands() == 1)
1008 if (
auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))
1009 libraries.push_back(mdString->getString());
1011 if (!libraries.empty())
1012 mlirModule->setAttr(LLVM::LLVMDialect::getDependentLibrariesAttrName(),
1013 builder.getStrArrayAttr(libraries));
1019 for (
const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
1022 if (named.getName() != LLVMDialect::getIdentAttrName())
1025 if (named.getNumOperands() == 1)
1026 if (
auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))
1027 if (md->getNumOperands() == 1)
1028 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
1029 mlirModule->setAttr(LLVMDialect::getIdentAttrName(),
1030 builder.getStringAttr(mdStr->getString()));
1036 for (
const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {
1039 if (nmd.getName() != LLVMDialect::getCommandlineAttrName())
1042 if (nmd.getNumOperands() == 1)
1043 if (
auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))
1044 if (md->getNumOperands() == 1)
1045 if (
auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))
1046 mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),
1047 builder.getStringAttr(mdStr->getString()));
1054 builder.setInsertionPointToEnd(mlirModule.getBody());
1055 for (
const llvm::Function &
func : llvmModule->functions()) {
1056 for (
const llvm::Instruction &inst : llvm::instructions(
func)) {
1058 if (llvm::MDNode *node =
1059 inst.getMetadata(llvm::LLVMContext::MD_access_group))
1060 if (failed(processAccessGroupMetadata(node)))
1064 llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();
1065 if (!aliasAnalysisNodes)
1067 if (aliasAnalysisNodes.TBAA)
1068 if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))
1070 if (aliasAnalysisNodes.Scope)
1071 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))
1073 if (aliasAnalysisNodes.NoAlias)
1074 if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))
1091void ModuleImport::processComdat(
const llvm::Comdat *comdat) {
1092 if (comdatMapping.contains(comdat))
1095 ComdatOp comdatOp = getGlobalComdatOp();
1098 auto selectorOp = ComdatSelectorOp::create(
1099 builder, mlirModule.getLoc(), comdat->getName(),
1100 convertComdatFromLLVM(comdat->getSelectionKind()));
1104 comdatMapping.try_emplace(comdat, symbolRef);
1108 for (llvm::GlobalVariable &globalVar : llvmModule->globals())
1109 if (globalVar.hasComdat())
1110 processComdat(globalVar.getComdat());
1111 for (llvm::Function &
func : llvmModule->functions())
1112 if (
func.hasComdat())
1113 processComdat(
func.getComdat());
1118 for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {
1121 if (failed(convertGlobalCtorsAndDtors(&globalVar))) {
1122 return emitError(UnknownLoc::get(context))
1123 <<
"unhandled global variable: " <<
diag(globalVar);
1127 if (failed(convertGlobal(&globalVar))) {
1128 return emitError(UnknownLoc::get(context))
1129 <<
"unhandled global variable: " <<
diag(globalVar);
1136 for (llvm::GlobalAlias &alias : llvmModule->aliases()) {
1137 if (failed(convertAlias(&alias))) {
1138 return emitError(UnknownLoc::get(context))
1139 <<
"unhandled global alias: " <<
diag(alias);
1146 for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {
1147 if (failed(convertIFunc(&ifunc))) {
1148 return emitError(UnknownLoc::get(context))
1149 <<
"unhandled global ifunc: " <<
diag(ifunc);
1156 Location loc = mlirModule.getLoc();
1158 context, llvmModule->getDataLayout().getStringRepresentation());
1160 return emitError(loc,
"cannot translate data layout: ")
1164 emitWarning(loc,
"unhandled data layout token: ") << token;
1166 mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
1172 mlirModule->setAttr(
1173 LLVM::LLVMDialect::getTargetTripleAttrName(),
1174 builder.getStringAttr(llvmModule->getTargetTriple().str()));
1180 for (
const llvm::Module::GlobalAsmFragment &Frag :
1181 llvmModule->getModuleInlineAsm()) {
1183 for (llvm::StringRef line : llvm::split(Frag.Asm,
'\n'))
1185 asmArrayAttr.push_back(builder.getStringAttr(line));
1188 mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
1189 builder.getArrayAttr(asmArrayAttr));
1193 for (llvm::Function &
func : llvmModule->functions())
1199void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,
1202 inst->getAllMetadataOtherThanDebugLoc(allMetadata);
1203 for (
auto &[kind, node] : allMetadata) {
1207 if (emitExpensiveWarnings) {
1208 Location loc = debugImporter->translateLoc(inst->getDebugLoc());
1210 <<
diagMD(node, llvmModule.get()) <<
" on "
1219 auto iface = cast<IntegerOverflowFlagsInterface>(op);
1221 IntegerOverflowFlags value = {};
1222 value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());
1224 bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());
1226 iface.setOverflowFlags(value);
1230 auto iface = cast<ExactFlagInterface>(op);
1232 iface.setIsExact(inst->isExact());
1237 auto iface = cast<DisjointFlagInterface>(op);
1238 auto *instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);
1240 iface.setIsDisjoint(instDisjoint->isDisjoint());
1244 auto iface = cast<NonNegFlagInterface>(op);
1246 iface.setNonNeg(inst->hasNonNeg());
1251 auto iface = cast<FastmathFlagsInterface>(op);
1257 if (!isa<llvm::FPMathOperator>(inst))
1259 llvm::FastMathFlags flags = inst->getFastMathFlags();
1262 FastmathFlags value = {};
1263 value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());
1264 value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());
1265 value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());
1266 value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());
1267 value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());
1268 value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());
1269 value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());
1270 FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);
1271 iface->setAttr(iface.getFastmathAttrName(), attr);
1283 if (numElements.isScalable()) {
1285 <<
"scalable vectors not supported";
1290 Type elementType = cast<VectorType>(type).getElementType();
1294 SmallVector<int64_t> shape(arrayShape);
1295 shape.push_back(numElements.getKnownMinValue());
1296 return VectorType::get(shape, elementType);
1299Type ModuleImport::getBuiltinTypeForAttr(Type type) {
1313 SmallVector<int64_t> arrayShape;
1314 while (
auto arrayType = dyn_cast<LLVMArrayType>(type)) {
1315 arrayShape.push_back(arrayType.getNumElements());
1316 type = arrayType.getElementType();
1319 return RankedTensorType::get(arrayShape, type);
1326 llvm::Constant *constScalar) {
1329 if (constScalar->getType()->isVectorTy())
1333 if (
auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {
1335 IntegerType::get(context, constInt->getBitWidth()),
1336 constInt->getValue());
1340 if (
auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {
1341 llvm::Type *type = constFloat->getType();
1342 FloatType floatType =
1344 ? BFloat16Type::get(context)
1348 <<
"unexpected floating-point type";
1351 return builder.
getFloatAttr(floatType, constFloat->getValueAPF());
1358static SmallVector<Attribute>
1360 llvm::ConstantDataSequential *constSequence) {
1362 elementAttrs.reserve(constSequence->getNumElements());
1363 for (
auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {
1364 llvm::Constant *constElement = constSequence->getElementAsConstant(idx);
1367 return elementAttrs;
1370Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {
1376 auto getConstantShape = [&](llvm::Type *type) {
1377 return llvm::dyn_cast_if_present<ShapedType>(
1382 if (isa<llvm::ConstantInt, llvm::ConstantFP>(constant)) {
1383 assert(constant->getType()->isVectorTy() &&
"expected a vector splat");
1384 auto shape = getConstantShape(constant->getType());
1387 Attribute splatAttr =
1394 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {
1395 if (constArray->isString())
1396 return builder.getStringAttr(constArray->getAsString());
1397 auto shape = getConstantShape(constArray->getType());
1401 auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);
1402 if (constVector && constVector->isSplat()) {
1405 builder, constVector->getElementAsConstant(0));
1409 SmallVector<Attribute> elementAttrs =
1416 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {
1417 auto shape = getConstantShape(constAggregate->getType());
1421 SmallVector<Attribute> elementAttrs;
1422 SmallVector<llvm::Constant *> workList = {constAggregate};
1423 while (!workList.empty()) {
1424 llvm::Constant *current = workList.pop_back_val();
1427 if (
auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {
1429 reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))
1430 workList.push_back(constAggregate->getAggregateElement(idx));
1435 if (
auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {
1436 SmallVector<Attribute> attrs =
1438 elementAttrs.append(attrs.begin(), attrs.end());
1444 elementAttrs.push_back(scalarAttr);
1455 if (
auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1456 auto shape = llvm::dyn_cast_if_present<ShapedType>(
1457 getBuiltinTypeForAttr(
convertType(constZero->getType())));
1461 Attribute splatAttr = builder.getZeroAttr(shape.getElementType());
1462 assert(splatAttr &&
"expected non-null zero attribute for scalar types");
1469ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {
1470 assert(globalVar->getName().empty() &&
1471 "expected to work with a nameless global");
1472 auto [it,
success] = namelessGlobals.try_emplace(globalVar);
1479 [
this](StringRef newName) {
return llvmModule->getNamedValue(newName); },
1482 it->getSecond() = symbolRef;
1486OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {
1487 OpBuilder::InsertionGuard guard(builder);
1488 if (globalInsertionOp)
1489 builder.setInsertionPointAfter(globalInsertionOp);
1491 builder.setInsertionPointToStart(mlirModule.getBody());
1495LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {
1497 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1500 AliasOp aliasOp = AliasOp::create(
1501 builder, mlirModule.getLoc(), type,
1502 convertLinkageFromLLVM(alias->getLinkage()), alias->getName(),
1503 alias->isDSOLocal(),
1504 convertThreadLocalModeFromLLVM(alias->getThreadLocalMode()),
1505 ArrayRef<NamedAttribute>());
1506 globalInsertionOp = aliasOp;
1509 Block *block = builder.createBlock(&aliasOp.getInitializerRegion());
1510 setConstantInsertionPointToStart(block);
1511 FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());
1514 ReturnOp::create(builder, aliasOp.getLoc(), *initializer);
1516 if (alias->hasAtLeastLocalUnnamedAddr())
1517 aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));
1518 aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));
1523LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {
1524 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1527 llvm::Constant *resolver = ifunc->getResolver();
1528 Type resolverType =
convertType(resolver->getType());
1529 IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,
1530 resolver->getName(), resolverType,
1531 convertLinkageFromLLVM(ifunc->getLinkage()),
1532 ifunc->isDSOLocal(), ifunc->getAddressSpace(),
1533 convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),
1534 convertVisibilityFromLLVM(ifunc->getVisibility()));
1544 ArrayRef<StringLiteral> attributePrefixesToSkip = {}) {
1545 SmallVector<Attribute> mlirAttributes;
1546 for (llvm::Attribute attr : attributes) {
1548 if (attr.isStringAttribute())
1549 attrName = attr.getKindAsString();
1551 attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());
1552 if (llvm::is_contained(attributesToSkip, attrName))
1555 auto attrNameStartsWith = [attrName](StringLiteral sl) {
1556 return attrName.starts_with(sl);
1558 if (attributePrefixesToSkip.end() !=
1559 llvm::find_if(attributePrefixesToSkip, attrNameStartsWith))
1562 auto keyAttr = StringAttr::get(context, attrName);
1563 if (attr.isStringAttribute()) {
1564 StringRef val = attr.getValueAsString();
1567 mlirAttributes.push_back(keyAttr);
1571 mlirAttributes.push_back(
1572 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1575 if (attr.isIntAttribute()) {
1578 auto val = std::to_string(attr.getValueAsInt());
1579 mlirAttributes.push_back(
1580 ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));
1583 if (attr.isEnumAttribute()) {
1585 mlirAttributes.push_back(keyAttr);
1591 <<
"' attribute is invalid on current operation, skipping it";
1593 return ArrayAttr::get(context, mlirAttributes);
1599 GlobalOp globalOp) {
1601 globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());
1602 if (!targetSpecificAttrs.empty())
1603 globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);
1606LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {
1608 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1610 Attribute valueAttr;
1611 if (globalVar->hasInitializer())
1612 valueAttr = getConstantAsAttr(globalVar->getInitializer());
1613 Type type =
convertType(globalVar->getValueType());
1615 uint64_t alignment = 0;
1616 llvm::MaybeAlign maybeAlign = globalVar->getAlign();
1617 if (maybeAlign.has_value()) {
1618 llvm::Align align = *maybeAlign;
1619 alignment = align.value();
1624 SmallVector<Attribute> globalExpressionAttrs;
1625 SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;
1626 globalVar->getDebugInfo(globalExpressions);
1628 for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {
1629 DIGlobalVariableExpressionAttr globalExpressionAttr =
1630 debugImporter->translateGlobalVariableExpression(expr);
1631 globalExpressionAttrs.push_back(globalExpressionAttr);
1636 StringRef globalName = globalVar->getName();
1637 if (globalName.empty())
1638 globalName = getOrCreateNamelessSymbolName(globalVar).getValue();
1640 GlobalOp globalOp = GlobalOp::create(
1641 builder, mlirModule.getLoc(), type, globalVar->isConstant(),
1642 convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),
1643 valueAttr, alignment, globalVar->getAddressSpace(),
1644 globalVar->isDSOLocal(),
1645 convertThreadLocalModeFromLLVM(globalVar->getThreadLocalMode()),
1647 ArrayRef<NamedAttribute>(), globalExpressionAttrs);
1648 globalInsertionOp = globalOp;
1650 if (globalVar->hasInitializer() && !valueAttr) {
1652 Block *block = builder.createBlock(&globalOp.getInitializerRegion());
1653 setConstantInsertionPointToStart(block);
1654 FailureOr<Value> initializer =
1655 convertConstantExpr(globalVar->getInitializer());
1658 ReturnOp::create(builder, globalOp.getLoc(), *initializer);
1660 if (globalVar->hasAtLeastLocalUnnamedAddr()) {
1661 globalOp.setUnnamedAddr(
1662 convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));
1664 if (globalVar->hasSection())
1665 globalOp.setSection(globalVar->getSection());
1666 globalOp.setVisibility_(
1667 convertVisibilityFromLLVM(globalVar->getVisibility()));
1669 if (globalVar->hasComdat())
1670 globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));
1678ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {
1679 if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())
1681 llvm::Constant *initializer = globalVar->getInitializer();
1683 bool knownInit = isa<llvm::ConstantArray>(initializer) ||
1684 isa<llvm::ConstantAggregateZero>(initializer);
1691 if (
auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {
1692 if (caz->getElementCount().getFixedValue() != 0)
1696 SmallVector<Attribute> funcs;
1697 SmallVector<int32_t> priorities;
1698 SmallVector<Attribute> dataList;
1699 for (llvm::Value *operand : initializer->operands()) {
1700 auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);
1701 if (!aggregate || aggregate->getNumOperands() != 3)
1704 auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));
1705 auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));
1706 auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));
1707 if (!priority || !func || !data)
1710 auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);
1714 else if (data->isNullValue())
1715 dataAttr = ZeroAttr::get(context);
1720 priorities.push_back(priority->getValue().getZExtValue());
1721 dataList.push_back(dataAttr);
1725 OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();
1728 globalInsertionOp = LLVM::GlobalCtorsOp::create(
1729 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1730 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1733 globalInsertionOp = LLVM::GlobalDtorsOp::create(
1734 builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),
1735 builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));
1740ModuleImport::getConstantsToConvert(llvm::Constant *constant) {
1742 if (valueMapping.contains(constant))
1751 workList.insert(constant);
1752 while (!workList.empty()) {
1753 llvm::Constant *current = workList.back();
1756 if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {
1757 orderedSet.insert(current);
1758 workList.pop_back();
1764 auto [adjacencyIt,
inserted] = adjacencyLists.try_emplace(current);
1768 for (llvm::Value *operand : current->operands())
1769 if (
auto *constDependency = dyn_cast<llvm::Constant>(operand))
1770 adjacencyIt->getSecond().push_back(constDependency);
1773 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {
1774 unsigned numElements = constAgg->getElementCount().getFixedValue();
1775 for (
unsigned i = 0, e = numElements; i != e; ++i)
1776 adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));
1782 if (adjacencyIt->getSecond().empty()) {
1783 orderedSet.insert(current);
1784 workList.pop_back();
1792 llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();
1793 if (valueMapping.contains(dependency) || workList.contains(dependency) ||
1794 orderedSet.contains(dependency))
1796 workList.insert(dependency);
1802FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {
1803 Location loc = UnknownLoc::get(context);
1806 if (Attribute attr = getConstantAsAttr(constant)) {
1808 if (
auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {
1809 return AddressOfOp::create(builder, loc, type, symbolRef.getValue())
1812 return ConstantOp::create(builder, loc, type, attr).getResult();
1816 if (
auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {
1818 return ZeroOp::create(builder, loc, type).getResult();
1822 if (isa<llvm::ConstantTokenNone>(constant)) {
1823 return NoneTokenOp::create(builder, loc).getResult();
1827 if (
auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {
1829 return PoisonOp::create(builder, loc, type).getResult();
1833 if (
auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {
1835 return UndefOp::create(builder, loc, type).getResult();
1839 if (
auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {
1840 Type type =
convertType(dsoLocalEquivalent->getType());
1841 return DSOLocalEquivalentOp::create(
1844 builder.getContext(),
1845 dsoLocalEquivalent->getGlobalValue()->getName()))
1850 if (
auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {
1852 StringRef globalName = globalObj->getName();
1853 FlatSymbolRefAttr symbolRef;
1855 if (globalName.empty())
1857 getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));
1860 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1864 if (
auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {
1865 Type type =
convertType(globalAliasObj->getType());
1866 StringRef aliaseeName = globalAliasObj->getName();
1868 return AddressOfOp::create(builder, loc, type, symbolRef).getResult();
1872 if (
auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {
1878 llvm::Instruction *inst = constExpr->getAsInstruction();
1879 llvm::scope_exit guard([&]() {
1880 assert(!noResultOpMapping.contains(inst) &&
1881 "expected constant expression to return a result");
1882 valueMapping.erase(inst);
1883 inst->deleteValue();
1887 assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {
1888 return valueMapping.contains(value);
1890 if (
failed(processInstruction(inst)))
1896 if (
auto *aggregateZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {
1897 Type type =
convertType(aggregateZero->getType());
1898 return ZeroOp::create(builder, loc, type).getResult();
1902 if (
auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {
1904 SmallVector<Value> elementValues;
1906 elementValues.reserve(constAgg->getNumOperands());
1907 for (llvm::Value *operand : constAgg->operands())
1910 assert(llvm::count(elementValues,
nullptr) == 0 &&
1911 "expected all elements have been converted before");
1915 bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);
1917 "unrecognized aggregate type");
1918 Value root = UndefOp::create(builder, loc, rootType);
1919 for (
const auto &it : llvm::enumerate(elementValues)) {
1920 if (isArrayOrStruct) {
1922 InsertValueOp::create(builder, loc, root, it.value(), it.index());
1924 Attribute indexAttr = builder.getI32IntegerAttr(it.index());
1926 ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);
1927 root = InsertElementOp::create(builder, loc, rootType, root, it.value(),
1934 if (
auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {
1935 LLVMTargetExtType targetExtType =
1936 cast<LLVMTargetExtType>(
convertType(constTargetNone->getType()));
1937 assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&
1938 "target extension type does not support zero-initialization");
1941 return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();
1944 if (
auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {
1948 BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());
1949 return BlockAddressOp::create(
1951 BlockAddressAttr::get(context, fnSym, blockTag))
1955 StringRef error =
"";
1957 if (isa<llvm::ConstantPtrAuth>(constant))
1958 error =
" since ptrauth(...) is unsupported";
1960 if (isa<llvm::NoCFIValue>(constant))
1961 error =
" since no_cfi is unsupported";
1963 if (isa<llvm::GlobalValue>(constant))
1964 error =
" since global value is unsupported";
1966 return emitError(loc) <<
"unhandled constant: " <<
diag(*constant) << error;
1969FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {
1973 assert(!valueMapping.contains(constant) &&
1974 "expected constant has not been converted before");
1975 assert(constantInsertionBlock &&
1976 "expected the constant insertion block to be non-null");
1979 OpBuilder::InsertionGuard guard(builder);
1980 if (!constantInsertionOp)
1981 builder.setInsertionPointToStart(constantInsertionBlock);
1983 builder.setInsertionPointAfter(constantInsertionOp);
1987 getConstantsToConvert(constant);
1988 for (llvm::Constant *constantToConvert : constantsToConvert) {
1989 FailureOr<Value> converted = convertConstant(constantToConvert);
1992 mapValue(constantToConvert, *converted);
1997 constantInsertionOp =
result.getDefiningOp();
2003 auto it = valueMapping.find(value);
2004 if (it != valueMapping.end())
2005 return it->getSecond();
2012 if (
auto *mdAsVal = dyn_cast<llvm::MetadataAsValue>(value)) {
2013 llvm::Metadata *md = mdAsVal->getMetadata();
2014 Attribute mdAttr = convertMetadataToAttr(md);
2017 <<
"unsupported metadata: " <<
diagMD(md, llvmModule.get());
2019 MetadataAsValueOp::create(builder, UnknownLoc::get(context), mdAttr)
2026 if (
auto *constant = dyn_cast<llvm::Constant>(value))
2027 return convertConstantExpr(constant);
2029 Location loc = UnknownLoc::get(context);
2030 if (
auto *inst = dyn_cast<llvm::Instruction>(value))
2032 return emitError(loc) <<
"unhandled value: " <<
diag(*value);
2038 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
2041 auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
2044 value = node->getValue();
2047 auto it = valueMapping.find(value);
2048 if (it != valueMapping.end())
2049 return it->getSecond();
2052 if (
auto *constant = dyn_cast<llvm::Constant>(value))
2053 return convertConstantExpr(constant);
2057FailureOr<SmallVector<Value>>
2060 remapped.reserve(values.size());
2061 for (llvm::Value *value : values) {
2063 if (failed(converted))
2065 remapped.push_back(*converted);
2075 assert(immArgPositions.size() == immArgAttrNames.size() &&
2076 "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "
2080 for (
auto [immArgPos, immArgName] :
2081 llvm::zip(immArgPositions, immArgAttrNames)) {
2082 auto &value = operands[immArgPos];
2083 auto *constant = llvm::cast<llvm::Constant>(value);
2085 assert(attr && attr.getType().isIntOrFloat() &&
2086 "expected immarg to be float or integer constant");
2087 auto nameAttr = StringAttr::get(attr.getContext(), immArgName);
2088 attrsOut.push_back({nameAttr, attr});
2093 for (llvm::Value *value : operands) {
2097 if (failed(mlirValue))
2099 valuesOut.push_back(*mlirValue);
2104 if (requiresOpBundles) {
2105 opBundleSizes.reserve(opBundles.size());
2106 opBundleTagAttrs.reserve(opBundles.size());
2108 for (
const llvm::OperandBundleUse &bundle : opBundles) {
2109 opBundleSizes.push_back(bundle.Inputs.size());
2110 opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));
2112 for (
const llvm::Use &opBundleOperand : bundle.Inputs) {
2113 auto operandMlirValue =
convertValue(opBundleOperand.get());
2114 if (failed(operandMlirValue))
2116 valuesOut.push_back(*operandMlirValue);
2121 auto opBundleSizesAttrNameAttr =
2122 StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());
2123 attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});
2125 auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);
2126 auto opBundleTagsAttrNameAttr =
2127 StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());
2128 attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});
2135 IntegerAttr integerAttr;
2137 bool success = succeeded(converted) &&
2139 assert(
success &&
"expected a constant integer value");
2145 FloatAttr floatAttr;
2149 assert(
success &&
"expected a constant float value");
2156 llvm::DILocalVariable *node =
nullptr;
2157 if (
auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {
2158 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2159 node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());
2161 node = cast<llvm::DILocalVariable *>(valOrVariable);
2163 return debugImporter->translate(node);
2167 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2168 auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());
2169 return debugImporter->translate(node);
2172FPExceptionBehaviorAttr
2174 auto *metadata = cast<llvm::MetadataAsValue>(value);
2175 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2176 std::optional<llvm::fp::ExceptionBehavior> optLLVM =
2177 llvm::convertStrToExceptionBehavior(mdstr->getString());
2178 assert(optLLVM &&
"Expecting FP exception behavior");
2179 return builder.getAttr<FPExceptionBehaviorAttr>(
2180 convertFPExceptionBehaviorFromLLVM(*optLLVM));
2184 auto *metadata = cast<llvm::MetadataAsValue>(value);
2185 auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());
2186 std::optional<llvm::RoundingMode> optLLVM =
2187 llvm::convertStrToRoundingMode(mdstr->getString());
2188 assert(optLLVM &&
"Expecting rounding mode");
2189 return builder.getAttr<RoundingModeAttr>(
2190 convertRoundingModeFromLLVM(*optLLVM));
2193FailureOr<SmallVector<AliasScopeAttr>>
2195 auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);
2196 auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());
2201 return debugImporter->translateLoc(loc);
2205ModuleImport::convertBranchArgs(llvm::Instruction *branch,
2206 llvm::BasicBlock *
target,
2208 for (
auto inst =
target->begin(); isa<llvm::PHINode>(inst); ++inst) {
2209 auto *phiInst = cast<llvm::PHINode>(&*inst);
2210 llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());
2212 if (failed(converted))
2214 blockArguments.push_back(*converted);
2219FailureOr<SmallVector<Value>>
2220ModuleImport::convertCallOperands(llvm::CallBase *callInst,
2221 bool allowInlineAsm) {
2222 bool isInlineAsm = callInst->isInlineAsm();
2223 if (isInlineAsm && !allowInlineAsm)
2233 llvm::Value *calleeOperand = callInst->getCalledOperand();
2234 if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {
2238 operands.push_back(*called);
2241 SmallVector<llvm::Value *> args(callInst->args());
2242 FailureOr<SmallVector<Value>> arguments =
convertValues(args);
2246 llvm::append_range(operands, *arguments);
2254 LLVMFunctionType calleeType) {
2255 if (callType.getReturnType() != calleeType.getReturnType())
2258 if (calleeType.isVarArg()) {
2261 if (callType.getNumParams() < calleeType.getNumParams())
2266 if (callType.getNumParams() != calleeType.getNumParams())
2271 for (
auto [operandType, argumentType] :
2272 llvm::zip(callType.getParams(), calleeType.getParams()))
2273 if (operandType != argumentType)
2279FailureOr<LLVMFunctionType>
2280ModuleImport::convertFunctionType(llvm::CallBase *callInst,
2281 bool &isIncompatibleCall) {
2282 isIncompatibleCall =
false;
2283 auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {
2284 auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);
2290 llvm::Value *calledOperand = callInst->getCalledOperand();
2291 FailureOr<LLVMFunctionType> callType =
2292 castOrFailure(
convertType(callInst->getFunctionType()));
2295 auto *callee = dyn_cast<llvm::Function>(calledOperand);
2297 llvm::FunctionType *origCalleeType =
nullptr;
2299 origCalleeType = callee->getFunctionType();
2300 }
else if (
auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {
2301 origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());
2305 if (!origCalleeType)
2308 FailureOr<LLVMFunctionType> calleeType =
2316 isIncompatibleCall =
true;
2318 emitWarning(loc) <<
"incompatible call and callee types: " << *callType
2319 <<
" and " << *calleeType;
2326FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {
2327 llvm::Value *calledOperand = callInst->getCalledOperand();
2328 if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))
2329 return SymbolRefAttr::get(context, calledOperand->getName());
2333LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {
2334 if (succeeded(iface.convertIntrinsic(builder, inst, *
this)))
2338 return emitError(loc) <<
"unhandled intrinsic: " <<
diag(*inst);
2342ModuleImport::convertAsmInlineOperandAttrs(
const llvm::CallBase &llvmCall) {
2343 const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());
2344 unsigned argIdx = 0;
2345 SmallVector<mlir::Attribute> opAttrs;
2346 bool hasIndirect =
false;
2348 for (
const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {
2350 if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())
2355 if (ci.isIndirect) {
2356 if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {
2357 SmallVector<mlir::NamedAttribute> attrs;
2358 attrs.push_back(builder.getNamedAttr(
2359 mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),
2361 opAttrs.push_back(builder.getDictionaryAttr(attrs));
2365 opAttrs.push_back(builder.getDictionaryAttr({}));
2371 return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)
2375LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {
2378 if (
auto *brInst = dyn_cast<llvm::UncondBrInst>(inst)) {
2379 llvm::BasicBlock *succ = brInst->getSuccessor();
2380 SmallVector<Value> blockArgs;
2381 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2384 auto brOp = LLVM::BrOp::create(builder, loc, blockArgs,
lookupBlock(succ));
2388 if (
auto *brInst = dyn_cast<llvm::CondBrInst>(inst)) {
2389 SmallVector<Block *> succBlocks;
2390 SmallVector<SmallVector<Value>> succBlockArgs;
2391 for (
auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {
2392 llvm::BasicBlock *succ = brInst->getSuccessor(i);
2393 SmallVector<Value> blockArgs;
2394 if (
failed(convertBranchArgs(brInst, succ, blockArgs)))
2397 succBlockArgs.push_back(blockArgs);
2400 FailureOr<Value> condition =
convertValue(brInst->getCondition());
2403 auto condBrOp = LLVM::CondBrOp::create(
2404 builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),
2405 succBlocks.back(), succBlockArgs.back());
2409 if (inst->getOpcode() == llvm::Instruction::Switch) {
2410 auto *swInst = cast<llvm::SwitchInst>(inst);
2412 FailureOr<Value> condition =
convertValue(swInst->getCondition());
2415 SmallVector<Value> defaultBlockArgs;
2417 llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
2418 if (
failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))
2422 unsigned numCases = swInst->getNumCases();
2423 SmallVector<SmallVector<Value>> caseOperands(numCases);
2424 SmallVector<ValueRange> caseOperandRefs(numCases);
2425 SmallVector<APInt> caseValues(numCases);
2426 SmallVector<Block *> caseBlocks(numCases);
2427 for (
const auto &it : llvm::enumerate(swInst->cases())) {
2428 const llvm::SwitchInst::CaseHandle &caseHandle = it.value();
2429 llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
2430 if (
failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))
2432 caseOperandRefs[it.index()] = caseOperands[it.index()];
2433 caseValues[it.index()] = caseHandle.getCaseValue()->getValue();
2437 auto switchOp = SwitchOp::create(builder, loc, *condition,
2439 caseValues, caseBlocks, caseOperandRefs);
2443 if (inst->getOpcode() == llvm::Instruction::PHI) {
2445 mapValue(inst, builder.getInsertionBlock()->addArgument(
2449 if (inst->getOpcode() == llvm::Instruction::Call) {
2450 auto *callInst = cast<llvm::CallInst>(inst);
2451 llvm::Value *calledOperand = callInst->getCalledOperand();
2453 FailureOr<SmallVector<Value>> operands =
2454 convertCallOperands(callInst,
true);
2458 auto callOp = [&]() -> FailureOr<Operation *> {
2459 if (
auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {
2463 ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);
2464 return InlineAsmOp::create(
2465 builder, loc, resultTy, *operands,
2466 builder.getStringAttr(asmI->getAsmString()),
2467 builder.getStringAttr(asmI->getConstraintString()),
2468 asmI->hasSideEffects(), asmI->isAlignStack(),
2469 convertTailCallKindFromLLVM(callInst->getTailCallKind()),
2470 AsmDialectAttr::get(
2471 mlirModule.getContext(),
2472 convertAsmDialectFromLLVM(asmI->getDialect())),
2476 bool isIncompatibleCall;
2477 FailureOr<LLVMFunctionType> funcTy =
2478 convertFunctionType(callInst, isIncompatibleCall);
2482 FlatSymbolRefAttr callee =
nullptr;
2483 if (isIncompatibleCall) {
2487 FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);
2488 Value indirectCallVal = LLVM::AddressOfOp::create(
2489 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2490 operands->insert(operands->begin(), indirectCallVal);
2493 callee = convertCalleeName(callInst);
2495 CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);
2497 if (
failed(convertCallAttributes(callInst, callOp)))
2502 if (!isIncompatibleCall)
2504 return callOp.getOperation();
2510 if (!callInst->getType()->isVoidTy())
2511 mapValue(inst, (*callOp)->getResult(0));
2516 if (inst->getOpcode() == llvm::Instruction::LandingPad) {
2517 auto *lpInst = cast<llvm::LandingPadInst>(inst);
2519 SmallVector<Value> operands;
2520 operands.reserve(lpInst->getNumClauses());
2521 for (
auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {
2522 FailureOr<Value> operand =
convertValue(lpInst->getClause(i));
2525 operands.push_back(*operand);
2530 LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);
2534 if (inst->getOpcode() == llvm::Instruction::Invoke) {
2535 auto *invokeInst = cast<llvm::InvokeInst>(inst);
2537 if (invokeInst->isInlineAsm())
2538 return emitError(loc) <<
"invoke of inline assembly is not supported";
2540 FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);
2546 bool invokeResultUsedInPhi = llvm::any_of(
2547 invokeInst->getNormalDest()->phis(), [&](
const llvm::PHINode &phi) {
2548 return phi.getIncomingValueForBlock(invokeInst->getParent()) ==
2553 Block *directNormalDest = normalDest;
2554 if (invokeResultUsedInPhi) {
2559 OpBuilder::InsertionGuard g(builder);
2560 directNormalDest = builder.createBlock(normalDest);
2563 SmallVector<Value> unwindArgs;
2564 if (
failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),
2568 bool isIncompatibleInvoke;
2569 FailureOr<LLVMFunctionType> funcTy =
2570 convertFunctionType(invokeInst, isIncompatibleInvoke);
2574 FlatSymbolRefAttr calleeName =
nullptr;
2575 if (isIncompatibleInvoke) {
2579 FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);
2580 Value indirectInvokeVal = LLVM::AddressOfOp::create(
2581 builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);
2582 operands->insert(operands->begin(), indirectInvokeVal);
2585 calleeName = convertCalleeName(invokeInst);
2590 auto invokeOp = InvokeOp::create(
2591 builder, loc, *funcTy, calleeName, *operands, directNormalDest,
2594 if (
failed(convertInvokeAttributes(invokeInst, invokeOp)))
2599 if (!isIncompatibleInvoke)
2602 if (!invokeInst->getType()->isVoidTy())
2603 mapValue(inst, invokeOp.getResults().front());
2607 SmallVector<Value> normalArgs;
2608 if (
failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),
2612 if (invokeResultUsedInPhi) {
2616 OpBuilder::InsertionGuard g(builder);
2617 builder.setInsertionPointToStart(directNormalDest);
2618 LLVM::BrOp::create(builder, loc, normalArgs, normalDest);
2622 assert(llvm::none_of(
2624 [&](Value val) {
return val.
getDefiningOp() == invokeOp; }) &&
2625 "An llvm.invoke operation cannot pass its result as a block "
2627 invokeOp.getNormalDestOperandsMutable().append(normalArgs);
2632 if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {
2633 auto *gepInst = cast<llvm::GetElementPtrInst>(inst);
2634 Type sourceElementType =
convertType(gepInst->getSourceElementType());
2635 FailureOr<Value> basePtr =
convertValue(gepInst->getOperand(0));
2644 for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {
2652 auto gepOp = GEPOp::create(
2653 builder, loc, type, sourceElementType, *basePtr,
indices,
2654 static_cast<GEPNoWrapFlags
>(gepInst->getNoWrapFlags().getRaw()));
2659 if (inst->getOpcode() == llvm::Instruction::IndirectBr) {
2660 auto *indBrInst = cast<llvm::IndirectBrInst>(inst);
2662 FailureOr<Value> basePtr =
convertValue(indBrInst->getAddress());
2666 SmallVector<Block *> succBlocks;
2667 SmallVector<SmallVector<Value>> succBlockArgs;
2668 for (
auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {
2669 llvm::BasicBlock *succ = indBrInst->getSuccessor(i);
2670 SmallVector<Value> blockArgs;
2671 if (
failed(convertBranchArgs(indBrInst, succ, blockArgs)))
2674 succBlockArgs.push_back(blockArgs);
2676 SmallVector<ValueRange> succBlockArgsRange =
2677 llvm::to_vector_of<ValueRange>(succBlockArgs);
2679 auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,
2680 succBlockArgsRange, succBlocks);
2690 return emitError(loc) <<
"unhandled instruction: " <<
diag(*inst);
2693LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {
2700 if (
auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))
2701 return convertIntrinsic(intrinsic);
2706 if (inst->DebugMarker) {
2707 for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {
2709 if (
auto *dbgVariableRecord =
2710 dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {
2715 auto emitUnsupportedWarning = [&]() -> LogicalResult {
2716 if (!emitExpensiveWarnings)
2719 llvm::raw_string_ostream optionsStream(
options);
2720 dbgRecord.print(optionsStream);
2721 emitWarning(loc) <<
"unhandled debug record " << optionsStream.str();
2725 if (
auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {
2726 DILabelAttr labelAttr =
2727 debugImporter->translate(dbgLabelRecord->getLabel());
2729 return emitUnsupportedWarning();
2730 LLVM::DbgLabelOp::create(builder, loc, labelAttr);
2734 return emitUnsupportedWarning();
2739 return convertInstruction(inst);
2742FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {
2743 if (!f->hasPersonalityFn())
2746 llvm::Constant *pf = f->getPersonalityFn();
2750 return SymbolRefAttr::get(builder.getContext(), pf->getName());
2754 if (
auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
2755 if (ce->getOpcode() == llvm::Instruction::BitCast &&
2756 ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {
2757 if (
auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
2758 return SymbolRefAttr::get(builder.getContext(), func->getName());
2761 return FlatSymbolRefAttr();
2765 llvm::MemoryEffects memEffects =
func->getMemoryEffects();
2767 auto othermem = convertModRefInfoFromLLVM(
2768 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
2769 auto argMem = convertModRefInfoFromLLVM(
2770 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
2771 auto inaccessibleMem = convertModRefInfoFromLLVM(
2772 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
2773 auto errnoMem = convertModRefInfoFromLLVM(
2774 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
2775 auto targetMem0 = convertModRefInfoFromLLVM(
2776 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
2777 auto targetMem1 = convertModRefInfoFromLLVM(
2778 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
2780 MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,
2781 inaccessibleMem, errnoMem, targetMem0, targetMem1);
2783 if (memAttr.isReadWrite())
2785 funcOp.setMemoryEffectsAttr(memAttr);
2789 llvm::DenormalFPEnv denormalFpEnv =
func->getDenormalFPEnv();
2791 if (denormalFpEnv == llvm::DenormalFPEnv::getDefault())
2794 llvm::DenormalMode defaultMode = denormalFpEnv.DefaultMode;
2795 llvm::DenormalMode floatMode = denormalFpEnv.F32Mode;
2797 auto denormalFpEnvAttr = DenormalFPEnvAttr::get(
2798 funcOp.getContext(), convertDenormalModeKindFromLLVM(defaultMode.Output),
2799 convertDenormalModeKindFromLLVM(defaultMode.Input),
2800 convertDenormalModeKindFromLLVM(floatMode.Output),
2801 convertDenormalModeKindFromLLVM(floatMode.Input));
2802 funcOp.setDenormalFpenvAttr(denormalFpEnvAttr);
2808 StringLiteral(
"aarch64_in_za"),
2809 StringLiteral(
"aarch64_inout_za"),
2810 StringLiteral(
"aarch64_new_za"),
2811 StringLiteral(
"aarch64_out_za"),
2812 StringLiteral(
"aarch64_preserves_za"),
2813 StringLiteral(
"aarch64_pstate_sm_body"),
2814 StringLiteral(
"aarch64_pstate_sm_compatible"),
2815 StringLiteral(
"aarch64_pstate_sm_enabled"),
2816 StringLiteral(
"allocsize"),
2817 StringLiteral(
"alwaysinline"),
2818 StringLiteral(
"cold"),
2819 StringLiteral(
"convergent"),
2820 StringLiteral(
"fp-contract"),
2821 StringLiteral(
"frame-pointer"),
2822 StringLiteral(
"hot"),
2823 StringLiteral(
"inlinehint"),
2824 StringLiteral(
"instrument-function-entry"),
2825 StringLiteral(
"instrument-function-exit"),
2826 StringLiteral(
"modular-format"),
2827 StringLiteral(
"memory"),
2828 StringLiteral(
"minsize"),
2829 StringLiteral(
"no_caller_saved_registers"),
2830 StringLiteral(
"no-signed-zeros-fp-math"),
2831 StringLiteral(
"no-builtins"),
2832 StringLiteral(
"nocallback"),
2833 StringLiteral(
"noduplicate"),
2834 StringLiteral(
"noinline"),
2835 StringLiteral(
"noreturn"),
2836 StringLiteral(
"nounwind"),
2837 StringLiteral(
"optnone"),
2838 StringLiteral(
"optsize"),
2839 StringLiteral(
"returns_twice"),
2840 StringLiteral(
"save-reg-params"),
2841 StringLiteral(
"target-features"),
2842 StringLiteral(
"trap-func-name"),
2843 StringLiteral(
"tune-cpu"),
2844 StringLiteral(
"uwtable"),
2845 StringLiteral(
"vscale_range"),
2846 StringLiteral(
"willreturn"),
2847 StringLiteral(
"zero-call-used-regs"),
2848 StringLiteral(
"denormal_fpenv"),
2854 StringLiteral(
"no-builtin-"),
2857template <
typename OpTy>
2859 const llvm::AttributeSet &attrs,
2862 if (attrs.hasAttribute(
"no-builtins")) {
2863 target.setNobuiltinsAttr(ArrayAttr::get(ctx, {}));
2868 for (llvm::Attribute attr : attrs) {
2871 if (attr.hasKindAsEnum())
2874 StringRef val = attr.getKindAsString();
2876 if (val.starts_with(
"no-builtin-"))
2878 StringAttr::get(ctx, val.drop_front(
sizeof(
"no-builtin-") - 1)));
2881 if (!nbAttrs.empty())
2882 target.setNobuiltinsAttr(ArrayAttr::get(ctx, nbAttrs.getArrayRef()));
2885template <
typename OpTy>
2887 const llvm::AttributeSet &attrs, OpTy
target) {
2888 llvm::Attribute attr = attrs.getAttribute(llvm::Attribute::AllocSize);
2889 if (!attr.isValid())
2892 auto [elemSize, numElems] = attr.getAllocSizeArgs();
2896 static_cast<int32_t
>(*numElems)}));
2907 llvm::AttributeSet funcAttrs =
func->getAttributes().getAttributes(
2908 llvm::AttributeList::AttrIndex::FunctionIndex);
2910 funcOp.getLoc(), funcOp.getContext(), funcAttrs,
2912 if (!passthroughAttr.empty())
2913 funcOp.setPassthroughAttr(passthroughAttr);
2917 LLVMFuncOp funcOp) {
2922 if (
func->hasFnAttribute(llvm::Attribute::NoInline))
2923 funcOp.setNoInline(
true);
2924 if (
func->hasFnAttribute(llvm::Attribute::AlwaysInline))
2925 funcOp.setAlwaysInline(
true);
2926 if (
func->hasFnAttribute(llvm::Attribute::InlineHint))
2927 funcOp.setInlineHint(
true);
2928 if (
func->hasFnAttribute(llvm::Attribute::OptimizeNone))
2929 funcOp.setOptimizeNone(
true);
2930 if (
func->hasFnAttribute(llvm::Attribute::Convergent))
2931 funcOp.setConvergent(
true);
2932 if (
func->hasFnAttribute(llvm::Attribute::NoUnwind))
2933 funcOp.setNoUnwind(
true);
2934 if (
func->hasFnAttribute(llvm::Attribute::WillReturn))
2935 funcOp.setWillReturn(
true);
2936 if (
func->hasFnAttribute(llvm::Attribute::NoReturn))
2937 funcOp.setNoreturn(
true);
2938 if (
func->hasFnAttribute(llvm::Attribute::OptimizeForSize))
2939 funcOp.setOptsize(
true);
2940 if (
func->hasFnAttribute(
"save-reg-params"))
2941 funcOp.setSaveRegParams(
true);
2942 if (
func->hasFnAttribute(llvm::Attribute::MinSize))
2943 funcOp.setMinsize(
true);
2944 if (
func->hasFnAttribute(llvm::Attribute::ReturnsTwice))
2945 funcOp.setReturnsTwice(
true);
2946 if (
func->hasFnAttribute(llvm::Attribute::Cold))
2947 funcOp.setCold(
true);
2948 if (
func->hasFnAttribute(llvm::Attribute::Hot))
2949 funcOp.setHot(
true);
2950 if (
func->hasFnAttribute(llvm::Attribute::NoDuplicate))
2951 funcOp.setNoduplicate(
true);
2952 if (
func->hasFnAttribute(
"no_caller_saved_registers"))
2953 funcOp.setNoCallerSavedRegisters(
true);
2954 if (
func->hasFnAttribute(llvm::Attribute::NoCallback))
2955 funcOp.setNocallback(
true);
2956 if (llvm::Attribute attr =
func->getFnAttribute(
"modular-format");
2957 attr.isStringAttribute())
2958 funcOp.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
2959 if (llvm::Attribute attr =
func->getFnAttribute(
"zero-call-used-regs");
2960 attr.isStringAttribute())
2961 funcOp.setZeroCallUsedRegsAttr(
2962 StringAttr::get(context, attr.getValueAsString()));
2964 if (
func->hasFnAttribute(
"aarch64_pstate_sm_enabled"))
2965 funcOp.setArmStreaming(
true);
2966 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_body"))
2967 funcOp.setArmLocallyStreaming(
true);
2968 else if (
func->hasFnAttribute(
"aarch64_pstate_sm_compatible"))
2969 funcOp.setArmStreamingCompatible(
true);
2971 if (
func->hasFnAttribute(
"aarch64_new_za"))
2972 funcOp.setArmNewZa(
true);
2973 else if (
func->hasFnAttribute(
"aarch64_in_za"))
2974 funcOp.setArmInZa(
true);
2975 else if (
func->hasFnAttribute(
"aarch64_out_za"))
2976 funcOp.setArmOutZa(
true);
2977 else if (
func->hasFnAttribute(
"aarch64_inout_za"))
2978 funcOp.setArmInoutZa(
true);
2979 else if (
func->hasFnAttribute(
"aarch64_preserves_za"))
2980 funcOp.setArmPreservesZa(
true);
2985 llvm::Attribute attr =
func->getFnAttribute(llvm::Attribute::VScaleRange);
2986 if (attr.isValid()) {
2988 auto intTy = IntegerType::get(context, 32);
2989 funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(
2990 context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),
2991 IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));
2995 if (
func->hasFnAttribute(
"frame-pointer")) {
2996 StringRef stringRefFramePointerKind =
2997 func->getFnAttribute(
"frame-pointer").getValueAsString();
2998 funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(
2999 funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(
3000 stringRefFramePointerKind)
3004 if (
func->hasFnAttribute(
"use-sample-profile"))
3005 funcOp.setUseSampleProfile(
true);
3007 if (llvm::Attribute attr =
func->getFnAttribute(
"target-cpu");
3008 attr.isStringAttribute())
3009 funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3011 if (llvm::Attribute attr =
func->getFnAttribute(
"tune-cpu");
3012 attr.isStringAttribute())
3013 funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));
3015 if (llvm::Attribute attr =
func->getFnAttribute(
"target-features");
3016 attr.isStringAttribute())
3017 funcOp.setTargetFeaturesAttr(
3018 LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
3020 if (llvm::Attribute attr =
func->getFnAttribute(
"reciprocal-estimates");
3021 attr.isStringAttribute())
3022 funcOp.setReciprocalEstimatesAttr(
3023 StringAttr::get(context, attr.getValueAsString()));
3025 if (llvm::Attribute attr =
func->getFnAttribute(
"prefer-vector-width");
3026 attr.isStringAttribute())
3027 funcOp.setPreferVectorWidth(attr.getValueAsString());
3029 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-entry");
3030 attr.isStringAttribute())
3031 funcOp.setInstrumentFunctionEntry(
3032 StringAttr::get(context, attr.getValueAsString()));
3034 if (llvm::Attribute attr =
func->getFnAttribute(
"instrument-function-exit");
3035 attr.isStringAttribute())
3036 funcOp.setInstrumentFunctionExit(
3037 StringAttr::get(context, attr.getValueAsString()));
3039 if (llvm::Attribute attr =
func->getFnAttribute(
"no-signed-zeros-fp-math");
3040 attr.isStringAttribute())
3041 funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());
3043 if (llvm::Attribute attr =
func->getFnAttribute(
"fp-contract");
3044 attr.isStringAttribute())
3045 funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));
3047 if (
func->hasUWTable()) {
3048 ::llvm::UWTableKind uwtableKind =
func->getUWTableKind();
3049 funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(
3050 funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));
3055ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {
3058 auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);
3060 if (!llvmAttr.isValid())
3065 if (llvmAttr.hasKindAsEnum() &&
3066 llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {
3067 if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))
3068 paramAttrs.push_back(
3074 if (llvmAttr.isTypeAttribute())
3075 mlirAttr = TypeAttr::get(
convertType(llvmAttr.getValueAsType()));
3076 else if (llvmAttr.isIntAttribute())
3078 else if (llvmAttr.isEnumAttribute())
3080 else if (llvmAttr.isConstantRangeAttribute()) {
3081 const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();
3082 mlirAttr = builder.
getAttr<LLVM::ConstantRangeAttr>(value.getLower(),
3085 llvm_unreachable(
"unexpected parameter attribute kind");
3087 paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));
3090 return builder.getDictionaryAttr(paramAttrs);
3094 LLVMFuncOp funcOp) {
3095 auto llvmAttrs = func->getAttributes();
3096 for (
size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {
3097 llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);
3098 funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));
3102 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3103 if (!llvmResAttr.hasAttributes())
3105 funcOp.setResAttrsAttr(
3106 builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));
3110 llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,
3113 llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),
3114 immArgPositions.end());
3116 llvm::AttributeList llvmAttrs = call->getAttributes();
3118 bool anyArgAttrs =
false;
3119 for (
size_t i = 0, e = call->arg_size(); i < e; ++i) {
3121 if (immArgPositionsSet.contains(i))
3123 llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));
3124 if (llvmArgAttrsSet.back().hasAttributes())
3129 for (
auto &dict : dictAttrs)
3130 attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));
3131 return builder.getArrayAttr(attrs);
3135 for (
auto &llvmArgAttrs : llvmArgAttrsSet)
3136 argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));
3137 attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));
3141 llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();
3142 if (!llvmResAttr.hasAttributes())
3144 DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);
3145 attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));
3148template <
typename Op>
3150 op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));
3154LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,
3159LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,
3165 llvm::AttributeList callAttrs = inst->getAttributes();
3167 op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));
3168 op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());
3169 op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());
3170 op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());
3171 op.setNoreturn(callAttrs.getFnAttr(llvm::Attribute::NoReturn).isValid());
3173 callAttrs.getFnAttr(llvm::Attribute::OptimizeForSize).isValid());
3174 op.setSaveRegParams(callAttrs.getFnAttr(
"save-reg-params").isValid());
3175 op.setBuiltin(callAttrs.getFnAttr(llvm::Attribute::Builtin).isValid());
3176 op.setNobuiltin(callAttrs.getFnAttr(llvm::Attribute::NoBuiltin).isValid());
3177 op.setMinsize(callAttrs.getFnAttr(llvm::Attribute::MinSize).isValid());
3180 callAttrs.getFnAttr(llvm::Attribute::ReturnsTwice).isValid());
3181 op.setHot(callAttrs.getFnAttr(llvm::Attribute::Hot).isValid());
3182 op.setCold(callAttrs.getFnAttr(llvm::Attribute::Cold).isValid());
3184 callAttrs.getFnAttr(llvm::Attribute::NoDuplicate).isValid());
3185 op.setNoCallerSavedRegisters(
3186 callAttrs.getFnAttr(
"no_caller_saved_registers").isValid());
3187 op.setNocallback(callAttrs.getFnAttr(llvm::Attribute::NoCallback).isValid());
3189 if (llvm::Attribute attr = callAttrs.getFnAttr(
"modular-format");
3190 attr.isStringAttribute())
3191 op.setModularFormat(StringAttr::get(context, attr.getValueAsString()));
3192 if (llvm::Attribute attr = callAttrs.getFnAttr(
"zero-call-used-regs");
3193 attr.isStringAttribute())
3194 op.setZeroCallUsedRegsAttr(
3195 StringAttr::get(context, attr.getValueAsString()));
3196 if (llvm::Attribute attr = callAttrs.getFnAttr(
"trap-func-name");
3197 attr.isStringAttribute())
3198 op.setTrapFuncNameAttr(StringAttr::get(context, attr.getValueAsString()));
3199 op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());
3201 callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());
3202 op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());
3204 llvm::MemoryEffects memEffects = inst->getMemoryEffects();
3205 ModRefInfo othermem = convertModRefInfoFromLLVM(
3206 memEffects.getModRef(llvm::MemoryEffects::Location::Other));
3207 ModRefInfo argMem = convertModRefInfoFromLLVM(
3208 memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));
3209 ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(
3210 memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));
3211 ModRefInfo errnoMem = convertModRefInfoFromLLVM(
3212 memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));
3213 ModRefInfo targetMem0 = convertModRefInfoFromLLVM(
3214 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));
3215 ModRefInfo targetMem1 = convertModRefInfoFromLLVM(
3216 memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));
3218 MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,
3219 errnoMem, targetMem0, targetMem1);
3221 if (!memAttr.isReadWrite())
3222 op.setMemoryEffectsAttr(memAttr);
3235 if (
func->isIntrinsic() &&
3236 iface.isConvertibleIntrinsic(
func->getIntrinsicID()))
3239 bool dsoLocal =
func->isDSOLocal();
3240 CConv cconv = convertCConvFromLLVM(
func->getCallingConv());
3244 builder.setInsertionPointToEnd(mlirModule.getBody());
3246 Location loc = debugImporter->translateFuncLocation(
func);
3247 LLVMFuncOp funcOp = LLVMFuncOp::create(
3248 builder, loc,
func->getName(), functionType,
3249 convertLinkageFromLLVM(
func->getLinkage()), dsoLocal, cconv);
3254 funcOp.setPersonalityAttr(personality);
3255 else if (
func->hasPersonalityFn())
3256 emitWarning(funcOp.getLoc(),
"could not deduce personality, skipping it");
3259 funcOp.setGarbageCollector(StringRef(
func->getGC()));
3261 if (
func->hasAtLeastLocalUnnamedAddr())
3262 funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(
func->getUnnamedAddr()));
3264 if (
func->hasSection())
3265 funcOp.setSection(StringRef(
func->getSection()));
3267 funcOp.setVisibility_(convertVisibilityFromLLVM(
func->getVisibility()));
3269 if (
func->hasComdat())
3270 funcOp.setComdatAttr(comdatMapping.lookup(
func->getComdat()));
3272 if (llvm::MaybeAlign maybeAlign =
func->getAlign())
3273 funcOp.setAlignment(maybeAlign->value());
3280 func->getAllMetadata(allMetadata);
3281 for (
auto &[kind, node] : allMetadata) {
3282 if (!iface.isConvertibleMetadata(kind))
3284 if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *
this))) {
3286 <<
"unhandled function metadata: " <<
diagMD(node, llvmModule.get())
3291 if (
func->isDeclaration())
3300 llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;
3301 for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(
func, reachable))
3306 for (llvm::BasicBlock &basicBlock : *
func) {
3308 if (!reachable.contains(&basicBlock)) {
3309 if (basicBlock.hasAddressTaken())
3311 <<
"unreachable block '" << basicBlock.getName()
3312 <<
"' with address taken";
3315 Region &body = funcOp.getBody();
3316 Block *block = builder.createBlock(&body, body.
end());
3318 reachableBasicBlocks.push_back(&basicBlock);
3322 for (
const auto &it : llvm::enumerate(
func->args())) {
3323 BlockArgument blockArg = funcOp.getFunctionBody().addArgument(
3324 functionType.getParamType(it.index()), funcOp.getLoc());
3333 setConstantInsertionPointToStart(
lookupBlock(blocks.front()));
3334 for (llvm::BasicBlock *basicBlock : blocks)
3335 if (failed(processBasicBlock(basicBlock,
lookupBlock(basicBlock))))
3340 if (failed(processDebugIntrinsics()))
3345 if (failed(processDebugRecords()))
3354 if (!dbgIntr->isKillLocation())
3356 llvm::Value *value = dbgIntr->getArgOperand(0);
3357 auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);
3360 return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());
3372 auto dominatedBlocks = domInfo.
getNode(op->getBlock())->children();
3375 if (dominatedBlocks.empty())
3379 Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();
3382 Value insertPt = argOperand;
3383 if (
auto blockArg = dyn_cast<BlockArgument>(argOperand)) {
3389 if (!insertionBlock->
empty() &&
3390 isa<LandingpadOp>(insertionBlock->
front()))
3391 insertPt = cast<LandingpadOp>(insertionBlock->
front()).getRes();
3399std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>
3400ModuleImport::processDebugOpArgumentsAndInsertionPt(
3402 llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,
3403 llvm::Value *address,
3404 llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,
3405 llvm::DIExpression *expression, DominanceInfo &domInfo) {
3411 FailureOr<Value> argOperand = convertArgOperandToValue();
3412 if (
failed(argOperand)) {
3413 emitError(loc) <<
"failed to convert a debug operand: " <<
diag(*address);
3421 return {localVarAttr, debugImporter->translateExpression(expression),
3426ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,
3427 DominanceInfo &domInfo) {
3429 auto emitUnsupportedWarning = [&]() {
3430 if (emitExpensiveWarnings)
3435 OpBuilder::InsertionGuard guard(builder);
3436 auto convertArgOperandToValue = [&]() {
3442 if (dbgIntr->hasArgList())
3443 return emitUnsupportedWarning();
3450 return emitUnsupportedWarning();
3452 auto [localVariableAttr, locationExprAttr, locVal] =
3453 processDebugOpArgumentsAndInsertionPt(
3454 loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),
3455 dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);
3457 if (!localVariableAttr)
3458 return emitUnsupportedWarning();
3463 Operation *op =
nullptr;
3464 if (isa<llvm::DbgDeclareInst>(dbgIntr))
3465 op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3467 else if (isa<llvm::DbgValueInst>(dbgIntr))
3468 op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3471 return emitUnsupportedWarning();
3474 setNonDebugMetadataAttrs(dbgIntr, op);
3479ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,
3480 DominanceInfo &domInfo) {
3481 OpBuilder::InsertionGuard guard(builder);
3483 auto emitUnsupportedWarning = [&]() -> LogicalResult {
3484 if (!emitExpensiveWarnings)
3487 llvm::raw_string_ostream optionsStream(
options);
3488 dbgRecord.print(optionsStream);
3489 emitWarning(loc) <<
"unhandled debug variable record "
3490 << optionsStream.str();
3496 if (dbgRecord.hasArgList())
3497 return emitUnsupportedWarning();
3502 if (!dbgRecord.getAddress())
3503 return emitUnsupportedWarning();
3505 auto convertArgOperandToValue = [&]() -> FailureOr<Value> {
3506 llvm::Value *value = dbgRecord.getAddress();
3509 auto it = valueMapping.find(value);
3510 if (it != valueMapping.end())
3511 return it->getSecond();
3514 if (
auto *constant = dyn_cast<llvm::Constant>(value))
3515 return convertConstantExpr(constant);
3519 auto [localVariableAttr, locationExprAttr, locVal] =
3520 processDebugOpArgumentsAndInsertionPt(
3521 loc, convertArgOperandToValue, dbgRecord.getAddress(),
3522 dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);
3524 if (!localVariableAttr)
3525 return emitUnsupportedWarning();
3530 if (dbgRecord.isDbgDeclare())
3531 LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,
3533 else if (dbgRecord.isDbgValue())
3534 LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,
3537 return emitUnsupportedWarning();
3542LogicalResult ModuleImport::processDebugIntrinsics() {
3543 DominanceInfo domInfo;
3544 for (llvm::Instruction *inst : debugIntrinsics) {
3545 auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);
3546 if (
failed(processDebugIntrinsic(intrCall, domInfo)))
3552LogicalResult ModuleImport::processDebugRecords() {
3553 DominanceInfo domInfo;
3554 for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)
3555 if (
failed(processDebugRecord(*dbgRecord, domInfo)))
3561LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,
3563 builder.setInsertionPointToStart(block);
3564 for (llvm::Instruction &inst : *bb) {
3565 if (
failed(processInstruction(&inst)))
3570 if (debugIntrinsics.contains(&inst))
3577 setNonDebugMetadataAttrs(&inst, op);
3578 }
else if (inst.getOpcode() != llvm::Instruction::PHI) {
3579 if (emitExpensiveWarnings) {
3580 Location loc = debugImporter->translateLoc(inst.getDebugLoc());
3586 if (bb->hasAddressTaken()) {
3587 OpBuilder::InsertionGuard guard(builder);
3588 builder.setInsertionPointToStart(block);
3590 BlockTagAttr::get(context, bb->getNumber()));
3595FailureOr<SmallVector<AccessGroupAttr>>
3597 return loopAnnotationImporter->lookupAccessGroupAttrs(node);
3603 return loopAnnotationImporter->translateLoopAnnotation(node, loc);
3606FailureOr<DereferenceableAttr>
3609 Location loc = mlirModule.getLoc();
3613 if (node->getNumOperands() != 1)
3614 return emitError(loc) <<
"dereferenceable metadata must have one operand: "
3615 <<
diagMD(node, llvmModule.get());
3617 auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));
3618 auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());
3619 if (!numBytesCst || !numBytesCst->getValue().isNonNegative())
3620 return emitError(loc) <<
"dereferenceable metadata operand must be a "
3621 "non-negative constant integer: "
3622 <<
diagMD(node, llvmModule.get());
3624 bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;
3625 auto derefAttr = builder.getAttr<DereferenceableAttr>(
3626 numBytesCst->getZExtValue(), mayBeNull);
3632 std::unique_ptr<llvm::Module> llvmModule,
MLIRContext *context,
3633 bool emitExpensiveWarnings,
bool dropDICompositeTypeElements,
3634 bool loadAllDialects,
bool preferUnregisteredIntrinsics,
3635 bool importStructsAsLiterals) {
3642 LLVMDialect::getDialectNamespace()));
3644 DLTIDialect::getDialectNamespace()));
3645 if (loadAllDialects)
3648 StringAttr::get(context, llvmModule->getSourceFileName()), 0,
3652 emitExpensiveWarnings, dropDICompositeTypeElements,
3653 preferUnregisteredIntrinsics,
3654 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.
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.