xref: /llvm-project/mlir/lib/Target/LLVMIR/ModuleImport.cpp (revision 4fc514af516f9434bf5ba3de404943a1f92817f7)
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