19dbf3625STobias Gysi //===- ModuleImport.cpp - LLVM to MLIR conversion ---------------*- C++ -*-===// 29dbf3625STobias Gysi // 39dbf3625STobias Gysi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49dbf3625STobias Gysi // See https://llvm.org/LICENSE.txt for license information. 59dbf3625STobias Gysi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69dbf3625STobias Gysi // 79dbf3625STobias Gysi //===----------------------------------------------------------------------===// 89dbf3625STobias Gysi // 99dbf3625STobias Gysi // This file implements the import of an LLVM IR module into an LLVM dialect 109dbf3625STobias Gysi // module. 119dbf3625STobias Gysi // 129dbf3625STobias Gysi //===----------------------------------------------------------------------===// 139dbf3625STobias Gysi 149dbf3625STobias Gysi #include "mlir/Target/LLVMIR/ModuleImport.h" 15fbee8d5aSIvan R. Ivanov #include "mlir/IR/BuiltinAttributes.h" 169dbf3625STobias Gysi #include "mlir/Target/LLVMIR/Import.h" 179dbf3625STobias Gysi 1852120584SChristian Ulmann #include "AttrKindDetail.h" 199d2b84efSTobias Gysi #include "DataLayoutImporter.h" 209dbf3625STobias Gysi #include "DebugImporter.h" 21b83caa32SChristian Ulmann #include "LoopAnnotationImporter.h" 229dbf3625STobias Gysi 239dbf3625STobias Gysi #include "mlir/Dialect/DLTI/DLTI.h" 249dbf3625STobias Gysi #include "mlir/Dialect/LLVMIR/LLVMDialect.h" 25382eb7c2SJan Sjodin #include "mlir/IR/Builders.h" 269dbf3625STobias Gysi #include "mlir/IR/Matchers.h" 279dbf3625STobias Gysi #include "mlir/Interfaces/DataLayoutInterfaces.h" 289dbf3625STobias Gysi #include "mlir/Tools/mlir-translate/Translation.h" 299dbf3625STobias Gysi 309dd0eb9cSTobias Gysi #include "llvm/ADT/DepthFirstIterator.h" 319dbf3625STobias Gysi #include "llvm/ADT/PostOrderIterator.h" 329dbf3625STobias Gysi #include "llvm/ADT/ScopeExit.h" 339dbf3625STobias Gysi #include "llvm/ADT/StringSet.h" 34b808648aSChristian Ulmann #include "llvm/ADT/TypeSwitch.h" 359d4c1be8SDavid Truby #include "llvm/IR/Comdat.h" 369dbf3625STobias Gysi #include "llvm/IR/Constants.h" 379dbf3625STobias Gysi #include "llvm/IR/InlineAsm.h" 382f66c891SSlava Zakharin #include "llvm/IR/InstIterator.h" 399dbf3625STobias Gysi #include "llvm/IR/Instructions.h" 409dbf3625STobias Gysi #include "llvm/IR/IntrinsicInst.h" 410cf06639STobias Gysi #include "llvm/IR/Metadata.h" 429dbf3625STobias Gysi #include "llvm/IR/Operator.h" 439b9cfe77SChristian Ulmann #include "llvm/Support/ModRef.h" 449dbf3625STobias Gysi 459dbf3625STobias Gysi using namespace mlir; 469dbf3625STobias Gysi using namespace mlir::LLVM; 479dbf3625STobias Gysi using namespace mlir::LLVM::detail; 489dbf3625STobias Gysi 499dbf3625STobias Gysi #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc" 509dbf3625STobias Gysi 519dbf3625STobias Gysi // Utility to print an LLVM value as a string for passing to emitError(). 529dbf3625STobias Gysi // FIXME: Diagnostic should be able to natively handle types that have 539dbf3625STobias Gysi // operator << (raw_ostream&) defined. 542f66c891SSlava Zakharin static std::string diag(const llvm::Value &value) { 559dbf3625STobias Gysi std::string str; 569dbf3625STobias Gysi llvm::raw_string_ostream os(str); 579dbf3625STobias Gysi os << value; 58095b41c6SJOE1994 return str; 599dbf3625STobias Gysi } 609dbf3625STobias Gysi 612f66c891SSlava Zakharin // Utility to print an LLVM metadata node as a string for passing 622f66c891SSlava Zakharin // to emitError(). The module argument is needed to print the nodes 632f66c891SSlava Zakharin // canonically numbered. 642f66c891SSlava Zakharin static std::string diagMD(const llvm::Metadata *node, 652f66c891SSlava Zakharin const llvm::Module *module) { 662f66c891SSlava Zakharin std::string str; 672f66c891SSlava Zakharin llvm::raw_string_ostream os(str); 682f66c891SSlava Zakharin node->print(os, module, /*IsForDebug=*/true); 69095b41c6SJOE1994 return str; 702f66c891SSlava Zakharin } 712f66c891SSlava Zakharin 729b76a302SChristian Ulmann /// Returns the name of the global_ctors global variables. 739b76a302SChristian Ulmann static constexpr StringRef getGlobalCtorsVarName() { 749b76a302SChristian Ulmann return "llvm.global_ctors"; 759b76a302SChristian Ulmann } 769b76a302SChristian Ulmann 77fbee8d5aSIvan R. Ivanov /// Prefix used for symbols of nameless llvm globals. 78fbee8d5aSIvan R. Ivanov static constexpr StringRef getNamelessGlobalPrefix() { 79fbee8d5aSIvan R. Ivanov return "mlir.llvm.nameless_global"; 80fbee8d5aSIvan R. Ivanov } 81fbee8d5aSIvan R. Ivanov 829b76a302SChristian Ulmann /// Returns the name of the global_dtors global variables. 839b76a302SChristian Ulmann static constexpr StringRef getGlobalDtorsVarName() { 849b76a302SChristian Ulmann return "llvm.global_dtors"; 859b76a302SChristian Ulmann } 869b76a302SChristian Ulmann 879d4c1be8SDavid Truby /// Returns the symbol name for the module-level comdat operation. It must not 889d4c1be8SDavid Truby /// conflict with the user namespace. 899d4c1be8SDavid Truby static constexpr StringRef getGlobalComdatOpName() { 909d4c1be8SDavid Truby return "__llvm_global_comdat"; 919d4c1be8SDavid Truby } 929d4c1be8SDavid Truby 937f97895fSTobias Gysi /// Converts the sync scope identifier of `inst` to the string representation 947f97895fSTobias Gysi /// necessary to build an atomic LLVM dialect operation. Returns the empty 957f97895fSTobias Gysi /// string if the operation has either no sync scope or the default system-level 967f97895fSTobias Gysi /// sync scope attached. The atomic operations only set their sync scope 977f97895fSTobias Gysi /// attribute if they have a non-default sync scope attached. 987f97895fSTobias Gysi static StringRef getLLVMSyncScope(llvm::Instruction *inst) { 997f97895fSTobias Gysi std::optional<llvm::SyncScope::ID> syncScopeID = 1007f97895fSTobias Gysi llvm::getAtomicSyncScopeID(inst); 1017f97895fSTobias Gysi if (!syncScopeID) 1027f97895fSTobias Gysi return ""; 1037f97895fSTobias Gysi 1047f97895fSTobias Gysi // Search the sync scope name for the given identifier. The default 1057f97895fSTobias Gysi // system-level sync scope thereby maps to the empty string. 1067f97895fSTobias Gysi SmallVector<StringRef> syncScopeName; 1077f97895fSTobias Gysi llvm::LLVMContext &llvmContext = inst->getContext(); 1087f97895fSTobias Gysi llvmContext.getSyncScopeNames(syncScopeName); 1097f97895fSTobias Gysi auto *it = llvm::find_if(syncScopeName, [&](StringRef name) { 1107f97895fSTobias Gysi return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name); 1117f97895fSTobias Gysi }); 1127f97895fSTobias Gysi if (it != syncScopeName.end()) 1137f97895fSTobias Gysi return *it; 1149dbf3625STobias Gysi llvm_unreachable("incorrect sync scope identifier"); 1159dbf3625STobias Gysi } 1169dbf3625STobias Gysi 1179dbf3625STobias Gysi /// Converts an array of unsigned indices to a signed integer position array. 1189dbf3625STobias Gysi static SmallVector<int64_t> getPositionFromIndices(ArrayRef<unsigned> indices) { 1199dbf3625STobias Gysi SmallVector<int64_t> position; 1209dbf3625STobias Gysi llvm::append_range(position, indices); 1219dbf3625STobias Gysi return position; 1229dbf3625STobias Gysi } 1239dbf3625STobias Gysi 1246e395206STobias Gysi /// Converts the LLVM instructions that have a generated MLIR builder. Using a 1256e395206STobias Gysi /// static implementation method called from the module import ensures the 1266e395206STobias Gysi /// builders have to use the `moduleImport` argument and cannot directly call 1276e395206STobias Gysi /// import methods. As a result, both the intrinsic and the instruction MLIR 1286e395206STobias Gysi /// builders have to use the `moduleImport` argument and none of them has direct 1296e395206STobias Gysi /// access to the private module import methods. 1306e395206STobias Gysi static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder, 1316e395206STobias Gysi llvm::Instruction *inst, 132a2c4b7c8SFabian Mora ModuleImport &moduleImport, 133a2c4b7c8SFabian Mora LLVMImportInterface &iface) { 1346e395206STobias Gysi // Copy the operands to an LLVM operands array reference for conversion. 1356e395206STobias Gysi SmallVector<llvm::Value *> operands(inst->operands()); 1366e395206STobias Gysi ArrayRef<llvm::Value *> llvmOperands(operands); 1376e395206STobias Gysi 1386e395206STobias Gysi // Convert all instructions that provide an MLIR builder. 139a2c4b7c8SFabian Mora if (iface.isConvertibleInstruction(inst->getOpcode())) 140a2c4b7c8SFabian Mora return iface.convertInstruction(odsBuilder, inst, llvmOperands, 141a2c4b7c8SFabian Mora moduleImport); 142a2c4b7c8SFabian Mora // TODO: Implement the `convertInstruction` hooks in the 143a2c4b7c8SFabian Mora // `LLVMDialectLLVMIRImportInterface` and move the following include there. 1446e395206STobias Gysi #include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc" 1456e395206STobias Gysi return failure(); 1466e395206STobias Gysi } 1476e395206STobias Gysi 1489dd0eb9cSTobias Gysi /// Get a topologically sorted list of blocks for the given basic blocks. 1499dbf3625STobias Gysi static SetVector<llvm::BasicBlock *> 1509dd0eb9cSTobias Gysi getTopologicallySortedBlocks(ArrayRef<llvm::BasicBlock *> basicBlocks) { 1519dbf3625STobias Gysi SetVector<llvm::BasicBlock *> blocks; 1529dd0eb9cSTobias Gysi for (llvm::BasicBlock *basicBlock : basicBlocks) { 1539dd0eb9cSTobias Gysi if (!blocks.contains(basicBlock)) { 1549dd0eb9cSTobias Gysi llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock); 1559dbf3625STobias Gysi blocks.insert(traversal.begin(), traversal.end()); 1569dbf3625STobias Gysi } 1579dbf3625STobias Gysi } 1589dd0eb9cSTobias Gysi assert(blocks.size() == basicBlocks.size() && "some blocks are not sorted"); 1599dbf3625STobias Gysi return blocks; 1609dbf3625STobias Gysi } 1619dbf3625STobias Gysi 1629dbf3625STobias Gysi ModuleImport::ModuleImport(ModuleOp mlirModule, 163a014fadbSTobias Gysi std::unique_ptr<llvm::Module> llvmModule, 164090d03d1SChristian Ulmann bool emitExpensiveWarnings, 165090d03d1SChristian Ulmann bool importEmptyDICompositeTypes) 1669dbf3625STobias Gysi : builder(mlirModule->getContext()), context(mlirModule->getContext()), 1679dbf3625STobias Gysi mlirModule(mlirModule), llvmModule(std::move(llvmModule)), 168cf487cceSTobias Gysi iface(mlirModule->getContext()), 1699dbf3625STobias Gysi typeTranslator(*mlirModule->getContext()), 170090d03d1SChristian Ulmann debugImporter(std::make_unique<DebugImporter>( 171090d03d1SChristian Ulmann mlirModule, importEmptyDICompositeTypes)), 172e630a502SChristian Ulmann loopAnnotationImporter( 173a014fadbSTobias Gysi std::make_unique<LoopAnnotationImporter>(*this, builder)), 174a014fadbSTobias Gysi emitExpensiveWarnings(emitExpensiveWarnings) { 1759dbf3625STobias Gysi builder.setInsertionPointToStart(mlirModule.getBody()); 1769dbf3625STobias Gysi } 1779dbf3625STobias Gysi 1789d4c1be8SDavid Truby ComdatOp ModuleImport::getGlobalComdatOp() { 1799d4c1be8SDavid Truby if (globalComdatOp) 1809d4c1be8SDavid Truby return globalComdatOp; 1819d4c1be8SDavid Truby 1829d4c1be8SDavid Truby OpBuilder::InsertionGuard guard(builder); 183b126ee65STobias Gysi builder.setInsertionPointToEnd(mlirModule.getBody()); 184b126ee65STobias Gysi globalComdatOp = 185b126ee65STobias Gysi builder.create<ComdatOp>(mlirModule.getLoc(), getGlobalComdatOpName()); 186b126ee65STobias Gysi globalInsertionOp = globalComdatOp; 187b126ee65STobias Gysi return globalComdatOp; 1889d4c1be8SDavid Truby } 1899d4c1be8SDavid Truby 1902f66c891SSlava Zakharin LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) { 1912f66c891SSlava Zakharin Location loc = mlirModule.getLoc(); 1922f66c891SSlava Zakharin 1931dda134fSMarkus Böck // If `node` is a valid TBAA root node, then return its optional identity 1941dda134fSMarkus Böck // string, otherwise return failure. 1952f66c891SSlava Zakharin auto getIdentityIfRootNode = 1961dda134fSMarkus Böck [&](const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> { 1972f66c891SSlava Zakharin // Root node, e.g.: 1982f66c891SSlava Zakharin // !0 = !{!"Simple C/C++ TBAA"} 1991dda134fSMarkus Böck // !1 = !{} 2001dda134fSMarkus Böck if (node->getNumOperands() > 1) 2011dda134fSMarkus Böck return failure(); 2022f66c891SSlava Zakharin // If the operand is MDString, then assume that this is a root node. 2031dda134fSMarkus Böck if (node->getNumOperands() == 1) 20425acbf3eSMehdi Amini if (const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0))) 2051dda134fSMarkus Böck return std::optional<StringRef>{op0->getString()}; 2061dda134fSMarkus Böck return std::optional<StringRef>{}; 2072f66c891SSlava Zakharin }; 2082f66c891SSlava Zakharin 2092f66c891SSlava Zakharin // If `node` looks like a TBAA type descriptor metadata, 2102f66c891SSlava Zakharin // then return true, if it is a valid node, and false otherwise. 2112f66c891SSlava Zakharin // If it does not look like a TBAA type descriptor metadata, then 2122f66c891SSlava Zakharin // return std::nullopt. 2132f66c891SSlava Zakharin // If `identity` and `memberTypes/Offsets` are non-null, then they will 2142f66c891SSlava Zakharin // contain the converted metadata operands for a valid TBAA node (i.e. when 2152f66c891SSlava Zakharin // true is returned). 2161dda134fSMarkus Böck auto isTypeDescriptorNode = [&](const llvm::MDNode *node, 2171dda134fSMarkus Böck StringRef *identity = nullptr, 2181dda134fSMarkus Böck SmallVectorImpl<TBAAMemberAttr> *members = 2192f66c891SSlava Zakharin nullptr) -> std::optional<bool> { 2202f66c891SSlava Zakharin unsigned numOperands = node->getNumOperands(); 2212f66c891SSlava Zakharin // Type descriptor, e.g.: 2222f66c891SSlava Zakharin // !1 = !{!"int", !0, /*optional*/i64 0} /* scalar int type */ 2232f66c891SSlava Zakharin // !2 = !{!"agg_t", !1, i64 0} /* struct agg_t { int x; } */ 2242f66c891SSlava Zakharin if (numOperands < 2) 2252f66c891SSlava Zakharin return std::nullopt; 2262f66c891SSlava Zakharin 2272f66c891SSlava Zakharin // TODO: support "new" format (D41501) for type descriptors, 2282f66c891SSlava Zakharin // where the first operand is an MDNode. 22925acbf3eSMehdi Amini const auto *identityNode = 23025acbf3eSMehdi Amini dyn_cast<const llvm::MDString>(node->getOperand(0)); 2312f66c891SSlava Zakharin if (!identityNode) 2322f66c891SSlava Zakharin return std::nullopt; 2332f66c891SSlava Zakharin 2342f66c891SSlava Zakharin // This should be a type descriptor node. 2352f66c891SSlava Zakharin if (identity) 2362f66c891SSlava Zakharin *identity = identityNode->getString(); 2372f66c891SSlava Zakharin 2382f66c891SSlava Zakharin for (unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) { 2392f66c891SSlava Zakharin const auto *memberNode = 2402f66c891SSlava Zakharin dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1)); 2412f66c891SSlava Zakharin if (!memberNode) { 2422f66c891SSlava Zakharin emitError(loc) << "operand '" << 2 * pairNum + 1 << "' must be MDNode: " 2432f66c891SSlava Zakharin << diagMD(node, llvmModule.get()); 2442f66c891SSlava Zakharin return false; 2452f66c891SSlava Zakharin } 2462f66c891SSlava Zakharin int64_t offset = 0; 2472f66c891SSlava Zakharin if (2 * pairNum + 2 >= numOperands) { 2482f66c891SSlava Zakharin // Allow for optional 0 offset in 2-operand nodes. 2492f66c891SSlava Zakharin if (numOperands != 2) { 2502f66c891SSlava Zakharin emitError(loc) << "missing member offset: " 2512f66c891SSlava Zakharin << diagMD(node, llvmModule.get()); 2522f66c891SSlava Zakharin return false; 2532f66c891SSlava Zakharin } 2542f66c891SSlava Zakharin } else { 2552f66c891SSlava Zakharin auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>( 2562f66c891SSlava Zakharin node->getOperand(2 * pairNum + 2)); 2572f66c891SSlava Zakharin if (!offsetCI) { 2582f66c891SSlava Zakharin emitError(loc) << "operand '" << 2 * pairNum + 2 2592f66c891SSlava Zakharin << "' must be ConstantInt: " 2602f66c891SSlava Zakharin << diagMD(node, llvmModule.get()); 2612f66c891SSlava Zakharin return false; 2622f66c891SSlava Zakharin } 2632f66c891SSlava Zakharin offset = offsetCI->getZExtValue(); 2642f66c891SSlava Zakharin } 2652f66c891SSlava Zakharin 2661dda134fSMarkus Böck if (members) 2671dda134fSMarkus Böck members->push_back(TBAAMemberAttr::get( 2681dda134fSMarkus Böck cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset)); 2692f66c891SSlava Zakharin } 2702f66c891SSlava Zakharin 2712f66c891SSlava Zakharin return true; 2722f66c891SSlava Zakharin }; 2732f66c891SSlava Zakharin 2742f66c891SSlava Zakharin // If `node` looks like a TBAA access tag metadata, 2752f66c891SSlava Zakharin // then return true, if it is a valid node, and false otherwise. 2762f66c891SSlava Zakharin // If it does not look like a TBAA access tag metadata, then 2772f66c891SSlava Zakharin // return std::nullopt. 2782f66c891SSlava Zakharin // If the other arguments are non-null, then they will contain 2792f66c891SSlava Zakharin // the converted metadata operands for a valid TBAA node (i.e. when true is 2802f66c891SSlava Zakharin // returned). 2811dda134fSMarkus Böck auto isTagNode = [&](const llvm::MDNode *node, 2821dda134fSMarkus Böck TBAATypeDescriptorAttr *baseAttr = nullptr, 2831dda134fSMarkus Böck TBAATypeDescriptorAttr *accessAttr = nullptr, 2841dda134fSMarkus Böck int64_t *offset = nullptr, 2852f66c891SSlava Zakharin bool *isConstant = nullptr) -> std::optional<bool> { 2862f66c891SSlava Zakharin // Access tag, e.g.: 2872f66c891SSlava Zakharin // !3 = !{!1, !1, i64 0} /* scalar int access */ 2882f66c891SSlava Zakharin // !4 = !{!2, !1, i64 0} /* agg_t::x access */ 2892f66c891SSlava Zakharin // 2902f66c891SSlava Zakharin // Optional 4th argument is ConstantInt 0/1 identifying whether 2912f66c891SSlava Zakharin // the location being accessed is "constant" (see for details: 2922f66c891SSlava Zakharin // https://llvm.org/docs/LangRef.html#representation). 2932f66c891SSlava Zakharin unsigned numOperands = node->getNumOperands(); 2942f66c891SSlava Zakharin if (numOperands != 3 && numOperands != 4) 2952f66c891SSlava Zakharin return std::nullopt; 29625acbf3eSMehdi Amini const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0)); 29725acbf3eSMehdi Amini const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1)); 29825acbf3eSMehdi Amini auto *offsetCI = 2992f66c891SSlava Zakharin llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2)); 3002f66c891SSlava Zakharin if (!baseMD || !accessMD || !offsetCI) 3012f66c891SSlava Zakharin return std::nullopt; 3022f66c891SSlava Zakharin // TODO: support "new" TBAA format, if needed (see D41501). 3032f66c891SSlava Zakharin // In the "old" format the first operand of the access type 3042f66c891SSlava Zakharin // metadata is MDString. We have to distinguish the formats, 3052f66c891SSlava Zakharin // because access tags have the same structure, but different 3062f66c891SSlava Zakharin // meaning for the operands. 3072f66c891SSlava Zakharin if (accessMD->getNumOperands() < 1 || 3082f66c891SSlava Zakharin !isa<llvm::MDString>(accessMD->getOperand(0))) 3092f66c891SSlava Zakharin return std::nullopt; 3102f66c891SSlava Zakharin bool isConst = false; 3112f66c891SSlava Zakharin if (numOperands == 4) { 31225acbf3eSMehdi Amini auto *isConstantCI = 3132f66c891SSlava Zakharin llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3)); 3142f66c891SSlava Zakharin if (!isConstantCI) { 3152f66c891SSlava Zakharin emitError(loc) << "operand '3' must be ConstantInt: " 3162f66c891SSlava Zakharin << diagMD(node, llvmModule.get()); 3172f66c891SSlava Zakharin return false; 3182f66c891SSlava Zakharin } 3192f66c891SSlava Zakharin isConst = isConstantCI->getValue()[0]; 3202f66c891SSlava Zakharin } 3211dda134fSMarkus Böck if (baseAttr) 3221dda134fSMarkus Böck *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD)); 3231dda134fSMarkus Böck if (accessAttr) 3241dda134fSMarkus Böck *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD)); 3252f66c891SSlava Zakharin if (offset) 3262f66c891SSlava Zakharin *offset = offsetCI->getZExtValue(); 3272f66c891SSlava Zakharin if (isConstant) 3282f66c891SSlava Zakharin *isConstant = isConst; 3292f66c891SSlava Zakharin return true; 3302f66c891SSlava Zakharin }; 3312f66c891SSlava Zakharin 3321dda134fSMarkus Böck // Do a post-order walk over the TBAA Graph. Since a correct TBAA Graph is a 3331dda134fSMarkus Böck // DAG, a post-order walk guarantees that we convert any metadata node we 3341dda134fSMarkus Böck // depend on, prior to converting the current node. 3351dda134fSMarkus Böck DenseSet<const llvm::MDNode *> seen; 3361dda134fSMarkus Böck SmallVector<const llvm::MDNode *> workList; 3371dda134fSMarkus Böck workList.push_back(node); 3381dda134fSMarkus Böck while (!workList.empty()) { 3391dda134fSMarkus Böck const llvm::MDNode *current = workList.back(); 3401dda134fSMarkus Böck if (tbaaMapping.contains(current)) { 3411dda134fSMarkus Böck // Already converted. Just pop from the worklist. 3421dda134fSMarkus Böck workList.pop_back(); 3431dda134fSMarkus Böck continue; 3441dda134fSMarkus Böck } 345af3a5ef1STobias Gysi 3461dda134fSMarkus Böck // If any child of this node is not yet converted, don't pop the current 3471dda134fSMarkus Böck // node from the worklist but push the not-yet-converted children in the 3481dda134fSMarkus Böck // front of the worklist. 3491dda134fSMarkus Böck bool anyChildNotConverted = false; 3501dda134fSMarkus Böck for (const llvm::MDOperand &operand : current->operands()) 3511dda134fSMarkus Böck if (auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get())) 3521dda134fSMarkus Böck if (!tbaaMapping.contains(childNode)) { 3531dda134fSMarkus Böck workList.push_back(childNode); 3541dda134fSMarkus Böck anyChildNotConverted = true; 3551dda134fSMarkus Böck } 3562f66c891SSlava Zakharin 3571dda134fSMarkus Böck if (anyChildNotConverted) { 3581dda134fSMarkus Böck // If this is the second time we failed to convert an element in the 3591dda134fSMarkus Böck // worklist it must be because a child is dependent on it being converted 3601dda134fSMarkus Böck // and we have a cycle in the graph. Cycles are not allowed in TBAA 3611dda134fSMarkus Böck // graphs. 3621dda134fSMarkus Böck if (!seen.insert(current).second) 3631dda134fSMarkus Böck return emitError(loc) << "has cycle in TBAA graph: " 3642f66c891SSlava Zakharin << diagMD(current, llvmModule.get()); 3652f66c891SSlava Zakharin 3661dda134fSMarkus Böck continue; 3671dda134fSMarkus Böck } 3681dda134fSMarkus Böck 3691dda134fSMarkus Böck // Otherwise simply import the current node. 3701dda134fSMarkus Böck workList.pop_back(); 3711dda134fSMarkus Böck 3721dda134fSMarkus Böck FailureOr<std::optional<StringRef>> rootNodeIdentity = 3731dda134fSMarkus Böck getIdentityIfRootNode(current); 3741dda134fSMarkus Böck if (succeeded(rootNodeIdentity)) { 3751dda134fSMarkus Böck StringAttr stringAttr = *rootNodeIdentity 3761dda134fSMarkus Böck ? builder.getStringAttr(**rootNodeIdentity) 3771dda134fSMarkus Böck : nullptr; 3782f66c891SSlava Zakharin // The root nodes do not have operands, so we can create 3790fc8d9e4STobias Gysi // the TBAARootAttr on the first walk. 3801dda134fSMarkus Böck tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)}); 3812f66c891SSlava Zakharin continue; 3822f66c891SSlava Zakharin } 3831dda134fSMarkus Böck 3841dda134fSMarkus Böck StringRef identity; 3851dda134fSMarkus Böck SmallVector<TBAAMemberAttr> members; 3861dda134fSMarkus Böck if (std::optional<bool> isValid = 3871dda134fSMarkus Böck isTypeDescriptorNode(current, &identity, &members)) { 3881dda134fSMarkus Böck assert(isValid.value() && "type descriptor node must be valid"); 3891dda134fSMarkus Böck 3901dda134fSMarkus Böck tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>( 3911dda134fSMarkus Böck identity, members)}); 3922f66c891SSlava Zakharin continue; 3932f66c891SSlava Zakharin } 3941dda134fSMarkus Böck 3951dda134fSMarkus Böck TBAATypeDescriptorAttr baseAttr, accessAttr; 3961dda134fSMarkus Böck int64_t offset; 3971dda134fSMarkus Böck bool isConstant; 3981dda134fSMarkus Böck if (std::optional<bool> isValid = 3991dda134fSMarkus Böck isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) { 4001dda134fSMarkus Böck assert(isValid.value() && "access tag node must be valid"); 4011dda134fSMarkus Böck tbaaMapping.insert( 4021dda134fSMarkus Böck {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset, 4031dda134fSMarkus Böck isConstant)}); 4042f66c891SSlava Zakharin continue; 4052f66c891SSlava Zakharin } 4061dda134fSMarkus Böck 4072f66c891SSlava Zakharin return emitError(loc) << "unsupported TBAA node format: " 4082f66c891SSlava Zakharin << diagMD(current, llvmModule.get()); 4092f66c891SSlava Zakharin } 4102f66c891SSlava Zakharin return success(); 4112f66c891SSlava Zakharin } 4122f66c891SSlava Zakharin 413af3a5ef1STobias Gysi LogicalResult 414af3a5ef1STobias Gysi ModuleImport::processAccessGroupMetadata(const llvm::MDNode *node) { 415af3a5ef1STobias Gysi Location loc = mlirModule.getLoc(); 4169170fa58SMarkus Böck if (failed(loopAnnotationImporter->translateAccessGroup(node, loc))) 417af3a5ef1STobias Gysi return emitError(loc) << "unsupported access group node: " 418e630a502SChristian Ulmann << diagMD(node, llvmModule.get()); 419af3a5ef1STobias Gysi return success(); 420af3a5ef1STobias Gysi } 421af3a5ef1STobias Gysi 4224469ec1dSTobias Gysi LogicalResult 4234469ec1dSTobias Gysi ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) { 4244469ec1dSTobias Gysi Location loc = mlirModule.getLoc(); 4254469ec1dSTobias Gysi // Helper that verifies the node has a self reference operand. 4264469ec1dSTobias Gysi auto verifySelfRef = [](const llvm::MDNode *node) { 4274469ec1dSTobias Gysi return node->getNumOperands() != 0 && 4284469ec1dSTobias Gysi node == dyn_cast<llvm::MDNode>(node->getOperand(0)); 4294469ec1dSTobias Gysi }; 4301c067a51SWilliam Moses auto verifySelfRefOrString = [](const llvm::MDNode *node) { 4311c067a51SWilliam Moses return node->getNumOperands() != 0 && 4321c067a51SWilliam Moses (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) || 4331c067a51SWilliam Moses isa<llvm::MDString>(node->getOperand(0))); 4341c067a51SWilliam Moses }; 4354469ec1dSTobias Gysi // Helper that verifies the given operand is a string or does not exist. 4364469ec1dSTobias Gysi auto verifyDescription = [](const llvm::MDNode *node, unsigned idx) { 4374469ec1dSTobias Gysi return idx >= node->getNumOperands() || 4384469ec1dSTobias Gysi isa<llvm::MDString>(node->getOperand(idx)); 4394469ec1dSTobias Gysi }; 4401c067a51SWilliam Moses 4411c067a51SWilliam Moses auto getIdAttr = [&](const llvm::MDNode *node) -> Attribute { 4421c067a51SWilliam Moses if (verifySelfRef(node)) 4431c067a51SWilliam Moses return DistinctAttr::create(builder.getUnitAttr()); 4441c067a51SWilliam Moses 4451c067a51SWilliam Moses auto name = cast<llvm::MDString>(node->getOperand(0)); 4461c067a51SWilliam Moses return builder.getStringAttr(name->getString()); 4471c067a51SWilliam Moses }; 4481c067a51SWilliam Moses 44978d00a16SMarkus Böck // Helper that creates an alias scope domain attribute. 4504469ec1dSTobias Gysi auto createAliasScopeDomainOp = [&](const llvm::MDNode *aliasDomain) { 4514469ec1dSTobias Gysi StringAttr description = nullptr; 4524469ec1dSTobias Gysi if (aliasDomain->getNumOperands() >= 2) 4534469ec1dSTobias Gysi if (auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1))) 4544469ec1dSTobias Gysi description = builder.getStringAttr(operand->getString()); 4551c067a51SWilliam Moses Attribute idAttr = getIdAttr(aliasDomain); 4561c067a51SWilliam Moses return builder.getAttr<AliasScopeDomainAttr>(idAttr, description); 4574469ec1dSTobias Gysi }; 4584469ec1dSTobias Gysi 4594469ec1dSTobias Gysi // Collect the alias scopes and domains to translate them. 4604469ec1dSTobias Gysi for (const llvm::MDOperand &operand : node->operands()) { 4614469ec1dSTobias Gysi if (const auto *scope = dyn_cast<llvm::MDNode>(operand)) { 4624469ec1dSTobias Gysi llvm::AliasScopeNode aliasScope(scope); 4634469ec1dSTobias Gysi const llvm::MDNode *domain = aliasScope.getDomain(); 4644469ec1dSTobias Gysi 4654469ec1dSTobias Gysi // Verify the scope node points to valid scope metadata which includes 4664469ec1dSTobias Gysi // verifying its domain. Perform the verification before looking it up in 4674469ec1dSTobias Gysi // the alias scope mapping since it could have been inserted as a domain 4684469ec1dSTobias Gysi // node before. 4691c067a51SWilliam Moses if (!verifySelfRefOrString(scope) || !domain || 4701c067a51SWilliam Moses !verifyDescription(scope, 2)) 4714469ec1dSTobias Gysi return emitError(loc) << "unsupported alias scope node: " 4724469ec1dSTobias Gysi << diagMD(scope, llvmModule.get()); 4731c067a51SWilliam Moses if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1)) 4744469ec1dSTobias Gysi return emitError(loc) << "unsupported alias domain node: " 4754469ec1dSTobias Gysi << diagMD(domain, llvmModule.get()); 4764469ec1dSTobias Gysi 477dc47813eSTobias Gysi if (aliasScopeMapping.contains(scope)) 4784469ec1dSTobias Gysi continue; 4794469ec1dSTobias Gysi 4804469ec1dSTobias Gysi // Convert the domain metadata node if it has not been translated before. 4814469ec1dSTobias Gysi auto it = aliasScopeMapping.find(aliasScope.getDomain()); 4824469ec1dSTobias Gysi if (it == aliasScopeMapping.end()) { 4834469ec1dSTobias Gysi auto aliasScopeDomainOp = createAliasScopeDomainOp(domain); 48478d00a16SMarkus Böck it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first; 4854469ec1dSTobias Gysi } 4864469ec1dSTobias Gysi 4874469ec1dSTobias Gysi // Convert the scope metadata node if it has not been converted before. 4884469ec1dSTobias Gysi StringAttr description = nullptr; 4894469ec1dSTobias Gysi if (!aliasScope.getName().empty()) 4904469ec1dSTobias Gysi description = builder.getStringAttr(aliasScope.getName()); 4911c067a51SWilliam Moses Attribute idAttr = getIdAttr(scope); 49278d00a16SMarkus Böck auto aliasScopeOp = builder.getAttr<AliasScopeAttr>( 4931c067a51SWilliam Moses idAttr, cast<AliasScopeDomainAttr>(it->second), description); 4941c067a51SWilliam Moses 49578d00a16SMarkus Böck aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp); 4964469ec1dSTobias Gysi } 4974469ec1dSTobias Gysi } 4984469ec1dSTobias Gysi return success(); 4994469ec1dSTobias Gysi } 5004469ec1dSTobias Gysi 50178d00a16SMarkus Böck FailureOr<SmallVector<AliasScopeAttr>> 5024469ec1dSTobias Gysi ModuleImport::lookupAliasScopeAttrs(const llvm::MDNode *node) const { 50378d00a16SMarkus Böck SmallVector<AliasScopeAttr> aliasScopes; 5044469ec1dSTobias Gysi aliasScopes.reserve(node->getNumOperands()); 5054469ec1dSTobias Gysi for (const llvm::MDOperand &operand : node->operands()) { 5064469ec1dSTobias Gysi auto *node = cast<llvm::MDNode>(operand.get()); 50778d00a16SMarkus Böck aliasScopes.push_back( 50878d00a16SMarkus Böck dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node))); 5094469ec1dSTobias Gysi } 5104469ec1dSTobias Gysi // Return failure if one of the alias scope lookups failed. 5114469ec1dSTobias Gysi if (llvm::is_contained(aliasScopes, nullptr)) 5124469ec1dSTobias Gysi return failure(); 5134469ec1dSTobias Gysi return aliasScopes; 5144469ec1dSTobias Gysi } 5154469ec1dSTobias Gysi 516b808648aSChristian Ulmann void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) { 517b808648aSChristian Ulmann debugIntrinsics.insert(intrinsic); 518b808648aSChristian Ulmann } 519b808648aSChristian Ulmann 520a72e034fSDavid Truby LogicalResult ModuleImport::convertLinkerOptionsMetadata() { 521a72e034fSDavid Truby for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) { 522a72e034fSDavid Truby if (named.getName() != "llvm.linker.options") 523a72e034fSDavid Truby continue; 524a72e034fSDavid Truby // llvm.linker.options operands are lists of strings. 5256d2bbba1SVictor Perez for (const llvm::MDNode *node : named.operands()) { 526a72e034fSDavid Truby SmallVector<StringRef> options; 5276d2bbba1SVictor Perez options.reserve(node->getNumOperands()); 5286d2bbba1SVictor Perez for (const llvm::MDOperand &option : node->operands()) 529a72e034fSDavid Truby options.push_back(cast<llvm::MDString>(option)->getString()); 530a72e034fSDavid Truby builder.create<LLVM::LinkerOptionsOp>(mlirModule.getLoc(), 531a72e034fSDavid Truby builder.getStrArrayAttr(options)); 532a72e034fSDavid Truby } 533a72e034fSDavid Truby } 534a72e034fSDavid Truby return success(); 535a72e034fSDavid Truby } 536a72e034fSDavid Truby 53790aac06cSTarun Prabhu LogicalResult ModuleImport::convertIdentMetadata() { 53890aac06cSTarun Prabhu for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) { 53990aac06cSTarun Prabhu // llvm.ident should have a single operand. That operand is itself an 54090aac06cSTarun Prabhu // MDNode with a single string operand. 54190aac06cSTarun Prabhu if (named.getName() != LLVMDialect::getIdentAttrName()) 54290aac06cSTarun Prabhu continue; 54390aac06cSTarun Prabhu 54490aac06cSTarun Prabhu if (named.getNumOperands() == 1) 54590aac06cSTarun Prabhu if (auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0))) 54690aac06cSTarun Prabhu if (md->getNumOperands() == 1) 54790aac06cSTarun Prabhu if (auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0))) 54890aac06cSTarun Prabhu mlirModule->setAttr(LLVMDialect::getIdentAttrName(), 54990aac06cSTarun Prabhu builder.getStringAttr(mdStr->getString())); 55090aac06cSTarun Prabhu } 55190aac06cSTarun Prabhu return success(); 55290aac06cSTarun Prabhu } 55390aac06cSTarun Prabhu 554839344f0STarun Prabhu LogicalResult ModuleImport::convertCommandlineMetadata() { 555839344f0STarun Prabhu for (const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) { 556839344f0STarun Prabhu // llvm.commandline should have a single operand. That operand is itself an 557839344f0STarun Prabhu // MDNode with a single string operand. 558839344f0STarun Prabhu if (nmd.getName() != LLVMDialect::getCommandlineAttrName()) 559839344f0STarun Prabhu continue; 560839344f0STarun Prabhu 561839344f0STarun Prabhu if (nmd.getNumOperands() == 1) 562839344f0STarun Prabhu if (auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0))) 563839344f0STarun Prabhu if (md->getNumOperands() == 1) 564839344f0STarun Prabhu if (auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0))) 565839344f0STarun Prabhu mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(), 566839344f0STarun Prabhu builder.getStringAttr(mdStr->getString())); 567839344f0STarun Prabhu } 568839344f0STarun Prabhu return success(); 569839344f0STarun Prabhu } 570839344f0STarun Prabhu 5712f66c891SSlava Zakharin LogicalResult ModuleImport::convertMetadata() { 5722f66c891SSlava Zakharin OpBuilder::InsertionGuard guard(builder); 57319992b1dSSlava Zakharin builder.setInsertionPointToEnd(mlirModule.getBody()); 574af3a5ef1STobias Gysi for (const llvm::Function &func : llvmModule->functions()) { 5752f66c891SSlava Zakharin for (const llvm::Instruction &inst : llvm::instructions(func)) { 576af3a5ef1STobias Gysi // Convert access group metadata nodes. 577af3a5ef1STobias Gysi if (llvm::MDNode *node = 578af3a5ef1STobias Gysi inst.getMetadata(llvm::LLVMContext::MD_access_group)) 579af3a5ef1STobias Gysi if (failed(processAccessGroupMetadata(node))) 5802f66c891SSlava Zakharin return failure(); 5812f66c891SSlava Zakharin 582af3a5ef1STobias Gysi // Convert alias analysis metadata nodes. 583af3a5ef1STobias Gysi llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata(); 584af3a5ef1STobias Gysi if (!aliasAnalysisNodes) 585af3a5ef1STobias Gysi continue; 586af3a5ef1STobias Gysi if (aliasAnalysisNodes.TBAA) 587af3a5ef1STobias Gysi if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA))) 588af3a5ef1STobias Gysi return failure(); 5894469ec1dSTobias Gysi if (aliasAnalysisNodes.Scope) 5904469ec1dSTobias Gysi if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope))) 5914469ec1dSTobias Gysi return failure(); 5924469ec1dSTobias Gysi if (aliasAnalysisNodes.NoAlias) 5934469ec1dSTobias Gysi if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias))) 5944469ec1dSTobias Gysi return failure(); 595af3a5ef1STobias Gysi } 596af3a5ef1STobias Gysi } 597a72e034fSDavid Truby if (failed(convertLinkerOptionsMetadata())) 598a72e034fSDavid Truby return failure(); 59990aac06cSTarun Prabhu if (failed(convertIdentMetadata())) 60090aac06cSTarun Prabhu return failure(); 601839344f0STarun Prabhu if (failed(convertCommandlineMetadata())) 602839344f0STarun Prabhu return failure(); 6032f66c891SSlava Zakharin return success(); 6042f66c891SSlava Zakharin } 6052f66c891SSlava Zakharin 606b126ee65STobias Gysi void ModuleImport::processComdat(const llvm::Comdat *comdat) { 607b126ee65STobias Gysi if (comdatMapping.contains(comdat)) 608b126ee65STobias Gysi return; 609b126ee65STobias Gysi 610b126ee65STobias Gysi ComdatOp comdatOp = getGlobalComdatOp(); 6119d4c1be8SDavid Truby OpBuilder::InsertionGuard guard(builder); 612b126ee65STobias Gysi builder.setInsertionPointToEnd(&comdatOp.getBody().back()); 613b126ee65STobias Gysi auto selectorOp = builder.create<ComdatSelectorOp>( 614b126ee65STobias Gysi mlirModule.getLoc(), comdat->getName(), 615b126ee65STobias Gysi convertComdatFromLLVM(comdat->getSelectionKind())); 616b126ee65STobias Gysi auto symbolRef = 617b126ee65STobias Gysi SymbolRefAttr::get(builder.getContext(), getGlobalComdatOpName(), 618b126ee65STobias Gysi FlatSymbolRefAttr::get(selectorOp.getSymNameAttr())); 619b126ee65STobias Gysi comdatMapping.try_emplace(comdat, symbolRef); 6209d4c1be8SDavid Truby } 6219d4c1be8SDavid Truby 622b126ee65STobias Gysi LogicalResult ModuleImport::convertComdats() { 623b126ee65STobias Gysi for (llvm::GlobalVariable &globalVar : llvmModule->globals()) 624b126ee65STobias Gysi if (globalVar.hasComdat()) 625b126ee65STobias Gysi processComdat(globalVar.getComdat()); 626b126ee65STobias Gysi for (llvm::Function &func : llvmModule->functions()) 627b126ee65STobias Gysi if (func.hasComdat()) 628b126ee65STobias Gysi processComdat(func.getComdat()); 6299d4c1be8SDavid Truby return success(); 6309d4c1be8SDavid Truby } 6319d4c1be8SDavid Truby 6329dbf3625STobias Gysi LogicalResult ModuleImport::convertGlobals() { 6339b76a302SChristian Ulmann for (llvm::GlobalVariable &globalVar : llvmModule->globals()) { 6349b76a302SChristian Ulmann if (globalVar.getName() == getGlobalCtorsVarName() || 6359b76a302SChristian Ulmann globalVar.getName() == getGlobalDtorsVarName()) { 6369b76a302SChristian Ulmann if (failed(convertGlobalCtorsAndDtors(&globalVar))) { 6377d5b4ebbSChristian Ulmann return emitError(UnknownLoc::get(context)) 6383589885dSTobias Gysi << "unhandled global variable: " << diag(globalVar); 6399b76a302SChristian Ulmann } 6409b76a302SChristian Ulmann continue; 6419b76a302SChristian Ulmann } 6420fde03cbSTobias Gysi if (failed(convertGlobal(&globalVar))) { 6437d5b4ebbSChristian Ulmann return emitError(UnknownLoc::get(context)) 6443589885dSTobias Gysi << "unhandled global variable: " << diag(globalVar); 6450fde03cbSTobias Gysi } 6469b76a302SChristian Ulmann } 6479dbf3625STobias Gysi return success(); 6489dbf3625STobias Gysi } 6499dbf3625STobias Gysi 6509d2b84efSTobias Gysi LogicalResult ModuleImport::convertDataLayout() { 6519d2b84efSTobias Gysi Location loc = mlirModule.getLoc(); 6529d2b84efSTobias Gysi DataLayoutImporter dataLayoutImporter(context, llvmModule->getDataLayout()); 6539d2b84efSTobias Gysi if (!dataLayoutImporter.getDataLayout()) 6549d2b84efSTobias Gysi return emitError(loc, "cannot translate data layout: ") 6559d2b84efSTobias Gysi << dataLayoutImporter.getLastToken(); 6569d2b84efSTobias Gysi 6579d2b84efSTobias Gysi for (StringRef token : dataLayoutImporter.getUnhandledTokens()) 6589d2b84efSTobias Gysi emitWarning(loc, "unhandled data layout token: ") << token; 6599d2b84efSTobias Gysi 6609d2b84efSTobias Gysi mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName, 6619d2b84efSTobias Gysi dataLayoutImporter.getDataLayout()); 6629d2b84efSTobias Gysi return success(); 6639d2b84efSTobias Gysi } 6649d2b84efSTobias Gysi 6659dbf3625STobias Gysi LogicalResult ModuleImport::convertFunctions() { 6669dbf3625STobias Gysi for (llvm::Function &func : llvmModule->functions()) 6679dbf3625STobias Gysi if (failed(processFunction(&func))) 6689dbf3625STobias Gysi return failure(); 6699dbf3625STobias Gysi return success(); 6709dbf3625STobias Gysi } 6719dbf3625STobias Gysi 6720cf06639STobias Gysi void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst, 6730cf06639STobias Gysi Operation *op) { 6740cf06639STobias Gysi SmallVector<std::pair<unsigned, llvm::MDNode *>> allMetadata; 6750cf06639STobias Gysi inst->getAllMetadataOtherThanDebugLoc(allMetadata); 6760cf06639STobias Gysi for (auto &[kind, node] : allMetadata) { 6770cf06639STobias Gysi if (!iface.isConvertibleMetadata(kind)) 6780cf06639STobias Gysi continue; 6790cf06639STobias Gysi if (failed(iface.setMetadataAttrs(builder, kind, node, op, *this))) { 680a014fadbSTobias Gysi if (emitExpensiveWarnings) { 6810cf06639STobias Gysi Location loc = debugImporter->translateLoc(inst->getDebugLoc()); 6823589885dSTobias Gysi emitWarning(loc) << "unhandled metadata: " 6833589885dSTobias Gysi << diagMD(node, llvmModule.get()) << " on " 6843589885dSTobias Gysi << diag(*inst); 6850cf06639STobias Gysi } 6860cf06639STobias Gysi } 6870cf06639STobias Gysi } 688a014fadbSTobias Gysi } 6890cf06639STobias Gysi 690e553ac4dSJeff Niu void ModuleImport::setIntegerOverflowFlags(llvm::Instruction *inst, 691e9e1c411STom Eccles Operation *op) const { 692e9e1c411STom Eccles auto iface = cast<IntegerOverflowFlagsInterface>(op); 693e9e1c411STom Eccles 694e9e1c411STom Eccles IntegerOverflowFlags value = {}; 695e9e1c411STom Eccles value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap()); 696e9e1c411STom Eccles value = 697e9e1c411STom Eccles bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap()); 698e9e1c411STom Eccles 699e553ac4dSJeff Niu iface.setOverflowFlags(value); 700e9e1c411STom Eccles } 701e9e1c411STom Eccles 702afa178d3Slfrenot void ModuleImport::setExactFlag(llvm::Instruction *inst, Operation *op) const { 703afa178d3Slfrenot auto iface = cast<ExactFlagInterface>(op); 704afa178d3Slfrenot 705afa178d3Slfrenot iface.setIsExact(inst->isExact()); 706afa178d3Slfrenot } 707afa178d3Slfrenot 70840afff7bSlfrenot void ModuleImport::setDisjointFlag(llvm::Instruction *inst, 70940afff7bSlfrenot Operation *op) const { 71040afff7bSlfrenot auto iface = cast<DisjointFlagInterface>(op); 71140afff7bSlfrenot auto instDisjoint = cast<llvm::PossiblyDisjointInst>(inst); 71240afff7bSlfrenot 71340afff7bSlfrenot iface.setIsDisjoint(instDisjoint->isDisjoint()); 71440afff7bSlfrenot } 71540afff7bSlfrenot 71689aaf2cfSlfrenot void ModuleImport::setNonNegFlag(llvm::Instruction *inst, Operation *op) const { 71789aaf2cfSlfrenot auto iface = cast<NonNegFlagInterface>(op); 71889aaf2cfSlfrenot 71989aaf2cfSlfrenot iface.setNonNeg(inst->hasNonNeg()); 72089aaf2cfSlfrenot } 72189aaf2cfSlfrenot 7229dbf3625STobias Gysi void ModuleImport::setFastmathFlagsAttr(llvm::Instruction *inst, 7239dbf3625STobias Gysi Operation *op) const { 7249dbf3625STobias Gysi auto iface = cast<FastmathFlagsInterface>(op); 7259dbf3625STobias Gysi 7269dbf3625STobias Gysi // Even if the imported operation implements the fastmath interface, the 7279dbf3625STobias Gysi // original instruction may not have fastmath flags set. Exit if an 7289dbf3625STobias Gysi // instruction, such as a non floating-point function call, does not have 7299dbf3625STobias Gysi // fastmath flags. 7309dbf3625STobias Gysi if (!isa<llvm::FPMathOperator>(inst)) 7319dbf3625STobias Gysi return; 7329dbf3625STobias Gysi llvm::FastMathFlags flags = inst->getFastMathFlags(); 7339dbf3625STobias Gysi 7349dbf3625STobias Gysi // Set the fastmath bits flag-by-flag. 7359dbf3625STobias Gysi FastmathFlags value = {}; 7369dbf3625STobias Gysi value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs()); 7379dbf3625STobias Gysi value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs()); 7389dbf3625STobias Gysi value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros()); 7399dbf3625STobias Gysi value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal()); 7409dbf3625STobias Gysi value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract()); 7419dbf3625STobias Gysi value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc()); 7429dbf3625STobias Gysi value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc()); 7439dbf3625STobias Gysi FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value); 7449dbf3625STobias Gysi iface->setAttr(iface.getFastmathAttrName(), attr); 7459dbf3625STobias Gysi } 7469dbf3625STobias Gysi 747f7cd55f5STobias Gysi /// Returns if `type` is a scalar integer or floating-point type. 748f7cd55f5STobias Gysi static bool isScalarType(Type type) { 7495550c821STres Popp return isa<IntegerType, FloatType>(type); 750f7cd55f5STobias Gysi } 7519dbf3625STobias Gysi 752f7cd55f5STobias Gysi /// Returns `type` if it is a builtin integer or floating-point vector type that 753f7cd55f5STobias Gysi /// can be used to create an attribute or nullptr otherwise. If provided, 754f7cd55f5STobias Gysi /// `arrayShape` is added to the shape of the vector to create an attribute that 755f7cd55f5STobias Gysi /// matches an array of vectors. 756f7cd55f5STobias Gysi static Type getVectorTypeForAttr(Type type, ArrayRef<int64_t> arrayShape = {}) { 757f7cd55f5STobias Gysi if (!LLVM::isCompatibleVectorType(type)) 758f7cd55f5STobias Gysi return {}; 7599dbf3625STobias Gysi 7609dbf3625STobias Gysi llvm::ElementCount numElements = LLVM::getVectorNumElements(type); 7619dbf3625STobias Gysi if (numElements.isScalable()) { 762f7cd55f5STobias Gysi emitError(UnknownLoc::get(type.getContext())) 763f7cd55f5STobias Gysi << "scalable vectors not supported"; 764f7cd55f5STobias Gysi return {}; 7659dbf3625STobias Gysi } 7669dbf3625STobias Gysi 767f7cd55f5STobias Gysi // An LLVM dialect vector can only contain scalars. 768f7cd55f5STobias Gysi Type elementType = LLVM::getVectorElementType(type); 769f7cd55f5STobias Gysi if (!isScalarType(elementType)) 770f7cd55f5STobias Gysi return {}; 7719dbf3625STobias Gysi 7725262865aSKazu Hirata SmallVector<int64_t> shape(arrayShape); 7739dbf3625STobias Gysi shape.push_back(numElements.getKnownMinValue()); 7749dbf3625STobias Gysi return VectorType::get(shape, elementType); 7759dbf3625STobias Gysi } 7769dbf3625STobias Gysi 777f7cd55f5STobias Gysi Type ModuleImport::getBuiltinTypeForAttr(Type type) { 778f7cd55f5STobias Gysi if (!type) 779f7cd55f5STobias Gysi return {}; 780f7cd55f5STobias Gysi 781f7cd55f5STobias Gysi // Return builtin integer and floating-point types as is. 782f7cd55f5STobias Gysi if (isScalarType(type)) 783f7cd55f5STobias Gysi return type; 784f7cd55f5STobias Gysi 785f7cd55f5STobias Gysi // Return builtin vectors of integer and floating-point types as is. 786f7cd55f5STobias Gysi if (Type vectorType = getVectorTypeForAttr(type)) 787f7cd55f5STobias Gysi return vectorType; 788f7cd55f5STobias Gysi 789f7cd55f5STobias Gysi // Multi-dimensional array types are converted to tensors or vectors, 790f7cd55f5STobias Gysi // depending on the innermost type being a scalar or a vector. 791f7cd55f5STobias Gysi SmallVector<int64_t> arrayShape; 792f7cd55f5STobias Gysi while (auto arrayType = dyn_cast<LLVMArrayType>(type)) { 793f7cd55f5STobias Gysi arrayShape.push_back(arrayType.getNumElements()); 794f7cd55f5STobias Gysi type = arrayType.getElementType(); 795f7cd55f5STobias Gysi } 796f7cd55f5STobias Gysi if (isScalarType(type)) 797f7cd55f5STobias Gysi return RankedTensorType::get(arrayShape, type); 798f7cd55f5STobias Gysi return getVectorTypeForAttr(type, arrayShape); 7999dbf3625STobias Gysi } 8009dbf3625STobias Gysi 801f7cd55f5STobias Gysi /// Returns an integer or float attribute for the provided scalar constant 802f7cd55f5STobias Gysi /// `constScalar` or nullptr if the conversion fails. 803dbb86433SBenjamin Maxwell static TypedAttr getScalarConstantAsAttr(OpBuilder &builder, 804f7cd55f5STobias Gysi llvm::Constant *constScalar) { 805f7cd55f5STobias Gysi MLIRContext *context = builder.getContext(); 8069dbf3625STobias Gysi 807f7cd55f5STobias Gysi // Convert scalar intergers. 808f7cd55f5STobias Gysi if (auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) { 8099dbf3625STobias Gysi return builder.getIntegerAttr( 810dea16ebdSPaul Walker IntegerType::get(context, constInt->getBitWidth()), 811f7cd55f5STobias Gysi constInt->getValue()); 8129dbf3625STobias Gysi } 8139dbf3625STobias Gysi 814f7cd55f5STobias Gysi // Convert scalar floats. 815f7cd55f5STobias Gysi if (auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) { 816f7cd55f5STobias Gysi llvm::Type *type = constFloat->getType(); 817f7cd55f5STobias Gysi FloatType floatType = 818f7cd55f5STobias Gysi type->isBFloatTy() 819f023da12SMatthias Springer ? BFloat16Type::get(context) 820f7cd55f5STobias Gysi : LLVM::detail::getFloatType(context, type->getScalarSizeInBits()); 821f7cd55f5STobias Gysi if (!floatType) { 822f7cd55f5STobias Gysi emitError(UnknownLoc::get(builder.getContext())) 823f7cd55f5STobias Gysi << "unexpected floating-point type"; 824f7cd55f5STobias Gysi return {}; 825f7cd55f5STobias Gysi } 826f7cd55f5STobias Gysi return builder.getFloatAttr(floatType, constFloat->getValueAPF()); 827f7cd55f5STobias Gysi } 828f7cd55f5STobias Gysi return {}; 829f7cd55f5STobias Gysi } 830f7cd55f5STobias Gysi 831f7cd55f5STobias Gysi /// Returns an integer or float attribute array for the provided constant 832f7cd55f5STobias Gysi /// sequence `constSequence` or nullptr if the conversion fails. 833f7cd55f5STobias Gysi static SmallVector<Attribute> 834f7cd55f5STobias Gysi getSequenceConstantAsAttrs(OpBuilder &builder, 835f7cd55f5STobias Gysi llvm::ConstantDataSequential *constSequence) { 836f7cd55f5STobias Gysi SmallVector<Attribute> elementAttrs; 837f7cd55f5STobias Gysi elementAttrs.reserve(constSequence->getNumElements()); 838f7cd55f5STobias Gysi for (auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) { 839f7cd55f5STobias Gysi llvm::Constant *constElement = constSequence->getElementAsConstant(idx); 840f7cd55f5STobias Gysi elementAttrs.push_back(getScalarConstantAsAttr(builder, constElement)); 841f7cd55f5STobias Gysi } 842f7cd55f5STobias Gysi return elementAttrs; 843f7cd55f5STobias Gysi } 844f7cd55f5STobias Gysi 845f7cd55f5STobias Gysi Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) { 846f7cd55f5STobias Gysi // Convert scalar constants. 847f7cd55f5STobias Gysi if (Attribute scalarAttr = getScalarConstantAsAttr(builder, constant)) 848f7cd55f5STobias Gysi return scalarAttr; 849f7cd55f5STobias Gysi 850f7cd55f5STobias Gysi // Returns the static shape of the provided type if possible. 851f7cd55f5STobias Gysi auto getConstantShape = [&](llvm::Type *type) { 8528d3c4ff8SChristian Ulmann return llvm::dyn_cast_if_present<ShapedType>( 8538d3c4ff8SChristian Ulmann getBuiltinTypeForAttr(convertType(type))); 854f7cd55f5STobias Gysi }; 8559dbf3625STobias Gysi 856f7cd55f5STobias Gysi // Convert one-dimensional constant arrays or vectors that store 1/2/4/8-byte 857f7cd55f5STobias Gysi // integer or half/bfloat/float/double values. 858f7cd55f5STobias Gysi if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) { 859f7cd55f5STobias Gysi if (constArray->isString()) 860f7cd55f5STobias Gysi return builder.getStringAttr(constArray->getAsString()); 861f7cd55f5STobias Gysi auto shape = getConstantShape(constArray->getType()); 862f7cd55f5STobias Gysi if (!shape) 863f7cd55f5STobias Gysi return {}; 864f7cd55f5STobias Gysi // Convert splat constants to splat elements attributes. 865f7cd55f5STobias Gysi auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant); 866f7cd55f5STobias Gysi if (constVector && constVector->isSplat()) { 867f7cd55f5STobias Gysi // A vector is guaranteed to have at least size one. 868f7cd55f5STobias Gysi Attribute splatAttr = getScalarConstantAsAttr( 869f7cd55f5STobias Gysi builder, constVector->getElementAsConstant(0)); 870f7cd55f5STobias Gysi return SplatElementsAttr::get(shape, splatAttr); 871f7cd55f5STobias Gysi } 872f7cd55f5STobias Gysi // Convert non-splat constants to dense elements attributes. 873f7cd55f5STobias Gysi SmallVector<Attribute> elementAttrs = 874f7cd55f5STobias Gysi getSequenceConstantAsAttrs(builder, constArray); 875f7cd55f5STobias Gysi return DenseElementsAttr::get(shape, elementAttrs); 8769dbf3625STobias Gysi } 8779dbf3625STobias Gysi 878f7cd55f5STobias Gysi // Convert multi-dimensional constant aggregates that store all kinds of 879f7cd55f5STobias Gysi // integer and floating-point types. 880f7cd55f5STobias Gysi if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) { 881f7cd55f5STobias Gysi auto shape = getConstantShape(constAggregate->getType()); 882f7cd55f5STobias Gysi if (!shape) 883f7cd55f5STobias Gysi return {}; 884f7cd55f5STobias Gysi // Collect the aggregate elements in depths first order. 885f7cd55f5STobias Gysi SmallVector<Attribute> elementAttrs; 886f7cd55f5STobias Gysi SmallVector<llvm::Constant *> workList = {constAggregate}; 887f7cd55f5STobias Gysi while (!workList.empty()) { 888f7cd55f5STobias Gysi llvm::Constant *current = workList.pop_back_val(); 889f7cd55f5STobias Gysi // Append any nested aggregates in reverse order to ensure the head 890f7cd55f5STobias Gysi // element of the nested aggregates is at the back of the work list. 891f7cd55f5STobias Gysi if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) { 892f7cd55f5STobias Gysi for (auto idx : 893f7cd55f5STobias Gysi reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands()))) 894f7cd55f5STobias Gysi workList.push_back(constAggregate->getAggregateElement(idx)); 895f7cd55f5STobias Gysi continue; 896f7cd55f5STobias Gysi } 897f7cd55f5STobias Gysi // Append the elements of nested constant arrays or vectors that store 898f7cd55f5STobias Gysi // 1/2/4/8-byte integer or half/bfloat/float/double values. 899f7cd55f5STobias Gysi if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) { 900f7cd55f5STobias Gysi SmallVector<Attribute> attrs = 901f7cd55f5STobias Gysi getSequenceConstantAsAttrs(builder, constArray); 902f7cd55f5STobias Gysi elementAttrs.append(attrs.begin(), attrs.end()); 903f7cd55f5STobias Gysi continue; 904f7cd55f5STobias Gysi } 905f7cd55f5STobias Gysi // Append nested scalar constants that store all kinds of integer and 906f7cd55f5STobias Gysi // floating-point types. 907f7cd55f5STobias Gysi if (Attribute scalarAttr = getScalarConstantAsAttr(builder, current)) { 908f7cd55f5STobias Gysi elementAttrs.push_back(scalarAttr); 909f7cd55f5STobias Gysi continue; 910f7cd55f5STobias Gysi } 911f7cd55f5STobias Gysi // Bail if the aggregate contains a unsupported constant type such as a 912f7cd55f5STobias Gysi // constant expression. 913f7cd55f5STobias Gysi return {}; 914f7cd55f5STobias Gysi } 915f7cd55f5STobias Gysi return DenseElementsAttr::get(shape, elementAttrs); 9169dbf3625STobias Gysi } 9179dbf3625STobias Gysi 918f7cd55f5STobias Gysi // Convert zero aggregates. 919f7cd55f5STobias Gysi if (auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) { 9208d3c4ff8SChristian Ulmann auto shape = llvm::dyn_cast_if_present<ShapedType>( 9218d3c4ff8SChristian Ulmann getBuiltinTypeForAttr(convertType(constZero->getType()))); 922f7cd55f5STobias Gysi if (!shape) 923f7cd55f5STobias Gysi return {}; 924f7cd55f5STobias Gysi // Convert zero aggregates with a static shape to splat elements attributes. 925f7cd55f5STobias Gysi Attribute splatAttr = builder.getZeroAttr(shape.getElementType()); 926f7cd55f5STobias Gysi assert(splatAttr && "expected non-null zero attribute for scalar types"); 927f7cd55f5STobias Gysi return SplatElementsAttr::get(shape, splatAttr); 9289dbf3625STobias Gysi } 929f7cd55f5STobias Gysi return {}; 9309dbf3625STobias Gysi } 9319dbf3625STobias Gysi 93254d3cf14SChristian Ulmann FlatSymbolRefAttr 93354d3cf14SChristian Ulmann ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) { 93454d3cf14SChristian Ulmann assert(globalVar->getName().empty() && 93554d3cf14SChristian Ulmann "expected to work with a nameless global"); 93654d3cf14SChristian Ulmann auto [it, success] = namelessGlobals.try_emplace(globalVar); 93754d3cf14SChristian Ulmann if (!success) 93854d3cf14SChristian Ulmann return it->second; 93954d3cf14SChristian Ulmann 94054d3cf14SChristian Ulmann // Make sure the symbol name does not clash with an existing symbol. 94154d3cf14SChristian Ulmann SmallString<128> globalName = SymbolTable::generateSymbolName<128>( 94254d3cf14SChristian Ulmann getNamelessGlobalPrefix(), 94354d3cf14SChristian Ulmann [this](StringRef newName) { return llvmModule->getNamedValue(newName); }, 94454d3cf14SChristian Ulmann namelessGlobalId); 94554d3cf14SChristian Ulmann auto symbolRef = FlatSymbolRefAttr::get(context, globalName); 94654d3cf14SChristian Ulmann it->getSecond() = symbolRef; 94754d3cf14SChristian Ulmann return symbolRef; 94854d3cf14SChristian Ulmann } 94954d3cf14SChristian Ulmann 9500fde03cbSTobias Gysi LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) { 9519dbf3625STobias Gysi // Insert the global after the last one or at the start of the module. 9529dbf3625STobias Gysi OpBuilder::InsertionGuard guard(builder); 9530fde03cbSTobias Gysi if (!globalInsertionOp) 9549dbf3625STobias Gysi builder.setInsertionPointToStart(mlirModule.getBody()); 9550fde03cbSTobias Gysi else 9569dbf3625STobias Gysi builder.setInsertionPointAfter(globalInsertionOp); 9579dbf3625STobias Gysi 9589dbf3625STobias Gysi Attribute valueAttr; 9599dbf3625STobias Gysi if (globalVar->hasInitializer()) 9609dbf3625STobias Gysi valueAttr = getConstantAsAttr(globalVar->getInitializer()); 9619dbf3625STobias Gysi Type type = convertType(globalVar->getValueType()); 9629dbf3625STobias Gysi 9639dbf3625STobias Gysi uint64_t alignment = 0; 9649dbf3625STobias Gysi llvm::MaybeAlign maybeAlign = globalVar->getAlign(); 9659dbf3625STobias Gysi if (maybeAlign.has_value()) { 9669dbf3625STobias Gysi llvm::Align align = *maybeAlign; 9679dbf3625STobias Gysi alignment = align.value(); 9689dbf3625STobias Gysi } 9699dbf3625STobias Gysi 9706da578ceSJustin Wilson // Get the global expression associated with this global variable and convert 9716da578ceSJustin Wilson // it. 972cd12ffb6SAbid Qadeer SmallVector<Attribute> globalExpressionAttrs; 9736da578ceSJustin Wilson SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions; 9746da578ceSJustin Wilson globalVar->getDebugInfo(globalExpressions); 9756da578ceSJustin Wilson 976cd12ffb6SAbid Qadeer for (llvm::DIGlobalVariableExpression *expr : globalExpressions) { 977cd12ffb6SAbid Qadeer DIGlobalVariableExpressionAttr globalExpressionAttr = 978cd12ffb6SAbid Qadeer debugImporter->translateGlobalVariableExpression(expr); 979cd12ffb6SAbid Qadeer globalExpressionAttrs.push_back(globalExpressionAttr); 980cd12ffb6SAbid Qadeer } 9816da578ceSJustin Wilson 982fbee8d5aSIvan R. Ivanov // Workaround to support LLVM's nameless globals. MLIR, in contrast to LLVM, 983fbee8d5aSIvan R. Ivanov // always requires a symbol name. 98454d3cf14SChristian Ulmann StringRef globalName = globalVar->getName(); 98554d3cf14SChristian Ulmann if (globalName.empty()) 98654d3cf14SChristian Ulmann globalName = getOrCreateNamelessSymbolName(globalVar).getValue(); 98754d3cf14SChristian Ulmann 9889dbf3625STobias Gysi GlobalOp globalOp = builder.create<GlobalOp>( 9890fde03cbSTobias Gysi mlirModule.getLoc(), type, globalVar->isConstant(), 990fbee8d5aSIvan R. Ivanov convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName), 9919dbf3625STobias Gysi valueAttr, alignment, /*addr_space=*/globalVar->getAddressSpace(), 9929dbf3625STobias Gysi /*dso_local=*/globalVar->isDSOLocal(), 9936da578ceSJustin Wilson /*thread_local=*/globalVar->isThreadLocal(), /*comdat=*/SymbolRefAttr(), 994cd12ffb6SAbid Qadeer /*attrs=*/ArrayRef<NamedAttribute>(), /*dbgExprs=*/globalExpressionAttrs); 9959dbf3625STobias Gysi globalInsertionOp = globalOp; 9969dbf3625STobias Gysi 9979dbf3625STobias Gysi if (globalVar->hasInitializer() && !valueAttr) { 998b808648aSChristian Ulmann clearRegionState(); 9999dbf3625STobias Gysi Block *block = builder.createBlock(&globalOp.getInitializerRegion()); 10009dbf3625STobias Gysi setConstantInsertionPointToStart(block); 10019dbf3625STobias Gysi FailureOr<Value> initializer = 10029dbf3625STobias Gysi convertConstantExpr(globalVar->getInitializer()); 10039dbf3625STobias Gysi if (failed(initializer)) 10040fde03cbSTobias Gysi return failure(); 10059dbf3625STobias Gysi builder.create<ReturnOp>(globalOp.getLoc(), *initializer); 10069dbf3625STobias Gysi } 10079dbf3625STobias Gysi if (globalVar->hasAtLeastLocalUnnamedAddr()) { 10089dbf3625STobias Gysi globalOp.setUnnamedAddr( 10099dbf3625STobias Gysi convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr())); 10109dbf3625STobias Gysi } 10119dbf3625STobias Gysi if (globalVar->hasSection()) 10129dbf3625STobias Gysi globalOp.setSection(globalVar->getSection()); 10136628767eSChristian Ulmann globalOp.setVisibility_( 10146628767eSChristian Ulmann convertVisibilityFromLLVM(globalVar->getVisibility())); 10159dbf3625STobias Gysi 1016b126ee65STobias Gysi if (globalVar->hasComdat()) 1017b126ee65STobias Gysi globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat())); 10189d4c1be8SDavid Truby 10190fde03cbSTobias Gysi return success(); 10209dbf3625STobias Gysi } 10219dbf3625STobias Gysi 10229b76a302SChristian Ulmann LogicalResult 10239b76a302SChristian Ulmann ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) { 10249b76a302SChristian Ulmann if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage()) 10259b76a302SChristian Ulmann return failure(); 10269b76a302SChristian Ulmann auto *initializer = 10279b76a302SChristian Ulmann dyn_cast<llvm::ConstantArray>(globalVar->getInitializer()); 10289b76a302SChristian Ulmann if (!initializer) 10299b76a302SChristian Ulmann return failure(); 10309b76a302SChristian Ulmann 10319b76a302SChristian Ulmann SmallVector<Attribute> funcs; 10329b76a302SChristian Ulmann SmallVector<int32_t> priorities; 10339b76a302SChristian Ulmann for (llvm::Value *operand : initializer->operands()) { 10349b76a302SChristian Ulmann auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand); 10359b76a302SChristian Ulmann if (!aggregate || aggregate->getNumOperands() != 3) 10369b76a302SChristian Ulmann return failure(); 10379b76a302SChristian Ulmann 10389b76a302SChristian Ulmann auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0)); 10399b76a302SChristian Ulmann auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1)); 10409b76a302SChristian Ulmann auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2)); 10419b76a302SChristian Ulmann if (!priority || !func || !data) 10429b76a302SChristian Ulmann return failure(); 10439b76a302SChristian Ulmann 10449b76a302SChristian Ulmann // GlobalCtorsOps and GlobalDtorsOps do not support non-null data fields. 10459b76a302SChristian Ulmann if (!data->isNullValue()) 10469b76a302SChristian Ulmann return failure(); 10479b76a302SChristian Ulmann 10489b76a302SChristian Ulmann funcs.push_back(FlatSymbolRefAttr::get(context, func->getName())); 10499b76a302SChristian Ulmann priorities.push_back(priority->getValue().getZExtValue()); 10509b76a302SChristian Ulmann } 10519b76a302SChristian Ulmann 10529b76a302SChristian Ulmann OpBuilder::InsertionGuard guard(builder); 10539b76a302SChristian Ulmann if (!globalInsertionOp) 10549b76a302SChristian Ulmann builder.setInsertionPointToStart(mlirModule.getBody()); 10559b76a302SChristian Ulmann else 10569b76a302SChristian Ulmann builder.setInsertionPointAfter(globalInsertionOp); 10579b76a302SChristian Ulmann 10589b76a302SChristian Ulmann if (globalVar->getName() == getGlobalCtorsVarName()) { 10599b76a302SChristian Ulmann globalInsertionOp = builder.create<LLVM::GlobalCtorsOp>( 10609b76a302SChristian Ulmann mlirModule.getLoc(), builder.getArrayAttr(funcs), 10619b76a302SChristian Ulmann builder.getI32ArrayAttr(priorities)); 10629b76a302SChristian Ulmann return success(); 10639b76a302SChristian Ulmann } 10649b76a302SChristian Ulmann globalInsertionOp = builder.create<LLVM::GlobalDtorsOp>( 10659b76a302SChristian Ulmann mlirModule.getLoc(), builder.getArrayAttr(funcs), 10669b76a302SChristian Ulmann builder.getI32ArrayAttr(priorities)); 10679b76a302SChristian Ulmann return success(); 10689b76a302SChristian Ulmann } 10699b76a302SChristian Ulmann 10709dbf3625STobias Gysi SetVector<llvm::Constant *> 10719dbf3625STobias Gysi ModuleImport::getConstantsToConvert(llvm::Constant *constant) { 1072b6a2e335STobias Gysi // Return the empty set if the constant has been translated before. 1073dc47813eSTobias Gysi if (valueMapping.contains(constant)) 1074b6a2e335STobias Gysi return {}; 1075b6a2e335STobias Gysi 1076b6a2e335STobias Gysi // Traverse the constants in post-order and stop the traversal if a constant 1077b6a2e335STobias Gysi // already has a `valueMapping` from an earlier constant translation or if the 1078b6a2e335STobias Gysi // constant is traversed a second time. 1079b6a2e335STobias Gysi SetVector<llvm::Constant *> orderedSet; 1080b6a2e335STobias Gysi SetVector<llvm::Constant *> workList; 1081b6a2e335STobias Gysi DenseMap<llvm::Constant *, SmallVector<llvm::Constant *>> adjacencyLists; 1082b6a2e335STobias Gysi workList.insert(constant); 10839dbf3625STobias Gysi while (!workList.empty()) { 1084b6a2e335STobias Gysi llvm::Constant *current = workList.back(); 10851d3bfbb0SChristian Ulmann // References of global objects are just pointers to the object. Avoid 10861d3bfbb0SChristian Ulmann // walking the elements of these here. 10871d3bfbb0SChristian Ulmann if (isa<llvm::GlobalObject>(current)) { 10881d3bfbb0SChristian Ulmann orderedSet.insert(current); 10891d3bfbb0SChristian Ulmann workList.pop_back(); 10901d3bfbb0SChristian Ulmann continue; 10911d3bfbb0SChristian Ulmann } 10921d3bfbb0SChristian Ulmann 1093b6a2e335STobias Gysi // Collect all dependencies of the current constant and add them to the 1094b6a2e335STobias Gysi // adjacency list if none has been computed before. 10957cf18ff2SKazu Hirata auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current); 10967cf18ff2SKazu Hirata if (inserted) { 1097b6a2e335STobias Gysi // Add all constant operands to the adjacency list and skip any other 1098b6a2e335STobias Gysi // values such as basic block addresses. 10999dbf3625STobias Gysi for (llvm::Value *operand : current->operands()) 11009dbf3625STobias Gysi if (auto *constDependency = dyn_cast<llvm::Constant>(operand)) 1101b6a2e335STobias Gysi adjacencyIt->getSecond().push_back(constDependency); 1102b6a2e335STobias Gysi // Use the getElementValue method to add the dependencies of zero 11039dbf3625STobias Gysi // initialized aggregate constants since they do not take any operands. 11049dbf3625STobias Gysi if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) { 11059dbf3625STobias Gysi unsigned numElements = constAgg->getElementCount().getFixedValue(); 11069dbf3625STobias Gysi for (unsigned i = 0, e = numElements; i != e; ++i) 1107b6a2e335STobias Gysi adjacencyIt->getSecond().push_back(constAgg->getElementValue(i)); 11089dbf3625STobias Gysi } 11099dbf3625STobias Gysi } 1110b6a2e335STobias Gysi // Add the current constant to the `orderedSet` of the traversed nodes if 1111b6a2e335STobias Gysi // all its dependencies have been traversed before. Additionally, remove the 1112b6a2e335STobias Gysi // constant from the `workList` and continue the traversal. 1113b6a2e335STobias Gysi if (adjacencyIt->getSecond().empty()) { 1114b6a2e335STobias Gysi orderedSet.insert(current); 1115b6a2e335STobias Gysi workList.pop_back(); 1116b6a2e335STobias Gysi continue; 1117b6a2e335STobias Gysi } 1118b6a2e335STobias Gysi // Add the next dependency from the adjacency list to the `workList` and 1119b6a2e335STobias Gysi // continue the traversal. Remove the dependency from the adjacency list to 1120b6a2e335STobias Gysi // mark that it has been processed. Only enqueue the dependency if it has no 1121b6a2e335STobias Gysi // `valueMapping` from an earlier translation and if it has not been 1122b6a2e335STobias Gysi // enqueued before. 1123b6a2e335STobias Gysi llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val(); 1124dc47813eSTobias Gysi if (valueMapping.contains(dependency) || workList.contains(dependency) || 1125dc47813eSTobias Gysi orderedSet.contains(dependency)) 1126b6a2e335STobias Gysi continue; 1127b6a2e335STobias Gysi workList.insert(dependency); 1128b6a2e335STobias Gysi } 11299dbf3625STobias Gysi 11309dbf3625STobias Gysi return orderedSet; 11319dbf3625STobias Gysi } 11329dbf3625STobias Gysi 11339dbf3625STobias Gysi FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) { 11347d5b4ebbSChristian Ulmann Location loc = UnknownLoc::get(context); 11359dbf3625STobias Gysi 11369dbf3625STobias Gysi // Convert constants that can be represented as attributes. 11379dbf3625STobias Gysi if (Attribute attr = getConstantAsAttr(constant)) { 11389dbf3625STobias Gysi Type type = convertType(constant->getType()); 11395550c821STres Popp if (auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) { 11409dbf3625STobias Gysi return builder.create<AddressOfOp>(loc, type, symbolRef.getValue()) 11419dbf3625STobias Gysi .getResult(); 11429dbf3625STobias Gysi } 11439dbf3625STobias Gysi return builder.create<ConstantOp>(loc, type, attr).getResult(); 11449dbf3625STobias Gysi } 11459dbf3625STobias Gysi 11469dbf3625STobias Gysi // Convert null pointer constants. 11479dbf3625STobias Gysi if (auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) { 11489dbf3625STobias Gysi Type type = convertType(nullPtr->getType()); 114985175eddSTobias Gysi return builder.create<ZeroOp>(loc, type).getResult(); 11509dbf3625STobias Gysi } 11519dbf3625STobias Gysi 115251d5d7bbSAnton Korobeynikov // Convert none token constants. 115397217d18SMichael Liao if (isa<llvm::ConstantTokenNone>(constant)) { 115451d5d7bbSAnton Korobeynikov return builder.create<NoneTokenOp>(loc).getResult(); 115551d5d7bbSAnton Korobeynikov } 115651d5d7bbSAnton Korobeynikov 1157a35f9c6eSThéo Degioanni // Convert poison. 1158a35f9c6eSThéo Degioanni if (auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) { 1159a35f9c6eSThéo Degioanni Type type = convertType(poisonVal->getType()); 1160a35f9c6eSThéo Degioanni return builder.create<PoisonOp>(loc, type).getResult(); 1161a35f9c6eSThéo Degioanni } 1162a35f9c6eSThéo Degioanni 11639dbf3625STobias Gysi // Convert undef. 11649dbf3625STobias Gysi if (auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) { 11659dbf3625STobias Gysi Type type = convertType(undefVal->getType()); 11669dbf3625STobias Gysi return builder.create<UndefOp>(loc, type).getResult(); 11679dbf3625STobias Gysi } 11689dbf3625STobias Gysi 11699dbf3625STobias Gysi // Convert global variable accesses. 117054d3cf14SChristian Ulmann if (auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) { 117154d3cf14SChristian Ulmann Type type = convertType(globalObj->getType()); 117254d3cf14SChristian Ulmann StringRef globalName = globalObj->getName(); 1173fbee8d5aSIvan R. Ivanov FlatSymbolRefAttr symbolRef; 11741d3bfbb0SChristian Ulmann // Empty names are only allowed for global variables. 1175fbee8d5aSIvan R. Ivanov if (globalName.empty()) 117654d3cf14SChristian Ulmann symbolRef = 117754d3cf14SChristian Ulmann getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj)); 1178fbee8d5aSIvan R. Ivanov else 1179fbee8d5aSIvan R. Ivanov symbolRef = FlatSymbolRefAttr::get(context, globalName); 11800fde03cbSTobias Gysi return builder.create<AddressOfOp>(loc, type, symbolRef).getResult(); 11819dbf3625STobias Gysi } 11829dbf3625STobias Gysi 11839dbf3625STobias Gysi // Convert constant expressions. 11849dbf3625STobias Gysi if (auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) { 11859dbf3625STobias Gysi // Convert the constant expression to a temporary LLVM instruction and 11869dbf3625STobias Gysi // translate it using the `processInstruction` method. Delete the 11879dbf3625STobias Gysi // instruction after the translation and remove it from `valueMapping`, 11889dbf3625STobias Gysi // since later calls to `getAsInstruction` may return the same address 11899dbf3625STobias Gysi // resulting in a conflicting `valueMapping` entry. 11909dbf3625STobias Gysi llvm::Instruction *inst = constExpr->getAsInstruction(); 11919dbf3625STobias Gysi auto guard = llvm::make_scope_exit([&]() { 11924e585e51SKazu Hirata assert(!noResultOpMapping.contains(inst) && 11930cf06639STobias Gysi "expected constant expression to return a result"); 11949dbf3625STobias Gysi valueMapping.erase(inst); 11959dbf3625STobias Gysi inst->deleteValue(); 11969dbf3625STobias Gysi }); 11979dbf3625STobias Gysi // Note: `processInstruction` does not call `convertConstant` recursively 11989dbf3625STobias Gysi // since all constant dependencies have been converted before. 11999dbf3625STobias Gysi assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) { 1200dc47813eSTobias Gysi return valueMapping.contains(value); 12019dbf3625STobias Gysi })); 12029dbf3625STobias Gysi if (failed(processInstruction(inst))) 12039dbf3625STobias Gysi return failure(); 12049dbf3625STobias Gysi return lookupValue(inst); 12059dbf3625STobias Gysi } 12069dbf3625STobias Gysi 12079dbf3625STobias Gysi // Convert aggregate constants. 12089dbf3625STobias Gysi if (isa<llvm::ConstantAggregate>(constant) || 12099dbf3625STobias Gysi isa<llvm::ConstantAggregateZero>(constant)) { 12109dbf3625STobias Gysi // Lookup the aggregate elements that have been converted before. 12119dbf3625STobias Gysi SmallVector<Value> elementValues; 12129dbf3625STobias Gysi if (auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) { 12139dbf3625STobias Gysi elementValues.reserve(constAgg->getNumOperands()); 12149dbf3625STobias Gysi for (llvm::Value *operand : constAgg->operands()) 12159dbf3625STobias Gysi elementValues.push_back(lookupValue(operand)); 12169dbf3625STobias Gysi } 12179dbf3625STobias Gysi if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) { 12189dbf3625STobias Gysi unsigned numElements = constAgg->getElementCount().getFixedValue(); 12199dbf3625STobias Gysi elementValues.reserve(numElements); 12209dbf3625STobias Gysi for (unsigned i = 0, e = numElements; i != e; ++i) 12219dbf3625STobias Gysi elementValues.push_back(lookupValue(constAgg->getElementValue(i))); 12229dbf3625STobias Gysi } 12239dbf3625STobias Gysi assert(llvm::count(elementValues, nullptr) == 0 && 12249dbf3625STobias Gysi "expected all elements have been converted before"); 12259dbf3625STobias Gysi 12269dbf3625STobias Gysi // Generate an UndefOp as root value and insert the aggregate elements. 12279dbf3625STobias Gysi Type rootType = convertType(constant->getType()); 12285550c821STres Popp bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType); 12299dbf3625STobias Gysi assert((isArrayOrStruct || LLVM::isCompatibleVectorType(rootType)) && 12309dbf3625STobias Gysi "unrecognized aggregate type"); 12319dbf3625STobias Gysi Value root = builder.create<UndefOp>(loc, rootType); 12329dbf3625STobias Gysi for (const auto &it : llvm::enumerate(elementValues)) { 12339dbf3625STobias Gysi if (isArrayOrStruct) { 12349dbf3625STobias Gysi root = builder.create<InsertValueOp>(loc, root, it.value(), it.index()); 12359dbf3625STobias Gysi } else { 12369dbf3625STobias Gysi Attribute indexAttr = builder.getI32IntegerAttr(it.index()); 12379dbf3625STobias Gysi Value indexValue = 12389dbf3625STobias Gysi builder.create<ConstantOp>(loc, builder.getI32Type(), indexAttr); 12399dbf3625STobias Gysi root = builder.create<InsertElementOp>(loc, rootType, root, it.value(), 12409dbf3625STobias Gysi indexValue); 12419dbf3625STobias Gysi } 12429dbf3625STobias Gysi } 12439dbf3625STobias Gysi return root; 12449dbf3625STobias Gysi } 12459dbf3625STobias Gysi 12462582b2e3SLukas Sommer if (auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) { 12472582b2e3SLukas Sommer LLVMTargetExtType targetExtType = 12482582b2e3SLukas Sommer cast<LLVMTargetExtType>(convertType(constTargetNone->getType())); 12492582b2e3SLukas Sommer assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) && 12502582b2e3SLukas Sommer "target extension type does not support zero-initialization"); 125193e0658aSLukas Sommer // Create llvm.mlir.zero operation to represent zero-initialization of 125293e0658aSLukas Sommer // target extension type. 125393e0658aSLukas Sommer return builder.create<LLVM::ZeroOp>(loc, targetExtType).getRes(); 12542582b2e3SLukas Sommer } 12552582b2e3SLukas Sommer 12568ac014aeSTobias Gysi StringRef error = ""; 12578ac014aeSTobias Gysi if (isa<llvm::BlockAddress>(constant)) 12588ac014aeSTobias Gysi error = " since blockaddress(...) is unsupported"; 1259ca5e2e3aSArthur Lafrance 12608ac014aeSTobias Gysi return emitError(loc) << "unhandled constant: " << diag(*constant) << error; 12619dbf3625STobias Gysi } 12629dbf3625STobias Gysi 12639dbf3625STobias Gysi FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) { 1264c00b7c84STobias Gysi // Only call the function for constants that have not been translated before 1265c00b7c84STobias Gysi // since it updates the constant insertion point assuming the converted 1266c00b7c84STobias Gysi // constant has been introduced at the end of the constant section. 1267c00b7c84STobias Gysi assert(!valueMapping.contains(constant) && 1268c00b7c84STobias Gysi "expected constant has not been converted before"); 12699dbf3625STobias Gysi assert(constantInsertionBlock && 12709dbf3625STobias Gysi "expected the constant insertion block to be non-null"); 12719dbf3625STobias Gysi 1272c00b7c84STobias Gysi // Insert the constant after the last one or at the start of the entry block. 12739dbf3625STobias Gysi OpBuilder::InsertionGuard guard(builder); 12740fde03cbSTobias Gysi if (!constantInsertionOp) 12759dbf3625STobias Gysi builder.setInsertionPointToStart(constantInsertionBlock); 12760fde03cbSTobias Gysi else 12779dbf3625STobias Gysi builder.setInsertionPointAfter(constantInsertionOp); 12789dbf3625STobias Gysi 12799dbf3625STobias Gysi // Convert all constants of the expression and add them to `valueMapping`. 12809dbf3625STobias Gysi SetVector<llvm::Constant *> constantsToConvert = 12819dbf3625STobias Gysi getConstantsToConvert(constant); 12829dbf3625STobias Gysi for (llvm::Constant *constantToConvert : constantsToConvert) { 12839dbf3625STobias Gysi FailureOr<Value> converted = convertConstant(constantToConvert); 12849dbf3625STobias Gysi if (failed(converted)) 12859dbf3625STobias Gysi return failure(); 12869dbf3625STobias Gysi mapValue(constantToConvert, *converted); 12879dbf3625STobias Gysi } 12889dbf3625STobias Gysi 12899dbf3625STobias Gysi // Update the constant insertion point and return the converted constant. 12909dbf3625STobias Gysi Value result = lookupValue(constant); 12919dbf3625STobias Gysi constantInsertionOp = result.getDefiningOp(); 12929dbf3625STobias Gysi return result; 12939dbf3625STobias Gysi } 12949dbf3625STobias Gysi 12959dbf3625STobias Gysi FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) { 129628542e99SChristian Ulmann assert(!isa<llvm::MetadataAsValue>(value) && 129728542e99SChristian Ulmann "expected value to not be metadata"); 12989dbf3625STobias Gysi 12999dbf3625STobias Gysi // Return the mapped value if it has been converted before. 1300dc47813eSTobias Gysi auto it = valueMapping.find(value); 1301dc47813eSTobias Gysi if (it != valueMapping.end()) 1302dc47813eSTobias Gysi return it->getSecond(); 13039dbf3625STobias Gysi 13049dbf3625STobias Gysi // Convert constants such as immediate values that have no mapping yet. 13059dbf3625STobias Gysi if (auto *constant = dyn_cast<llvm::Constant>(value)) 13069dbf3625STobias Gysi return convertConstantExpr(constant); 13079dbf3625STobias Gysi 13087d5b4ebbSChristian Ulmann Location loc = UnknownLoc::get(context); 13099dbf3625STobias Gysi if (auto *inst = dyn_cast<llvm::Instruction>(value)) 13109dbf3625STobias Gysi loc = translateLoc(inst->getDebugLoc()); 13113589885dSTobias Gysi return emitError(loc) << "unhandled value: " << diag(*value); 13129dbf3625STobias Gysi } 13139dbf3625STobias Gysi 131428542e99SChristian Ulmann FailureOr<Value> ModuleImport::convertMetadataValue(llvm::Value *value) { 131528542e99SChristian Ulmann // A value may be wrapped as metadata, for example, when passed to a debug 131628542e99SChristian Ulmann // intrinsic. Unwrap these values before the conversion. 131728542e99SChristian Ulmann auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value); 131828542e99SChristian Ulmann if (!nodeAsVal) 131928542e99SChristian Ulmann return failure(); 132028542e99SChristian Ulmann auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata()); 132128542e99SChristian Ulmann if (!node) 132228542e99SChristian Ulmann return failure(); 132328542e99SChristian Ulmann value = node->getValue(); 132428542e99SChristian Ulmann 132528542e99SChristian Ulmann // Return the mapped value if it has been converted before. 1326dc47813eSTobias Gysi auto it = valueMapping.find(value); 1327dc47813eSTobias Gysi if (it != valueMapping.end()) 1328dc47813eSTobias Gysi return it->getSecond(); 132928542e99SChristian Ulmann 133028542e99SChristian Ulmann // Convert constants such as immediate values that have no mapping yet. 133128542e99SChristian Ulmann if (auto *constant = dyn_cast<llvm::Constant>(value)) 133228542e99SChristian Ulmann return convertConstantExpr(constant); 133328542e99SChristian Ulmann return failure(); 133428542e99SChristian Ulmann } 133528542e99SChristian Ulmann 13369dbf3625STobias Gysi FailureOr<SmallVector<Value>> 13379dbf3625STobias Gysi ModuleImport::convertValues(ArrayRef<llvm::Value *> values) { 13389dbf3625STobias Gysi SmallVector<Value> remapped; 13399dbf3625STobias Gysi remapped.reserve(values.size()); 13409dbf3625STobias Gysi for (llvm::Value *value : values) { 13419dbf3625STobias Gysi FailureOr<Value> converted = convertValue(value); 13429dbf3625STobias Gysi if (failed(converted)) 13439dbf3625STobias Gysi return failure(); 13449dbf3625STobias Gysi remapped.push_back(*converted); 13459dbf3625STobias Gysi } 13469dbf3625STobias Gysi return remapped; 13479dbf3625STobias Gysi } 13489dbf3625STobias Gysi 1349dbb86433SBenjamin Maxwell LogicalResult ModuleImport::convertIntrinsicArguments( 13501dfb104eSSirui Mu ArrayRef<llvm::Value *> values, ArrayRef<llvm::OperandBundleUse> opBundles, 13511dfb104eSSirui Mu bool requiresOpBundles, ArrayRef<unsigned> immArgPositions, 1352dbb86433SBenjamin Maxwell ArrayRef<StringLiteral> immArgAttrNames, SmallVectorImpl<Value> &valuesOut, 1353dbb86433SBenjamin Maxwell SmallVectorImpl<NamedAttribute> &attrsOut) { 1354dbb86433SBenjamin Maxwell assert(immArgPositions.size() == immArgAttrNames.size() && 1355dbb86433SBenjamin Maxwell "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal " 1356dbb86433SBenjamin Maxwell "length"); 1357dbb86433SBenjamin Maxwell 1358dbb86433SBenjamin Maxwell SmallVector<llvm::Value *> operands(values); 1359dbb86433SBenjamin Maxwell for (auto [immArgPos, immArgName] : 1360dbb86433SBenjamin Maxwell llvm::zip(immArgPositions, immArgAttrNames)) { 1361dbb86433SBenjamin Maxwell auto &value = operands[immArgPos]; 1362dbb86433SBenjamin Maxwell auto *constant = llvm::cast<llvm::Constant>(value); 1363dbb86433SBenjamin Maxwell auto attr = getScalarConstantAsAttr(builder, constant); 1364dbb86433SBenjamin Maxwell assert(attr && attr.getType().isIntOrFloat() && 1365dbb86433SBenjamin Maxwell "expected immarg to be float or integer constant"); 1366dbb86433SBenjamin Maxwell auto nameAttr = StringAttr::get(attr.getContext(), immArgName); 1367dbb86433SBenjamin Maxwell attrsOut.push_back({nameAttr, attr}); 1368dbb86433SBenjamin Maxwell // Mark matched attribute values as null (so they can be removed below). 1369dbb86433SBenjamin Maxwell value = nullptr; 1370dbb86433SBenjamin Maxwell } 1371dbb86433SBenjamin Maxwell 1372dbb86433SBenjamin Maxwell for (llvm::Value *value : operands) { 1373dbb86433SBenjamin Maxwell if (!value) 1374dbb86433SBenjamin Maxwell continue; 1375dbb86433SBenjamin Maxwell auto mlirValue = convertValue(value); 1376dbb86433SBenjamin Maxwell if (failed(mlirValue)) 1377dbb86433SBenjamin Maxwell return failure(); 1378dbb86433SBenjamin Maxwell valuesOut.push_back(*mlirValue); 1379dbb86433SBenjamin Maxwell } 1380dbb86433SBenjamin Maxwell 13811dfb104eSSirui Mu SmallVector<int> opBundleSizes; 13821dfb104eSSirui Mu SmallVector<Attribute> opBundleTagAttrs; 13831dfb104eSSirui Mu if (requiresOpBundles) { 13841dfb104eSSirui Mu opBundleSizes.reserve(opBundles.size()); 13851dfb104eSSirui Mu opBundleTagAttrs.reserve(opBundles.size()); 13861dfb104eSSirui Mu 13871dfb104eSSirui Mu for (const llvm::OperandBundleUse &bundle : opBundles) { 13881dfb104eSSirui Mu opBundleSizes.push_back(bundle.Inputs.size()); 13891dfb104eSSirui Mu opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName())); 13901dfb104eSSirui Mu 13911dfb104eSSirui Mu for (const llvm::Use &opBundleOperand : bundle.Inputs) { 13921dfb104eSSirui Mu auto operandMlirValue = convertValue(opBundleOperand.get()); 13931dfb104eSSirui Mu if (failed(operandMlirValue)) 13941dfb104eSSirui Mu return failure(); 13951dfb104eSSirui Mu valuesOut.push_back(*operandMlirValue); 13961dfb104eSSirui Mu } 13971dfb104eSSirui Mu } 13981dfb104eSSirui Mu 13991dfb104eSSirui Mu auto opBundleSizesAttr = DenseI32ArrayAttr::get(context, opBundleSizes); 14001dfb104eSSirui Mu auto opBundleSizesAttrNameAttr = 14011dfb104eSSirui Mu StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName()); 14021dfb104eSSirui Mu attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr}); 14031dfb104eSSirui Mu 14041dfb104eSSirui Mu auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs); 14051dfb104eSSirui Mu auto opBundleTagsAttrNameAttr = 14061dfb104eSSirui Mu StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName()); 14071dfb104eSSirui Mu attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr}); 14081dfb104eSSirui Mu } 14091dfb104eSSirui Mu 1410dbb86433SBenjamin Maxwell return success(); 1411dbb86433SBenjamin Maxwell } 1412dbb86433SBenjamin Maxwell 14139dbf3625STobias Gysi IntegerAttr ModuleImport::matchIntegerAttr(llvm::Value *value) { 14149dbf3625STobias Gysi IntegerAttr integerAttr; 14159dbf3625STobias Gysi FailureOr<Value> converted = convertValue(value); 14169dbf3625STobias Gysi bool success = succeeded(converted) && 14179dbf3625STobias Gysi matchPattern(*converted, m_Constant(&integerAttr)); 14184af24585STobias Gysi assert(success && "expected a constant integer value"); 14199dbf3625STobias Gysi (void)success; 14209dbf3625STobias Gysi return integerAttr; 14219dbf3625STobias Gysi } 14229dbf3625STobias Gysi 14234af24585STobias Gysi FloatAttr ModuleImport::matchFloatAttr(llvm::Value *value) { 14244af24585STobias Gysi FloatAttr floatAttr; 14254af24585STobias Gysi FailureOr<Value> converted = convertValue(value); 14264af24585STobias Gysi bool success = 14274af24585STobias Gysi succeeded(converted) && matchPattern(*converted, m_Constant(&floatAttr)); 14284af24585STobias Gysi assert(success && "expected a constant float value"); 14294af24585STobias Gysi (void)success; 14304af24585STobias Gysi return floatAttr; 14314af24585STobias Gysi } 14324af24585STobias Gysi 14339dbf3625STobias Gysi DILocalVariableAttr ModuleImport::matchLocalVariableAttr(llvm::Value *value) { 14349dbf3625STobias Gysi auto *nodeAsVal = cast<llvm::MetadataAsValue>(value); 14359dbf3625STobias Gysi auto *node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata()); 14369dbf3625STobias Gysi return debugImporter->translate(node); 14379dbf3625STobias Gysi } 14389dbf3625STobias Gysi 1439ac1b69b9STobias Gysi DILabelAttr ModuleImport::matchLabelAttr(llvm::Value *value) { 1440ac1b69b9STobias Gysi auto *nodeAsVal = cast<llvm::MetadataAsValue>(value); 1441ac1b69b9STobias Gysi auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata()); 1442ac1b69b9STobias Gysi return debugImporter->translate(node); 1443ac1b69b9STobias Gysi } 1444ac1b69b9STobias Gysi 144577cbc9bfSVictor Perez FPExceptionBehaviorAttr 144677cbc9bfSVictor Perez ModuleImport::matchFPExceptionBehaviorAttr(llvm::Value *value) { 144777cbc9bfSVictor Perez auto *metadata = cast<llvm::MetadataAsValue>(value); 144877cbc9bfSVictor Perez auto *mdstr = cast<llvm::MDString>(metadata->getMetadata()); 144977cbc9bfSVictor Perez std::optional<llvm::fp::ExceptionBehavior> optLLVM = 145077cbc9bfSVictor Perez llvm::convertStrToExceptionBehavior(mdstr->getString()); 145177cbc9bfSVictor Perez assert(optLLVM && "Expecting FP exception behavior"); 145277cbc9bfSVictor Perez return builder.getAttr<FPExceptionBehaviorAttr>( 145377cbc9bfSVictor Perez convertFPExceptionBehaviorFromLLVM(*optLLVM)); 145477cbc9bfSVictor Perez } 145577cbc9bfSVictor Perez 145677cbc9bfSVictor Perez RoundingModeAttr ModuleImport::matchRoundingModeAttr(llvm::Value *value) { 145777cbc9bfSVictor Perez auto *metadata = cast<llvm::MetadataAsValue>(value); 145877cbc9bfSVictor Perez auto *mdstr = cast<llvm::MDString>(metadata->getMetadata()); 145977cbc9bfSVictor Perez std::optional<llvm::RoundingMode> optLLVM = 146077cbc9bfSVictor Perez llvm::convertStrToRoundingMode(mdstr->getString()); 146177cbc9bfSVictor Perez assert(optLLVM && "Expecting rounding mode"); 146277cbc9bfSVictor Perez return builder.getAttr<RoundingModeAttr>( 146377cbc9bfSVictor Perez convertRoundingModeFromLLVM(*optLLVM)); 146477cbc9bfSVictor Perez } 146577cbc9bfSVictor Perez 146678d00a16SMarkus Böck FailureOr<SmallVector<AliasScopeAttr>> 146756d94a90STobias Gysi ModuleImport::matchAliasScopeAttrs(llvm::Value *value) { 146856d94a90STobias Gysi auto *nodeAsVal = cast<llvm::MetadataAsValue>(value); 146956d94a90STobias Gysi auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata()); 147056d94a90STobias Gysi return lookupAliasScopeAttrs(node); 147156d94a90STobias Gysi } 147256d94a90STobias Gysi 14739dbf3625STobias Gysi Location ModuleImport::translateLoc(llvm::DILocation *loc) { 14749dbf3625STobias Gysi return debugImporter->translateLoc(loc); 14759dbf3625STobias Gysi } 14769dbf3625STobias Gysi 14779dbf3625STobias Gysi LogicalResult 14789dbf3625STobias Gysi ModuleImport::convertBranchArgs(llvm::Instruction *branch, 14799dbf3625STobias Gysi llvm::BasicBlock *target, 14809dbf3625STobias Gysi SmallVectorImpl<Value> &blockArguments) { 14819dbf3625STobias Gysi for (auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) { 14829dbf3625STobias Gysi auto *phiInst = cast<llvm::PHINode>(&*inst); 14839dbf3625STobias Gysi llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent()); 14849dbf3625STobias Gysi FailureOr<Value> converted = convertValue(value); 14859dbf3625STobias Gysi if (failed(converted)) 14869dbf3625STobias Gysi return failure(); 14879dbf3625STobias Gysi blockArguments.push_back(*converted); 14889dbf3625STobias Gysi } 14899dbf3625STobias Gysi return success(); 14909dbf3625STobias Gysi } 14919dbf3625STobias Gysi 14922a1f7958SHenrich Lauko FailureOr<SmallVector<Value>> 14932a1f7958SHenrich Lauko ModuleImport::convertCallOperands(llvm::CallBase *callInst, 14942a1f7958SHenrich Lauko bool allowInlineAsm) { 149595d993a8SHenrich Lauko bool isInlineAsm = callInst->isInlineAsm(); 149695d993a8SHenrich Lauko if (isInlineAsm && !allowInlineAsm) 149795d993a8SHenrich Lauko return failure(); 149895d993a8SHenrich Lauko 14992a1f7958SHenrich Lauko SmallVector<Value> operands; 15002a1f7958SHenrich Lauko 150195d993a8SHenrich Lauko // Cannot use isIndirectCall() here because we need to handle Constant callees 150295d993a8SHenrich Lauko // that are not considered indirect calls by LLVM. However, in MLIR, they are 150395d993a8SHenrich Lauko // treated as indirect calls to constant operands that need to be converted. 150495d993a8SHenrich Lauko // Skip the callee operand if it's inline assembly, as it's handled separately 150595d993a8SHenrich Lauko // in InlineAsmOp. 150695d993a8SHenrich Lauko if (!isa<llvm::Function>(callInst->getCalledOperand()) && !isInlineAsm) { 15079dbf3625STobias Gysi FailureOr<Value> called = convertValue(callInst->getCalledOperand()); 15089dbf3625STobias Gysi if (failed(called)) 15099dbf3625STobias Gysi return failure(); 15109dbf3625STobias Gysi operands.push_back(*called); 15119dbf3625STobias Gysi } 151295d993a8SHenrich Lauko 15139dbf3625STobias Gysi SmallVector<llvm::Value *> args(callInst->args()); 15149dbf3625STobias Gysi FailureOr<SmallVector<Value>> arguments = convertValues(args); 15159dbf3625STobias Gysi if (failed(arguments)) 15169dbf3625STobias Gysi return failure(); 15172a1f7958SHenrich Lauko 15189dbf3625STobias Gysi llvm::append_range(operands, *arguments); 15192a1f7958SHenrich Lauko return operands; 15202a1f7958SHenrich Lauko } 15212a1f7958SHenrich Lauko 15222a1f7958SHenrich Lauko LLVMFunctionType ModuleImport::convertFunctionType(llvm::CallBase *callInst) { 15232a1f7958SHenrich Lauko llvm::Value *calledOperand = callInst->getCalledOperand(); 15242a1f7958SHenrich Lauko Type converted = [&] { 15252a1f7958SHenrich Lauko if (auto callee = dyn_cast<llvm::Function>(calledOperand)) 15262a1f7958SHenrich Lauko return convertType(callee->getFunctionType()); 15272a1f7958SHenrich Lauko return convertType(callInst->getFunctionType()); 15282a1f7958SHenrich Lauko }(); 15292a1f7958SHenrich Lauko 15302a1f7958SHenrich Lauko if (auto funcTy = dyn_cast_or_null<LLVMFunctionType>(converted)) 15312a1f7958SHenrich Lauko return funcTy; 15322a1f7958SHenrich Lauko return {}; 15332a1f7958SHenrich Lauko } 15342a1f7958SHenrich Lauko 15352a1f7958SHenrich Lauko FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) { 15362a1f7958SHenrich Lauko llvm::Value *calledOperand = callInst->getCalledOperand(); 15372a1f7958SHenrich Lauko if (auto callee = dyn_cast<llvm::Function>(calledOperand)) 15382a1f7958SHenrich Lauko return SymbolRefAttr::get(context, callee->getName()); 15392a1f7958SHenrich Lauko return {}; 15409dbf3625STobias Gysi } 15419dbf3625STobias Gysi 15426e395206STobias Gysi LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) { 1543cf487cceSTobias Gysi if (succeeded(iface.convertIntrinsic(builder, inst, *this))) 1544cf487cceSTobias Gysi return success(); 1545cf487cceSTobias Gysi 15469dbf3625STobias Gysi Location loc = translateLoc(inst->getDebugLoc()); 15473589885dSTobias Gysi return emitError(loc) << "unhandled intrinsic: " << diag(*inst); 15489dbf3625STobias Gysi } 15499dbf3625STobias Gysi 15506e395206STobias Gysi LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) { 15516e395206STobias Gysi // Convert all instructions that do not provide an MLIR builder. 15529dbf3625STobias Gysi Location loc = translateLoc(inst->getDebugLoc()); 15539dbf3625STobias Gysi if (inst->getOpcode() == llvm::Instruction::Br) { 15549dbf3625STobias Gysi auto *brInst = cast<llvm::BranchInst>(inst); 15559dbf3625STobias Gysi 15569dbf3625STobias Gysi SmallVector<Block *> succBlocks; 15579dbf3625STobias Gysi SmallVector<SmallVector<Value>> succBlockArgs; 15589dbf3625STobias Gysi for (auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) { 15599dbf3625STobias Gysi llvm::BasicBlock *succ = brInst->getSuccessor(i); 15609dbf3625STobias Gysi SmallVector<Value> blockArgs; 15619dbf3625STobias Gysi if (failed(convertBranchArgs(brInst, succ, blockArgs))) 15629dbf3625STobias Gysi return failure(); 15639dbf3625STobias Gysi succBlocks.push_back(lookupBlock(succ)); 15649dbf3625STobias Gysi succBlockArgs.push_back(blockArgs); 15659dbf3625STobias Gysi } 15669dbf3625STobias Gysi 15670cf06639STobias Gysi if (!brInst->isConditional()) { 15680cf06639STobias Gysi auto brOp = builder.create<LLVM::BrOp>(loc, succBlockArgs.front(), 15690cf06639STobias Gysi succBlocks.front()); 15700cf06639STobias Gysi mapNoResultOp(inst, brOp); 15710cf06639STobias Gysi return success(); 15720cf06639STobias Gysi } 15739dbf3625STobias Gysi FailureOr<Value> condition = convertValue(brInst->getCondition()); 15749dbf3625STobias Gysi if (failed(condition)) 15759dbf3625STobias Gysi return failure(); 15760cf06639STobias Gysi auto condBrOp = builder.create<LLVM::CondBrOp>( 15770cf06639STobias Gysi loc, *condition, succBlocks.front(), succBlockArgs.front(), 15780cf06639STobias Gysi succBlocks.back(), succBlockArgs.back()); 15790cf06639STobias Gysi mapNoResultOp(inst, condBrOp); 15809dbf3625STobias Gysi return success(); 15819dbf3625STobias Gysi } 15829dbf3625STobias Gysi if (inst->getOpcode() == llvm::Instruction::Switch) { 15839dbf3625STobias Gysi auto *swInst = cast<llvm::SwitchInst>(inst); 15849dbf3625STobias Gysi // Process the condition value. 15859dbf3625STobias Gysi FailureOr<Value> condition = convertValue(swInst->getCondition()); 15869dbf3625STobias Gysi if (failed(condition)) 15879dbf3625STobias Gysi return failure(); 15889dbf3625STobias Gysi SmallVector<Value> defaultBlockArgs; 15899dbf3625STobias Gysi // Process the default case. 15909dbf3625STobias Gysi llvm::BasicBlock *defaultBB = swInst->getDefaultDest(); 15919dbf3625STobias Gysi if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs))) 15929dbf3625STobias Gysi return failure(); 15939dbf3625STobias Gysi 15949dbf3625STobias Gysi // Process the cases. 15959dbf3625STobias Gysi unsigned numCases = swInst->getNumCases(); 15969dbf3625STobias Gysi SmallVector<SmallVector<Value>> caseOperands(numCases); 15979dbf3625STobias Gysi SmallVector<ValueRange> caseOperandRefs(numCases); 159888f07a31STobias Gysi SmallVector<APInt> caseValues(numCases); 15999dbf3625STobias Gysi SmallVector<Block *> caseBlocks(numCases); 16009dbf3625STobias Gysi for (const auto &it : llvm::enumerate(swInst->cases())) { 16019dbf3625STobias Gysi const llvm::SwitchInst::CaseHandle &caseHandle = it.value(); 16029dbf3625STobias Gysi llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor(); 16039dbf3625STobias Gysi if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()]))) 16049dbf3625STobias Gysi return failure(); 16059dbf3625STobias Gysi caseOperandRefs[it.index()] = caseOperands[it.index()]; 160688f07a31STobias Gysi caseValues[it.index()] = caseHandle.getCaseValue()->getValue(); 16079dbf3625STobias Gysi caseBlocks[it.index()] = lookupBlock(succBB); 16089dbf3625STobias Gysi } 16099dbf3625STobias Gysi 16100cf06639STobias Gysi auto switchOp = builder.create<SwitchOp>( 16110cf06639STobias Gysi loc, *condition, lookupBlock(defaultBB), defaultBlockArgs, caseValues, 16120cf06639STobias Gysi caseBlocks, caseOperandRefs); 16130cf06639STobias Gysi mapNoResultOp(inst, switchOp); 16149dbf3625STobias Gysi return success(); 16159dbf3625STobias Gysi } 16169dbf3625STobias Gysi if (inst->getOpcode() == llvm::Instruction::PHI) { 16179dbf3625STobias Gysi Type type = convertType(inst->getType()); 16189dbf3625STobias Gysi mapValue(inst, builder.getInsertionBlock()->addArgument( 16199dbf3625STobias Gysi type, translateLoc(inst->getDebugLoc()))); 16209dbf3625STobias Gysi return success(); 16219dbf3625STobias Gysi } 16229dbf3625STobias Gysi if (inst->getOpcode() == llvm::Instruction::Call) { 162395d993a8SHenrich Lauko auto callInst = cast<llvm::CallInst>(inst); 162495d993a8SHenrich Lauko llvm::Value *calledOperand = callInst->getCalledOperand(); 16259dbf3625STobias Gysi 16262a1f7958SHenrich Lauko FailureOr<SmallVector<Value>> operands = 16272a1f7958SHenrich Lauko convertCallOperands(callInst, /*allowInlineAsm=*/true); 16282a1f7958SHenrich Lauko if (failed(operands)) 16299dbf3625STobias Gysi return failure(); 16309dbf3625STobias Gysi 16312a1f7958SHenrich Lauko auto callOp = [&]() -> FailureOr<Operation *> { 163295d993a8SHenrich Lauko if (auto asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) { 163395d993a8SHenrich Lauko Type resultTy = convertType(callInst->getType()); 163495d993a8SHenrich Lauko if (!resultTy) 163526eb4285SIvan R. Ivanov return failure(); 16362a1f7958SHenrich Lauko return builder 16372a1f7958SHenrich Lauko .create<InlineAsmOp>( 16382a1f7958SHenrich Lauko loc, resultTy, *operands, 16392a1f7958SHenrich Lauko builder.getStringAttr(asmI->getAsmString()), 1640b5f21671SWilliam Moses builder.getStringAttr(asmI->getConstraintString()), 1641b5f21671SWilliam Moses /*has_side_effects=*/true, 1642b5f21671SWilliam Moses /*is_align_stack=*/false, /*asm_dialect=*/nullptr, 16432a1f7958SHenrich Lauko /*operand_attrs=*/nullptr) 16442a1f7958SHenrich Lauko .getOperation(); 1645b5f21671SWilliam Moses } else { 16462a1f7958SHenrich Lauko LLVMFunctionType funcTy = convertFunctionType(callInst); 164795d993a8SHenrich Lauko if (!funcTy) 164895d993a8SHenrich Lauko return failure(); 164995d993a8SHenrich Lauko 16502a1f7958SHenrich Lauko FlatSymbolRefAttr callee = convertCalleeName(callInst); 16512a1f7958SHenrich Lauko auto callOp = builder.create<CallOp>(loc, funcTy, callee, *operands); 16522a1f7958SHenrich Lauko if (failed(convertCallAttributes(callInst, callOp))) 16532a1f7958SHenrich Lauko return failure(); 16542a1f7958SHenrich Lauko return callOp.getOperation(); 16559dbf3625STobias Gysi } 165695d993a8SHenrich Lauko }(); 165795d993a8SHenrich Lauko 16582a1f7958SHenrich Lauko if (failed(callOp)) 16592a1f7958SHenrich Lauko return failure(); 1660fde27bd2SFinlay 16619dbf3625STobias Gysi if (!callInst->getType()->isVoidTy()) 16622a1f7958SHenrich Lauko mapValue(inst, (*callOp)->getResult(0)); 16630cf06639STobias Gysi else 16642a1f7958SHenrich Lauko mapNoResultOp(inst, *callOp); 16659dbf3625STobias Gysi return success(); 16669dbf3625STobias Gysi } 16679dbf3625STobias Gysi if (inst->getOpcode() == llvm::Instruction::LandingPad) { 16689dbf3625STobias Gysi auto *lpInst = cast<llvm::LandingPadInst>(inst); 16699dbf3625STobias Gysi 16709dbf3625STobias Gysi SmallVector<Value> operands; 16719dbf3625STobias Gysi operands.reserve(lpInst->getNumClauses()); 16729dbf3625STobias Gysi for (auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) { 1673d67901ddSVictor Perez FailureOr<Value> operand = convertValue(lpInst->getClause(i)); 16749dbf3625STobias Gysi if (failed(operand)) 16759dbf3625STobias Gysi return failure(); 16769dbf3625STobias Gysi operands.push_back(*operand); 16779dbf3625STobias Gysi } 16789dbf3625STobias Gysi 16799dbf3625STobias Gysi Type type = convertType(lpInst->getType()); 16800cf06639STobias Gysi auto lpOp = 16819dbf3625STobias Gysi builder.create<LandingpadOp>(loc, type, lpInst->isCleanup(), operands); 16820cf06639STobias Gysi mapValue(inst, lpOp); 16839dbf3625STobias Gysi return success(); 16849dbf3625STobias Gysi } 16859dbf3625STobias Gysi if (inst->getOpcode() == llvm::Instruction::Invoke) { 16869dbf3625STobias Gysi auto *invokeInst = cast<llvm::InvokeInst>(inst); 16879dbf3625STobias Gysi 16882a1f7958SHenrich Lauko if (invokeInst->isInlineAsm()) 16892a1f7958SHenrich Lauko return emitError(loc) << "invoke of inline assembly is not supported"; 16902a1f7958SHenrich Lauko 16912a1f7958SHenrich Lauko FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst); 16922a1f7958SHenrich Lauko if (failed(operands)) 16939dbf3625STobias Gysi return failure(); 16949dbf3625STobias Gysi 1695be717f0aSVictor Perez // Check whether the invoke result is an argument to the normal destination 1696be717f0aSVictor Perez // block. 1697be717f0aSVictor Perez bool invokeResultUsedInPhi = llvm::any_of( 1698be717f0aSVictor Perez invokeInst->getNormalDest()->phis(), [&](const llvm::PHINode &phi) { 1699be717f0aSVictor Perez return phi.getIncomingValueForBlock(invokeInst->getParent()) == 1700be717f0aSVictor Perez invokeInst; 1701be717f0aSVictor Perez }); 17029dbf3625STobias Gysi 1703be717f0aSVictor Perez Block *normalDest = lookupBlock(invokeInst->getNormalDest()); 1704be717f0aSVictor Perez Block *directNormalDest = normalDest; 1705be717f0aSVictor Perez if (invokeResultUsedInPhi) { 1706be717f0aSVictor Perez // The invoke result cannot be an argument to the normal destination 1707be717f0aSVictor Perez // block, as that would imply using the invoke operation result in its 1708be717f0aSVictor Perez // definition, so we need to create a dummy block to serve as an 1709be717f0aSVictor Perez // intermediate destination. 1710be717f0aSVictor Perez OpBuilder::InsertionGuard g(builder); 1711be717f0aSVictor Perez directNormalDest = builder.createBlock(normalDest); 1712be717f0aSVictor Perez } 1713be717f0aSVictor Perez 1714be717f0aSVictor Perez SmallVector<Value> unwindArgs; 1715be717f0aSVictor Perez if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(), 1716be717f0aSVictor Perez unwindArgs))) 1717be717f0aSVictor Perez return failure(); 1718be717f0aSVictor Perez 17192a1f7958SHenrich Lauko auto funcTy = convertFunctionType(invokeInst); 172026eb4285SIvan R. Ivanov if (!funcTy) 172126eb4285SIvan R. Ivanov return failure(); 172226eb4285SIvan R. Ivanov 17232a1f7958SHenrich Lauko FlatSymbolRefAttr calleeName = convertCalleeName(invokeInst); 17242a1f7958SHenrich Lauko 1725be717f0aSVictor Perez // Create the invoke operation. Normal destination block arguments will be 1726be717f0aSVictor Perez // added later on to handle the case in which the operation result is 1727be717f0aSVictor Perez // included in this list. 17282a1f7958SHenrich Lauko auto invokeOp = builder.create<InvokeOp>( 17292a1f7958SHenrich Lauko loc, funcTy, calleeName, *operands, directNormalDest, ValueRange(), 17309dbf3625STobias Gysi lookupBlock(invokeInst->getUnwindDest()), unwindArgs); 17312a1f7958SHenrich Lauko 17322a1f7958SHenrich Lauko if (failed(convertInvokeAttributes(invokeInst, invokeOp))) 17332a1f7958SHenrich Lauko return failure(); 17342a1f7958SHenrich Lauko 17359dbf3625STobias Gysi if (!invokeInst->getType()->isVoidTy()) 17369dbf3625STobias Gysi mapValue(inst, invokeOp.getResults().front()); 17370cf06639STobias Gysi else 17380cf06639STobias Gysi mapNoResultOp(inst, invokeOp); 1739be717f0aSVictor Perez 1740be717f0aSVictor Perez SmallVector<Value> normalArgs; 1741be717f0aSVictor Perez if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(), 1742be717f0aSVictor Perez normalArgs))) 1743be717f0aSVictor Perez return failure(); 1744be717f0aSVictor Perez 1745be717f0aSVictor Perez if (invokeResultUsedInPhi) { 1746be717f0aSVictor Perez // The dummy normal dest block will just host an unconditional branch 1747be717f0aSVictor Perez // instruction to the normal destination block passing the required block 1748be717f0aSVictor Perez // arguments (including the invoke operation's result). 1749be717f0aSVictor Perez OpBuilder::InsertionGuard g(builder); 1750be717f0aSVictor Perez builder.setInsertionPointToStart(directNormalDest); 1751be717f0aSVictor Perez builder.create<LLVM::BrOp>(loc, normalArgs, normalDest); 1752be717f0aSVictor Perez } else { 1753be717f0aSVictor Perez // If the invoke operation's result is not a block argument to the normal 1754be717f0aSVictor Perez // destination block, just add the block arguments as usual. 1755be717f0aSVictor Perez assert(llvm::none_of( 1756be717f0aSVictor Perez normalArgs, 1757be717f0aSVictor Perez [&](Value val) { return val.getDefiningOp() == invokeOp; }) && 1758be717f0aSVictor Perez "An llvm.invoke operation cannot pass its result as a block " 1759be717f0aSVictor Perez "argument."); 1760be717f0aSVictor Perez invokeOp.getNormalDestOperandsMutable().append(normalArgs); 1761be717f0aSVictor Perez } 1762be717f0aSVictor Perez 17639dbf3625STobias Gysi return success(); 17649dbf3625STobias Gysi } 17659dbf3625STobias Gysi if (inst->getOpcode() == llvm::Instruction::GetElementPtr) { 17669dbf3625STobias Gysi auto *gepInst = cast<llvm::GetElementPtrInst>(inst); 17679dbf3625STobias Gysi Type sourceElementType = convertType(gepInst->getSourceElementType()); 17689dbf3625STobias Gysi FailureOr<Value> basePtr = convertValue(gepInst->getOperand(0)); 17699dbf3625STobias Gysi if (failed(basePtr)) 17709dbf3625STobias Gysi return failure(); 17719dbf3625STobias Gysi 17729dbf3625STobias Gysi // Treat every indices as dynamic since GEPOp::build will refine those 17739dbf3625STobias Gysi // indices into static attributes later. One small downside of this 17749dbf3625STobias Gysi // approach is that many unused `llvm.mlir.constant` would be emitted 17759dbf3625STobias Gysi // at first place. 17769dbf3625STobias Gysi SmallVector<GEPArg> indices; 17779dbf3625STobias Gysi for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) { 17789dbf3625STobias Gysi FailureOr<Value> index = convertValue(operand); 17799dbf3625STobias Gysi if (failed(index)) 17809dbf3625STobias Gysi return failure(); 17819dbf3625STobias Gysi indices.push_back(*index); 17829dbf3625STobias Gysi } 17839dbf3625STobias Gysi 17849dbf3625STobias Gysi Type type = convertType(inst->getType()); 17850cf06639STobias Gysi auto gepOp = builder.create<GEPOp>(loc, type, sourceElementType, *basePtr, 17869dbf3625STobias Gysi indices, gepInst->isInBounds()); 17870cf06639STobias Gysi mapValue(inst, gepOp); 17889dbf3625STobias Gysi return success(); 17899dbf3625STobias Gysi } 17909dbf3625STobias Gysi 17916e395206STobias Gysi // Convert all instructions that have an mlirBuilder. 1792a2c4b7c8SFabian Mora if (succeeded(convertInstructionImpl(builder, inst, *this, iface))) 17936e395206STobias Gysi return success(); 17946e395206STobias Gysi 17953589885dSTobias Gysi return emitError(loc) << "unhandled instruction: " << diag(*inst); 17969dbf3625STobias Gysi } 17979dbf3625STobias Gysi 17989dbf3625STobias Gysi LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) { 17999dbf3625STobias Gysi // FIXME: Support uses of SubtargetData. 18009dbf3625STobias Gysi // FIXME: Add support for call / operand attributes. 18019dbf3625STobias Gysi // FIXME: Add support for the indirectbr, cleanupret, catchret, catchswitch, 1802b808648aSChristian Ulmann // callbr, vaarg, catchpad, cleanuppad instructions. 18039dbf3625STobias Gysi 18049dbf3625STobias Gysi // Convert LLVM intrinsics calls to MLIR intrinsics. 1805b808648aSChristian Ulmann if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst)) 1806b808648aSChristian Ulmann return convertIntrinsic(intrinsic); 18079dbf3625STobias Gysi 18089dbf3625STobias Gysi // Convert all remaining LLVM instructions to MLIR operations. 18096e395206STobias Gysi return convertInstruction(inst); 18109dbf3625STobias Gysi } 18119dbf3625STobias Gysi 18129dbf3625STobias Gysi FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) { 18139dbf3625STobias Gysi if (!f->hasPersonalityFn()) 18149dbf3625STobias Gysi return nullptr; 18159dbf3625STobias Gysi 18169dbf3625STobias Gysi llvm::Constant *pf = f->getPersonalityFn(); 18179dbf3625STobias Gysi 18189dbf3625STobias Gysi // If it directly has a name, we can use it. 18199dbf3625STobias Gysi if (pf->hasName()) 18209dbf3625STobias Gysi return SymbolRefAttr::get(builder.getContext(), pf->getName()); 18219dbf3625STobias Gysi 18229dbf3625STobias Gysi // If it doesn't have a name, currently, only function pointers that are 18239dbf3625STobias Gysi // bitcast to i8* are parsed. 18249dbf3625STobias Gysi if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) { 18259dbf3625STobias Gysi if (ce->getOpcode() == llvm::Instruction::BitCast && 18267b9d73c2SPaulo Matos ce->getType() == llvm::PointerType::getUnqual(f->getContext())) { 18279dbf3625STobias Gysi if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0))) 18289dbf3625STobias Gysi return SymbolRefAttr::get(builder.getContext(), func->getName()); 18299dbf3625STobias Gysi } 18309dbf3625STobias Gysi } 18319dbf3625STobias Gysi return FlatSymbolRefAttr(); 18329dbf3625STobias Gysi } 18339dbf3625STobias Gysi 18349b9cfe77SChristian Ulmann static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp) { 18359b9cfe77SChristian Ulmann llvm::MemoryEffects memEffects = func->getMemoryEffects(); 18369b9cfe77SChristian Ulmann 18379b9cfe77SChristian Ulmann auto othermem = convertModRefInfoFromLLVM( 18389b9cfe77SChristian Ulmann memEffects.getModRef(llvm::MemoryEffects::Location::Other)); 18399b9cfe77SChristian Ulmann auto argMem = convertModRefInfoFromLLVM( 18409b9cfe77SChristian Ulmann memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem)); 18419b9cfe77SChristian Ulmann auto inaccessibleMem = convertModRefInfoFromLLVM( 18429b9cfe77SChristian Ulmann memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem)); 18439b9cfe77SChristian Ulmann auto memAttr = MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem, 18449b9cfe77SChristian Ulmann inaccessibleMem); 18459b9cfe77SChristian Ulmann // Only set the attr when it does not match the default value. 18469b9cfe77SChristian Ulmann if (memAttr.isReadWrite()) 18479b9cfe77SChristian Ulmann return; 18482eea9d6aSFinlay funcOp.setMemoryEffectsAttr(memAttr); 18499b9cfe77SChristian Ulmann } 18509b9cfe77SChristian Ulmann 1851783ac3b6SBenjamin Maxwell // List of LLVM IR attributes that map to an explicit attribute on the MLIR 1852783ac3b6SBenjamin Maxwell // LLVMFuncOp. 1853c012e487SJohannes de Fine Licht static constexpr std::array kExplicitAttributes{ 1854c012e487SJohannes de Fine Licht StringLiteral("aarch64_in_za"), 1855c012e487SJohannes de Fine Licht StringLiteral("aarch64_inout_za"), 1856c012e487SJohannes de Fine Licht StringLiteral("aarch64_new_za"), 1857c012e487SJohannes de Fine Licht StringLiteral("aarch64_out_za"), 1858c012e487SJohannes de Fine Licht StringLiteral("aarch64_preserves_za"), 1859783ac3b6SBenjamin Maxwell StringLiteral("aarch64_pstate_sm_body"), 186079524ba5STom Eccles StringLiteral("aarch64_pstate_sm_compatible"), 1861c012e487SJohannes de Fine Licht StringLiteral("aarch64_pstate_sm_enabled"), 1862c012e487SJohannes de Fine Licht StringLiteral("alwaysinline"), 1863c012e487SJohannes de Fine Licht StringLiteral("approx-func-fp-math"), 1864d6df0187SFinlay StringLiteral("convergent"), 1865e5865ec9Srunseny StringLiteral("denormal-fp-math"), 1866e5865ec9Srunseny StringLiteral("denormal-fp-math-f32"), 1867e5865ec9Srunseny StringLiteral("fp-contract"), 18683257e4caSRadu Salavat StringLiteral("frame-pointer"), 1869748c2959SAlex Bradbury StringLiteral("no-infs-fp-math"), 1870748c2959SAlex Bradbury StringLiteral("no-nans-fp-math"), 1871748c2959SAlex Bradbury StringLiteral("no-signed-zeros-fp-math"), 1872c012e487SJohannes de Fine Licht StringLiteral("noinline"), 1873aa21ee79SFinlay StringLiteral("nounwind"), 1874c012e487SJohannes de Fine Licht StringLiteral("optnone"), 1875c012e487SJohannes de Fine Licht StringLiteral("target-features"), 1876f1d3fe7aSAlexis Perry-Holby StringLiteral("tune-cpu"), 1877c012e487SJohannes de Fine Licht StringLiteral("unsafe-fp-math"), 1878c012e487SJohannes de Fine Licht StringLiteral("vscale_range"), 1879aa21ee79SFinlay StringLiteral("willreturn"), 1880783ac3b6SBenjamin Maxwell }; 1881783ac3b6SBenjamin Maxwell 18823d36df3eSChristian Ulmann static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) { 18833d36df3eSChristian Ulmann MLIRContext *context = funcOp.getContext(); 18843d36df3eSChristian Ulmann SmallVector<Attribute> passthroughs; 18853d36df3eSChristian Ulmann llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes( 18863d36df3eSChristian Ulmann llvm::AttributeList::AttrIndex::FunctionIndex); 18873d36df3eSChristian Ulmann for (llvm::Attribute attr : funcAttrs) { 18883d36df3eSChristian Ulmann // Skip the memory attribute since the LLVMFuncOp has an explicit memory 18893d36df3eSChristian Ulmann // attribute. 18903d36df3eSChristian Ulmann if (attr.hasAttribute(llvm::Attribute::Memory)) 18913d36df3eSChristian Ulmann continue; 18923d36df3eSChristian Ulmann 18933d36df3eSChristian Ulmann // Skip invalid type attributes. 18943d36df3eSChristian Ulmann if (attr.isTypeAttribute()) { 18953d36df3eSChristian Ulmann emitWarning(funcOp.getLoc(), 18963d36df3eSChristian Ulmann "type attributes on a function are invalid, skipping it"); 18973d36df3eSChristian Ulmann continue; 18983d36df3eSChristian Ulmann } 18993d36df3eSChristian Ulmann 19003d36df3eSChristian Ulmann StringRef attrName; 19013d36df3eSChristian Ulmann if (attr.isStringAttribute()) 19023d36df3eSChristian Ulmann attrName = attr.getKindAsString(); 19033d36df3eSChristian Ulmann else 19043d36df3eSChristian Ulmann attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum()); 19053d36df3eSChristian Ulmann auto keyAttr = StringAttr::get(context, attrName); 19063d36df3eSChristian Ulmann 1907783ac3b6SBenjamin Maxwell // Skip attributes that map to an explicit attribute on the LLVMFuncOp. 1908c012e487SJohannes de Fine Licht if (llvm::is_contained(kExplicitAttributes, attrName)) 19097d465909SCullen Rhodes continue; 19107d465909SCullen Rhodes 19113d36df3eSChristian Ulmann if (attr.isStringAttribute()) { 19123d36df3eSChristian Ulmann StringRef val = attr.getValueAsString(); 19133d36df3eSChristian Ulmann if (val.empty()) { 19143d36df3eSChristian Ulmann passthroughs.push_back(keyAttr); 19153d36df3eSChristian Ulmann continue; 19163d36df3eSChristian Ulmann } 19173d36df3eSChristian Ulmann passthroughs.push_back( 19183d36df3eSChristian Ulmann ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)})); 19193d36df3eSChristian Ulmann continue; 19203d36df3eSChristian Ulmann } 19213d36df3eSChristian Ulmann if (attr.isIntAttribute()) { 19223d36df3eSChristian Ulmann auto val = std::to_string(attr.getValueAsInt()); 19233d36df3eSChristian Ulmann passthroughs.push_back( 19243d36df3eSChristian Ulmann ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)})); 19253d36df3eSChristian Ulmann continue; 19263d36df3eSChristian Ulmann } 19273d36df3eSChristian Ulmann if (attr.isEnumAttribute()) { 19283d36df3eSChristian Ulmann passthroughs.push_back(keyAttr); 19293d36df3eSChristian Ulmann continue; 19303d36df3eSChristian Ulmann } 19313d36df3eSChristian Ulmann 19323d36df3eSChristian Ulmann llvm_unreachable("unexpected attribute kind"); 19333d36df3eSChristian Ulmann } 19343d36df3eSChristian Ulmann 19353d36df3eSChristian Ulmann if (!passthroughs.empty()) 19363d36df3eSChristian Ulmann funcOp.setPassthroughAttr(ArrayAttr::get(context, passthroughs)); 19373d36df3eSChristian Ulmann } 19383d36df3eSChristian Ulmann 19399dbf3625STobias Gysi void ModuleImport::processFunctionAttributes(llvm::Function *func, 19409dbf3625STobias Gysi LLVMFuncOp funcOp) { 19419b9cfe77SChristian Ulmann processMemoryEffects(func, funcOp); 19423d36df3eSChristian Ulmann processPassthroughAttrs(func, funcOp); 19437d465909SCullen Rhodes 1944c012e487SJohannes de Fine Licht if (func->hasFnAttribute(llvm::Attribute::NoInline)) 1945c012e487SJohannes de Fine Licht funcOp.setNoInline(true); 1946c012e487SJohannes de Fine Licht if (func->hasFnAttribute(llvm::Attribute::AlwaysInline)) 1947c012e487SJohannes de Fine Licht funcOp.setAlwaysInline(true); 1948c012e487SJohannes de Fine Licht if (func->hasFnAttribute(llvm::Attribute::OptimizeNone)) 1949c012e487SJohannes de Fine Licht funcOp.setOptimizeNone(true); 1950d6df0187SFinlay if (func->hasFnAttribute(llvm::Attribute::Convergent)) 1951d6df0187SFinlay funcOp.setConvergent(true); 1952aa21ee79SFinlay if (func->hasFnAttribute(llvm::Attribute::NoUnwind)) 1953aa21ee79SFinlay funcOp.setNoUnwind(true); 1954aa21ee79SFinlay if (func->hasFnAttribute(llvm::Attribute::WillReturn)) 1955aa21ee79SFinlay funcOp.setWillReturn(true); 1956c012e487SJohannes de Fine Licht 19577d465909SCullen Rhodes if (func->hasFnAttribute("aarch64_pstate_sm_enabled")) 19587d465909SCullen Rhodes funcOp.setArmStreaming(true); 19597d465909SCullen Rhodes else if (func->hasFnAttribute("aarch64_pstate_sm_body")) 19607d465909SCullen Rhodes funcOp.setArmLocallyStreaming(true); 196179524ba5STom Eccles else if (func->hasFnAttribute("aarch64_pstate_sm_compatible")) 196279524ba5STom Eccles funcOp.setArmStreamingCompatible(true); 1963783ac3b6SBenjamin Maxwell 1964d313614bSSander de Smalen if (func->hasFnAttribute("aarch64_new_za")) 1965783ac3b6SBenjamin Maxwell funcOp.setArmNewZa(true); 1966d313614bSSander de Smalen else if (func->hasFnAttribute("aarch64_in_za")) 1967d313614bSSander de Smalen funcOp.setArmInZa(true); 1968d313614bSSander de Smalen else if (func->hasFnAttribute("aarch64_out_za")) 1969d313614bSSander de Smalen funcOp.setArmOutZa(true); 1970d313614bSSander de Smalen else if (func->hasFnAttribute("aarch64_inout_za")) 1971d313614bSSander de Smalen funcOp.setArmInoutZa(true); 1972d313614bSSander de Smalen else if (func->hasFnAttribute("aarch64_preserves_za")) 197321e1bf2dSMats Petersson funcOp.setArmPreservesZa(true); 1974783ac3b6SBenjamin Maxwell 19755bfd5c60SMats Petersson llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange); 19765bfd5c60SMats Petersson if (attr.isValid()) { 19775bfd5c60SMats Petersson MLIRContext *context = funcOp.getContext(); 19785bfd5c60SMats Petersson auto intTy = IntegerType::get(context, 32); 19795bfd5c60SMats Petersson funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get( 19805bfd5c60SMats Petersson context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()), 19815bfd5c60SMats Petersson IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0)))); 19825bfd5c60SMats Petersson } 19833257e4caSRadu Salavat 19843257e4caSRadu Salavat // Process frame-pointer attribute. 19853257e4caSRadu Salavat if (func->hasFnAttribute("frame-pointer")) { 19863257e4caSRadu Salavat StringRef stringRefFramePointerKind = 19873257e4caSRadu Salavat func->getFnAttribute("frame-pointer").getValueAsString(); 19883257e4caSRadu Salavat funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get( 19893257e4caSRadu Salavat funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind( 19903257e4caSRadu Salavat stringRefFramePointerKind) 19913257e4caSRadu Salavat .value())); 19923257e4caSRadu Salavat } 199317de468dSBenjamin Maxwell 19948fb685fbSSergio Afonso if (llvm::Attribute attr = func->getFnAttribute("target-cpu"); 19958fb685fbSSergio Afonso attr.isStringAttribute()) 19968fb685fbSSergio Afonso funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString())); 19978fb685fbSSergio Afonso 1998f1d3fe7aSAlexis Perry-Holby if (llvm::Attribute attr = func->getFnAttribute("tune-cpu"); 1999f1d3fe7aSAlexis Perry-Holby attr.isStringAttribute()) 2000f1d3fe7aSAlexis Perry-Holby funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString())); 2001f1d3fe7aSAlexis Perry-Holby 200217de468dSBenjamin Maxwell if (llvm::Attribute attr = func->getFnAttribute("target-features"); 20038fb685fbSSergio Afonso attr.isStringAttribute()) 200417de468dSBenjamin Maxwell funcOp.setTargetFeaturesAttr( 200517de468dSBenjamin Maxwell LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString())); 2006748c2959SAlex Bradbury 2007748c2959SAlex Bradbury if (llvm::Attribute attr = func->getFnAttribute("unsafe-fp-math"); 2008748c2959SAlex Bradbury attr.isStringAttribute()) 2009748c2959SAlex Bradbury funcOp.setUnsafeFpMath(attr.getValueAsBool()); 2010748c2959SAlex Bradbury 2011748c2959SAlex Bradbury if (llvm::Attribute attr = func->getFnAttribute("no-infs-fp-math"); 2012748c2959SAlex Bradbury attr.isStringAttribute()) 2013748c2959SAlex Bradbury funcOp.setNoInfsFpMath(attr.getValueAsBool()); 2014748c2959SAlex Bradbury 2015748c2959SAlex Bradbury if (llvm::Attribute attr = func->getFnAttribute("no-nans-fp-math"); 2016748c2959SAlex Bradbury attr.isStringAttribute()) 2017748c2959SAlex Bradbury funcOp.setNoNansFpMath(attr.getValueAsBool()); 2018748c2959SAlex Bradbury 2019748c2959SAlex Bradbury if (llvm::Attribute attr = func->getFnAttribute("approx-func-fp-math"); 2020748c2959SAlex Bradbury attr.isStringAttribute()) 2021748c2959SAlex Bradbury funcOp.setApproxFuncFpMath(attr.getValueAsBool()); 2022748c2959SAlex Bradbury 2023748c2959SAlex Bradbury if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math"); 2024748c2959SAlex Bradbury attr.isStringAttribute()) 2025748c2959SAlex Bradbury funcOp.setNoSignedZerosFpMath(attr.getValueAsBool()); 2026e5865ec9Srunseny 2027e5865ec9Srunseny if (llvm::Attribute attr = func->getFnAttribute("denormal-fp-math"); 2028e5865ec9Srunseny attr.isStringAttribute()) 2029e5865ec9Srunseny funcOp.setDenormalFpMathAttr( 2030e5865ec9Srunseny StringAttr::get(context, attr.getValueAsString())); 2031e5865ec9Srunseny 2032e5865ec9Srunseny if (llvm::Attribute attr = func->getFnAttribute("denormal-fp-math-f32"); 2033e5865ec9Srunseny attr.isStringAttribute()) 2034e5865ec9Srunseny funcOp.setDenormalFpMathF32Attr( 2035e5865ec9Srunseny StringAttr::get(context, attr.getValueAsString())); 2036e5865ec9Srunseny 2037e5865ec9Srunseny if (llvm::Attribute attr = func->getFnAttribute("fp-contract"); 2038e5865ec9Srunseny attr.isStringAttribute()) 2039e5865ec9Srunseny funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString())); 204017de468dSBenjamin Maxwell } 20419dbf3625STobias Gysi 204256880fd2SChristian Ulmann DictionaryAttr 204356880fd2SChristian Ulmann ModuleImport::convertParameterAttribute(llvm::AttributeSet llvmParamAttrs, 204456880fd2SChristian Ulmann OpBuilder &builder) { 204556880fd2SChristian Ulmann SmallVector<NamedAttribute> paramAttrs; 204652120584SChristian Ulmann for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) { 204756880fd2SChristian Ulmann auto llvmAttr = llvmParamAttrs.getAttribute(llvmKind); 204856880fd2SChristian Ulmann // Skip attributes that are not attached. 204956880fd2SChristian Ulmann if (!llvmAttr.isValid()) 205056880fd2SChristian Ulmann continue; 205129441e4fSNikita Popov 205229441e4fSNikita Popov // TODO: Import captures(none) as a nocapture unit attribute until the 205329441e4fSNikita Popov // LLVM dialect switches to the captures representation. 205429441e4fSNikita Popov if (llvmAttr.hasKindAsEnum() && 205529441e4fSNikita Popov llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) { 205629441e4fSNikita Popov if (llvm::capturesNothing(llvmAttr.getCaptureInfo())) 205729441e4fSNikita Popov paramAttrs.push_back( 205829441e4fSNikita Popov builder.getNamedAttr(mlirName, builder.getUnitAttr())); 205929441e4fSNikita Popov continue; 206029441e4fSNikita Popov } 206129441e4fSNikita Popov 206256880fd2SChristian Ulmann Attribute mlirAttr; 206356880fd2SChristian Ulmann if (llvmAttr.isTypeAttribute()) 206456880fd2SChristian Ulmann mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType())); 206556880fd2SChristian Ulmann else if (llvmAttr.isIntAttribute()) 206656880fd2SChristian Ulmann mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt()); 206756880fd2SChristian Ulmann else if (llvmAttr.isEnumAttribute()) 206856880fd2SChristian Ulmann mlirAttr = builder.getUnitAttr(); 206992a15dd7SKrzysztof Drewniak else if (llvmAttr.isConstantRangeAttribute()) { 207092a15dd7SKrzysztof Drewniak const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange(); 207192a15dd7SKrzysztof Drewniak mlirAttr = builder.getAttr<LLVM::ConstantRangeAttr>(value.getLower(), 207292a15dd7SKrzysztof Drewniak value.getUpper()); 207392a15dd7SKrzysztof Drewniak } else 207456880fd2SChristian Ulmann llvm_unreachable("unexpected parameter attribute kind"); 207556880fd2SChristian Ulmann paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr)); 207656880fd2SChristian Ulmann } 207756880fd2SChristian Ulmann 207856880fd2SChristian Ulmann return builder.getDictionaryAttr(paramAttrs); 207956880fd2SChristian Ulmann } 208056880fd2SChristian Ulmann 208156880fd2SChristian Ulmann void ModuleImport::convertParameterAttributes(llvm::Function *func, 208256880fd2SChristian Ulmann LLVMFuncOp funcOp, 208356880fd2SChristian Ulmann OpBuilder &builder) { 208456880fd2SChristian Ulmann auto llvmAttrs = func->getAttributes(); 208556880fd2SChristian Ulmann for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) { 208656880fd2SChristian Ulmann llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i); 208756880fd2SChristian Ulmann funcOp.setArgAttrs(i, convertParameterAttribute(llvmArgAttrs, builder)); 208856880fd2SChristian Ulmann } 208956880fd2SChristian Ulmann // Convert the result attributes and attach them wrapped in an ArrayAttribute 209056880fd2SChristian Ulmann // to the funcOp. 209156880fd2SChristian Ulmann llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs(); 20928d3c4ff8SChristian Ulmann if (!llvmResAttr.hasAttributes()) 20938d3c4ff8SChristian Ulmann return; 209456880fd2SChristian Ulmann funcOp.setResAttrsAttr( 209556880fd2SChristian Ulmann builder.getArrayAttr(convertParameterAttribute(llvmResAttr, builder))); 209656880fd2SChristian Ulmann } 209756880fd2SChristian Ulmann 20982a1f7958SHenrich Lauko template <typename Op> 20992a1f7958SHenrich Lauko static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op) { 21002a1f7958SHenrich Lauko op.setCConv(convertCConvFromLLVM(inst->getCallingConv())); 21012a1f7958SHenrich Lauko return success(); 21022a1f7958SHenrich Lauko } 21032a1f7958SHenrich Lauko 21042a1f7958SHenrich Lauko LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst, 21052a1f7958SHenrich Lauko InvokeOp op) { 21062a1f7958SHenrich Lauko return convertCallBaseAttributes(inst, op); 21072a1f7958SHenrich Lauko } 21082a1f7958SHenrich Lauko 21092a1f7958SHenrich Lauko LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst, 21102a1f7958SHenrich Lauko CallOp op) { 21112a1f7958SHenrich Lauko setFastmathFlagsAttr(inst, op.getOperation()); 21122a1f7958SHenrich Lauko op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind())); 21132a1f7958SHenrich Lauko op.setConvergent(inst->isConvergent()); 21142a1f7958SHenrich Lauko op.setNoUnwind(inst->doesNotThrow()); 21152a1f7958SHenrich Lauko op.setWillReturn(inst->hasFnAttr(llvm::Attribute::WillReturn)); 21162a1f7958SHenrich Lauko 21172a1f7958SHenrich Lauko llvm::MemoryEffects memEffects = inst->getMemoryEffects(); 21182a1f7958SHenrich Lauko ModRefInfo othermem = convertModRefInfoFromLLVM( 21192a1f7958SHenrich Lauko memEffects.getModRef(llvm::MemoryEffects::Location::Other)); 21202a1f7958SHenrich Lauko ModRefInfo argMem = convertModRefInfoFromLLVM( 21212a1f7958SHenrich Lauko memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem)); 21222a1f7958SHenrich Lauko ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM( 21232a1f7958SHenrich Lauko memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem)); 21242a1f7958SHenrich Lauko auto memAttr = MemoryEffectsAttr::get(op.getContext(), othermem, argMem, 21252a1f7958SHenrich Lauko inaccessibleMem); 21262a1f7958SHenrich Lauko // Only set the attribute when it does not match the default value. 21272a1f7958SHenrich Lauko if (!memAttr.isReadWrite()) 21282a1f7958SHenrich Lauko op.setMemoryEffectsAttr(memAttr); 21292a1f7958SHenrich Lauko 21302a1f7958SHenrich Lauko return convertCallBaseAttributes(inst, op); 21312a1f7958SHenrich Lauko } 21322a1f7958SHenrich Lauko 21339dbf3625STobias Gysi LogicalResult ModuleImport::processFunction(llvm::Function *func) { 2134b808648aSChristian Ulmann clearRegionState(); 21359dbf3625STobias Gysi 21369dbf3625STobias Gysi auto functionType = 21375550c821STres Popp dyn_cast<LLVMFunctionType>(convertType(func->getFunctionType())); 2138cf487cceSTobias Gysi if (func->isIntrinsic() && 2139cf487cceSTobias Gysi iface.isConvertibleIntrinsic(func->getIntrinsicID())) 21409dbf3625STobias Gysi return success(); 21419dbf3625STobias Gysi 2142*4fc514afSGuojin bool dsoLocal = func->isDSOLocal(); 21439dbf3625STobias Gysi CConv cconv = convertCConvFromLLVM(func->getCallingConv()); 21449dbf3625STobias Gysi 21459dbf3625STobias Gysi // Insert the function at the end of the module. 21469dbf3625STobias Gysi OpBuilder::InsertionGuard guard(builder); 2147b613a540SMatthias Springer builder.setInsertionPointToEnd(mlirModule.getBody()); 21489dbf3625STobias Gysi 21497d5b4ebbSChristian Ulmann Location loc = debugImporter->translateFuncLocation(func); 21509dbf3625STobias Gysi LLVMFuncOp funcOp = builder.create<LLVMFuncOp>( 21517d5b4ebbSChristian Ulmann loc, func->getName(), functionType, 21529dbf3625STobias Gysi convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv); 21539dbf3625STobias Gysi 215456880fd2SChristian Ulmann convertParameterAttributes(func, funcOp, builder); 21559dbf3625STobias Gysi 21569dbf3625STobias Gysi if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func)) 21579dbf3625STobias Gysi funcOp.setPersonalityAttr(personality); 21589dbf3625STobias Gysi else if (func->hasPersonalityFn()) 21593589885dSTobias Gysi emitWarning(funcOp.getLoc(), "could not deduce personality, skipping it"); 21609dbf3625STobias Gysi 21619dbf3625STobias Gysi if (func->hasGC()) 21629dbf3625STobias Gysi funcOp.setGarbageCollector(StringRef(func->getGC())); 21639dbf3625STobias Gysi 216410417b13SChristian Ulmann if (func->hasAtLeastLocalUnnamedAddr()) 216510417b13SChristian Ulmann funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr())); 216610417b13SChristian Ulmann 2167bc609640SChristian Ulmann if (func->hasSection()) 2168bc609640SChristian Ulmann funcOp.setSection(StringRef(func->getSection())); 2169bc609640SChristian Ulmann 21706628767eSChristian Ulmann funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility())); 21716628767eSChristian Ulmann 2172b126ee65STobias Gysi if (func->hasComdat()) 2173b126ee65STobias Gysi funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat())); 2174b126ee65STobias Gysi 2175c55a8861SChristian Ulmann if (llvm::MaybeAlign maybeAlign = func->getAlign()) 2176c55a8861SChristian Ulmann funcOp.setAlignment(maybeAlign->value()); 2177c55a8861SChristian Ulmann 21789dbf3625STobias Gysi // Handle Function attributes. 21799dbf3625STobias Gysi processFunctionAttributes(func, funcOp); 21809dbf3625STobias Gysi 2181b72dd6f7SChristian Ulmann // Convert non-debug metadata by using the dialect interface. 2182b72dd6f7SChristian Ulmann SmallVector<std::pair<unsigned, llvm::MDNode *>> allMetadata; 2183b72dd6f7SChristian Ulmann func->getAllMetadata(allMetadata); 2184b72dd6f7SChristian Ulmann for (auto &[kind, node] : allMetadata) { 2185b72dd6f7SChristian Ulmann if (!iface.isConvertibleMetadata(kind)) 2186b72dd6f7SChristian Ulmann continue; 2187b72dd6f7SChristian Ulmann if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *this))) { 21883589885dSTobias Gysi emitWarning(funcOp.getLoc()) 21893589885dSTobias Gysi << "unhandled function metadata: " << diagMD(node, llvmModule.get()) 21903589885dSTobias Gysi << " on " << diag(*func); 2191b72dd6f7SChristian Ulmann } 2192b72dd6f7SChristian Ulmann } 2193b72dd6f7SChristian Ulmann 21949dbf3625STobias Gysi if (func->isDeclaration()) 21959dbf3625STobias Gysi return success(); 21969dbf3625STobias Gysi 21979dd0eb9cSTobias Gysi // Collect the set of basic blocks reachable from the function's entry block. 21989dd0eb9cSTobias Gysi // This step is crucial as LLVM IR can contain unreachable blocks that 21999dd0eb9cSTobias Gysi // self-dominate. As a result, an operation might utilize a variable it 22009dd0eb9cSTobias Gysi // defines, which the import does not support. Given that MLIR lacks block 22019dd0eb9cSTobias Gysi // label support, we can safely remove unreachable blocks, as there are no 22029dd0eb9cSTobias Gysi // indirect branch instructions that could potentially target these blocks. 22039dd0eb9cSTobias Gysi llvm::df_iterator_default_set<llvm::BasicBlock *> reachable; 22049dd0eb9cSTobias Gysi for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable)) 22059dd0eb9cSTobias Gysi (void)basicBlock; 22069dd0eb9cSTobias Gysi 22079dd0eb9cSTobias Gysi // Eagerly create all reachable blocks. 22089dd0eb9cSTobias Gysi SmallVector<llvm::BasicBlock *> reachableBasicBlocks; 22099dd0eb9cSTobias Gysi for (llvm::BasicBlock &basicBlock : *func) { 22109dd0eb9cSTobias Gysi // Skip unreachable blocks. 22119dd0eb9cSTobias Gysi if (!reachable.contains(&basicBlock)) 22129dd0eb9cSTobias Gysi continue; 22139dd0eb9cSTobias Gysi Region &body = funcOp.getBody(); 22149dd0eb9cSTobias Gysi Block *block = builder.createBlock(&body, body.end()); 22159dd0eb9cSTobias Gysi mapBlock(&basicBlock, block); 22169dd0eb9cSTobias Gysi reachableBasicBlocks.push_back(&basicBlock); 22179dbf3625STobias Gysi } 22189dbf3625STobias Gysi 22199dbf3625STobias Gysi // Add function arguments to the entry block. 22209dbf3625STobias Gysi for (const auto &it : llvm::enumerate(func->args())) { 22219dbf3625STobias Gysi BlockArgument blockArg = funcOp.getFunctionBody().addArgument( 22229dbf3625STobias Gysi functionType.getParamType(it.index()), funcOp.getLoc()); 22239dbf3625STobias Gysi mapValue(&it.value(), blockArg); 22249dbf3625STobias Gysi } 22259dbf3625STobias Gysi 22269dbf3625STobias Gysi // Process the blocks in topological order. The ordered traversal ensures 22279dbf3625STobias Gysi // operands defined in a dominating block have a valid mapping to an MLIR 22289dbf3625STobias Gysi // value once a block is translated. 22299dd0eb9cSTobias Gysi SetVector<llvm::BasicBlock *> blocks = 22309dd0eb9cSTobias Gysi getTopologicallySortedBlocks(reachableBasicBlocks); 22319dbf3625STobias Gysi setConstantInsertionPointToStart(lookupBlock(blocks.front())); 22329dd0eb9cSTobias Gysi for (llvm::BasicBlock *basicBlock : blocks) 22339dd0eb9cSTobias Gysi if (failed(processBasicBlock(basicBlock, lookupBlock(basicBlock)))) 22349dbf3625STobias Gysi return failure(); 2235b808648aSChristian Ulmann 2236b808648aSChristian Ulmann // Process the debug intrinsics that require a delayed conversion after 2237b808648aSChristian Ulmann // everything else was converted. 2238b808648aSChristian Ulmann if (failed(processDebugIntrinsics())) 2239b808648aSChristian Ulmann return failure(); 2240b808648aSChristian Ulmann 2241b808648aSChristian Ulmann return success(); 22429dbf3625STobias Gysi } 22439dbf3625STobias Gysi 2244667a195fSChristian Ulmann /// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA 2245667a195fSChristian Ulmann /// value. 2246667a195fSChristian Ulmann static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) { 2247667a195fSChristian Ulmann if (!dbgIntr->isKillLocation()) 2248667a195fSChristian Ulmann return false; 2249667a195fSChristian Ulmann llvm::Value *value = dbgIntr->getArgOperand(0); 2250667a195fSChristian Ulmann auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value); 2251667a195fSChristian Ulmann if (!nodeAsVal) 2252667a195fSChristian Ulmann return false; 2253667a195fSChristian Ulmann return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata()); 2254667a195fSChristian Ulmann } 2255667a195fSChristian Ulmann 2256b808648aSChristian Ulmann LogicalResult 2257b808648aSChristian Ulmann ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr, 2258b808648aSChristian Ulmann DominanceInfo &domInfo) { 2259b808648aSChristian Ulmann Location loc = translateLoc(dbgIntr->getDebugLoc()); 2260b808648aSChristian Ulmann auto emitUnsupportedWarning = [&]() { 2261b808648aSChristian Ulmann if (emitExpensiveWarnings) 2262b808648aSChristian Ulmann emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr); 2263b808648aSChristian Ulmann return success(); 2264b808648aSChristian Ulmann }; 22650ab6b20cSBilly Zhu // Drop debug intrinsics with arg lists. 22660ab6b20cSBilly Zhu // TODO: Support debug intrinsics that have arg lists. 22670ab6b20cSBilly Zhu if (dbgIntr->hasArgList()) 2268b808648aSChristian Ulmann return emitUnsupportedWarning(); 2269667a195fSChristian Ulmann // Kill locations can have metadata nodes as location operand. This 2270667a195fSChristian Ulmann // cannot be converted to poison as the type cannot be reconstructed. 2271667a195fSChristian Ulmann // TODO: find a way to support this case. 2272667a195fSChristian Ulmann if (isMetadataKillLocation(dbgIntr)) 2273667a195fSChristian Ulmann return emitUnsupportedWarning(); 2274335d34d9STobias Gysi // Drop debug intrinsics if the associated variable information cannot be 2275335d34d9STobias Gysi // translated due to cyclic debug metadata. 2276335d34d9STobias Gysi // TODO: Support cyclic debug metadata. 2277335d34d9STobias Gysi DILocalVariableAttr localVariableAttr = 2278335d34d9STobias Gysi matchLocalVariableAttr(dbgIntr->getArgOperand(1)); 2279335d34d9STobias Gysi if (!localVariableAttr) 2280335d34d9STobias Gysi return emitUnsupportedWarning(); 2281b808648aSChristian Ulmann FailureOr<Value> argOperand = convertMetadataValue(dbgIntr->getArgOperand(0)); 2282b808648aSChristian Ulmann if (failed(argOperand)) 2283667a195fSChristian Ulmann return emitError(loc) << "failed to convert a debug intrinsic operand: " 2284667a195fSChristian Ulmann << diag(*dbgIntr); 2285b808648aSChristian Ulmann 2286922992a2SJay Foad // Ensure that the debug intrinsic is inserted right after its operand is 2287b808648aSChristian Ulmann // defined. Otherwise, the operand might not necessarily dominate the 2288b808648aSChristian Ulmann // intrinsic. If the defining operation is a terminator, insert the intrinsic 2289b808648aSChristian Ulmann // into a dominated block. 2290b808648aSChristian Ulmann OpBuilder::InsertionGuard guard(builder); 2291b808648aSChristian Ulmann if (Operation *op = argOperand->getDefiningOp(); 2292b808648aSChristian Ulmann op && op->hasTrait<OpTrait::IsTerminator>()) { 2293b808648aSChristian Ulmann // Find a dominated block that can hold the debug intrinsic. 2294b808648aSChristian Ulmann auto dominatedBlocks = domInfo.getNode(op->getBlock())->children(); 2295b808648aSChristian Ulmann // If no block is dominated by the terminator, this intrinisc cannot be 2296b808648aSChristian Ulmann // converted. 2297b808648aSChristian Ulmann if (dominatedBlocks.empty()) 2298b808648aSChristian Ulmann return emitUnsupportedWarning(); 2299b808648aSChristian Ulmann // Set insertion point before the terminator, to avoid inserting something 2300b808648aSChristian Ulmann // before landingpads. 2301b808648aSChristian Ulmann Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock(); 2302b808648aSChristian Ulmann builder.setInsertionPoint(dominatedBlock->getTerminator()); 2303b808648aSChristian Ulmann } else { 2304b808648aSChristian Ulmann builder.setInsertionPointAfterValue(*argOperand); 2305b808648aSChristian Ulmann } 23060ab6b20cSBilly Zhu auto locationExprAttr = 23076da578ceSJustin Wilson debugImporter->translateExpression(dbgIntr->getExpression()); 2308b808648aSChristian Ulmann Operation *op = 2309b808648aSChristian Ulmann llvm::TypeSwitch<llvm::DbgVariableIntrinsic *, Operation *>(dbgIntr) 2310b808648aSChristian Ulmann .Case([&](llvm::DbgDeclareInst *) { 23110ab6b20cSBilly Zhu return builder.create<LLVM::DbgDeclareOp>( 23120ab6b20cSBilly Zhu loc, *argOperand, localVariableAttr, locationExprAttr); 2313b808648aSChristian Ulmann }) 2314b808648aSChristian Ulmann .Case([&](llvm::DbgValueInst *) { 23150ab6b20cSBilly Zhu return builder.create<LLVM::DbgValueOp>( 23160ab6b20cSBilly Zhu loc, *argOperand, localVariableAttr, locationExprAttr); 2317b808648aSChristian Ulmann }); 2318b808648aSChristian Ulmann mapNoResultOp(dbgIntr, op); 2319b808648aSChristian Ulmann setNonDebugMetadataAttrs(dbgIntr, op); 2320b808648aSChristian Ulmann return success(); 2321b808648aSChristian Ulmann } 2322b808648aSChristian Ulmann 2323b808648aSChristian Ulmann LogicalResult ModuleImport::processDebugIntrinsics() { 2324b808648aSChristian Ulmann DominanceInfo domInfo; 2325b808648aSChristian Ulmann for (llvm::Instruction *inst : debugIntrinsics) { 2326b808648aSChristian Ulmann auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst); 2327b808648aSChristian Ulmann if (failed(processDebugIntrinsic(intrCall, domInfo))) 2328b808648aSChristian Ulmann return failure(); 2329b808648aSChristian Ulmann } 23309dbf3625STobias Gysi return success(); 23319dbf3625STobias Gysi } 23329dbf3625STobias Gysi 23339dbf3625STobias Gysi LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb, 23349dbf3625STobias Gysi Block *block) { 23359dbf3625STobias Gysi builder.setInsertionPointToStart(block); 23369dbf3625STobias Gysi for (llvm::Instruction &inst : *bb) { 23379dbf3625STobias Gysi if (failed(processInstruction(&inst))) 23389dbf3625STobias Gysi return failure(); 23390cf06639STobias Gysi 2340b808648aSChristian Ulmann // Skip additional processing when the instructions is a debug intrinsics 2341b808648aSChristian Ulmann // that was not yet converted. 2342b808648aSChristian Ulmann if (debugIntrinsics.contains(&inst)) 2343b808648aSChristian Ulmann continue; 2344b808648aSChristian Ulmann 23450cf06639STobias Gysi // Set the non-debug metadata attributes on the imported operation and emit 23460cf06639STobias Gysi // a warning if an instruction other than a phi instruction is dropped 23470cf06639STobias Gysi // during the import. 23480cf06639STobias Gysi if (Operation *op = lookupOperation(&inst)) { 23490cf06639STobias Gysi setNonDebugMetadataAttrs(&inst, op); 23500cf06639STobias Gysi } else if (inst.getOpcode() != llvm::Instruction::PHI) { 2351a014fadbSTobias Gysi if (emitExpensiveWarnings) { 23520cf06639STobias Gysi Location loc = debugImporter->translateLoc(inst.getDebugLoc()); 23533589885dSTobias Gysi emitWarning(loc) << "dropped instruction: " << diag(inst); 23540cf06639STobias Gysi } 23559dbf3625STobias Gysi } 2356a014fadbSTobias Gysi } 23579dbf3625STobias Gysi return success(); 23589dbf3625STobias Gysi } 23599dbf3625STobias Gysi 23609170fa58SMarkus Böck FailureOr<SmallVector<AccessGroupAttr>> 2361b83caa32SChristian Ulmann ModuleImport::lookupAccessGroupAttrs(const llvm::MDNode *node) const { 2362e630a502SChristian Ulmann return loopAnnotationImporter->lookupAccessGroupAttrs(node); 2363b83caa32SChristian Ulmann } 2364b83caa32SChristian Ulmann 2365b83caa32SChristian Ulmann LoopAnnotationAttr 2366b83caa32SChristian Ulmann ModuleImport::translateLoopAnnotationAttr(const llvm::MDNode *node, 2367b83caa32SChristian Ulmann Location loc) const { 2368e630a502SChristian Ulmann return loopAnnotationImporter->translateLoopAnnotation(node, loc); 2369b83caa32SChristian Ulmann } 2370b83caa32SChristian Ulmann 23719dbf3625STobias Gysi OwningOpRef<ModuleOp> 23729dbf3625STobias Gysi mlir::translateLLVMIRToModule(std::unique_ptr<llvm::Module> llvmModule, 2373090d03d1SChristian Ulmann MLIRContext *context, bool emitExpensiveWarnings, 237438fcf624SWilliam Moses bool dropDICompositeTypeElements, 237538fcf624SWilliam Moses bool loadAllDialects) { 2376cf487cceSTobias Gysi // Preload all registered dialects to allow the import to iterate the 2377cf487cceSTobias Gysi // registered LLVMImportDialectInterface implementations and query the 2378cf487cceSTobias Gysi // supported LLVM IR constructs before starting the translation. Assumes the 2379cf487cceSTobias Gysi // LLVM and DLTI dialects that convert the core LLVM IR constructs have been 2380cf487cceSTobias Gysi // registered before. 2381cf487cceSTobias Gysi assert(llvm::is_contained(context->getAvailableDialects(), 2382cf487cceSTobias Gysi LLVMDialect::getDialectNamespace())); 2383cf487cceSTobias Gysi assert(llvm::is_contained(context->getAvailableDialects(), 2384cf487cceSTobias Gysi DLTIDialect::getDialectNamespace())); 238538fcf624SWilliam Moses if (loadAllDialects) 2386cf487cceSTobias Gysi context->loadAllAvailableDialects(); 23879dbf3625STobias Gysi OwningOpRef<ModuleOp> module(ModuleOp::create(FileLineColLoc::get( 23889dbf3625STobias Gysi StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0, 23899dbf3625STobias Gysi /*column=*/0))); 23909dbf3625STobias Gysi 2391a014fadbSTobias Gysi ModuleImport moduleImport(module.get(), std::move(llvmModule), 2392090d03d1SChristian Ulmann emitExpensiveWarnings, dropDICompositeTypeElements); 2393cf487cceSTobias Gysi if (failed(moduleImport.initializeImportInterface())) 2394cf487cceSTobias Gysi return {}; 23959d2b84efSTobias Gysi if (failed(moduleImport.convertDataLayout())) 23969d2b84efSTobias Gysi return {}; 23979d4c1be8SDavid Truby if (failed(moduleImport.convertComdats())) 23989d4c1be8SDavid Truby return {}; 2399b126ee65STobias Gysi if (failed(moduleImport.convertMetadata())) 2400b126ee65STobias Gysi return {}; 24019dbf3625STobias Gysi if (failed(moduleImport.convertGlobals())) 24029dbf3625STobias Gysi return {}; 24039dbf3625STobias Gysi if (failed(moduleImport.convertFunctions())) 24049dbf3625STobias Gysi return {}; 24059dbf3625STobias Gysi 24069dbf3625STobias Gysi return module; 24079dbf3625STobias Gysi } 2408