brintos

brintos / llvm-project-archived public Read only

0
0
Text · 133.0 KiB · d7d215b Raw
3404 lines · cpp
1//===- ModuleImport.cpp - LLVM to MLIR conversion ---------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the import of an LLVM IR module into an LLVM dialect10// module.11//12//===----------------------------------------------------------------------===//13 14#include "mlir/Target/LLVMIR/ModuleImport.h"15#include "mlir/IR/BuiltinAttributes.h"16#include "mlir/Target/LLVMIR/Import.h"17 18#include "AttrKindDetail.h"19#include "DebugImporter.h"20#include "LoopAnnotationImporter.h"21 22#include "mlir/Dialect/DLTI/DLTI.h"23#include "mlir/Dialect/LLVMIR/LLVMDialect.h"24#include "mlir/IR/Builders.h"25#include "mlir/IR/Matchers.h"26#include "mlir/Interfaces/DataLayoutInterfaces.h"27#include "mlir/Target/LLVMIR/DataLayoutImporter.h"28#include "mlir/Tools/mlir-translate/Translation.h"29 30#include "llvm/ADT/DepthFirstIterator.h"31#include "llvm/ADT/PostOrderIterator.h"32#include "llvm/ADT/ScopeExit.h"33#include "llvm/ADT/StringExtras.h"34#include "llvm/ADT/TypeSwitch.h"35#include "llvm/IR/Comdat.h"36#include "llvm/IR/Constants.h"37#include "llvm/IR/DebugProgramInstruction.h"38#include "llvm/IR/InlineAsm.h"39#include "llvm/IR/InstIterator.h"40#include "llvm/IR/Instructions.h"41#include "llvm/IR/IntrinsicInst.h"42#include "llvm/IR/Metadata.h"43#include "llvm/IR/Operator.h"44#include "llvm/Support/LogicalResult.h"45#include "llvm/Support/ModRef.h"46#include <optional>47 48using namespace mlir;49using namespace mlir::LLVM;50using namespace mlir::LLVM::detail;51 52#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"53 54// Utility to print an LLVM value as a string for passing to emitError().55// FIXME: Diagnostic should be able to natively handle types that have56// operator << (raw_ostream&) defined.57static std::string diag(const llvm::Value &value) {58  std::string str;59  llvm::raw_string_ostream os(str);60  os << value;61  return str;62}63 64// Utility to print an LLVM metadata node as a string for passing65// to emitError(). The module argument is needed to print the nodes66// canonically numbered.67static std::string diagMD(const llvm::Metadata *node,68                          const llvm::Module *module) {69  std::string str;70  llvm::raw_string_ostream os(str);71  node->print(os, module, /*IsForDebug=*/true);72  return str;73}74 75/// Returns the name of the global_ctors global variables.76static constexpr StringRef getGlobalCtorsVarName() {77  return "llvm.global_ctors";78}79 80/// Prefix used for symbols of nameless llvm globals.81static constexpr StringRef getNamelessGlobalPrefix() {82  return "mlir.llvm.nameless_global";83}84 85/// Returns the name of the global_dtors global variables.86static constexpr StringRef getGlobalDtorsVarName() {87  return "llvm.global_dtors";88}89 90/// Returns the symbol name for the module-level comdat operation. It must not91/// conflict with the user namespace.92static constexpr StringRef getGlobalComdatOpName() {93  return "__llvm_global_comdat";94}95 96/// Converts the sync scope identifier of `inst` to the string representation97/// necessary to build an atomic LLVM dialect operation. Returns the empty98/// string if the operation has either no sync scope or the default system-level99/// sync scope attached. The atomic operations only set their sync scope100/// attribute if they have a non-default sync scope attached.101static StringRef getLLVMSyncScope(llvm::Instruction *inst) {102  std::optional<llvm::SyncScope::ID> syncScopeID =103      llvm::getAtomicSyncScopeID(inst);104  if (!syncScopeID)105    return "";106 107  // Search the sync scope name for the given identifier. The default108  // system-level sync scope thereby maps to the empty string.109  SmallVector<StringRef> syncScopeName;110  llvm::LLVMContext &llvmContext = inst->getContext();111  llvmContext.getSyncScopeNames(syncScopeName);112  auto *it = llvm::find_if(syncScopeName, [&](StringRef name) {113    return *syncScopeID == llvmContext.getOrInsertSyncScopeID(name);114  });115  if (it != syncScopeName.end())116    return *it;117  llvm_unreachable("incorrect sync scope identifier");118}119 120/// Converts an array of unsigned indices to a signed integer position array.121static SmallVector<int64_t> getPositionFromIndices(ArrayRef<unsigned> indices) {122  SmallVector<int64_t> position;123  llvm::append_range(position, indices);124  return position;125}126 127/// Converts the LLVM instructions that have a generated MLIR builder. Using a128/// static implementation method called from the module import ensures the129/// builders have to use the `moduleImport` argument and cannot directly call130/// import methods. As a result, both the intrinsic and the instruction MLIR131/// builders have to use the `moduleImport` argument and none of them has direct132/// access to the private module import methods.133static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder,134                                            llvm::Instruction *inst,135                                            ModuleImport &moduleImport,136                                            LLVMImportInterface &iface) {137  // Copy the operands to an LLVM operands array reference for conversion.138  SmallVector<llvm::Value *> operands(inst->operands());139  ArrayRef<llvm::Value *> llvmOperands(operands);140 141  // Convert all instructions that provide an MLIR builder.142  if (iface.isConvertibleInstruction(inst->getOpcode()))143    return iface.convertInstruction(odsBuilder, inst, llvmOperands,144                                    moduleImport);145  // TODO: Implement the `convertInstruction` hooks in the146  // `LLVMDialectLLVMIRImportInterface` and move the following include there.147#include "mlir/Dialect/LLVMIR/LLVMOpFromLLVMIRConversions.inc"148 149  return failure();150}151 152/// Get a topologically sorted list of blocks for the given basic blocks.153static SetVector<llvm::BasicBlock *>154getTopologicallySortedBlocks(ArrayRef<llvm::BasicBlock *> basicBlocks) {155  SetVector<llvm::BasicBlock *> blocks;156  for (llvm::BasicBlock *basicBlock : basicBlocks) {157    if (!blocks.contains(basicBlock)) {158      llvm::ReversePostOrderTraversal<llvm::BasicBlock *> traversal(basicBlock);159      blocks.insert_range(traversal);160    }161  }162  assert(blocks.size() == basicBlocks.size() && "some blocks are not sorted");163  return blocks;164}165 166ModuleImport::ModuleImport(ModuleOp mlirModule,167                           std::unique_ptr<llvm::Module> llvmModule,168                           bool emitExpensiveWarnings,169                           bool importEmptyDICompositeTypes,170                           bool preferUnregisteredIntrinsics,171                           bool importStructsAsLiterals)172    : builder(mlirModule->getContext()), context(mlirModule->getContext()),173      mlirModule(mlirModule), llvmModule(std::move(llvmModule)),174      iface(mlirModule->getContext()),175      typeTranslator(*mlirModule->getContext(), importStructsAsLiterals),176      debugImporter(std::make_unique<DebugImporter>(177          mlirModule, importEmptyDICompositeTypes)),178      loopAnnotationImporter(179          std::make_unique<LoopAnnotationImporter>(*this, builder)),180      emitExpensiveWarnings(emitExpensiveWarnings),181      preferUnregisteredIntrinsics(preferUnregisteredIntrinsics) {182  builder.setInsertionPointToStart(mlirModule.getBody());183}184 185ComdatOp ModuleImport::getGlobalComdatOp() {186  if (globalComdatOp)187    return globalComdatOp;188 189  OpBuilder::InsertionGuard guard(builder);190  builder.setInsertionPointToEnd(mlirModule.getBody());191  globalComdatOp =192      ComdatOp::create(builder, mlirModule.getLoc(), getGlobalComdatOpName());193  globalInsertionOp = globalComdatOp;194  return globalComdatOp;195}196 197LogicalResult ModuleImport::processTBAAMetadata(const llvm::MDNode *node) {198  Location loc = mlirModule.getLoc();199 200  // If `node` is a valid TBAA root node, then return its optional identity201  // string, otherwise return failure.202  auto getIdentityIfRootNode =203      [&](const llvm::MDNode *node) -> FailureOr<std::optional<StringRef>> {204    // Root node, e.g.:205    //   !0 = !{!"Simple C/C++ TBAA"}206    //   !1 = !{}207    if (node->getNumOperands() > 1)208      return failure();209    // If the operand is MDString, then assume that this is a root node.210    if (node->getNumOperands() == 1)211      if (const auto *op0 = dyn_cast<const llvm::MDString>(node->getOperand(0)))212        return std::optional<StringRef>{op0->getString()};213    return std::optional<StringRef>{};214  };215 216  // If `node` looks like a TBAA type descriptor metadata,217  // then return true, if it is a valid node, and false otherwise.218  // If it does not look like a TBAA type descriptor metadata, then219  // return std::nullopt.220  // If `identity` and `memberTypes/Offsets` are non-null, then they will221  // contain the converted metadata operands for a valid TBAA node (i.e. when222  // true is returned).223  auto isTypeDescriptorNode = [&](const llvm::MDNode *node,224                                  StringRef *identity = nullptr,225                                  SmallVectorImpl<TBAAMemberAttr> *members =226                                      nullptr) -> std::optional<bool> {227    unsigned numOperands = node->getNumOperands();228    // Type descriptor, e.g.:229    //   !1 = !{!"int", !0, /*optional*/i64 0} /* scalar int type */230    //   !2 = !{!"agg_t", !1, i64 0} /* struct agg_t { int x; } */231    if (numOperands < 2)232      return std::nullopt;233 234    // TODO: support "new" format (D41501) for type descriptors,235    //       where the first operand is an MDNode.236    const auto *identityNode =237        dyn_cast<const llvm::MDString>(node->getOperand(0));238    if (!identityNode)239      return std::nullopt;240 241    // This should be a type descriptor node.242    if (identity)243      *identity = identityNode->getString();244 245    for (unsigned pairNum = 0, e = numOperands / 2; pairNum < e; ++pairNum) {246      const auto *memberNode =247          dyn_cast<const llvm::MDNode>(node->getOperand(2 * pairNum + 1));248      if (!memberNode) {249        emitError(loc) << "operand '" << 2 * pairNum + 1 << "' must be MDNode: "250                       << diagMD(node, llvmModule.get());251        return false;252      }253      int64_t offset = 0;254      if (2 * pairNum + 2 >= numOperands) {255        // Allow for optional 0 offset in 2-operand nodes.256        if (numOperands != 2) {257          emitError(loc) << "missing member offset: "258                         << diagMD(node, llvmModule.get());259          return false;260        }261      } else {262        auto *offsetCI = llvm::mdconst::dyn_extract<llvm::ConstantInt>(263            node->getOperand(2 * pairNum + 2));264        if (!offsetCI) {265          emitError(loc) << "operand '" << 2 * pairNum + 2266                         << "' must be ConstantInt: "267                         << diagMD(node, llvmModule.get());268          return false;269        }270        offset = offsetCI->getZExtValue();271      }272 273      if (members)274        members->push_back(TBAAMemberAttr::get(275            cast<TBAANodeAttr>(tbaaMapping.lookup(memberNode)), offset));276    }277 278    return true;279  };280 281  // If `node` looks like a TBAA access tag metadata,282  // then return true, if it is a valid node, and false otherwise.283  // If it does not look like a TBAA access tag metadata, then284  // return std::nullopt.285  // If the other arguments are non-null, then they will contain286  // the converted metadata operands for a valid TBAA node (i.e. when true is287  // returned).288  auto isTagNode = [&](const llvm::MDNode *node,289                       TBAATypeDescriptorAttr *baseAttr = nullptr,290                       TBAATypeDescriptorAttr *accessAttr = nullptr,291                       int64_t *offset = nullptr,292                       bool *isConstant = nullptr) -> std::optional<bool> {293    // Access tag, e.g.:294    //   !3 = !{!1, !1, i64 0} /* scalar int access */295    //   !4 = !{!2, !1, i64 0} /* agg_t::x access */296    //297    // Optional 4th argument is ConstantInt 0/1 identifying whether298    // the location being accessed is "constant" (see for details:299    // https://llvm.org/docs/LangRef.html#representation).300    unsigned numOperands = node->getNumOperands();301    if (numOperands != 3 && numOperands != 4)302      return std::nullopt;303    const auto *baseMD = dyn_cast<const llvm::MDNode>(node->getOperand(0));304    const auto *accessMD = dyn_cast<const llvm::MDNode>(node->getOperand(1));305    auto *offsetCI =306        llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(2));307    if (!baseMD || !accessMD || !offsetCI)308      return std::nullopt;309    // TODO: support "new" TBAA format, if needed (see D41501).310    // In the "old" format the first operand of the access type311    // metadata is MDString. We have to distinguish the formats,312    // because access tags have the same structure, but different313    // meaning for the operands.314    if (accessMD->getNumOperands() < 1 ||315        !isa<llvm::MDString>(accessMD->getOperand(0)))316      return std::nullopt;317    bool isConst = false;318    if (numOperands == 4) {319      auto *isConstantCI =320          llvm::mdconst::dyn_extract<llvm::ConstantInt>(node->getOperand(3));321      if (!isConstantCI) {322        emitError(loc) << "operand '3' must be ConstantInt: "323                       << diagMD(node, llvmModule.get());324        return false;325      }326      isConst = isConstantCI->getValue()[0];327    }328    if (baseAttr)329      *baseAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(baseMD));330    if (accessAttr)331      *accessAttr = cast<TBAATypeDescriptorAttr>(tbaaMapping.lookup(accessMD));332    if (offset)333      *offset = offsetCI->getZExtValue();334    if (isConstant)335      *isConstant = isConst;336    return true;337  };338 339  // Do a post-order walk over the TBAA Graph. Since a correct TBAA Graph is a340  // DAG, a post-order walk guarantees that we convert any metadata node we341  // depend on, prior to converting the current node.342  DenseSet<const llvm::MDNode *> seen;343  SmallVector<const llvm::MDNode *> workList;344  workList.push_back(node);345  while (!workList.empty()) {346    const llvm::MDNode *current = workList.back();347    if (tbaaMapping.contains(current)) {348      // Already converted. Just pop from the worklist.349      workList.pop_back();350      continue;351    }352 353    // If any child of this node is not yet converted, don't pop the current354    // node from the worklist but push the not-yet-converted children in the355    // front of the worklist.356    bool anyChildNotConverted = false;357    for (const llvm::MDOperand &operand : current->operands())358      if (auto *childNode = dyn_cast_or_null<const llvm::MDNode>(operand.get()))359        if (!tbaaMapping.contains(childNode)) {360          workList.push_back(childNode);361          anyChildNotConverted = true;362        }363 364    if (anyChildNotConverted) {365      // If this is the second time we failed to convert an element in the366      // worklist it must be because a child is dependent on it being converted367      // and we have a cycle in the graph. Cycles are not allowed in TBAA368      // graphs.369      if (!seen.insert(current).second)370        return emitError(loc) << "has cycle in TBAA graph: "371                              << diagMD(current, llvmModule.get());372 373      continue;374    }375 376    // Otherwise simply import the current node.377    workList.pop_back();378 379    FailureOr<std::optional<StringRef>> rootNodeIdentity =380        getIdentityIfRootNode(current);381    if (succeeded(rootNodeIdentity)) {382      StringAttr stringAttr = *rootNodeIdentity383                                  ? builder.getStringAttr(**rootNodeIdentity)384                                  : nullptr;385      // The root nodes do not have operands, so we can create386      // the TBAARootAttr on the first walk.387      tbaaMapping.insert({current, builder.getAttr<TBAARootAttr>(stringAttr)});388      continue;389    }390 391    StringRef identity;392    SmallVector<TBAAMemberAttr> members;393    if (std::optional<bool> isValid =394            isTypeDescriptorNode(current, &identity, &members)) {395      assert(isValid.value() && "type descriptor node must be valid");396 397      tbaaMapping.insert({current, builder.getAttr<TBAATypeDescriptorAttr>(398                                       identity, members)});399      continue;400    }401 402    TBAATypeDescriptorAttr baseAttr, accessAttr;403    int64_t offset;404    bool isConstant;405    if (std::optional<bool> isValid =406            isTagNode(current, &baseAttr, &accessAttr, &offset, &isConstant)) {407      assert(isValid.value() && "access tag node must be valid");408      tbaaMapping.insert(409          {current, builder.getAttr<TBAATagAttr>(baseAttr, accessAttr, offset,410                                                 isConstant)});411      continue;412    }413 414    return emitError(loc) << "unsupported TBAA node format: "415                          << diagMD(current, llvmModule.get());416  }417  return success();418}419 420LogicalResult421ModuleImport::processAccessGroupMetadata(const llvm::MDNode *node) {422  Location loc = mlirModule.getLoc();423  if (failed(loopAnnotationImporter->translateAccessGroup(node, loc)))424    return emitError(loc) << "unsupported access group node: "425                          << diagMD(node, llvmModule.get());426  return success();427}428 429LogicalResult430ModuleImport::processAliasScopeMetadata(const llvm::MDNode *node) {431  Location loc = mlirModule.getLoc();432  // Helper that verifies the node has a self reference operand.433  auto verifySelfRef = [](const llvm::MDNode *node) {434    return node->getNumOperands() != 0 &&435           node == dyn_cast<llvm::MDNode>(node->getOperand(0));436  };437  auto verifySelfRefOrString = [](const llvm::MDNode *node) {438    return node->getNumOperands() != 0 &&439           (node == dyn_cast<llvm::MDNode>(node->getOperand(0)) ||440            isa<llvm::MDString>(node->getOperand(0)));441  };442  // Helper that verifies the given operand is a string or does not exist.443  auto verifyDescription = [](const llvm::MDNode *node, unsigned idx) {444    return idx >= node->getNumOperands() ||445           isa<llvm::MDString>(node->getOperand(idx));446  };447 448  auto getIdAttr = [&](const llvm::MDNode *node) -> Attribute {449    if (verifySelfRef(node))450      return DistinctAttr::create(builder.getUnitAttr());451 452    auto *name = cast<llvm::MDString>(node->getOperand(0));453    return builder.getStringAttr(name->getString());454  };455 456  // Helper that creates an alias scope domain attribute.457  auto createAliasScopeDomainOp = [&](const llvm::MDNode *aliasDomain) {458    StringAttr description = nullptr;459    if (aliasDomain->getNumOperands() >= 2)460      if (auto *operand = dyn_cast<llvm::MDString>(aliasDomain->getOperand(1)))461        description = builder.getStringAttr(operand->getString());462    Attribute idAttr = getIdAttr(aliasDomain);463    return builder.getAttr<AliasScopeDomainAttr>(idAttr, description);464  };465 466  // Collect the alias scopes and domains to translate them.467  for (const llvm::MDOperand &operand : node->operands()) {468    if (const auto *scope = dyn_cast<llvm::MDNode>(operand)) {469      llvm::AliasScopeNode aliasScope(scope);470      const llvm::MDNode *domain = aliasScope.getDomain();471 472      // Verify the scope node points to valid scope metadata which includes473      // verifying its domain. Perform the verification before looking it up in474      // the alias scope mapping since it could have been inserted as a domain475      // node before.476      if (!verifySelfRefOrString(scope) || !domain ||477          !verifyDescription(scope, 2))478        return emitError(loc) << "unsupported alias scope node: "479                              << diagMD(scope, llvmModule.get());480      if (!verifySelfRefOrString(domain) || !verifyDescription(domain, 1))481        return emitError(loc) << "unsupported alias domain node: "482                              << diagMD(domain, llvmModule.get());483 484      if (aliasScopeMapping.contains(scope))485        continue;486 487      // Convert the domain metadata node if it has not been translated before.488      auto it = aliasScopeMapping.find(aliasScope.getDomain());489      if (it == aliasScopeMapping.end()) {490        auto aliasScopeDomainOp = createAliasScopeDomainOp(domain);491        it = aliasScopeMapping.try_emplace(domain, aliasScopeDomainOp).first;492      }493 494      // Convert the scope metadata node if it has not been converted before.495      StringAttr description = nullptr;496      if (!aliasScope.getName().empty())497        description = builder.getStringAttr(aliasScope.getName());498      Attribute idAttr = getIdAttr(scope);499      auto aliasScopeOp = builder.getAttr<AliasScopeAttr>(500          idAttr, cast<AliasScopeDomainAttr>(it->second), description);501 502      aliasScopeMapping.try_emplace(aliasScope.getNode(), aliasScopeOp);503    }504  }505  return success();506}507 508FailureOr<SmallVector<AliasScopeAttr>>509ModuleImport::lookupAliasScopeAttrs(const llvm::MDNode *node) const {510  SmallVector<AliasScopeAttr> aliasScopes;511  aliasScopes.reserve(node->getNumOperands());512  for (const llvm::MDOperand &operand : node->operands()) {513    auto *node = cast<llvm::MDNode>(operand.get());514    aliasScopes.push_back(515        dyn_cast_or_null<AliasScopeAttr>(aliasScopeMapping.lookup(node)));516  }517  // Return failure if one of the alias scope lookups failed.518  if (llvm::is_contained(aliasScopes, nullptr))519    return failure();520  return aliasScopes;521}522 523void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) {524  debugIntrinsics.insert(intrinsic);525}526 527void ModuleImport::addDebugRecord(llvm::DbgVariableRecord *dbgRecord) {528  if (!dbgRecords.contains(dbgRecord))529    dbgRecords.insert(dbgRecord);530}531 532static Attribute convertCGProfileModuleFlagValue(ModuleOp mlirModule,533                                                 llvm::MDTuple *mdTuple) {534  auto getLLVMFunction =535      [&](const llvm::MDOperand &funcMDO) -> llvm::Function * {536    auto *f = cast_or_null<llvm::ValueAsMetadata>(funcMDO);537    // nullptr is a valid value for the function pointer.538    if (!f)539      return nullptr;540    auto *llvmFn = cast<llvm::Function>(f->getValue()->stripPointerCasts());541    return llvmFn;542  };543 544  // Each tuple element becomes one ModuleFlagCGProfileEntryAttr.545  SmallVector<Attribute> cgProfile;546  for (unsigned i = 0; i < mdTuple->getNumOperands(); i++) {547    const llvm::MDOperand &mdo = mdTuple->getOperand(i);548    auto *cgEntry = cast<llvm::MDNode>(mdo);549    llvm::Constant *llvmConstant =550        cast<llvm::ConstantAsMetadata>(cgEntry->getOperand(2))->getValue();551    uint64_t count = cast<llvm::ConstantInt>(llvmConstant)->getZExtValue();552    auto *fromFn = getLLVMFunction(cgEntry->getOperand(0));553    auto *toFn = getLLVMFunction(cgEntry->getOperand(1));554    // FlatSymbolRefAttr::get(mlirModule->getContext(), llvmFn->getName());555    cgProfile.push_back(ModuleFlagCGProfileEntryAttr::get(556        mlirModule->getContext(),557        fromFn ? FlatSymbolRefAttr::get(mlirModule->getContext(),558                                        fromFn->getName())559               : nullptr,560        toFn ? FlatSymbolRefAttr::get(mlirModule->getContext(), toFn->getName())561             : nullptr,562        count));563  }564  return ArrayAttr::get(mlirModule->getContext(), cgProfile);565}566 567/// Extract a two element `MDTuple` from a `MDOperand`. Emit a warning in case568/// something else is found.569static llvm::MDTuple *getTwoElementMDTuple(ModuleOp mlirModule,570                                           const llvm::Module *llvmModule,571                                           const llvm::MDOperand &md) {572  auto *tupleEntry = dyn_cast_or_null<llvm::MDTuple>(md);573  if (!tupleEntry || tupleEntry->getNumOperands() != 2)574    emitWarning(mlirModule.getLoc())575        << "expected 2-element tuple metadata: " << diagMD(md, llvmModule);576  return tupleEntry;577}578 579/// Extract a constant metadata value from a two element tuple (<key, value>).580/// Return nullptr if requirements are not met. A warning is emitted if the581/// `matchKey` is different from the tuple's key.582static llvm::ConstantAsMetadata *getConstantMDFromKeyValueTuple(583    ModuleOp mlirModule, const llvm::Module *llvmModule,584    const llvm::MDOperand &md, StringRef matchKey, bool optional = false) {585  llvm::MDTuple *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, md);586  if (!tupleEntry)587    return nullptr;588  auto *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));589  if (!keyMD || keyMD->getString() != matchKey) {590    if (!optional)591      emitWarning(mlirModule.getLoc())592          << "expected '" << matchKey << "' key, but found: "593          << diagMD(tupleEntry->getOperand(0), llvmModule);594    return nullptr;595  }596 597  return dyn_cast<llvm::ConstantAsMetadata>(tupleEntry->getOperand(1));598}599 600/// Extract an integer value from a two element tuple (<key, value>).601/// Fail if requirements are not met. A warning is emitted if the602/// found value isn't a LLVM constant integer.603static FailureOr<uint64_t>604convertInt64FromKeyValueTuple(ModuleOp mlirModule,605                              const llvm::Module *llvmModule,606                              const llvm::MDOperand &md, StringRef matchKey) {607  llvm::ConstantAsMetadata *valMD =608      getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, matchKey);609  if (!valMD)610    return failure();611 612  if (auto *cstInt = dyn_cast<llvm::ConstantInt>(valMD->getValue()))613    return cstInt->getZExtValue();614 615  emitWarning(mlirModule.getLoc())616      << "expected integer metadata value for key '" << matchKey617      << "': " << diagMD(md, llvmModule);618  return failure();619}620 621static std::optional<ProfileSummaryFormatKind>622convertProfileSummaryFormat(ModuleOp mlirModule, const llvm::Module *llvmModule,623                            const llvm::MDOperand &formatMD) {624  auto *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, formatMD);625  if (!tupleEntry)626    return std::nullopt;627 628  llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));629  if (!keyMD || keyMD->getString() != "ProfileFormat") {630    emitWarning(mlirModule.getLoc())631        << "expected 'ProfileFormat' key: "632        << diagMD(tupleEntry->getOperand(0), llvmModule);633    return std::nullopt;634  }635 636  llvm::MDString *valMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(1));637  std::optional<ProfileSummaryFormatKind> fmtKind =638      symbolizeProfileSummaryFormatKind(valMD->getString());639  if (!fmtKind) {640    emitWarning(mlirModule.getLoc())641        << "expected 'SampleProfile', 'InstrProf' or 'CSInstrProf' values, "642           "but found: "643        << diagMD(valMD, llvmModule);644    return std::nullopt;645  }646 647  return fmtKind;648}649 650static FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>>651convertProfileSummaryDetailed(ModuleOp mlirModule,652                              const llvm::Module *llvmModule,653                              const llvm::MDOperand &summaryMD) {654  auto *tupleEntry = getTwoElementMDTuple(mlirModule, llvmModule, summaryMD);655  if (!tupleEntry)656    return failure();657 658  llvm::MDString *keyMD = dyn_cast<llvm::MDString>(tupleEntry->getOperand(0));659  if (!keyMD || keyMD->getString() != "DetailedSummary") {660    emitWarning(mlirModule.getLoc())661        << "expected 'DetailedSummary' key: "662        << diagMD(tupleEntry->getOperand(0), llvmModule);663    return failure();664  }665 666  llvm::MDTuple *entriesMD = dyn_cast<llvm::MDTuple>(tupleEntry->getOperand(1));667  if (!entriesMD) {668    emitWarning(mlirModule.getLoc())669        << "expected tuple value for 'DetailedSummary' key: "670        << diagMD(tupleEntry->getOperand(1), llvmModule);671    return failure();672  }673 674  SmallVector<ModuleFlagProfileSummaryDetailedAttr> detailedSummary;675  for (auto &&entry : entriesMD->operands()) {676    llvm::MDTuple *entryMD = dyn_cast<llvm::MDTuple>(entry);677    if (!entryMD || entryMD->getNumOperands() != 3) {678      emitWarning(mlirModule.getLoc())679          << "'DetailedSummary' entry expects 3 operands: "680          << diagMD(entry, llvmModule);681      return failure();682    }683 684    auto *op0 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(0));685    auto *op1 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(1));686    auto *op2 = dyn_cast<llvm::ConstantAsMetadata>(entryMD->getOperand(2));687    if (!op0 || !op1 || !op2) {688      emitWarning(mlirModule.getLoc())689          << "expected only integer entries in 'DetailedSummary': "690          << diagMD(entry, llvmModule);691      return failure();692    }693 694    auto detaildSummaryEntry = ModuleFlagProfileSummaryDetailedAttr::get(695        mlirModule->getContext(),696        cast<llvm::ConstantInt>(op0->getValue())->getZExtValue(),697        cast<llvm::ConstantInt>(op1->getValue())->getZExtValue(),698        cast<llvm::ConstantInt>(op2->getValue())->getZExtValue());699    detailedSummary.push_back(detaildSummaryEntry);700  }701  return detailedSummary;702}703 704static Attribute705convertProfileSummaryModuleFlagValue(ModuleOp mlirModule,706                                     const llvm::Module *llvmModule,707                                     llvm::MDTuple *mdTuple) {708  unsigned profileNumEntries = mdTuple->getNumOperands();709  if (profileNumEntries < 8) {710    emitWarning(mlirModule.getLoc())711        << "expected at 8 entries in 'ProfileSummary': "712        << diagMD(mdTuple, llvmModule);713    return nullptr;714  }715 716  unsigned summayIdx = 0;717  auto checkOptionalPosition = [&](const llvm::MDOperand &md,718                                   StringRef matchKey) -> LogicalResult {719    // Make sure we won't step over the bound of the array of summary entries.720    // Since (non-optional) DetailedSummary always comes last, the next entry in721    // the tuple operand array must exist.722    if (summayIdx + 1 >= profileNumEntries) {723      emitWarning(mlirModule.getLoc())724          << "the last summary entry is '" << matchKey725          << "', expected 'DetailedSummary': " << diagMD(md, llvmModule);726      return failure();727    }728 729    return success();730  };731 732  auto getOptIntValue =733      [&](const llvm::MDOperand &md,734          StringRef matchKey) -> FailureOr<std::optional<uint64_t>> {735    if (!getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md, matchKey,736                                        /*optional=*/true))737      return FailureOr<std::optional<uint64_t>>(std::nullopt);738    if (checkOptionalPosition(md, matchKey).failed())739      return failure();740    FailureOr<uint64_t> val =741        convertInt64FromKeyValueTuple(mlirModule, llvmModule, md, matchKey);742    if (failed(val))743      return failure();744    return val;745  };746 747  auto getOptDoubleValue = [&](const llvm::MDOperand &md,748                               StringRef matchKey) -> FailureOr<FloatAttr> {749    auto *valMD = getConstantMDFromKeyValueTuple(mlirModule, llvmModule, md,750                                                 matchKey, /*optional=*/true);751    if (!valMD)752      return FloatAttr{};753    if (auto *cstFP = dyn_cast<llvm::ConstantFP>(valMD->getValue())) {754      if (checkOptionalPosition(md, matchKey).failed())755        return failure();756      return FloatAttr::get(Float64Type::get(mlirModule.getContext()),757                            cstFP->getValueAPF());758    }759    emitWarning(mlirModule.getLoc())760        << "expected double metadata value for key '" << matchKey761        << "': " << diagMD(md, llvmModule);762    return failure();763  };764 765  // Build ModuleFlagProfileSummaryAttr by sequentially fetching elements in766  // a fixed order: format, total count, etc.767  std::optional<ProfileSummaryFormatKind> format = convertProfileSummaryFormat(768      mlirModule, llvmModule, mdTuple->getOperand(summayIdx++));769  if (!format.has_value())770    return nullptr;771 772  FailureOr<uint64_t> totalCount = convertInt64FromKeyValueTuple(773      mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "TotalCount");774  if (failed(totalCount))775    return nullptr;776 777  FailureOr<uint64_t> maxCount = convertInt64FromKeyValueTuple(778      mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "MaxCount");779  if (failed(maxCount))780    return nullptr;781 782  FailureOr<uint64_t> maxInternalCount = convertInt64FromKeyValueTuple(783      mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),784      "MaxInternalCount");785  if (failed(maxInternalCount))786    return nullptr;787 788  FailureOr<uint64_t> maxFunctionCount = convertInt64FromKeyValueTuple(789      mlirModule, llvmModule, mdTuple->getOperand(summayIdx++),790      "MaxFunctionCount");791  if (failed(maxFunctionCount))792    return nullptr;793 794  FailureOr<uint64_t> numCounts = convertInt64FromKeyValueTuple(795      mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumCounts");796  if (failed(numCounts))797    return nullptr;798 799  FailureOr<uint64_t> numFunctions = convertInt64FromKeyValueTuple(800      mlirModule, llvmModule, mdTuple->getOperand(summayIdx++), "NumFunctions");801  if (failed(numFunctions))802    return nullptr;803 804  // Handle optional keys.805  FailureOr<std::optional<uint64_t>> isPartialProfile =806      getOptIntValue(mdTuple->getOperand(summayIdx), "IsPartialProfile");807  if (failed(isPartialProfile))808    return nullptr;809  if (isPartialProfile->has_value())810    summayIdx++;811 812  FailureOr<FloatAttr> partialProfileRatio =813      getOptDoubleValue(mdTuple->getOperand(summayIdx), "PartialProfileRatio");814  if (failed(partialProfileRatio))815    return nullptr;816  if (*partialProfileRatio)817    summayIdx++;818 819  // Handle detailed summary.820  FailureOr<SmallVector<ModuleFlagProfileSummaryDetailedAttr>> detailed =821      convertProfileSummaryDetailed(mlirModule, llvmModule,822                                    mdTuple->getOperand(summayIdx));823  if (failed(detailed))824    return nullptr;825 826  // Build the final profile summary attribute.827  return ModuleFlagProfileSummaryAttr::get(828      mlirModule->getContext(), *format, *totalCount, *maxCount,829      *maxInternalCount, *maxFunctionCount, *numCounts, *numFunctions,830      *isPartialProfile, *partialProfileRatio, *detailed);831}832 833/// Invoke specific handlers for each known module flag value, returns nullptr834/// if the key is unknown or unimplemented.835static Attribute836convertModuleFlagValueFromMDTuple(ModuleOp mlirModule,837                                  const llvm::Module *llvmModule, StringRef key,838                                  llvm::MDTuple *mdTuple) {839  if (key == LLVMDialect::getModuleFlagKeyCGProfileName())840    return convertCGProfileModuleFlagValue(mlirModule, mdTuple);841  if (key == LLVMDialect::getModuleFlagKeyProfileSummaryName())842    return convertProfileSummaryModuleFlagValue(mlirModule, llvmModule,843                                                mdTuple);844  return nullptr;845}846 847LogicalResult ModuleImport::convertModuleFlagsMetadata() {848  SmallVector<llvm::Module::ModuleFlagEntry> llvmModuleFlags;849  llvmModule->getModuleFlagsMetadata(llvmModuleFlags);850 851  SmallVector<Attribute> moduleFlags;852  for (const auto [behavior, key, val] : llvmModuleFlags) {853    Attribute valAttr = nullptr;854    if (auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val)) {855      valAttr = builder.getI32IntegerAttr(constInt->getZExtValue());856    } else if (auto *mdString = dyn_cast<llvm::MDString>(val)) {857      valAttr = builder.getStringAttr(mdString->getString());858    } else if (auto *mdTuple = dyn_cast<llvm::MDTuple>(val)) {859      valAttr = convertModuleFlagValueFromMDTuple(mlirModule, llvmModule.get(),860                                                  key->getString(), mdTuple);861    }862 863    if (!valAttr) {864      emitWarning(mlirModule.getLoc())865          << "unsupported module flag value for key '" << key->getString()866          << "' : " << diagMD(val, llvmModule.get());867      continue;868    }869 870    moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(871        convertModFlagBehaviorFromLLVM(behavior),872        builder.getStringAttr(key->getString()), valAttr));873  }874 875  if (!moduleFlags.empty())876    LLVM::ModuleFlagsOp::create(builder, mlirModule.getLoc(),877                                builder.getArrayAttr(moduleFlags));878 879  return success();880}881 882LogicalResult ModuleImport::convertLinkerOptionsMetadata() {883  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {884    if (named.getName() != "llvm.linker.options")885      continue;886    // llvm.linker.options operands are lists of strings.887    for (const llvm::MDNode *node : named.operands()) {888      SmallVector<StringRef> options;889      options.reserve(node->getNumOperands());890      for (const llvm::MDOperand &option : node->operands())891        options.push_back(cast<llvm::MDString>(option)->getString());892      LLVM::LinkerOptionsOp::create(builder, mlirModule.getLoc(),893                                    builder.getStrArrayAttr(options));894    }895  }896  return success();897}898 899LogicalResult ModuleImport::convertDependentLibrariesMetadata() {900  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {901    if (named.getName() != "llvm.dependent-libraries")902      continue;903    SmallVector<StringRef> libraries;904    for (const llvm::MDNode *node : named.operands()) {905      if (node->getNumOperands() == 1)906        if (auto *mdString = dyn_cast<llvm::MDString>(node->getOperand(0)))907          libraries.push_back(mdString->getString());908    }909    if (!libraries.empty())910      mlirModule->setAttr(LLVM::LLVMDialect::getDependentLibrariesAttrName(),911                          builder.getStrArrayAttr(libraries));912  }913  return success();914}915 916LogicalResult ModuleImport::convertIdentMetadata() {917  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {918    // llvm.ident should have a single operand. That operand is itself an919    // MDNode with a single string operand.920    if (named.getName() != LLVMDialect::getIdentAttrName())921      continue;922 923    if (named.getNumOperands() == 1)924      if (auto *md = dyn_cast<llvm::MDNode>(named.getOperand(0)))925        if (md->getNumOperands() == 1)926          if (auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))927            mlirModule->setAttr(LLVMDialect::getIdentAttrName(),928                                builder.getStringAttr(mdStr->getString()));929  }930  return success();931}932 933LogicalResult ModuleImport::convertCommandlineMetadata() {934  for (const llvm::NamedMDNode &nmd : llvmModule->named_metadata()) {935    // llvm.commandline should have a single operand. That operand is itself an936    // MDNode with a single string operand.937    if (nmd.getName() != LLVMDialect::getCommandlineAttrName())938      continue;939 940    if (nmd.getNumOperands() == 1)941      if (auto *md = dyn_cast<llvm::MDNode>(nmd.getOperand(0)))942        if (md->getNumOperands() == 1)943          if (auto *mdStr = dyn_cast<llvm::MDString>(md->getOperand(0)))944            mlirModule->setAttr(LLVMDialect::getCommandlineAttrName(),945                                builder.getStringAttr(mdStr->getString()));946  }947  return success();948}949 950LogicalResult ModuleImport::convertMetadata() {951  OpBuilder::InsertionGuard guard(builder);952  builder.setInsertionPointToEnd(mlirModule.getBody());953  for (const llvm::Function &func : llvmModule->functions()) {954    for (const llvm::Instruction &inst : llvm::instructions(func)) {955      // Convert access group metadata nodes.956      if (llvm::MDNode *node =957              inst.getMetadata(llvm::LLVMContext::MD_access_group))958        if (failed(processAccessGroupMetadata(node)))959          return failure();960 961      // Convert alias analysis metadata nodes.962      llvm::AAMDNodes aliasAnalysisNodes = inst.getAAMetadata();963      if (!aliasAnalysisNodes)964        continue;965      if (aliasAnalysisNodes.TBAA)966        if (failed(processTBAAMetadata(aliasAnalysisNodes.TBAA)))967          return failure();968      if (aliasAnalysisNodes.Scope)969        if (failed(processAliasScopeMetadata(aliasAnalysisNodes.Scope)))970          return failure();971      if (aliasAnalysisNodes.NoAlias)972        if (failed(processAliasScopeMetadata(aliasAnalysisNodes.NoAlias)))973          return failure();974    }975  }976  if (failed(convertLinkerOptionsMetadata()))977    return failure();978  if (failed(convertDependentLibrariesMetadata()))979    return failure();980  if (failed(convertModuleFlagsMetadata()))981    return failure();982  if (failed(convertIdentMetadata()))983    return failure();984  if (failed(convertCommandlineMetadata()))985    return failure();986  return success();987}988 989void ModuleImport::processComdat(const llvm::Comdat *comdat) {990  if (comdatMapping.contains(comdat))991    return;992 993  ComdatOp comdatOp = getGlobalComdatOp();994  OpBuilder::InsertionGuard guard(builder);995  builder.setInsertionPointToEnd(&comdatOp.getBody().back());996  auto selectorOp = ComdatSelectorOp::create(997      builder, mlirModule.getLoc(), comdat->getName(),998      convertComdatFromLLVM(comdat->getSelectionKind()));999  auto symbolRef =1000      SymbolRefAttr::get(builder.getContext(), getGlobalComdatOpName(),1001                         FlatSymbolRefAttr::get(selectorOp.getSymNameAttr()));1002  comdatMapping.try_emplace(comdat, symbolRef);1003}1004 1005LogicalResult ModuleImport::convertComdats() {1006  for (llvm::GlobalVariable &globalVar : llvmModule->globals())1007    if (globalVar.hasComdat())1008      processComdat(globalVar.getComdat());1009  for (llvm::Function &func : llvmModule->functions())1010    if (func.hasComdat())1011      processComdat(func.getComdat());1012  return success();1013}1014 1015LogicalResult ModuleImport::convertGlobals() {1016  for (llvm::GlobalVariable &globalVar : llvmModule->globals()) {1017    if (globalVar.getName() == getGlobalCtorsVarName() ||1018        globalVar.getName() == getGlobalDtorsVarName()) {1019      if (failed(convertGlobalCtorsAndDtors(&globalVar))) {1020        return emitError(UnknownLoc::get(context))1021               << "unhandled global variable: " << diag(globalVar);1022      }1023      continue;1024    }1025    if (failed(convertGlobal(&globalVar))) {1026      return emitError(UnknownLoc::get(context))1027             << "unhandled global variable: " << diag(globalVar);1028    }1029  }1030  return success();1031}1032 1033LogicalResult ModuleImport::convertAliases() {1034  for (llvm::GlobalAlias &alias : llvmModule->aliases()) {1035    if (failed(convertAlias(&alias))) {1036      return emitError(UnknownLoc::get(context))1037             << "unhandled global alias: " << diag(alias);1038    }1039  }1040  return success();1041}1042 1043LogicalResult ModuleImport::convertIFuncs() {1044  for (llvm::GlobalIFunc &ifunc : llvmModule->ifuncs()) {1045    if (failed(convertIFunc(&ifunc))) {1046      return emitError(UnknownLoc::get(context))1047             << "unhandled global ifunc: " << diag(ifunc);1048    }1049  }1050  return success();1051}1052 1053LogicalResult ModuleImport::convertDataLayout() {1054  Location loc = mlirModule.getLoc();1055  DataLayoutImporter dataLayoutImporter(1056      context, llvmModule->getDataLayout().getStringRepresentation());1057  if (!dataLayoutImporter.getDataLayoutSpec())1058    return emitError(loc, "cannot translate data layout: ")1059           << dataLayoutImporter.getLastToken();1060 1061  for (StringRef token : dataLayoutImporter.getUnhandledTokens())1062    emitWarning(loc, "unhandled data layout token: ") << token;1063 1064  mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,1065                      dataLayoutImporter.getDataLayoutSpec());1066  return success();1067}1068 1069void ModuleImport::convertTargetTriple() {1070  mlirModule->setAttr(1071      LLVM::LLVMDialect::getTargetTripleAttrName(),1072      builder.getStringAttr(llvmModule->getTargetTriple().str()));1073}1074 1075void ModuleImport::convertModuleLevelAsm() {1076  llvm::StringRef asmStr = llvmModule->getModuleInlineAsm();1077  llvm::SmallVector<mlir::Attribute> asmArrayAttr;1078 1079  for (llvm::StringRef line : llvm::split(asmStr, '\n'))1080    if (!line.empty())1081      asmArrayAttr.push_back(builder.getStringAttr(line));1082 1083  mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),1084                      builder.getArrayAttr(asmArrayAttr));1085}1086 1087LogicalResult ModuleImport::convertFunctions() {1088  for (llvm::Function &func : llvmModule->functions())1089    if (failed(processFunction(&func)))1090      return failure();1091  return success();1092}1093 1094void ModuleImport::setNonDebugMetadataAttrs(llvm::Instruction *inst,1095                                            Operation *op) {1096  SmallVector<std::pair<unsigned, llvm::MDNode *>> allMetadata;1097  inst->getAllMetadataOtherThanDebugLoc(allMetadata);1098  for (auto &[kind, node] : allMetadata) {1099    if (!iface.isConvertibleMetadata(kind))1100      continue;1101    if (failed(iface.setMetadataAttrs(builder, kind, node, op, *this))) {1102      if (emitExpensiveWarnings) {1103        Location loc = debugImporter->translateLoc(inst->getDebugLoc());1104        emitWarning(loc) << "unhandled metadata: "1105                         << diagMD(node, llvmModule.get()) << " on "1106                         << diag(*inst);1107      }1108    }1109  }1110}1111 1112void ModuleImport::setIntegerOverflowFlags(llvm::Instruction *inst,1113                                           Operation *op) const {1114  auto iface = cast<IntegerOverflowFlagsInterface>(op);1115 1116  IntegerOverflowFlags value = {};1117  value = bitEnumSet(value, IntegerOverflowFlags::nsw, inst->hasNoSignedWrap());1118  value =1119      bitEnumSet(value, IntegerOverflowFlags::nuw, inst->hasNoUnsignedWrap());1120 1121  iface.setOverflowFlags(value);1122}1123 1124void ModuleImport::setExactFlag(llvm::Instruction *inst, Operation *op) const {1125  auto iface = cast<ExactFlagInterface>(op);1126 1127  iface.setIsExact(inst->isExact());1128}1129 1130void ModuleImport::setDisjointFlag(llvm::Instruction *inst,1131                                   Operation *op) const {1132  auto iface = cast<DisjointFlagInterface>(op);1133  auto *instDisjoint = cast<llvm::PossiblyDisjointInst>(inst);1134 1135  iface.setIsDisjoint(instDisjoint->isDisjoint());1136}1137 1138void ModuleImport::setNonNegFlag(llvm::Instruction *inst, Operation *op) const {1139  auto iface = cast<NonNegFlagInterface>(op);1140 1141  iface.setNonNeg(inst->hasNonNeg());1142}1143 1144void ModuleImport::setFastmathFlagsAttr(llvm::Instruction *inst,1145                                        Operation *op) const {1146  auto iface = cast<FastmathFlagsInterface>(op);1147 1148  // Even if the imported operation implements the fastmath interface, the1149  // original instruction may not have fastmath flags set. Exit if an1150  // instruction, such as a non floating-point function call, does not have1151  // fastmath flags.1152  if (!isa<llvm::FPMathOperator>(inst))1153    return;1154  llvm::FastMathFlags flags = inst->getFastMathFlags();1155 1156  // Set the fastmath bits flag-by-flag.1157  FastmathFlags value = {};1158  value = bitEnumSet(value, FastmathFlags::nnan, flags.noNaNs());1159  value = bitEnumSet(value, FastmathFlags::ninf, flags.noInfs());1160  value = bitEnumSet(value, FastmathFlags::nsz, flags.noSignedZeros());1161  value = bitEnumSet(value, FastmathFlags::arcp, flags.allowReciprocal());1162  value = bitEnumSet(value, FastmathFlags::contract, flags.allowContract());1163  value = bitEnumSet(value, FastmathFlags::afn, flags.approxFunc());1164  value = bitEnumSet(value, FastmathFlags::reassoc, flags.allowReassoc());1165  FastmathFlagsAttr attr = FastmathFlagsAttr::get(builder.getContext(), value);1166  iface->setAttr(iface.getFastmathAttrName(), attr);1167}1168 1169/// Returns `type` if it is a builtin integer or floating-point vector type that1170/// can be used to create an attribute or nullptr otherwise. If provided,1171/// `arrayShape` is added to the shape of the vector to create an attribute that1172/// matches an array of vectors.1173static Type getVectorTypeForAttr(Type type, ArrayRef<int64_t> arrayShape = {}) {1174  if (!LLVM::isCompatibleVectorType(type))1175    return {};1176 1177  llvm::ElementCount numElements = LLVM::getVectorNumElements(type);1178  if (numElements.isScalable()) {1179    emitError(UnknownLoc::get(type.getContext()))1180        << "scalable vectors not supported";1181    return {};1182  }1183 1184  // An LLVM dialect vector can only contain scalars.1185  Type elementType = cast<VectorType>(type).getElementType();1186  if (!elementType.isIntOrFloat())1187    return {};1188 1189  SmallVector<int64_t> shape(arrayShape);1190  shape.push_back(numElements.getKnownMinValue());1191  return VectorType::get(shape, elementType);1192}1193 1194Type ModuleImport::getBuiltinTypeForAttr(Type type) {1195  if (!type)1196    return {};1197 1198  // Return builtin integer and floating-point types as is.1199  if (type.isIntOrFloat())1200    return type;1201 1202  // Return builtin vectors of integer and floating-point types as is.1203  if (Type vectorType = getVectorTypeForAttr(type))1204    return vectorType;1205 1206  // Multi-dimensional array types are converted to tensors or vectors,1207  // depending on the innermost type being a scalar or a vector.1208  SmallVector<int64_t> arrayShape;1209  while (auto arrayType = dyn_cast<LLVMArrayType>(type)) {1210    arrayShape.push_back(arrayType.getNumElements());1211    type = arrayType.getElementType();1212  }1213  if (type.isIntOrFloat())1214    return RankedTensorType::get(arrayShape, type);1215  return getVectorTypeForAttr(type, arrayShape);1216}1217 1218/// Returns an integer or float attribute for the provided scalar constant1219/// `constScalar` or nullptr if the conversion fails.1220static TypedAttr getScalarConstantAsAttr(OpBuilder &builder,1221                                         llvm::Constant *constScalar) {1222  MLIRContext *context = builder.getContext();1223 1224  // Convert scalar integers.1225  if (auto *constInt = dyn_cast<llvm::ConstantInt>(constScalar)) {1226    return builder.getIntegerAttr(1227        IntegerType::get(context, constInt->getBitWidth()),1228        constInt->getValue());1229  }1230 1231  // Convert scalar floats.1232  if (auto *constFloat = dyn_cast<llvm::ConstantFP>(constScalar)) {1233    llvm::Type *type = constFloat->getType();1234    FloatType floatType =1235        type->isBFloatTy()1236            ? BFloat16Type::get(context)1237            : LLVM::detail::getFloatType(context, type->getScalarSizeInBits());1238    if (!floatType) {1239      emitError(UnknownLoc::get(builder.getContext()))1240          << "unexpected floating-point type";1241      return {};1242    }1243    return builder.getFloatAttr(floatType, constFloat->getValueAPF());1244  }1245  return {};1246}1247 1248/// Returns an integer or float attribute array for the provided constant1249/// sequence `constSequence` or nullptr if the conversion fails.1250static SmallVector<Attribute>1251getSequenceConstantAsAttrs(OpBuilder &builder,1252                           llvm::ConstantDataSequential *constSequence) {1253  SmallVector<Attribute> elementAttrs;1254  elementAttrs.reserve(constSequence->getNumElements());1255  for (auto idx : llvm::seq<int64_t>(0, constSequence->getNumElements())) {1256    llvm::Constant *constElement = constSequence->getElementAsConstant(idx);1257    elementAttrs.push_back(getScalarConstantAsAttr(builder, constElement));1258  }1259  return elementAttrs;1260}1261 1262Attribute ModuleImport::getConstantAsAttr(llvm::Constant *constant) {1263  // Convert scalar constants.1264  if (Attribute scalarAttr = getScalarConstantAsAttr(builder, constant))1265    return scalarAttr;1266 1267  // Returns the static shape of the provided type if possible.1268  auto getConstantShape = [&](llvm::Type *type) {1269    return llvm::dyn_cast_if_present<ShapedType>(1270        getBuiltinTypeForAttr(convertType(type)));1271  };1272 1273  // Convert one-dimensional constant arrays or vectors that store 1/2/4/8-byte1274  // integer or half/bfloat/float/double values.1275  if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(constant)) {1276    if (constArray->isString())1277      return builder.getStringAttr(constArray->getAsString());1278    auto shape = getConstantShape(constArray->getType());1279    if (!shape)1280      return {};1281    // Convert splat constants to splat elements attributes.1282    auto *constVector = dyn_cast<llvm::ConstantDataVector>(constant);1283    if (constVector && constVector->isSplat()) {1284      // A vector is guaranteed to have at least size one.1285      Attribute splatAttr = getScalarConstantAsAttr(1286          builder, constVector->getElementAsConstant(0));1287      return SplatElementsAttr::get(shape, splatAttr);1288    }1289    // Convert non-splat constants to dense elements attributes.1290    SmallVector<Attribute> elementAttrs =1291        getSequenceConstantAsAttrs(builder, constArray);1292    return DenseElementsAttr::get(shape, elementAttrs);1293  }1294 1295  // Convert multi-dimensional constant aggregates that store all kinds of1296  // integer and floating-point types.1297  if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(constant)) {1298    auto shape = getConstantShape(constAggregate->getType());1299    if (!shape)1300      return {};1301    // Collect the aggregate elements in depths first order.1302    SmallVector<Attribute> elementAttrs;1303    SmallVector<llvm::Constant *> workList = {constAggregate};1304    while (!workList.empty()) {1305      llvm::Constant *current = workList.pop_back_val();1306      // Append any nested aggregates in reverse order to ensure the head1307      // element of the nested aggregates is at the back of the work list.1308      if (auto *constAggregate = dyn_cast<llvm::ConstantAggregate>(current)) {1309        for (auto idx :1310             reverse(llvm::seq<int64_t>(0, constAggregate->getNumOperands())))1311          workList.push_back(constAggregate->getAggregateElement(idx));1312        continue;1313      }1314      // Append the elements of nested constant arrays or vectors that store1315      // 1/2/4/8-byte integer or half/bfloat/float/double values.1316      if (auto *constArray = dyn_cast<llvm::ConstantDataSequential>(current)) {1317        SmallVector<Attribute> attrs =1318            getSequenceConstantAsAttrs(builder, constArray);1319        elementAttrs.append(attrs.begin(), attrs.end());1320        continue;1321      }1322      // Append nested scalar constants that store all kinds of integer and1323      // floating-point types.1324      if (Attribute scalarAttr = getScalarConstantAsAttr(builder, current)) {1325        elementAttrs.push_back(scalarAttr);1326        continue;1327      }1328      // Bail if the aggregate contains a unsupported constant type such as a1329      // constant expression.1330      return {};1331    }1332    return DenseElementsAttr::get(shape, elementAttrs);1333  }1334 1335  // Convert zero aggregates.1336  if (auto *constZero = dyn_cast<llvm::ConstantAggregateZero>(constant)) {1337    auto shape = llvm::dyn_cast_if_present<ShapedType>(1338        getBuiltinTypeForAttr(convertType(constZero->getType())));1339    if (!shape)1340      return {};1341    // Convert zero aggregates with a static shape to splat elements attributes.1342    Attribute splatAttr = builder.getZeroAttr(shape.getElementType());1343    assert(splatAttr && "expected non-null zero attribute for scalar types");1344    return SplatElementsAttr::get(shape, splatAttr);1345  }1346  return {};1347}1348 1349FlatSymbolRefAttr1350ModuleImport::getOrCreateNamelessSymbolName(llvm::GlobalVariable *globalVar) {1351  assert(globalVar->getName().empty() &&1352         "expected to work with a nameless global");1353  auto [it, success] = namelessGlobals.try_emplace(globalVar);1354  if (!success)1355    return it->second;1356 1357  // Make sure the symbol name does not clash with an existing symbol.1358  SmallString<128> globalName = SymbolTable::generateSymbolName<128>(1359      getNamelessGlobalPrefix(),1360      [this](StringRef newName) { return llvmModule->getNamedValue(newName); },1361      namelessGlobalId);1362  auto symbolRef = FlatSymbolRefAttr::get(context, globalName);1363  it->getSecond() = symbolRef;1364  return symbolRef;1365}1366 1367OpBuilder::InsertionGuard ModuleImport::setGlobalInsertionPoint() {1368  OpBuilder::InsertionGuard guard(builder);1369  if (globalInsertionOp)1370    builder.setInsertionPointAfter(globalInsertionOp);1371  else1372    builder.setInsertionPointToStart(mlirModule.getBody());1373  return guard;1374}1375 1376LogicalResult ModuleImport::convertAlias(llvm::GlobalAlias *alias) {1377  // Insert the alias after the last one or at the start of the module.1378  OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();1379 1380  Type type = convertType(alias->getValueType());1381  AliasOp aliasOp = AliasOp::create(builder, mlirModule.getLoc(), type,1382                                    convertLinkageFromLLVM(alias->getLinkage()),1383                                    alias->getName(),1384                                    /*dsoLocal=*/alias->isDSOLocal(),1385                                    /*thread_local=*/alias->isThreadLocal(),1386                                    /*attrs=*/ArrayRef<NamedAttribute>());1387  globalInsertionOp = aliasOp;1388 1389  clearRegionState();1390  Block *block = builder.createBlock(&aliasOp.getInitializerRegion());1391  setConstantInsertionPointToStart(block);1392  FailureOr<Value> initializer = convertConstantExpr(alias->getAliasee());1393  if (failed(initializer))1394    return failure();1395  ReturnOp::create(builder, aliasOp.getLoc(), *initializer);1396 1397  if (alias->hasAtLeastLocalUnnamedAddr())1398    aliasOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(alias->getUnnamedAddr()));1399  aliasOp.setVisibility_(convertVisibilityFromLLVM(alias->getVisibility()));1400 1401  return success();1402}1403 1404LogicalResult ModuleImport::convertIFunc(llvm::GlobalIFunc *ifunc) {1405  OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();1406 1407  Type type = convertType(ifunc->getValueType());1408  llvm::Constant *resolver = ifunc->getResolver();1409  Type resolverType = convertType(resolver->getType());1410  IFuncOp::create(builder, mlirModule.getLoc(), ifunc->getName(), type,1411                  resolver->getName(), resolverType,1412                  convertLinkageFromLLVM(ifunc->getLinkage()),1413                  ifunc->isDSOLocal(), ifunc->getAddressSpace(),1414                  convertUnnamedAddrFromLLVM(ifunc->getUnnamedAddr()),1415                  convertVisibilityFromLLVM(ifunc->getVisibility()));1416  return success();1417}1418 1419/// Converts LLVM string, integer, and enum attributes into MLIR attributes,1420/// skipping those in `attributesToSkip` and emitting a warning at `loc` for1421/// any other unsupported attributes.1422static ArrayAttr1423convertLLVMAttributesToMLIR(Location loc, MLIRContext *context,1424                            llvm::AttributeSet attributes,1425                            ArrayRef<StringLiteral> attributesToSkip = {}) {1426  SmallVector<Attribute> mlirAttributes;1427  for (llvm::Attribute attr : attributes) {1428    StringRef attrName;1429    if (attr.isStringAttribute())1430      attrName = attr.getKindAsString();1431    else1432      attrName = llvm::Attribute::getNameFromAttrKind(attr.getKindAsEnum());1433    if (llvm::is_contained(attributesToSkip, attrName))1434      continue;1435 1436    auto keyAttr = StringAttr::get(context, attrName);1437    if (attr.isStringAttribute()) {1438      StringRef val = attr.getValueAsString();1439      if (val.empty()) {1440        // For string attributes without values, add only the attribute name.1441        mlirAttributes.push_back(keyAttr);1442        continue;1443      }1444      // For string attributes with a value, create a [name, value] pair.1445      mlirAttributes.push_back(1446          ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));1447      continue;1448    }1449    if (attr.isIntAttribute()) {1450      // For integer attributes, convert the value to a string and create a1451      // [name, value] pair.1452      auto val = std::to_string(attr.getValueAsInt());1453      mlirAttributes.push_back(1454          ArrayAttr::get(context, {keyAttr, StringAttr::get(context, val)}));1455      continue;1456    }1457    if (attr.isEnumAttribute()) {1458      // For enum attributes, add only the attribute name.1459      mlirAttributes.push_back(keyAttr);1460      continue;1461    }1462 1463    emitWarning(loc)1464        << "'" << attrName1465        << "' attribute is invalid on current operation, skipping it";1466  }1467  return ArrayAttr::get(context, mlirAttributes);1468}1469 1470/// Converts LLVM attributes from `globalVar` into MLIR attributes and adds them1471/// to `globalOp` as target-specific attributes.1472static void processTargetSpecificAttrs(llvm::GlobalVariable *globalVar,1473                                       GlobalOp globalOp) {1474  ArrayAttr targetSpecificAttrs = convertLLVMAttributesToMLIR(1475      globalOp.getLoc(), globalOp.getContext(), globalVar->getAttributes());1476  if (!targetSpecificAttrs.empty())1477    globalOp.setTargetSpecificAttrsAttr(targetSpecificAttrs);1478}1479 1480LogicalResult ModuleImport::convertGlobal(llvm::GlobalVariable *globalVar) {1481  // Insert the global after the last one or at the start of the module.1482  OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();1483 1484  Attribute valueAttr;1485  if (globalVar->hasInitializer())1486    valueAttr = getConstantAsAttr(globalVar->getInitializer());1487  Type type = convertType(globalVar->getValueType());1488 1489  uint64_t alignment = 0;1490  llvm::MaybeAlign maybeAlign = globalVar->getAlign();1491  if (maybeAlign.has_value()) {1492    llvm::Align align = *maybeAlign;1493    alignment = align.value();1494  }1495 1496  // Get the global expression associated with this global variable and convert1497  // it.1498  SmallVector<Attribute> globalExpressionAttrs;1499  SmallVector<llvm::DIGlobalVariableExpression *> globalExpressions;1500  globalVar->getDebugInfo(globalExpressions);1501 1502  for (llvm::DIGlobalVariableExpression *expr : globalExpressions) {1503    DIGlobalVariableExpressionAttr globalExpressionAttr =1504        debugImporter->translateGlobalVariableExpression(expr);1505    globalExpressionAttrs.push_back(globalExpressionAttr);1506  }1507 1508  // Workaround to support LLVM's nameless globals. MLIR, in contrast to LLVM,1509  // always requires a symbol name.1510  StringRef globalName = globalVar->getName();1511  if (globalName.empty())1512    globalName = getOrCreateNamelessSymbolName(globalVar).getValue();1513 1514  GlobalOp globalOp = GlobalOp::create(1515      builder, mlirModule.getLoc(), type, globalVar->isConstant(),1516      convertLinkageFromLLVM(globalVar->getLinkage()), StringRef(globalName),1517      valueAttr, alignment, /*addrSpace=*/globalVar->getAddressSpace(),1518      /*dsoLocal=*/globalVar->isDSOLocal(),1519      /*thread_local=*/globalVar->isThreadLocal(), /*comdat=*/SymbolRefAttr(),1520      /*attrs=*/ArrayRef<NamedAttribute>(), /*dbgExprs=*/globalExpressionAttrs);1521  globalInsertionOp = globalOp;1522 1523  if (globalVar->hasInitializer() && !valueAttr) {1524    clearRegionState();1525    Block *block = builder.createBlock(&globalOp.getInitializerRegion());1526    setConstantInsertionPointToStart(block);1527    FailureOr<Value> initializer =1528        convertConstantExpr(globalVar->getInitializer());1529    if (failed(initializer))1530      return failure();1531    ReturnOp::create(builder, globalOp.getLoc(), *initializer);1532  }1533  if (globalVar->hasAtLeastLocalUnnamedAddr()) {1534    globalOp.setUnnamedAddr(1535        convertUnnamedAddrFromLLVM(globalVar->getUnnamedAddr()));1536  }1537  if (globalVar->hasSection())1538    globalOp.setSection(globalVar->getSection());1539  globalOp.setVisibility_(1540      convertVisibilityFromLLVM(globalVar->getVisibility()));1541 1542  if (globalVar->hasComdat())1543    globalOp.setComdatAttr(comdatMapping.lookup(globalVar->getComdat()));1544 1545  processTargetSpecificAttrs(globalVar, globalOp);1546 1547  return success();1548}1549 1550LogicalResult1551ModuleImport::convertGlobalCtorsAndDtors(llvm::GlobalVariable *globalVar) {1552  if (!globalVar->hasInitializer() || !globalVar->hasAppendingLinkage())1553    return failure();1554  llvm::Constant *initializer = globalVar->getInitializer();1555 1556  bool knownInit = isa<llvm::ConstantArray>(initializer) ||1557                   isa<llvm::ConstantAggregateZero>(initializer);1558  if (!knownInit)1559    return failure();1560 1561  // ConstantAggregateZero does not engage with the operand initialization1562  // in the loop that follows - there should be no operands. This implies1563  // empty ctor/dtor lists.1564  if (auto *caz = dyn_cast<llvm::ConstantAggregateZero>(initializer)) {1565    if (caz->getElementCount().getFixedValue() != 0)1566      return failure();1567  }1568 1569  SmallVector<Attribute> funcs;1570  SmallVector<int32_t> priorities;1571  SmallVector<Attribute> dataList;1572  for (llvm::Value *operand : initializer->operands()) {1573    auto *aggregate = dyn_cast<llvm::ConstantAggregate>(operand);1574    if (!aggregate || aggregate->getNumOperands() != 3)1575      return failure();1576 1577    auto *priority = dyn_cast<llvm::ConstantInt>(aggregate->getOperand(0));1578    auto *func = dyn_cast<llvm::Function>(aggregate->getOperand(1));1579    auto *data = dyn_cast<llvm::Constant>(aggregate->getOperand(2));1580    if (!priority || !func || !data)1581      return failure();1582 1583    auto *gv = dyn_cast_or_null<llvm::GlobalValue>(data);1584    Attribute dataAttr;1585    if (gv)1586      dataAttr = FlatSymbolRefAttr::get(context, gv->getName());1587    else if (data->isNullValue())1588      dataAttr = ZeroAttr::get(context);1589    else1590      return failure();1591 1592    funcs.push_back(FlatSymbolRefAttr::get(context, func->getName()));1593    priorities.push_back(priority->getValue().getZExtValue());1594    dataList.push_back(dataAttr);1595  }1596 1597  // Insert the global after the last one or at the start of the module.1598  OpBuilder::InsertionGuard guard = setGlobalInsertionPoint();1599 1600  if (globalVar->getName() == getGlobalCtorsVarName()) {1601    globalInsertionOp = LLVM::GlobalCtorsOp::create(1602        builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),1603        builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));1604    return success();1605  }1606  globalInsertionOp = LLVM::GlobalDtorsOp::create(1607      builder, mlirModule.getLoc(), builder.getArrayAttr(funcs),1608      builder.getI32ArrayAttr(priorities), builder.getArrayAttr(dataList));1609  return success();1610}1611 1612SetVector<llvm::Constant *>1613ModuleImport::getConstantsToConvert(llvm::Constant *constant) {1614  // Return the empty set if the constant has been translated before.1615  if (valueMapping.contains(constant))1616    return {};1617 1618  // Traverse the constants in post-order and stop the traversal if a constant1619  // already has a `valueMapping` from an earlier constant translation or if the1620  // constant is traversed a second time.1621  SetVector<llvm::Constant *> orderedSet;1622  SetVector<llvm::Constant *> workList;1623  DenseMap<llvm::Constant *, SmallVector<llvm::Constant *>> adjacencyLists;1624  workList.insert(constant);1625  while (!workList.empty()) {1626    llvm::Constant *current = workList.back();1627    // References of global objects are just pointers to the object. Avoid1628    // walking the elements of these here.1629    if (isa<llvm::GlobalObject>(current) || isa<llvm::GlobalAlias>(current)) {1630      orderedSet.insert(current);1631      workList.pop_back();1632      continue;1633    }1634 1635    // Collect all dependencies of the current constant and add them to the1636    // adjacency list if none has been computed before.1637    auto [adjacencyIt, inserted] = adjacencyLists.try_emplace(current);1638    if (inserted) {1639      // Add all constant operands to the adjacency list and skip any other1640      // values such as basic block addresses.1641      for (llvm::Value *operand : current->operands())1642        if (auto *constDependency = dyn_cast<llvm::Constant>(operand))1643          adjacencyIt->getSecond().push_back(constDependency);1644      // Use the getElementValue method to add the dependencies of zero1645      // initialized aggregate constants since they do not take any operands.1646      if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(current)) {1647        unsigned numElements = constAgg->getElementCount().getFixedValue();1648        for (unsigned i = 0, e = numElements; i != e; ++i)1649          adjacencyIt->getSecond().push_back(constAgg->getElementValue(i));1650      }1651    }1652    // Add the current constant to the `orderedSet` of the traversed nodes if1653    // all its dependencies have been traversed before. Additionally, remove the1654    // constant from the `workList` and continue the traversal.1655    if (adjacencyIt->getSecond().empty()) {1656      orderedSet.insert(current);1657      workList.pop_back();1658      continue;1659    }1660    // Add the next dependency from the adjacency list to the `workList` and1661    // continue the traversal. Remove the dependency from the adjacency list to1662    // mark that it has been processed. Only enqueue the dependency if it has no1663    // `valueMapping` from an earlier translation and if it has not been1664    // enqueued before.1665    llvm::Constant *dependency = adjacencyIt->getSecond().pop_back_val();1666    if (valueMapping.contains(dependency) || workList.contains(dependency) ||1667        orderedSet.contains(dependency))1668      continue;1669    workList.insert(dependency);1670  }1671 1672  return orderedSet;1673}1674 1675FailureOr<Value> ModuleImport::convertConstant(llvm::Constant *constant) {1676  Location loc = UnknownLoc::get(context);1677 1678  // Convert constants that can be represented as attributes.1679  if (Attribute attr = getConstantAsAttr(constant)) {1680    Type type = convertType(constant->getType());1681    if (auto symbolRef = dyn_cast<FlatSymbolRefAttr>(attr)) {1682      return AddressOfOp::create(builder, loc, type, symbolRef.getValue())1683          .getResult();1684    }1685    return ConstantOp::create(builder, loc, type, attr).getResult();1686  }1687 1688  // Convert null pointer constants.1689  if (auto *nullPtr = dyn_cast<llvm::ConstantPointerNull>(constant)) {1690    Type type = convertType(nullPtr->getType());1691    return ZeroOp::create(builder, loc, type).getResult();1692  }1693 1694  // Convert none token constants.1695  if (isa<llvm::ConstantTokenNone>(constant)) {1696    return NoneTokenOp::create(builder, loc).getResult();1697  }1698 1699  // Convert poison.1700  if (auto *poisonVal = dyn_cast<llvm::PoisonValue>(constant)) {1701    Type type = convertType(poisonVal->getType());1702    return PoisonOp::create(builder, loc, type).getResult();1703  }1704 1705  // Convert undef.1706  if (auto *undefVal = dyn_cast<llvm::UndefValue>(constant)) {1707    Type type = convertType(undefVal->getType());1708    return UndefOp::create(builder, loc, type).getResult();1709  }1710 1711  // Convert dso_local_equivalent.1712  if (auto *dsoLocalEquivalent = dyn_cast<llvm::DSOLocalEquivalent>(constant)) {1713    Type type = convertType(dsoLocalEquivalent->getType());1714    return DSOLocalEquivalentOp::create(1715               builder, loc, type,1716               FlatSymbolRefAttr::get(1717                   builder.getContext(),1718                   dsoLocalEquivalent->getGlobalValue()->getName()))1719        .getResult();1720  }1721 1722  // Convert global variable accesses.1723  if (auto *globalObj = dyn_cast<llvm::GlobalObject>(constant)) {1724    Type type = convertType(globalObj->getType());1725    StringRef globalName = globalObj->getName();1726    FlatSymbolRefAttr symbolRef;1727    // Empty names are only allowed for global variables.1728    if (globalName.empty())1729      symbolRef =1730          getOrCreateNamelessSymbolName(cast<llvm::GlobalVariable>(globalObj));1731    else1732      symbolRef = FlatSymbolRefAttr::get(context, globalName);1733    return AddressOfOp::create(builder, loc, type, symbolRef).getResult();1734  }1735 1736  // Convert global alias accesses.1737  if (auto *globalAliasObj = dyn_cast<llvm::GlobalAlias>(constant)) {1738    Type type = convertType(globalAliasObj->getType());1739    StringRef aliaseeName = globalAliasObj->getName();1740    FlatSymbolRefAttr symbolRef = FlatSymbolRefAttr::get(context, aliaseeName);1741    return AddressOfOp::create(builder, loc, type, symbolRef).getResult();1742  }1743 1744  // Convert constant expressions.1745  if (auto *constExpr = dyn_cast<llvm::ConstantExpr>(constant)) {1746    // Convert the constant expression to a temporary LLVM instruction and1747    // translate it using the `processInstruction` method. Delete the1748    // instruction after the translation and remove it from `valueMapping`,1749    // since later calls to `getAsInstruction` may return the same address1750    // resulting in a conflicting `valueMapping` entry.1751    llvm::Instruction *inst = constExpr->getAsInstruction();1752    auto guard = llvm::make_scope_exit([&]() {1753      assert(!noResultOpMapping.contains(inst) &&1754             "expected constant expression to return a result");1755      valueMapping.erase(inst);1756      inst->deleteValue();1757    });1758    // Note: `processInstruction` does not call `convertConstant` recursively1759    // since all constant dependencies have been converted before.1760    assert(llvm::all_of(inst->operands(), [&](llvm::Value *value) {1761      return valueMapping.contains(value);1762    }));1763    if (failed(processInstruction(inst)))1764      return failure();1765    return lookupValue(inst);1766  }1767 1768  // Convert aggregate constants.1769  if (isa<llvm::ConstantAggregate>(constant) ||1770      isa<llvm::ConstantAggregateZero>(constant)) {1771    // Lookup the aggregate elements that have been converted before.1772    SmallVector<Value> elementValues;1773    if (auto *constAgg = dyn_cast<llvm::ConstantAggregate>(constant)) {1774      elementValues.reserve(constAgg->getNumOperands());1775      for (llvm::Value *operand : constAgg->operands())1776        elementValues.push_back(lookupValue(operand));1777    }1778    if (auto *constAgg = dyn_cast<llvm::ConstantAggregateZero>(constant)) {1779      unsigned numElements = constAgg->getElementCount().getFixedValue();1780      elementValues.reserve(numElements);1781      for (unsigned i = 0, e = numElements; i != e; ++i)1782        elementValues.push_back(lookupValue(constAgg->getElementValue(i)));1783    }1784    assert(llvm::count(elementValues, nullptr) == 0 &&1785           "expected all elements have been converted before");1786 1787    // Generate an UndefOp as root value and insert the aggregate elements.1788    Type rootType = convertType(constant->getType());1789    bool isArrayOrStruct = isa<LLVMArrayType, LLVMStructType>(rootType);1790    assert((isArrayOrStruct || LLVM::isCompatibleVectorType(rootType)) &&1791           "unrecognized aggregate type");1792    Value root = UndefOp::create(builder, loc, rootType);1793    for (const auto &it : llvm::enumerate(elementValues)) {1794      if (isArrayOrStruct) {1795        root =1796            InsertValueOp::create(builder, loc, root, it.value(), it.index());1797      } else {1798        Attribute indexAttr = builder.getI32IntegerAttr(it.index());1799        Value indexValue =1800            ConstantOp::create(builder, loc, builder.getI32Type(), indexAttr);1801        root = InsertElementOp::create(builder, loc, rootType, root, it.value(),1802                                       indexValue);1803      }1804    }1805    return root;1806  }1807 1808  if (auto *constTargetNone = dyn_cast<llvm::ConstantTargetNone>(constant)) {1809    LLVMTargetExtType targetExtType =1810        cast<LLVMTargetExtType>(convertType(constTargetNone->getType()));1811    assert(targetExtType.hasProperty(LLVMTargetExtType::HasZeroInit) &&1812           "target extension type does not support zero-initialization");1813    // Create llvm.mlir.zero operation to represent zero-initialization of1814    // target extension type.1815    return LLVM::ZeroOp::create(builder, loc, targetExtType).getRes();1816  }1817 1818  if (auto *blockAddr = dyn_cast<llvm::BlockAddress>(constant)) {1819    auto fnSym =1820        FlatSymbolRefAttr::get(context, blockAddr->getFunction()->getName());1821    auto blockTag =1822        BlockTagAttr::get(context, blockAddr->getBasicBlock()->getNumber());1823    return BlockAddressOp::create(1824               builder, loc, convertType(blockAddr->getType()),1825               BlockAddressAttr::get(context, fnSym, blockTag))1826        .getRes();1827  }1828 1829  StringRef error = "";1830 1831  if (isa<llvm::ConstantPtrAuth>(constant))1832    error = " since ptrauth(...) is unsupported";1833 1834  if (isa<llvm::NoCFIValue>(constant))1835    error = " since no_cfi is unsupported";1836 1837  if (isa<llvm::GlobalValue>(constant))1838    error = " since global value is unsupported";1839 1840  return emitError(loc) << "unhandled constant: " << diag(*constant) << error;1841}1842 1843FailureOr<Value> ModuleImport::convertConstantExpr(llvm::Constant *constant) {1844  // Only call the function for constants that have not been translated before1845  // since it updates the constant insertion point assuming the converted1846  // constant has been introduced at the end of the constant section.1847  assert(!valueMapping.contains(constant) &&1848         "expected constant has not been converted before");1849  assert(constantInsertionBlock &&1850         "expected the constant insertion block to be non-null");1851 1852  // Insert the constant after the last one or at the start of the entry block.1853  OpBuilder::InsertionGuard guard(builder);1854  if (!constantInsertionOp)1855    builder.setInsertionPointToStart(constantInsertionBlock);1856  else1857    builder.setInsertionPointAfter(constantInsertionOp);1858 1859  // Convert all constants of the expression and add them to `valueMapping`.1860  SetVector<llvm::Constant *> constantsToConvert =1861      getConstantsToConvert(constant);1862  for (llvm::Constant *constantToConvert : constantsToConvert) {1863    FailureOr<Value> converted = convertConstant(constantToConvert);1864    if (failed(converted))1865      return failure();1866    mapValue(constantToConvert, *converted);1867  }1868 1869  // Update the constant insertion point and return the converted constant.1870  Value result = lookupValue(constant);1871  constantInsertionOp = result.getDefiningOp();1872  return result;1873}1874 1875FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {1876  assert(!isa<llvm::MetadataAsValue>(value) &&1877         "expected value to not be metadata");1878 1879  // Return the mapped value if it has been converted before.1880  auto it = valueMapping.find(value);1881  if (it != valueMapping.end())1882    return it->getSecond();1883 1884  // Convert constants such as immediate values that have no mapping yet.1885  if (auto *constant = dyn_cast<llvm::Constant>(value))1886    return convertConstantExpr(constant);1887 1888  Location loc = UnknownLoc::get(context);1889  if (auto *inst = dyn_cast<llvm::Instruction>(value))1890    loc = translateLoc(inst->getDebugLoc());1891  return emitError(loc) << "unhandled value: " << diag(*value);1892}1893 1894FailureOr<Value> ModuleImport::convertMetadataValue(llvm::Value *value) {1895  // A value may be wrapped as metadata, for example, when passed to a debug1896  // intrinsic. Unwrap these values before the conversion.1897  auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);1898  if (!nodeAsVal)1899    return failure();1900  auto *node = dyn_cast<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());1901  if (!node)1902    return failure();1903  value = node->getValue();1904 1905  // Return the mapped value if it has been converted before.1906  auto it = valueMapping.find(value);1907  if (it != valueMapping.end())1908    return it->getSecond();1909 1910  // Convert constants such as immediate values that have no mapping yet.1911  if (auto *constant = dyn_cast<llvm::Constant>(value))1912    return convertConstantExpr(constant);1913  return failure();1914}1915 1916FailureOr<SmallVector<Value>>1917ModuleImport::convertValues(ArrayRef<llvm::Value *> values) {1918  SmallVector<Value> remapped;1919  remapped.reserve(values.size());1920  for (llvm::Value *value : values) {1921    FailureOr<Value> converted = convertValue(value);1922    if (failed(converted))1923      return failure();1924    remapped.push_back(*converted);1925  }1926  return remapped;1927}1928 1929LogicalResult ModuleImport::convertIntrinsicArguments(1930    ArrayRef<llvm::Value *> values, ArrayRef<llvm::OperandBundleUse> opBundles,1931    bool requiresOpBundles, ArrayRef<unsigned> immArgPositions,1932    ArrayRef<StringLiteral> immArgAttrNames, SmallVectorImpl<Value> &valuesOut,1933    SmallVectorImpl<NamedAttribute> &attrsOut) {1934  assert(immArgPositions.size() == immArgAttrNames.size() &&1935         "LLVM `immArgPositions` and MLIR `immArgAttrNames` should have equal "1936         "length");1937 1938  SmallVector<llvm::Value *> operands(values);1939  for (auto [immArgPos, immArgName] :1940       llvm::zip(immArgPositions, immArgAttrNames)) {1941    auto &value = operands[immArgPos];1942    auto *constant = llvm::cast<llvm::Constant>(value);1943    auto attr = getScalarConstantAsAttr(builder, constant);1944    assert(attr && attr.getType().isIntOrFloat() &&1945           "expected immarg to be float or integer constant");1946    auto nameAttr = StringAttr::get(attr.getContext(), immArgName);1947    attrsOut.push_back({nameAttr, attr});1948    // Mark matched attribute values as null (so they can be removed below).1949    value = nullptr;1950  }1951 1952  for (llvm::Value *value : operands) {1953    if (!value)1954      continue;1955    auto mlirValue = convertValue(value);1956    if (failed(mlirValue))1957      return failure();1958    valuesOut.push_back(*mlirValue);1959  }1960 1961  SmallVector<int> opBundleSizes;1962  SmallVector<Attribute> opBundleTagAttrs;1963  if (requiresOpBundles) {1964    opBundleSizes.reserve(opBundles.size());1965    opBundleTagAttrs.reserve(opBundles.size());1966 1967    for (const llvm::OperandBundleUse &bundle : opBundles) {1968      opBundleSizes.push_back(bundle.Inputs.size());1969      opBundleTagAttrs.push_back(StringAttr::get(context, bundle.getTagName()));1970 1971      for (const llvm::Use &opBundleOperand : bundle.Inputs) {1972        auto operandMlirValue = convertValue(opBundleOperand.get());1973        if (failed(operandMlirValue))1974          return failure();1975        valuesOut.push_back(*operandMlirValue);1976      }1977    }1978 1979    auto opBundleSizesAttr = DenseI32ArrayAttr::get(context, opBundleSizes);1980    auto opBundleSizesAttrNameAttr =1981        StringAttr::get(context, LLVMDialect::getOpBundleSizesAttrName());1982    attrsOut.push_back({opBundleSizesAttrNameAttr, opBundleSizesAttr});1983 1984    auto opBundleTagsAttr = ArrayAttr::get(context, opBundleTagAttrs);1985    auto opBundleTagsAttrNameAttr =1986        StringAttr::get(context, LLVMDialect::getOpBundleTagsAttrName());1987    attrsOut.push_back({opBundleTagsAttrNameAttr, opBundleTagsAttr});1988  }1989 1990  return success();1991}1992 1993IntegerAttr ModuleImport::matchIntegerAttr(llvm::Value *value) {1994  IntegerAttr integerAttr;1995  FailureOr<Value> converted = convertValue(value);1996  bool success = succeeded(converted) &&1997                 matchPattern(*converted, m_Constant(&integerAttr));1998  assert(success && "expected a constant integer value");1999  (void)success;2000  return integerAttr;2001}2002 2003FloatAttr ModuleImport::matchFloatAttr(llvm::Value *value) {2004  FloatAttr floatAttr;2005  FailureOr<Value> converted = convertValue(value);2006  bool success =2007      succeeded(converted) && matchPattern(*converted, m_Constant(&floatAttr));2008  assert(success && "expected a constant float value");2009  (void)success;2010  return floatAttr;2011}2012 2013DILocalVariableAttr ModuleImport::matchLocalVariableAttr(2014    llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> valOrVariable) {2015  llvm::DILocalVariable *node = nullptr;2016  if (auto *value = dyn_cast<llvm::Value *>(valOrVariable)) {2017    auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);2018    node = cast<llvm::DILocalVariable>(nodeAsVal->getMetadata());2019  } else {2020    node = cast<llvm::DILocalVariable *>(valOrVariable);2021  }2022  return debugImporter->translate(node);2023}2024 2025DILabelAttr ModuleImport::matchLabelAttr(llvm::Value *value) {2026  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);2027  auto *node = cast<llvm::DILabel>(nodeAsVal->getMetadata());2028  return debugImporter->translate(node);2029}2030 2031FPExceptionBehaviorAttr2032ModuleImport::matchFPExceptionBehaviorAttr(llvm::Value *value) {2033  auto *metadata = cast<llvm::MetadataAsValue>(value);2034  auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());2035  std::optional<llvm::fp::ExceptionBehavior> optLLVM =2036      llvm::convertStrToExceptionBehavior(mdstr->getString());2037  assert(optLLVM && "Expecting FP exception behavior");2038  return builder.getAttr<FPExceptionBehaviorAttr>(2039      convertFPExceptionBehaviorFromLLVM(*optLLVM));2040}2041 2042RoundingModeAttr ModuleImport::matchRoundingModeAttr(llvm::Value *value) {2043  auto *metadata = cast<llvm::MetadataAsValue>(value);2044  auto *mdstr = cast<llvm::MDString>(metadata->getMetadata());2045  std::optional<llvm::RoundingMode> optLLVM =2046      llvm::convertStrToRoundingMode(mdstr->getString());2047  assert(optLLVM && "Expecting rounding mode");2048  return builder.getAttr<RoundingModeAttr>(2049      convertRoundingModeFromLLVM(*optLLVM));2050}2051 2052FailureOr<SmallVector<AliasScopeAttr>>2053ModuleImport::matchAliasScopeAttrs(llvm::Value *value) {2054  auto *nodeAsVal = cast<llvm::MetadataAsValue>(value);2055  auto *node = cast<llvm::MDNode>(nodeAsVal->getMetadata());2056  return lookupAliasScopeAttrs(node);2057}2058 2059Location ModuleImport::translateLoc(llvm::DILocation *loc) {2060  return debugImporter->translateLoc(loc);2061}2062 2063LogicalResult2064ModuleImport::convertBranchArgs(llvm::Instruction *branch,2065                                llvm::BasicBlock *target,2066                                SmallVectorImpl<Value> &blockArguments) {2067  for (auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {2068    auto *phiInst = cast<llvm::PHINode>(&*inst);2069    llvm::Value *value = phiInst->getIncomingValueForBlock(branch->getParent());2070    FailureOr<Value> converted = convertValue(value);2071    if (failed(converted))2072      return failure();2073    blockArguments.push_back(*converted);2074  }2075  return success();2076}2077 2078FailureOr<SmallVector<Value>>2079ModuleImport::convertCallOperands(llvm::CallBase *callInst,2080                                  bool allowInlineAsm) {2081  bool isInlineAsm = callInst->isInlineAsm();2082  if (isInlineAsm && !allowInlineAsm)2083    return failure();2084 2085  SmallVector<Value> operands;2086 2087  // Cannot use isIndirectCall() here because we need to handle Constant callees2088  // that are not considered indirect calls by LLVM. However, in MLIR, they are2089  // treated as indirect calls to constant operands that need to be converted.2090  // Skip the callee operand if it's inline assembly, as it's handled separately2091  // in InlineAsmOp.2092  llvm::Value *calleeOperand = callInst->getCalledOperand();2093  if (!isa<llvm::Function, llvm::GlobalIFunc>(calleeOperand) && !isInlineAsm) {2094    FailureOr<Value> called = convertValue(calleeOperand);2095    if (failed(called))2096      return failure();2097    operands.push_back(*called);2098  }2099 2100  SmallVector<llvm::Value *> args(callInst->args());2101  FailureOr<SmallVector<Value>> arguments = convertValues(args);2102  if (failed(arguments))2103    return failure();2104 2105  llvm::append_range(operands, *arguments);2106  return operands;2107}2108 2109/// Checks if `callType` and `calleeType` are compatible and can be represented2110/// in MLIR.2111static LogicalResult2112checkFunctionTypeCompatibility(LLVMFunctionType callType,2113                               LLVMFunctionType calleeType) {2114  if (callType.getReturnType() != calleeType.getReturnType())2115    return failure();2116 2117  if (calleeType.isVarArg()) {2118    // For variadic functions, the call can have more types than the callee2119    // specifies.2120    if (callType.getNumParams() < calleeType.getNumParams())2121      return failure();2122  } else {2123    // For non-variadic functions, the number of parameters needs to be the2124    // same.2125    if (callType.getNumParams() != calleeType.getNumParams())2126      return failure();2127  }2128 2129  // Check that all operands match.2130  for (auto [operandType, argumentType] :2131       llvm::zip(callType.getParams(), calleeType.getParams()))2132    if (operandType != argumentType)2133      return failure();2134 2135  return success();2136}2137 2138FailureOr<LLVMFunctionType>2139ModuleImport::convertFunctionType(llvm::CallBase *callInst,2140                                  bool &isIncompatibleCall) {2141  isIncompatibleCall = false;2142  auto castOrFailure = [](Type convertedType) -> FailureOr<LLVMFunctionType> {2143    auto funcTy = dyn_cast_or_null<LLVMFunctionType>(convertedType);2144    if (!funcTy)2145      return failure();2146    return funcTy;2147  };2148 2149  llvm::Value *calledOperand = callInst->getCalledOperand();2150  FailureOr<LLVMFunctionType> callType =2151      castOrFailure(convertType(callInst->getFunctionType()));2152  if (failed(callType))2153    return failure();2154  auto *callee = dyn_cast<llvm::Function>(calledOperand);2155 2156  llvm::FunctionType *origCalleeType = nullptr;2157  if (callee) {2158    origCalleeType = callee->getFunctionType();2159  } else if (auto *ifunc = dyn_cast<llvm::GlobalIFunc>(calledOperand)) {2160    origCalleeType = cast<llvm::FunctionType>(ifunc->getValueType());2161  }2162 2163  // For indirect calls, return the type of the call itself.2164  if (!origCalleeType)2165    return callType;2166 2167  FailureOr<LLVMFunctionType> calleeType =2168      castOrFailure(convertType(origCalleeType));2169  if (failed(calleeType))2170    return failure();2171 2172  // Compare the types and notify users via `isIncompatibleCall` if they are not2173  // compatible.2174  if (failed(checkFunctionTypeCompatibility(*callType, *calleeType))) {2175    isIncompatibleCall = true;2176    Location loc = translateLoc(callInst->getDebugLoc());2177    emitWarning(loc) << "incompatible call and callee types: " << *callType2178                     << " and " << *calleeType;2179    return callType;2180  }2181 2182  return calleeType;2183}2184 2185FlatSymbolRefAttr ModuleImport::convertCalleeName(llvm::CallBase *callInst) {2186  llvm::Value *calledOperand = callInst->getCalledOperand();2187  if (isa<llvm::Function, llvm::GlobalIFunc>(calledOperand))2188    return SymbolRefAttr::get(context, calledOperand->getName());2189  return {};2190}2191 2192LogicalResult ModuleImport::convertIntrinsic(llvm::CallInst *inst) {2193  if (succeeded(iface.convertIntrinsic(builder, inst, *this)))2194    return success();2195 2196  Location loc = translateLoc(inst->getDebugLoc());2197  return emitError(loc) << "unhandled intrinsic: " << diag(*inst);2198}2199 2200ArrayAttr2201ModuleImport::convertAsmInlineOperandAttrs(const llvm::CallBase &llvmCall) {2202  const auto *ia = cast<llvm::InlineAsm>(llvmCall.getCalledOperand());2203  unsigned argIdx = 0;2204  SmallVector<mlir::Attribute> opAttrs;2205  bool hasIndirect = false;2206 2207  for (const llvm::InlineAsm::ConstraintInfo &ci : ia->ParseConstraints()) {2208    // Only deal with constraints that correspond to call arguments.2209    if (ci.Type == llvm::InlineAsm::isLabel || !ci.hasArg())2210      continue;2211 2212    // Only increment `argIdx` in terms of constraints containing arguments,2213    // which are guaranteed to happen in the same order of the call arguments.2214    if (ci.isIndirect) {2215      if (llvm::Type *paramEltType = llvmCall.getParamElementType(argIdx)) {2216        SmallVector<mlir::NamedAttribute> attrs;2217        attrs.push_back(builder.getNamedAttr(2218            mlir::LLVM::InlineAsmOp::getElementTypeAttrName(),2219            mlir::TypeAttr::get(convertType(paramEltType))));2220        opAttrs.push_back(builder.getDictionaryAttr(attrs));2221        hasIndirect = true;2222      }2223    } else {2224      opAttrs.push_back(builder.getDictionaryAttr({}));2225    }2226    argIdx++;2227  }2228 2229  // Avoid emitting an array where all entries are empty dictionaries.2230  return hasIndirect ? ArrayAttr::get(mlirModule->getContext(), opAttrs)2231                     : nullptr;2232}2233 2234LogicalResult ModuleImport::convertInstruction(llvm::Instruction *inst) {2235  // Convert all instructions that do not provide an MLIR builder.2236  Location loc = translateLoc(inst->getDebugLoc());2237  if (inst->getOpcode() == llvm::Instruction::Br) {2238    auto *brInst = cast<llvm::BranchInst>(inst);2239 2240    SmallVector<Block *> succBlocks;2241    SmallVector<SmallVector<Value>> succBlockArgs;2242    for (auto i : llvm::seq<unsigned>(0, brInst->getNumSuccessors())) {2243      llvm::BasicBlock *succ = brInst->getSuccessor(i);2244      SmallVector<Value> blockArgs;2245      if (failed(convertBranchArgs(brInst, succ, blockArgs)))2246        return failure();2247      succBlocks.push_back(lookupBlock(succ));2248      succBlockArgs.push_back(blockArgs);2249    }2250 2251    if (!brInst->isConditional()) {2252      auto brOp = LLVM::BrOp::create(builder, loc, succBlockArgs.front(),2253                                     succBlocks.front());2254      mapNoResultOp(inst, brOp);2255      return success();2256    }2257    FailureOr<Value> condition = convertValue(brInst->getCondition());2258    if (failed(condition))2259      return failure();2260    auto condBrOp = LLVM::CondBrOp::create(2261        builder, loc, *condition, succBlocks.front(), succBlockArgs.front(),2262        succBlocks.back(), succBlockArgs.back());2263    mapNoResultOp(inst, condBrOp);2264    return success();2265  }2266  if (inst->getOpcode() == llvm::Instruction::Switch) {2267    auto *swInst = cast<llvm::SwitchInst>(inst);2268    // Process the condition value.2269    FailureOr<Value> condition = convertValue(swInst->getCondition());2270    if (failed(condition))2271      return failure();2272    SmallVector<Value> defaultBlockArgs;2273    // Process the default case.2274    llvm::BasicBlock *defaultBB = swInst->getDefaultDest();2275    if (failed(convertBranchArgs(swInst, defaultBB, defaultBlockArgs)))2276      return failure();2277 2278    // Process the cases.2279    unsigned numCases = swInst->getNumCases();2280    SmallVector<SmallVector<Value>> caseOperands(numCases);2281    SmallVector<ValueRange> caseOperandRefs(numCases);2282    SmallVector<APInt> caseValues(numCases);2283    SmallVector<Block *> caseBlocks(numCases);2284    for (const auto &it : llvm::enumerate(swInst->cases())) {2285      const llvm::SwitchInst::CaseHandle &caseHandle = it.value();2286      llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();2287      if (failed(convertBranchArgs(swInst, succBB, caseOperands[it.index()])))2288        return failure();2289      caseOperandRefs[it.index()] = caseOperands[it.index()];2290      caseValues[it.index()] = caseHandle.getCaseValue()->getValue();2291      caseBlocks[it.index()] = lookupBlock(succBB);2292    }2293 2294    auto switchOp = SwitchOp::create(builder, loc, *condition,2295                                     lookupBlock(defaultBB), defaultBlockArgs,2296                                     caseValues, caseBlocks, caseOperandRefs);2297    mapNoResultOp(inst, switchOp);2298    return success();2299  }2300  if (inst->getOpcode() == llvm::Instruction::PHI) {2301    Type type = convertType(inst->getType());2302    mapValue(inst, builder.getInsertionBlock()->addArgument(2303                       type, translateLoc(inst->getDebugLoc())));2304    return success();2305  }2306  if (inst->getOpcode() == llvm::Instruction::Call) {2307    auto *callInst = cast<llvm::CallInst>(inst);2308    llvm::Value *calledOperand = callInst->getCalledOperand();2309 2310    FailureOr<SmallVector<Value>> operands =2311        convertCallOperands(callInst, /*allowInlineAsm=*/true);2312    if (failed(operands))2313      return failure();2314 2315    auto callOp = [&]() -> FailureOr<Operation *> {2316      if (auto *asmI = dyn_cast<llvm::InlineAsm>(calledOperand)) {2317        Type resultTy = convertType(callInst->getType());2318        if (!resultTy)2319          return failure();2320        ArrayAttr operandAttrs = convertAsmInlineOperandAttrs(*callInst);2321        return InlineAsmOp::create(2322                   builder, loc, resultTy, *operands,2323                   builder.getStringAttr(asmI->getAsmString()),2324                   builder.getStringAttr(asmI->getConstraintString()),2325                   asmI->hasSideEffects(), asmI->isAlignStack(),2326                   convertTailCallKindFromLLVM(callInst->getTailCallKind()),2327                   AsmDialectAttr::get(2328                       mlirModule.getContext(),2329                       convertAsmDialectFromLLVM(asmI->getDialect())),2330                   operandAttrs)2331            .getOperation();2332      }2333      bool isIncompatibleCall;2334      FailureOr<LLVMFunctionType> funcTy =2335          convertFunctionType(callInst, isIncompatibleCall);2336      if (failed(funcTy))2337        return failure();2338 2339      FlatSymbolRefAttr callee = nullptr;2340      if (isIncompatibleCall) {2341        // Use an indirect call (in order to represent valid and verifiable LLVM2342        // IR). Build the indirect call by passing an empty `callee` operand and2343        // insert into `operands` to include the indirect call target.2344        FlatSymbolRefAttr calleeSym = convertCalleeName(callInst);2345        Value indirectCallVal = LLVM::AddressOfOp::create(2346            builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);2347        operands->insert(operands->begin(), indirectCallVal);2348      } else {2349        // Regular direct call using callee name.2350        callee = convertCalleeName(callInst);2351      }2352      CallOp callOp = CallOp::create(builder, loc, *funcTy, callee, *operands);2353 2354      if (failed(convertCallAttributes(callInst, callOp)))2355        return failure();2356 2357      // Handle parameter and result attributes unless it's an incompatible2358      // call.2359      if (!isIncompatibleCall)2360        convertArgAndResultAttrs(callInst, callOp);2361      return callOp.getOperation();2362    }();2363 2364    if (failed(callOp))2365      return failure();2366 2367    if (!callInst->getType()->isVoidTy())2368      mapValue(inst, (*callOp)->getResult(0));2369    else2370      mapNoResultOp(inst, *callOp);2371    return success();2372  }2373  if (inst->getOpcode() == llvm::Instruction::LandingPad) {2374    auto *lpInst = cast<llvm::LandingPadInst>(inst);2375 2376    SmallVector<Value> operands;2377    operands.reserve(lpInst->getNumClauses());2378    for (auto i : llvm::seq<unsigned>(0, lpInst->getNumClauses())) {2379      FailureOr<Value> operand = convertValue(lpInst->getClause(i));2380      if (failed(operand))2381        return failure();2382      operands.push_back(*operand);2383    }2384 2385    Type type = convertType(lpInst->getType());2386    auto lpOp =2387        LandingpadOp::create(builder, loc, type, lpInst->isCleanup(), operands);2388    mapValue(inst, lpOp);2389    return success();2390  }2391  if (inst->getOpcode() == llvm::Instruction::Invoke) {2392    auto *invokeInst = cast<llvm::InvokeInst>(inst);2393 2394    if (invokeInst->isInlineAsm())2395      return emitError(loc) << "invoke of inline assembly is not supported";2396 2397    FailureOr<SmallVector<Value>> operands = convertCallOperands(invokeInst);2398    if (failed(operands))2399      return failure();2400 2401    // Check whether the invoke result is an argument to the normal destination2402    // block.2403    bool invokeResultUsedInPhi = llvm::any_of(2404        invokeInst->getNormalDest()->phis(), [&](const llvm::PHINode &phi) {2405          return phi.getIncomingValueForBlock(invokeInst->getParent()) ==2406                 invokeInst;2407        });2408 2409    Block *normalDest = lookupBlock(invokeInst->getNormalDest());2410    Block *directNormalDest = normalDest;2411    if (invokeResultUsedInPhi) {2412      // The invoke result cannot be an argument to the normal destination2413      // block, as that would imply using the invoke operation result in its2414      // definition, so we need to create a dummy block to serve as an2415      // intermediate destination.2416      OpBuilder::InsertionGuard g(builder);2417      directNormalDest = builder.createBlock(normalDest);2418    }2419 2420    SmallVector<Value> unwindArgs;2421    if (failed(convertBranchArgs(invokeInst, invokeInst->getUnwindDest(),2422                                 unwindArgs)))2423      return failure();2424 2425    bool isIncompatibleInvoke;2426    FailureOr<LLVMFunctionType> funcTy =2427        convertFunctionType(invokeInst, isIncompatibleInvoke);2428    if (failed(funcTy))2429      return failure();2430 2431    FlatSymbolRefAttr calleeName = nullptr;2432    if (isIncompatibleInvoke) {2433      // Use an indirect invoke (in order to represent valid and verifiable LLVM2434      // IR). Build the indirect invoke by passing an empty `callee` operand and2435      // insert into `operands` to include the indirect invoke target.2436      FlatSymbolRefAttr calleeSym = convertCalleeName(invokeInst);2437      Value indirectInvokeVal = LLVM::AddressOfOp::create(2438          builder, loc, LLVM::LLVMPointerType::get(context), calleeSym);2439      operands->insert(operands->begin(), indirectInvokeVal);2440    } else {2441      // Regular direct invoke using callee name.2442      calleeName = convertCalleeName(invokeInst);2443    }2444    // Create the invoke operation. Normal destination block arguments will be2445    // added later on to handle the case in which the operation result is2446    // included in this list.2447    auto invokeOp = InvokeOp::create(2448        builder, loc, *funcTy, calleeName, *operands, directNormalDest,2449        ValueRange(), lookupBlock(invokeInst->getUnwindDest()), unwindArgs);2450 2451    if (failed(convertInvokeAttributes(invokeInst, invokeOp)))2452      return failure();2453 2454    // Handle parameter and result attributes unless it's an incompatible2455    // invoke.2456    if (!isIncompatibleInvoke)2457      convertArgAndResultAttrs(invokeInst, invokeOp);2458 2459    if (!invokeInst->getType()->isVoidTy())2460      mapValue(inst, invokeOp.getResults().front());2461    else2462      mapNoResultOp(inst, invokeOp);2463 2464    SmallVector<Value> normalArgs;2465    if (failed(convertBranchArgs(invokeInst, invokeInst->getNormalDest(),2466                                 normalArgs)))2467      return failure();2468 2469    if (invokeResultUsedInPhi) {2470      // The dummy normal dest block will just host an unconditional branch2471      // instruction to the normal destination block passing the required block2472      // arguments (including the invoke operation's result).2473      OpBuilder::InsertionGuard g(builder);2474      builder.setInsertionPointToStart(directNormalDest);2475      LLVM::BrOp::create(builder, loc, normalArgs, normalDest);2476    } else {2477      // If the invoke operation's result is not a block argument to the normal2478      // destination block, just add the block arguments as usual.2479      assert(llvm::none_of(2480                 normalArgs,2481                 [&](Value val) { return val.getDefiningOp() == invokeOp; }) &&2482             "An llvm.invoke operation cannot pass its result as a block "2483             "argument.");2484      invokeOp.getNormalDestOperandsMutable().append(normalArgs);2485    }2486 2487    return success();2488  }2489  if (inst->getOpcode() == llvm::Instruction::GetElementPtr) {2490    auto *gepInst = cast<llvm::GetElementPtrInst>(inst);2491    Type sourceElementType = convertType(gepInst->getSourceElementType());2492    FailureOr<Value> basePtr = convertValue(gepInst->getOperand(0));2493    if (failed(basePtr))2494      return failure();2495 2496    // Treat every indices as dynamic since GEPOp::build will refine those2497    // indices into static attributes later. One small downside of this2498    // approach is that many unused `llvm.mlir.constant` would be emitted2499    // at first place.2500    SmallVector<GEPArg> indices;2501    for (llvm::Value *operand : llvm::drop_begin(gepInst->operand_values())) {2502      FailureOr<Value> index = convertValue(operand);2503      if (failed(index))2504        return failure();2505      indices.push_back(*index);2506    }2507 2508    Type type = convertType(inst->getType());2509    auto gepOp = GEPOp::create(2510        builder, loc, type, sourceElementType, *basePtr, indices,2511        static_cast<GEPNoWrapFlags>(gepInst->getNoWrapFlags().getRaw()));2512    mapValue(inst, gepOp);2513    return success();2514  }2515 2516  if (inst->getOpcode() == llvm::Instruction::IndirectBr) {2517    auto *indBrInst = cast<llvm::IndirectBrInst>(inst);2518 2519    FailureOr<Value> basePtr = convertValue(indBrInst->getAddress());2520    if (failed(basePtr))2521      return failure();2522 2523    SmallVector<Block *> succBlocks;2524    SmallVector<SmallVector<Value>> succBlockArgs;2525    for (auto i : llvm::seq<unsigned>(0, indBrInst->getNumSuccessors())) {2526      llvm::BasicBlock *succ = indBrInst->getSuccessor(i);2527      SmallVector<Value> blockArgs;2528      if (failed(convertBranchArgs(indBrInst, succ, blockArgs)))2529        return failure();2530      succBlocks.push_back(lookupBlock(succ));2531      succBlockArgs.push_back(blockArgs);2532    }2533    SmallVector<ValueRange> succBlockArgsRange =2534        llvm::to_vector_of<ValueRange>(succBlockArgs);2535    Location loc = translateLoc(inst->getDebugLoc());2536    auto indBrOp = LLVM::IndirectBrOp::create(builder, loc, *basePtr,2537                                              succBlockArgsRange, succBlocks);2538 2539    mapNoResultOp(inst, indBrOp);2540    return success();2541  }2542 2543  // Convert all instructions that have an mlirBuilder.2544  if (succeeded(convertInstructionImpl(builder, inst, *this, iface)))2545    return success();2546 2547  return emitError(loc) << "unhandled instruction: " << diag(*inst);2548}2549 2550LogicalResult ModuleImport::processInstruction(llvm::Instruction *inst) {2551  // FIXME: Support uses of SubtargetData.2552  // FIXME: Add support for call / operand attributes.2553  // FIXME: Add support for the cleanupret, catchret, catchswitch, callbr,2554  // vaarg, catchpad, cleanuppad instructions.2555 2556  // Convert LLVM intrinsics calls to MLIR intrinsics.2557  if (auto *intrinsic = dyn_cast<llvm::IntrinsicInst>(inst))2558    return convertIntrinsic(intrinsic);2559 2560  // Process debug records attached to this instruction. Debug variable records2561  // are stored for later processing after all SSA values are converted, while2562  // debug label records can be converted immediately.2563  if (inst->DebugMarker) {2564    for (llvm::DbgRecord &dbgRecord : inst->DebugMarker->getDbgRecordRange()) {2565      // Store debug variable records for later processing.2566      if (auto *dbgVariableRecord =2567              dyn_cast<llvm::DbgVariableRecord>(&dbgRecord)) {2568        addDebugRecord(dbgVariableRecord);2569        continue;2570      }2571      Location loc = translateLoc(dbgRecord.getDebugLoc());2572      auto emitUnsupportedWarning = [&]() -> LogicalResult {2573        if (!emitExpensiveWarnings)2574          return success();2575        std::string options;2576        llvm::raw_string_ostream optionsStream(options);2577        dbgRecord.print(optionsStream);2578        emitWarning(loc) << "unhandled debug record " << optionsStream.str();2579        return success();2580      };2581      // Convert the debug label records in-place.2582      if (auto *dbgLabelRecord = dyn_cast<llvm::DbgLabelRecord>(&dbgRecord)) {2583        DILabelAttr labelAttr =2584            debugImporter->translate(dbgLabelRecord->getLabel());2585        if (!labelAttr)2586          return emitUnsupportedWarning();2587        LLVM::DbgLabelOp::create(builder, loc, labelAttr);2588        continue;2589      }2590      // Warn if an unsupported debug record is encountered.2591      return emitUnsupportedWarning();2592    }2593  }2594 2595  // Convert all remaining LLVM instructions to MLIR operations.2596  return convertInstruction(inst);2597}2598 2599FlatSymbolRefAttr ModuleImport::getPersonalityAsAttr(llvm::Function *f) {2600  if (!f->hasPersonalityFn())2601    return nullptr;2602 2603  llvm::Constant *pf = f->getPersonalityFn();2604 2605  // If it directly has a name, we can use it.2606  if (pf->hasName())2607    return SymbolRefAttr::get(builder.getContext(), pf->getName());2608 2609  // If it doesn't have a name, currently, only function pointers that are2610  // bitcast to i8* are parsed.2611  if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {2612    if (ce->getOpcode() == llvm::Instruction::BitCast &&2613        ce->getType() == llvm::PointerType::getUnqual(f->getContext())) {2614      if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))2615        return SymbolRefAttr::get(builder.getContext(), func->getName());2616    }2617  }2618  return FlatSymbolRefAttr();2619}2620 2621static void processMemoryEffects(llvm::Function *func, LLVMFuncOp funcOp) {2622  llvm::MemoryEffects memEffects = func->getMemoryEffects();2623 2624  auto othermem = convertModRefInfoFromLLVM(2625      memEffects.getModRef(llvm::MemoryEffects::Location::Other));2626  auto argMem = convertModRefInfoFromLLVM(2627      memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));2628  auto inaccessibleMem = convertModRefInfoFromLLVM(2629      memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));2630  auto errnoMem = convertModRefInfoFromLLVM(2631      memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));2632  auto targetMem0 = convertModRefInfoFromLLVM(2633      memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));2634  auto targetMem1 = convertModRefInfoFromLLVM(2635      memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));2636  auto memAttr =2637      MemoryEffectsAttr::get(funcOp.getContext(), othermem, argMem,2638                             inaccessibleMem, errnoMem, targetMem0, targetMem1);2639  // Only set the attr when it does not match the default value.2640  if (memAttr.isReadWrite())2641    return;2642  funcOp.setMemoryEffectsAttr(memAttr);2643}2644 2645// List of LLVM IR attributes that map to an explicit attribute on the MLIR2646// LLVMFuncOp.2647static constexpr std::array kExplicitLLVMFuncOpAttributes{2648    StringLiteral("aarch64_in_za"),2649    StringLiteral("aarch64_inout_za"),2650    StringLiteral("aarch64_new_za"),2651    StringLiteral("aarch64_out_za"),2652    StringLiteral("aarch64_preserves_za"),2653    StringLiteral("aarch64_pstate_sm_body"),2654    StringLiteral("aarch64_pstate_sm_compatible"),2655    StringLiteral("aarch64_pstate_sm_enabled"),2656    StringLiteral("alwaysinline"),2657    StringLiteral("convergent"),2658    StringLiteral("denormal-fp-math"),2659    StringLiteral("denormal-fp-math-f32"),2660    StringLiteral("fp-contract"),2661    StringLiteral("frame-pointer"),2662    StringLiteral("inlinehint"),2663    StringLiteral("instrument-function-entry"),2664    StringLiteral("instrument-function-exit"),2665    StringLiteral("memory"),2666    StringLiteral("no-infs-fp-math"),2667    StringLiteral("no-nans-fp-math"),2668    StringLiteral("no-signed-zeros-fp-math"),2669    StringLiteral("noinline"),2670    StringLiteral("nounwind"),2671    StringLiteral("optnone"),2672    StringLiteral("target-features"),2673    StringLiteral("tune-cpu"),2674    StringLiteral("uwtable"),2675    StringLiteral("vscale_range"),2676    StringLiteral("willreturn"),2677};2678 2679/// Converts LLVM attributes from `func` into MLIR attributes and adds them2680/// to `funcOp` as passthrough attributes, skipping those listed in2681/// `kExplicitLLVMFuncAttributes`.2682static void processPassthroughAttrs(llvm::Function *func, LLVMFuncOp funcOp) {2683  llvm::AttributeSet funcAttrs = func->getAttributes().getAttributes(2684      llvm::AttributeList::AttrIndex::FunctionIndex);2685  ArrayAttr passthroughAttr =2686      convertLLVMAttributesToMLIR(funcOp.getLoc(), funcOp.getContext(),2687                                  funcAttrs, kExplicitLLVMFuncOpAttributes);2688  if (!passthroughAttr.empty())2689    funcOp.setPassthroughAttr(passthroughAttr);2690}2691 2692void ModuleImport::processFunctionAttributes(llvm::Function *func,2693                                             LLVMFuncOp funcOp) {2694  processMemoryEffects(func, funcOp);2695  processPassthroughAttrs(func, funcOp);2696 2697  if (func->hasFnAttribute(llvm::Attribute::NoInline))2698    funcOp.setNoInline(true);2699  if (func->hasFnAttribute(llvm::Attribute::AlwaysInline))2700    funcOp.setAlwaysInline(true);2701  if (func->hasFnAttribute(llvm::Attribute::InlineHint))2702    funcOp.setInlineHint(true);2703  if (func->hasFnAttribute(llvm::Attribute::OptimizeNone))2704    funcOp.setOptimizeNone(true);2705  if (func->hasFnAttribute(llvm::Attribute::Convergent))2706    funcOp.setConvergent(true);2707  if (func->hasFnAttribute(llvm::Attribute::NoUnwind))2708    funcOp.setNoUnwind(true);2709  if (func->hasFnAttribute(llvm::Attribute::WillReturn))2710    funcOp.setWillReturn(true);2711 2712  if (func->hasFnAttribute("aarch64_pstate_sm_enabled"))2713    funcOp.setArmStreaming(true);2714  else if (func->hasFnAttribute("aarch64_pstate_sm_body"))2715    funcOp.setArmLocallyStreaming(true);2716  else if (func->hasFnAttribute("aarch64_pstate_sm_compatible"))2717    funcOp.setArmStreamingCompatible(true);2718 2719  if (func->hasFnAttribute("aarch64_new_za"))2720    funcOp.setArmNewZa(true);2721  else if (func->hasFnAttribute("aarch64_in_za"))2722    funcOp.setArmInZa(true);2723  else if (func->hasFnAttribute("aarch64_out_za"))2724    funcOp.setArmOutZa(true);2725  else if (func->hasFnAttribute("aarch64_inout_za"))2726    funcOp.setArmInoutZa(true);2727  else if (func->hasFnAttribute("aarch64_preserves_za"))2728    funcOp.setArmPreservesZa(true);2729 2730  llvm::Attribute attr = func->getFnAttribute(llvm::Attribute::VScaleRange);2731  if (attr.isValid()) {2732    MLIRContext *context = funcOp.getContext();2733    auto intTy = IntegerType::get(context, 32);2734    funcOp.setVscaleRangeAttr(LLVM::VScaleRangeAttr::get(2735        context, IntegerAttr::get(intTy, attr.getVScaleRangeMin()),2736        IntegerAttr::get(intTy, attr.getVScaleRangeMax().value_or(0))));2737  }2738 2739  // Process frame-pointer attribute.2740  if (func->hasFnAttribute("frame-pointer")) {2741    StringRef stringRefFramePointerKind =2742        func->getFnAttribute("frame-pointer").getValueAsString();2743    funcOp.setFramePointerAttr(LLVM::FramePointerKindAttr::get(2744        funcOp.getContext(), LLVM::framePointerKind::symbolizeFramePointerKind(2745                                 stringRefFramePointerKind)2746                                 .value()));2747  }2748 2749  if (llvm::Attribute attr = func->getFnAttribute("target-cpu");2750      attr.isStringAttribute())2751    funcOp.setTargetCpuAttr(StringAttr::get(context, attr.getValueAsString()));2752 2753  if (llvm::Attribute attr = func->getFnAttribute("tune-cpu");2754      attr.isStringAttribute())2755    funcOp.setTuneCpuAttr(StringAttr::get(context, attr.getValueAsString()));2756 2757  if (llvm::Attribute attr = func->getFnAttribute("target-features");2758      attr.isStringAttribute())2759    funcOp.setTargetFeaturesAttr(2760        LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));2761 2762  if (llvm::Attribute attr = func->getFnAttribute("reciprocal-estimates");2763      attr.isStringAttribute())2764    funcOp.setReciprocalEstimatesAttr(2765        StringAttr::get(context, attr.getValueAsString()));2766 2767  if (llvm::Attribute attr = func->getFnAttribute("prefer-vector-width");2768      attr.isStringAttribute())2769    funcOp.setPreferVectorWidth(attr.getValueAsString());2770 2771  if (llvm::Attribute attr = func->getFnAttribute("no-infs-fp-math");2772      attr.isStringAttribute())2773    funcOp.setNoInfsFpMath(attr.getValueAsBool());2774 2775  if (llvm::Attribute attr = func->getFnAttribute("no-nans-fp-math");2776      attr.isStringAttribute())2777    funcOp.setNoNansFpMath(attr.getValueAsBool());2778 2779  if (llvm::Attribute attr = func->getFnAttribute("instrument-function-entry");2780      attr.isStringAttribute())2781    funcOp.setInstrumentFunctionEntry(2782        StringAttr::get(context, attr.getValueAsString()));2783 2784  if (llvm::Attribute attr = func->getFnAttribute("instrument-function-exit");2785      attr.isStringAttribute())2786    funcOp.setInstrumentFunctionExit(2787        StringAttr::get(context, attr.getValueAsString()));2788 2789  if (llvm::Attribute attr = func->getFnAttribute("no-signed-zeros-fp-math");2790      attr.isStringAttribute())2791    funcOp.setNoSignedZerosFpMath(attr.getValueAsBool());2792 2793  if (llvm::Attribute attr = func->getFnAttribute("denormal-fp-math");2794      attr.isStringAttribute())2795    funcOp.setDenormalFpMathAttr(2796        StringAttr::get(context, attr.getValueAsString()));2797 2798  if (llvm::Attribute attr = func->getFnAttribute("denormal-fp-math-f32");2799      attr.isStringAttribute())2800    funcOp.setDenormalFpMathF32Attr(2801        StringAttr::get(context, attr.getValueAsString()));2802 2803  if (llvm::Attribute attr = func->getFnAttribute("fp-contract");2804      attr.isStringAttribute())2805    funcOp.setFpContractAttr(StringAttr::get(context, attr.getValueAsString()));2806 2807  if (func->hasUWTable()) {2808    ::llvm::UWTableKind uwtableKind = func->getUWTableKind();2809    funcOp.setUwtableKindAttr(LLVM::UWTableKindAttr::get(2810        funcOp.getContext(), convertUWTableKindFromLLVM(uwtableKind)));2811  }2812}2813 2814DictionaryAttr2815ModuleImport::convertArgOrResultAttrSet(llvm::AttributeSet llvmAttrSet) {2816  SmallVector<NamedAttribute> paramAttrs;2817  for (auto [llvmKind, mlirName] : getAttrKindToNameMapping()) {2818    auto llvmAttr = llvmAttrSet.getAttribute(llvmKind);2819    // Skip attributes that are not attached.2820    if (!llvmAttr.isValid())2821      continue;2822 2823    // TODO: Import captures(none) as a nocapture unit attribute until the2824    // LLVM dialect switches to the captures representation.2825    if (llvmAttr.hasKindAsEnum() &&2826        llvmAttr.getKindAsEnum() == llvm::Attribute::Captures) {2827      if (llvm::capturesNothing(llvmAttr.getCaptureInfo()))2828        paramAttrs.push_back(2829            builder.getNamedAttr(mlirName, builder.getUnitAttr()));2830      continue;2831    }2832 2833    Attribute mlirAttr;2834    if (llvmAttr.isTypeAttribute())2835      mlirAttr = TypeAttr::get(convertType(llvmAttr.getValueAsType()));2836    else if (llvmAttr.isIntAttribute())2837      mlirAttr = builder.getI64IntegerAttr(llvmAttr.getValueAsInt());2838    else if (llvmAttr.isEnumAttribute())2839      mlirAttr = builder.getUnitAttr();2840    else if (llvmAttr.isConstantRangeAttribute()) {2841      const llvm::ConstantRange &value = llvmAttr.getValueAsConstantRange();2842      mlirAttr = builder.getAttr<LLVM::ConstantRangeAttr>(value.getLower(),2843                                                          value.getUpper());2844    } else {2845      llvm_unreachable("unexpected parameter attribute kind");2846    }2847    paramAttrs.push_back(builder.getNamedAttr(mlirName, mlirAttr));2848  }2849 2850  return builder.getDictionaryAttr(paramAttrs);2851}2852 2853void ModuleImport::convertArgAndResultAttrs(llvm::Function *func,2854                                            LLVMFuncOp funcOp) {2855  auto llvmAttrs = func->getAttributes();2856  for (size_t i = 0, e = funcOp.getNumArguments(); i < e; ++i) {2857    llvm::AttributeSet llvmArgAttrs = llvmAttrs.getParamAttrs(i);2858    funcOp.setArgAttrs(i, convertArgOrResultAttrSet(llvmArgAttrs));2859  }2860  // Convert the result attributes and attach them wrapped in an ArrayAttribute2861  // to the funcOp.2862  llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();2863  if (!llvmResAttr.hasAttributes())2864    return;2865  funcOp.setResAttrsAttr(2866      builder.getArrayAttr({convertArgOrResultAttrSet(llvmResAttr)}));2867}2868 2869void ModuleImport::convertArgAndResultAttrs(2870    llvm::CallBase *call, ArgAndResultAttrsOpInterface attrsOp,2871    ArrayRef<unsigned> immArgPositions) {2872  // Compute the set of immediate argument positions.2873  llvm::SmallDenseSet<unsigned> immArgPositionsSet(immArgPositions.begin(),2874                                                   immArgPositions.end());2875  // Convert the argument attributes and filter out immediate arguments.2876  llvm::AttributeList llvmAttrs = call->getAttributes();2877  SmallVector<llvm::AttributeSet> llvmArgAttrsSet;2878  bool anyArgAttrs = false;2879  for (size_t i = 0, e = call->arg_size(); i < e; ++i) {2880    // Skip immediate arguments.2881    if (immArgPositionsSet.contains(i))2882      continue;2883    llvmArgAttrsSet.emplace_back(llvmAttrs.getParamAttrs(i));2884    if (llvmArgAttrsSet.back().hasAttributes())2885      anyArgAttrs = true;2886  }2887  auto getArrayAttr = [&](ArrayRef<DictionaryAttr> dictAttrs) {2888    SmallVector<Attribute> attrs;2889    for (auto &dict : dictAttrs)2890      attrs.push_back(dict ? dict : builder.getDictionaryAttr({}));2891    return builder.getArrayAttr(attrs);2892  };2893  if (anyArgAttrs) {2894    SmallVector<DictionaryAttr> argAttrs;2895    for (auto &llvmArgAttrs : llvmArgAttrsSet)2896      argAttrs.emplace_back(convertArgOrResultAttrSet(llvmArgAttrs));2897    attrsOp.setArgAttrsAttr(getArrayAttr(argAttrs));2898  }2899 2900  // Convert the result attributes.2901  llvm::AttributeSet llvmResAttr = llvmAttrs.getRetAttrs();2902  if (!llvmResAttr.hasAttributes())2903    return;2904  DictionaryAttr resAttrs = convertArgOrResultAttrSet(llvmResAttr);2905  attrsOp.setResAttrsAttr(getArrayAttr({resAttrs}));2906}2907 2908template <typename Op>2909static LogicalResult convertCallBaseAttributes(llvm::CallBase *inst, Op op) {2910  op.setCConv(convertCConvFromLLVM(inst->getCallingConv()));2911  return success();2912}2913 2914LogicalResult ModuleImport::convertInvokeAttributes(llvm::InvokeInst *inst,2915                                                    InvokeOp op) {2916  return convertCallBaseAttributes(inst, op);2917}2918 2919LogicalResult ModuleImport::convertCallAttributes(llvm::CallInst *inst,2920                                                  CallOp op) {2921  setFastmathFlagsAttr(inst, op.getOperation());2922  // Query the attributes directly instead of using `inst->getFnAttr(Kind)`, the2923  // latter does additional lookup to the parent and inherits, changing the2924  // semantics too early.2925  llvm::AttributeList callAttrs = inst->getAttributes();2926 2927  op.setTailCallKind(convertTailCallKindFromLLVM(inst->getTailCallKind()));2928  op.setConvergent(callAttrs.getFnAttr(llvm::Attribute::Convergent).isValid());2929  op.setNoUnwind(callAttrs.getFnAttr(llvm::Attribute::NoUnwind).isValid());2930  op.setWillReturn(callAttrs.getFnAttr(llvm::Attribute::WillReturn).isValid());2931  op.setNoInline(callAttrs.getFnAttr(llvm::Attribute::NoInline).isValid());2932  op.setAlwaysInline(2933      callAttrs.getFnAttr(llvm::Attribute::AlwaysInline).isValid());2934  op.setInlineHint(callAttrs.getFnAttr(llvm::Attribute::InlineHint).isValid());2935 2936  llvm::MemoryEffects memEffects = inst->getMemoryEffects();2937  ModRefInfo othermem = convertModRefInfoFromLLVM(2938      memEffects.getModRef(llvm::MemoryEffects::Location::Other));2939  ModRefInfo argMem = convertModRefInfoFromLLVM(2940      memEffects.getModRef(llvm::MemoryEffects::Location::ArgMem));2941  ModRefInfo inaccessibleMem = convertModRefInfoFromLLVM(2942      memEffects.getModRef(llvm::MemoryEffects::Location::InaccessibleMem));2943  ModRefInfo errnoMem = convertModRefInfoFromLLVM(2944      memEffects.getModRef(llvm::MemoryEffects::Location::ErrnoMem));2945  ModRefInfo targetMem0 = convertModRefInfoFromLLVM(2946      memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem0));2947  ModRefInfo targetMem1 = convertModRefInfoFromLLVM(2948      memEffects.getModRef(llvm::MemoryEffects::Location::TargetMem1));2949  auto memAttr =2950      MemoryEffectsAttr::get(op.getContext(), othermem, argMem, inaccessibleMem,2951                             errnoMem, targetMem0, targetMem1);2952  // Only set the attribute when it does not match the default value.2953  if (!memAttr.isReadWrite())2954    op.setMemoryEffectsAttr(memAttr);2955 2956  return convertCallBaseAttributes(inst, op);2957}2958 2959LogicalResult ModuleImport::processFunction(llvm::Function *func) {2960  clearRegionState();2961 2962  auto functionType =2963      dyn_cast<LLVMFunctionType>(convertType(func->getFunctionType()));2964  if (func->isIntrinsic() &&2965      iface.isConvertibleIntrinsic(func->getIntrinsicID()))2966    return success();2967 2968  bool dsoLocal = func->isDSOLocal();2969  CConv cconv = convertCConvFromLLVM(func->getCallingConv());2970 2971  // Insert the function at the end of the module.2972  OpBuilder::InsertionGuard guard(builder);2973  builder.setInsertionPointToEnd(mlirModule.getBody());2974 2975  Location loc = debugImporter->translateFuncLocation(func);2976  LLVMFuncOp funcOp = LLVMFuncOp::create(2977      builder, loc, func->getName(), functionType,2978      convertLinkageFromLLVM(func->getLinkage()), dsoLocal, cconv);2979 2980  convertArgAndResultAttrs(func, funcOp);2981 2982  if (FlatSymbolRefAttr personality = getPersonalityAsAttr(func))2983    funcOp.setPersonalityAttr(personality);2984  else if (func->hasPersonalityFn())2985    emitWarning(funcOp.getLoc(), "could not deduce personality, skipping it");2986 2987  if (func->hasGC())2988    funcOp.setGarbageCollector(StringRef(func->getGC()));2989 2990  if (func->hasAtLeastLocalUnnamedAddr())2991    funcOp.setUnnamedAddr(convertUnnamedAddrFromLLVM(func->getUnnamedAddr()));2992 2993  if (func->hasSection())2994    funcOp.setSection(StringRef(func->getSection()));2995 2996  funcOp.setVisibility_(convertVisibilityFromLLVM(func->getVisibility()));2997 2998  if (func->hasComdat())2999    funcOp.setComdatAttr(comdatMapping.lookup(func->getComdat()));3000 3001  if (llvm::MaybeAlign maybeAlign = func->getAlign())3002    funcOp.setAlignment(maybeAlign->value());3003 3004  // Handle Function attributes.3005  processFunctionAttributes(func, funcOp);3006 3007  // Convert non-debug metadata by using the dialect interface.3008  SmallVector<std::pair<unsigned, llvm::MDNode *>> allMetadata;3009  func->getAllMetadata(allMetadata);3010  for (auto &[kind, node] : allMetadata) {3011    if (!iface.isConvertibleMetadata(kind))3012      continue;3013    if (failed(iface.setMetadataAttrs(builder, kind, node, funcOp, *this))) {3014      emitWarning(funcOp.getLoc())3015          << "unhandled function metadata: " << diagMD(node, llvmModule.get())3016          << " on " << diag(*func);3017    }3018  }3019 3020  if (func->isDeclaration())3021    return success();3022 3023  // Collect the set of basic blocks reachable from the function's entry block.3024  // This step is crucial as LLVM IR can contain unreachable blocks that3025  // self-dominate. As a result, an operation might utilize a variable it3026  // defines, which the import does not support. Given that MLIR lacks block3027  // label support, we can safely remove unreachable blocks, as there are no3028  // indirect branch instructions that could potentially target these blocks.3029  llvm::df_iterator_default_set<llvm::BasicBlock *> reachable;3030  for (llvm::BasicBlock *basicBlock : llvm::depth_first_ext(func, reachable))3031    (void)basicBlock;3032 3033  // Eagerly create all reachable blocks.3034  SmallVector<llvm::BasicBlock *> reachableBasicBlocks;3035  for (llvm::BasicBlock &basicBlock : *func) {3036    // Skip unreachable blocks.3037    if (!reachable.contains(&basicBlock)) {3038      if (basicBlock.hasAddressTaken())3039        return emitError(funcOp.getLoc())3040               << "unreachable block '" << basicBlock.getName()3041               << "' with address taken";3042      continue;3043    }3044    Region &body = funcOp.getBody();3045    Block *block = builder.createBlock(&body, body.end());3046    mapBlock(&basicBlock, block);3047    reachableBasicBlocks.push_back(&basicBlock);3048  }3049 3050  // Add function arguments to the entry block.3051  for (const auto &it : llvm::enumerate(func->args())) {3052    BlockArgument blockArg = funcOp.getFunctionBody().addArgument(3053        functionType.getParamType(it.index()), funcOp.getLoc());3054    mapValue(&it.value(), blockArg);3055  }3056 3057  // Process the blocks in topological order. The ordered traversal ensures3058  // operands defined in a dominating block have a valid mapping to an MLIR3059  // value once a block is translated.3060  SetVector<llvm::BasicBlock *> blocks =3061      getTopologicallySortedBlocks(reachableBasicBlocks);3062  setConstantInsertionPointToStart(lookupBlock(blocks.front()));3063  for (llvm::BasicBlock *basicBlock : blocks)3064    if (failed(processBasicBlock(basicBlock, lookupBlock(basicBlock))))3065      return failure();3066 3067  // Process the debug intrinsics that require a delayed conversion after3068  // everything else was converted.3069  if (failed(processDebugIntrinsics()))3070    return failure();3071 3072  // Process the debug records that require a delayed conversion after3073  // everything else was converted.3074  if (failed(processDebugRecords()))3075    return failure();3076 3077  return success();3078}3079 3080/// Checks if `dbgIntr` is a kill location that holds metadata instead of an SSA3081/// value.3082static bool isMetadataKillLocation(llvm::DbgVariableIntrinsic *dbgIntr) {3083  if (!dbgIntr->isKillLocation())3084    return false;3085  llvm::Value *value = dbgIntr->getArgOperand(0);3086  auto *nodeAsVal = dyn_cast<llvm::MetadataAsValue>(value);3087  if (!nodeAsVal)3088    return false;3089  return !isa<llvm::ValueAsMetadata>(nodeAsVal->getMetadata());3090}3091 3092/// Ensure that the debug intrinsic is inserted right after the operand3093/// definition. Otherwise, the operand might not necessarily dominate the3094/// intrinsic. If the defining operation is a terminator, insert the intrinsic3095/// into a dominated block.3096static LogicalResult setDebugIntrinsicBuilderInsertionPoint(3097    mlir::OpBuilder &builder, DominanceInfo &domInfo, Value argOperand) {3098  if (Operation *op = argOperand.getDefiningOp();3099      op && op->hasTrait<OpTrait::IsTerminator>()) {3100    // Find a dominated block that can hold the debug intrinsic.3101    auto dominatedBlocks = domInfo.getNode(op->getBlock())->children();3102    // If no block is dominated by the terminator, this intrinisc cannot be3103    // converted.3104    if (dominatedBlocks.empty())3105      return failure();3106    // Set insertion point before the terminator, to avoid inserting something3107    // before landingpads.3108    Block *dominatedBlock = (*dominatedBlocks.begin())->getBlock();3109    builder.setInsertionPoint(dominatedBlock->getTerminator());3110  } else {3111    Value insertPt = argOperand;3112    if (auto blockArg = dyn_cast<BlockArgument>(argOperand)) {3113      // The value might be coming from a phi node and is now a block argument,3114      // which means the insertion point is set to the start of the block. If3115      // this block is a target destination of an invoke, the insertion point3116      // must happen after the landing pad operation.3117      Block *insertionBlock = argOperand.getParentBlock();3118      if (!insertionBlock->empty() &&3119          isa<LandingpadOp>(insertionBlock->front()))3120        insertPt = cast<LandingpadOp>(insertionBlock->front()).getRes();3121    }3122 3123    builder.setInsertionPointAfterValue(insertPt);3124  }3125  return success();3126}3127 3128std::tuple<DILocalVariableAttr, DIExpressionAttr, Value>3129ModuleImport::processDebugOpArgumentsAndInsertionPt(3130    Location loc,3131    llvm::function_ref<FailureOr<Value>()> convertArgOperandToValue,3132    llvm::Value *address,3133    llvm::PointerUnion<llvm::Value *, llvm::DILocalVariable *> variable,3134    llvm::DIExpression *expression, DominanceInfo &domInfo) {3135  // Drop debug intrinsics if the associated debug information cannot be3136  // translated due to an unsupported construct.3137  DILocalVariableAttr localVarAttr = matchLocalVariableAttr(variable);3138  if (!localVarAttr)3139    return {};3140  FailureOr<Value> argOperand = convertArgOperandToValue();3141  if (failed(argOperand)) {3142    emitError(loc) << "failed to convert a debug operand: " << diag(*address);3143    return {};3144  }3145 3146  if (setDebugIntrinsicBuilderInsertionPoint(builder, domInfo, *argOperand)3147          .failed())3148    return {};3149 3150  return {localVarAttr, debugImporter->translateExpression(expression),3151          *argOperand};3152}3153 3154LogicalResult3155ModuleImport::processDebugIntrinsic(llvm::DbgVariableIntrinsic *dbgIntr,3156                                    DominanceInfo &domInfo) {3157  Location loc = translateLoc(dbgIntr->getDebugLoc());3158  auto emitUnsupportedWarning = [&]() {3159    if (emitExpensiveWarnings)3160      emitWarning(loc) << "dropped intrinsic: " << diag(*dbgIntr);3161    return success();3162  };3163 3164  OpBuilder::InsertionGuard guard(builder);3165  auto convertArgOperandToValue = [&]() {3166    return convertMetadataValue(dbgIntr->getArgOperand(0));3167  };3168 3169  // Drop debug intrinsics with an argument list.3170  // TODO: Support this case.3171  if (dbgIntr->hasArgList())3172    return emitUnsupportedWarning();3173 3174  // Drop debug intrinsics with kill locations that have metadata nodes as3175  // location operand, which cannot be converted to poison as the type cannot be3176  // reconstructed.3177  // TODO: Support this case.3178  if (isMetadataKillLocation(dbgIntr))3179    return emitUnsupportedWarning();3180 3181  auto [localVariableAttr, locationExprAttr, locVal] =3182      processDebugOpArgumentsAndInsertionPt(3183          loc, convertArgOperandToValue, dbgIntr->getArgOperand(0),3184          dbgIntr->getArgOperand(1), dbgIntr->getExpression(), domInfo);3185 3186  if (!localVariableAttr)3187    return emitUnsupportedWarning();3188 3189  if (!locVal) // Expected if localVariableAttr is present.3190    return failure();3191 3192  Operation *op = nullptr;3193  if (isa<llvm::DbgDeclareInst>(dbgIntr))3194    op = LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,3195                                    locationExprAttr);3196  else if (isa<llvm::DbgValueInst>(dbgIntr))3197    op = LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,3198                                  locationExprAttr);3199  else3200    return emitUnsupportedWarning();3201 3202  mapNoResultOp(dbgIntr, op);3203  setNonDebugMetadataAttrs(dbgIntr, op);3204  return success();3205}3206 3207LogicalResult3208ModuleImport::processDebugRecord(llvm::DbgVariableRecord &dbgRecord,3209                                 DominanceInfo &domInfo) {3210  OpBuilder::InsertionGuard guard(builder);3211  Location loc = translateLoc(dbgRecord.getDebugLoc());3212  auto emitUnsupportedWarning = [&]() -> LogicalResult {3213    if (!emitExpensiveWarnings)3214      return success();3215    std::string options;3216    llvm::raw_string_ostream optionsStream(options);3217    dbgRecord.print(optionsStream);3218    emitWarning(loc) << "unhandled debug variable record "3219                     << optionsStream.str();3220    return success();3221  };3222 3223  // Drop debug records with an argument list.3224  // TODO: Support this case.3225  if (dbgRecord.hasArgList())3226    return emitUnsupportedWarning();3227 3228  // Drop all other debug records with a address operand that cannot be3229  // converted to an SSA value such as an empty metadata node.3230  // TODO: Support this case.3231  if (!dbgRecord.getAddress())3232    return emitUnsupportedWarning();3233 3234  auto convertArgOperandToValue = [&]() -> FailureOr<Value> {3235    llvm::Value *value = dbgRecord.getAddress();3236 3237    // Return the mapped value if it has been converted before.3238    auto it = valueMapping.find(value);3239    if (it != valueMapping.end())3240      return it->getSecond();3241 3242    // Convert constants such as immediate values that have no mapping yet.3243    if (auto *constant = dyn_cast<llvm::Constant>(value))3244      return convertConstantExpr(constant);3245    return failure();3246  };3247 3248  auto [localVariableAttr, locationExprAttr, locVal] =3249      processDebugOpArgumentsAndInsertionPt(3250          loc, convertArgOperandToValue, dbgRecord.getAddress(),3251          dbgRecord.getVariable(), dbgRecord.getExpression(), domInfo);3252 3253  if (!localVariableAttr)3254    return emitUnsupportedWarning();3255 3256  if (!locVal) // Expected if localVariableAttr is present.3257    return failure();3258 3259  if (dbgRecord.isDbgDeclare())3260    LLVM::DbgDeclareOp::create(builder, loc, locVal, localVariableAttr,3261                               locationExprAttr);3262  else if (dbgRecord.isDbgValue())3263    LLVM::DbgValueOp::create(builder, loc, locVal, localVariableAttr,3264                             locationExprAttr);3265  else // isDbgAssign3266    return emitUnsupportedWarning();3267 3268  return success();3269}3270 3271LogicalResult ModuleImport::processDebugIntrinsics() {3272  DominanceInfo domInfo;3273  for (llvm::Instruction *inst : debugIntrinsics) {3274    auto *intrCall = cast<llvm::DbgVariableIntrinsic>(inst);3275    if (failed(processDebugIntrinsic(intrCall, domInfo)))3276      return failure();3277  }3278  return success();3279}3280 3281LogicalResult ModuleImport::processDebugRecords() {3282  DominanceInfo domInfo;3283  for (llvm::DbgVariableRecord *dbgRecord : dbgRecords)3284    if (failed(processDebugRecord(*dbgRecord, domInfo)))3285      return failure();3286  dbgRecords.clear();3287  return success();3288}3289 3290LogicalResult ModuleImport::processBasicBlock(llvm::BasicBlock *bb,3291                                              Block *block) {3292  builder.setInsertionPointToStart(block);3293  for (llvm::Instruction &inst : *bb) {3294    if (failed(processInstruction(&inst)))3295      return failure();3296 3297    // Skip additional processing when the instructions is a debug intrinsics3298    // that was not yet converted.3299    if (debugIntrinsics.contains(&inst))3300      continue;3301 3302    // Set the non-debug metadata attributes on the imported operation and emit3303    // a warning if an instruction other than a phi instruction is dropped3304    // during the import.3305    if (Operation *op = lookupOperation(&inst)) {3306      setNonDebugMetadataAttrs(&inst, op);3307    } else if (inst.getOpcode() != llvm::Instruction::PHI) {3308      if (emitExpensiveWarnings) {3309        Location loc = debugImporter->translateLoc(inst.getDebugLoc());3310        emitWarning(loc) << "dropped instruction: " << diag(inst);3311      }3312    }3313  }3314 3315  if (bb->hasAddressTaken()) {3316    OpBuilder::InsertionGuard guard(builder);3317    builder.setInsertionPointToStart(block);3318    BlockTagOp::create(builder, block->getParentOp()->getLoc(),3319                       BlockTagAttr::get(context, bb->getNumber()));3320  }3321  return success();3322}3323 3324FailureOr<SmallVector<AccessGroupAttr>>3325ModuleImport::lookupAccessGroupAttrs(const llvm::MDNode *node) const {3326  return loopAnnotationImporter->lookupAccessGroupAttrs(node);3327}3328 3329LoopAnnotationAttr3330ModuleImport::translateLoopAnnotationAttr(const llvm::MDNode *node,3331                                          Location loc) const {3332  return loopAnnotationImporter->translateLoopAnnotation(node, loc);3333}3334 3335FailureOr<DereferenceableAttr>3336ModuleImport::translateDereferenceableAttr(const llvm::MDNode *node,3337                                           unsigned kindID) {3338  Location loc = mlirModule.getLoc();3339 3340  // The only operand should be a constant integer representing the number of3341  // dereferenceable bytes.3342  if (node->getNumOperands() != 1)3343    return emitError(loc) << "dereferenceable metadata must have one operand: "3344                          << diagMD(node, llvmModule.get());3345 3346  auto *numBytesMD = dyn_cast<llvm::ConstantAsMetadata>(node->getOperand(0));3347  auto *numBytesCst = dyn_cast<llvm::ConstantInt>(numBytesMD->getValue());3348  if (!numBytesCst || !numBytesCst->getValue().isNonNegative())3349    return emitError(loc) << "dereferenceable metadata operand must be a "3350                             "non-negative constant integer: "3351                          << diagMD(node, llvmModule.get());3352 3353  bool mayBeNull = kindID == llvm::LLVMContext::MD_dereferenceable_or_null;3354  auto derefAttr = builder.getAttr<DereferenceableAttr>(3355      numBytesCst->getZExtValue(), mayBeNull);3356 3357  return derefAttr;3358}3359 3360OwningOpRef<ModuleOp> mlir::translateLLVMIRToModule(3361    std::unique_ptr<llvm::Module> llvmModule, MLIRContext *context,3362    bool emitExpensiveWarnings, bool dropDICompositeTypeElements,3363    bool loadAllDialects, bool preferUnregisteredIntrinsics,3364    bool importStructsAsLiterals) {3365  // Preload all registered dialects to allow the import to iterate the3366  // registered LLVMImportDialectInterface implementations and query the3367  // supported LLVM IR constructs before starting the translation. Assumes the3368  // LLVM and DLTI dialects that convert the core LLVM IR constructs have been3369  // registered before.3370  assert(llvm::is_contained(context->getAvailableDialects(),3371                            LLVMDialect::getDialectNamespace()));3372  assert(llvm::is_contained(context->getAvailableDialects(),3373                            DLTIDialect::getDialectNamespace()));3374  if (loadAllDialects)3375    context->loadAllAvailableDialects();3376  OwningOpRef<ModuleOp> module(ModuleOp::create(FileLineColLoc::get(3377      StringAttr::get(context, llvmModule->getSourceFileName()), /*line=*/0,3378      /*column=*/0)));3379 3380  ModuleImport moduleImport(module.get(), std::move(llvmModule),3381                            emitExpensiveWarnings, dropDICompositeTypeElements,3382                            preferUnregisteredIntrinsics,3383                            importStructsAsLiterals);3384  if (failed(moduleImport.initializeImportInterface()))3385    return {};3386  if (failed(moduleImport.convertDataLayout()))3387    return {};3388  if (failed(moduleImport.convertComdats()))3389    return {};3390  if (failed(moduleImport.convertMetadata()))3391    return {};3392  if (failed(moduleImport.convertGlobals()))3393    return {};3394  if (failed(moduleImport.convertFunctions()))3395    return {};3396  if (failed(moduleImport.convertAliases()))3397    return {};3398  if (failed(moduleImport.convertIFuncs()))3399    return {};3400  moduleImport.convertTargetTriple();3401  moduleImport.convertModuleLevelAsm();3402  return module;3403}3404