16b534ecbSJames Molloy //===- ConvertFromLLVMIR.cpp - MLIR to LLVM IR conversion -----------------===//
26b534ecbSJames Molloy //
330857107SMehdi Amini // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
456222a06SMehdi Amini // See https://llvm.org/LICENSE.txt for license information.
556222a06SMehdi Amini // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66b534ecbSJames Molloy //
756222a06SMehdi Amini //===----------------------------------------------------------------------===//
86b534ecbSJames Molloy //
96b534ecbSJames Molloy // This file implements a translation between LLVM IR and the MLIR LLVM dialect.
106b534ecbSJames Molloy //
116b534ecbSJames Molloy //===----------------------------------------------------------------------===//
126b534ecbSJames Molloy 
13081cff62SMehdi Amini #include "mlir/Target/LLVMIR/Import.h"
14081cff62SMehdi Amini 
15ea998709SAlex Zinenko #include "mlir/Dialect/DLTI/DLTI.h"
166b534ecbSJames Molloy #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
176b534ecbSJames Molloy #include "mlir/IR/Builders.h"
1865fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h"
1909f7a55fSRiver Riddle #include "mlir/IR/BuiltinTypes.h"
206b534ecbSJames Molloy #include "mlir/IR/MLIRContext.h"
21ea998709SAlex Zinenko #include "mlir/Interfaces/DataLayoutInterfaces.h"
22929189a4SWilliam S. Moses #include "mlir/Target/LLVMIR/TypeFromLLVM.h"
23ee1d447eSRiver Riddle #include "mlir/Tools/mlir-translate/Translation.h"
246b534ecbSJames Molloy 
25758ddba3SWilliam S. Moses #include "llvm/ADT/StringSet.h"
2619db802eSAlex Zinenko #include "llvm/ADT/TypeSwitch.h"
276b534ecbSJames Molloy #include "llvm/IR/Attributes.h"
286b534ecbSJames Molloy #include "llvm/IR/Constants.h"
2919db802eSAlex Zinenko #include "llvm/IR/DerivedTypes.h"
306b534ecbSJames Molloy #include "llvm/IR/Function.h"
31047400edSNicolas Vasilache #include "llvm/IR/InlineAsm.h"
326b534ecbSJames Molloy #include "llvm/IR/Instructions.h"
3342c17073Sjacquesguan #include "llvm/IR/Intrinsics.h"
346b534ecbSJames Molloy #include "llvm/IR/Type.h"
356b534ecbSJames Molloy #include "llvm/IRReader/IRReader.h"
366b534ecbSJames Molloy #include "llvm/Support/Error.h"
376b534ecbSJames Molloy #include "llvm/Support/SourceMgr.h"
386b534ecbSJames Molloy 
396b534ecbSJames Molloy using namespace mlir;
406b534ecbSJames Molloy using namespace mlir::LLVM;
416b534ecbSJames Molloy 
42eb67bd78SAlex Zinenko #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsFromLLVM.inc"
43eb67bd78SAlex Zinenko 
446b534ecbSJames Molloy // Utility to print an LLVM value as a string for passing to emitError().
456b534ecbSJames Molloy // FIXME: Diagnostic should be able to natively handle types that have
466b534ecbSJames Molloy // operator << (raw_ostream&) defined.
diag(llvm::Value & v)476b534ecbSJames Molloy static std::string diag(llvm::Value &v) {
486b534ecbSJames Molloy   std::string s;
496b534ecbSJames Molloy   llvm::raw_string_ostream os(s);
506b534ecbSJames Molloy   os << v;
516b534ecbSJames Molloy   return os.str();
526b534ecbSJames Molloy }
536b534ecbSJames Molloy 
54ea998709SAlex Zinenko /// Creates an attribute containing ABI and preferred alignment numbers parsed
55ea998709SAlex Zinenko /// a string. The string may be either "abi:preferred" or just "abi". In the
56ea998709SAlex Zinenko /// latter case, the prefrred alignment is considered equal to ABI alignment.
parseDataLayoutAlignment(MLIRContext & ctx,StringRef spec)57ea998709SAlex Zinenko static DenseIntElementsAttr parseDataLayoutAlignment(MLIRContext &ctx,
58ea998709SAlex Zinenko                                                      StringRef spec) {
59ea998709SAlex Zinenko   auto i32 = IntegerType::get(&ctx, 32);
60ea998709SAlex Zinenko 
61ea998709SAlex Zinenko   StringRef abiString, preferredString;
62ea998709SAlex Zinenko   std::tie(abiString, preferredString) = spec.split(':');
63ea998709SAlex Zinenko   int abi, preferred;
64ea998709SAlex Zinenko   if (abiString.getAsInteger(/*Radix=*/10, abi))
65ea998709SAlex Zinenko     return nullptr;
66ea998709SAlex Zinenko 
67ea998709SAlex Zinenko   if (preferredString.empty())
68ea998709SAlex Zinenko     preferred = abi;
69ea998709SAlex Zinenko   else if (preferredString.getAsInteger(/*Radix=*/10, preferred))
70ea998709SAlex Zinenko     return nullptr;
71ea998709SAlex Zinenko 
72ea998709SAlex Zinenko   return DenseIntElementsAttr::get(VectorType::get({2}, i32), {abi, preferred});
73ea998709SAlex Zinenko }
74ea998709SAlex Zinenko 
75ea998709SAlex Zinenko /// Returns a supported MLIR floating point type of the given bit width or null
76ea998709SAlex Zinenko /// if the bit width is not supported.
getDLFloatType(MLIRContext & ctx,int32_t bitwidth)77ea998709SAlex Zinenko static FloatType getDLFloatType(MLIRContext &ctx, int32_t bitwidth) {
78ea998709SAlex Zinenko   switch (bitwidth) {
79ea998709SAlex Zinenko   case 16:
80ea998709SAlex Zinenko     return FloatType::getF16(&ctx);
81ea998709SAlex Zinenko   case 32:
82ea998709SAlex Zinenko     return FloatType::getF32(&ctx);
83ea998709SAlex Zinenko   case 64:
84ea998709SAlex Zinenko     return FloatType::getF64(&ctx);
85ea998709SAlex Zinenko   case 80:
86ea998709SAlex Zinenko     return FloatType::getF80(&ctx);
87ea998709SAlex Zinenko   case 128:
88ea998709SAlex Zinenko     return FloatType::getF128(&ctx);
89ea998709SAlex Zinenko   default:
90ea998709SAlex Zinenko     return nullptr;
91ea998709SAlex Zinenko   }
92ea998709SAlex Zinenko }
93ea998709SAlex Zinenko 
94ea998709SAlex Zinenko DataLayoutSpecInterface
translateDataLayout(const llvm::DataLayout & dataLayout,MLIRContext * context)95ea998709SAlex Zinenko mlir::translateDataLayout(const llvm::DataLayout &dataLayout,
96ea998709SAlex Zinenko                           MLIRContext *context) {
97ea998709SAlex Zinenko   assert(context && "expected MLIR context");
98758ddba3SWilliam S. Moses   std::string layoutstr = dataLayout.getStringRepresentation();
99758ddba3SWilliam S. Moses 
100758ddba3SWilliam S. Moses   // Remaining unhandled default layout defaults
101758ddba3SWilliam S. Moses   // e (little endian if not set)
102758ddba3SWilliam S. Moses   // p[n]:64:64:64 (non zero address spaces have 64-bit properties)
103758ddba3SWilliam S. Moses   std::string append =
104758ddba3SWilliam S. Moses       "p:64:64:64-S0-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f16:16:16-f64:"
105758ddba3SWilliam S. Moses       "64:64-f128:128:128-v64:64:64-v128:128:128-a:0:64";
106758ddba3SWilliam S. Moses   if (layoutstr.empty())
107758ddba3SWilliam S. Moses     layoutstr = append;
108758ddba3SWilliam S. Moses   else
109758ddba3SWilliam S. Moses     layoutstr = layoutstr + "-" + append;
110758ddba3SWilliam S. Moses 
111758ddba3SWilliam S. Moses   StringRef layout(layoutstr);
112758ddba3SWilliam S. Moses 
113ea998709SAlex Zinenko   SmallVector<DataLayoutEntryInterface> entries;
114758ddba3SWilliam S. Moses   StringSet<> seen;
115ea998709SAlex Zinenko   while (!layout.empty()) {
116ea998709SAlex Zinenko     // Split at '-'.
117ea998709SAlex Zinenko     std::pair<StringRef, StringRef> split = layout.split('-');
118ea998709SAlex Zinenko     StringRef current;
119ea998709SAlex Zinenko     std::tie(current, layout) = split;
120ea998709SAlex Zinenko 
121ea998709SAlex Zinenko     // Split at ':'.
122ea998709SAlex Zinenko     StringRef kind, spec;
123ea998709SAlex Zinenko     std::tie(kind, spec) = current.split(':');
124758ddba3SWilliam S. Moses     if (seen.contains(kind))
125758ddba3SWilliam S. Moses       continue;
126758ddba3SWilliam S. Moses     seen.insert(kind);
127ea998709SAlex Zinenko 
128ea998709SAlex Zinenko     char symbol = kind.front();
129ea998709SAlex Zinenko     StringRef parameter = kind.substr(1);
130ea998709SAlex Zinenko 
131ea998709SAlex Zinenko     if (symbol == 'i' || symbol == 'f') {
132ea998709SAlex Zinenko       unsigned bitwidth;
133ea998709SAlex Zinenko       if (parameter.getAsInteger(/*Radix=*/10, bitwidth))
134ea998709SAlex Zinenko         return nullptr;
135ea998709SAlex Zinenko       DenseIntElementsAttr params = parseDataLayoutAlignment(*context, spec);
136ea998709SAlex Zinenko       if (!params)
137ea998709SAlex Zinenko         return nullptr;
138ea998709SAlex Zinenko       auto entry = DataLayoutEntryAttr::get(
139ea998709SAlex Zinenko           symbol == 'i' ? static_cast<Type>(IntegerType::get(context, bitwidth))
140ea998709SAlex Zinenko                         : getDLFloatType(*context, bitwidth),
141ea998709SAlex Zinenko           params);
142ea998709SAlex Zinenko       entries.emplace_back(entry);
143ea998709SAlex Zinenko     } else if (symbol == 'e' || symbol == 'E') {
144ea998709SAlex Zinenko       auto value = StringAttr::get(
145ea998709SAlex Zinenko           context, symbol == 'e' ? DLTIDialect::kDataLayoutEndiannessLittle
146ea998709SAlex Zinenko                                  : DLTIDialect::kDataLayoutEndiannessBig);
147ea998709SAlex Zinenko       auto entry = DataLayoutEntryAttr::get(
148ea998709SAlex Zinenko           StringAttr::get(context, DLTIDialect::kDataLayoutEndiannessKey),
149ea998709SAlex Zinenko           value);
150ea998709SAlex Zinenko       entries.emplace_back(entry);
151ea998709SAlex Zinenko     }
152ea998709SAlex Zinenko   }
153ea998709SAlex Zinenko 
154ea998709SAlex Zinenko   return DataLayoutSpecAttr::get(context, entries);
155ea998709SAlex Zinenko }
156ea998709SAlex Zinenko 
1576b534ecbSJames Molloy // Handles importing globals and functions from an LLVM module.
1586b534ecbSJames Molloy namespace {
1596b534ecbSJames Molloy class Importer {
1606b534ecbSJames Molloy public:
Importer(MLIRContext * context,ModuleOp module)1616b534ecbSJames Molloy   Importer(MLIRContext *context, ModuleOp module)
1626b534ecbSJames Molloy       : b(context), context(context), module(module),
163a4bb667dSRiver Riddle         unknownLoc(FileLineColLoc::get(context, "imported-bitcode", 0, 0)),
164b2ab375dSAlex Zinenko         typeTranslator(*context) {
1656b534ecbSJames Molloy     b.setInsertionPointToStart(module.getBody());
1666b534ecbSJames Molloy   }
1676b534ecbSJames Molloy 
1686b534ecbSJames Molloy   /// Imports `f` into the current module.
1696b534ecbSJames Molloy   LogicalResult processFunction(llvm::Function *f);
1706b534ecbSJames Molloy 
1716b534ecbSJames Molloy   /// Imports GV as a GlobalOp, creating it if it doesn't exist.
17202b6fb21SMehdi Amini   GlobalOp processGlobal(llvm::GlobalVariable *gv);
1736b534ecbSJames Molloy 
1746b534ecbSJames Molloy private:
175ff77397fSShraiysh Vaishay   /// Returns personality of `f` as a FlatSymbolRefAttr.
176ff77397fSShraiysh Vaishay   FlatSymbolRefAttr getPersonalityAsAttr(llvm::Function *f);
1776b534ecbSJames Molloy   /// Imports `bb` into `block`, which must be initially empty.
1786b534ecbSJames Molloy   LogicalResult processBasicBlock(llvm::BasicBlock *bb, Block *block);
1796b534ecbSJames Molloy   /// Imports `inst` and populates instMap[inst] with the imported Value.
1806b534ecbSJames Molloy   LogicalResult processInstruction(llvm::Instruction *inst);
181c69c9e0fSAlex Zinenko   /// Creates an LLVM-compatible MLIR type for `type`.
182c69c9e0fSAlex Zinenko   Type processType(llvm::Type *type);
1836b534ecbSJames Molloy   /// `value` is an SSA-use. Return the remapped version of `value` or a
1846b534ecbSJames Molloy   /// placeholder that will be remapped later if this is an instruction that
1856b534ecbSJames Molloy   /// has not yet been visited.
186e62a6956SRiver Riddle   Value processValue(llvm::Value *value);
1876b534ecbSJames Molloy   /// Create the most accurate Location possible using a llvm::DebugLoc and
1886b534ecbSJames Molloy   /// possibly an llvm::Instruction to narrow the Location if debug information
1896b534ecbSJames Molloy   /// is unavailable.
1906b534ecbSJames Molloy   Location processDebugLoc(const llvm::DebugLoc &loc,
1916b534ecbSJames Molloy                            llvm::Instruction *inst = nullptr);
19284c3f05cSAlex Zinenko   /// `br` branches to `target`. Append the block arguments to attach to the
19384c3f05cSAlex Zinenko   /// generated branch op to `blockArguments`. These should be in the same order
19484c3f05cSAlex Zinenko   /// as the PHIs in `target`.
195d242aa24SShraiysh Vaishay   LogicalResult processBranchArgs(llvm::Instruction *br,
19684c3f05cSAlex Zinenko                                   llvm::BasicBlock *target,
19784c3f05cSAlex Zinenko                                   SmallVectorImpl<Value> &blockArguments);
19809f7a55fSRiver Riddle   /// Returns the builtin type equivalent to be used in attributes for the given
19909f7a55fSRiver Riddle   /// LLVM IR dialect type.
200c69c9e0fSAlex Zinenko   Type getStdTypeForAttr(Type type);
2016b534ecbSJames Molloy   /// Return `value` as an attribute to attach to a GlobalOp.
2026b534ecbSJames Molloy   Attribute getConstantAsAttr(llvm::Constant *value);
2036b534ecbSJames Molloy   /// Return `c` as an MLIR Value. This could either be a ConstantOp, or
2046b534ecbSJames Molloy   /// an expanded sequence of ops in the current function's entry block (for
2056b534ecbSJames Molloy   /// ConstantExprs or ConstantGEPs).
206e62a6956SRiver Riddle   Value processConstant(llvm::Constant *c);
2076b534ecbSJames Molloy 
2086b534ecbSJames Molloy   /// The current builder, pointing at where the next Instruction should be
2096b534ecbSJames Molloy   /// generated.
2106b534ecbSJames Molloy   OpBuilder b;
2116b534ecbSJames Molloy   /// The current context.
2126b534ecbSJames Molloy   MLIRContext *context;
2136b534ecbSJames Molloy   /// The current module being created.
2146b534ecbSJames Molloy   ModuleOp module;
2156b534ecbSJames Molloy   /// The entry block of the current function being processed.
216a9f13f80SMehdi Amini   Block *currentEntryBlock = nullptr;
2176b534ecbSJames Molloy 
2186b534ecbSJames Molloy   /// Globals are inserted before the first function, if any.
getGlobalInsertPt()2196b534ecbSJames Molloy   Block::iterator getGlobalInsertPt() {
220973ddb7dSMehdi Amini     auto it = module.getBody()->begin();
221973ddb7dSMehdi Amini     auto endIt = module.getBody()->end();
222973ddb7dSMehdi Amini     while (it != endIt && !isa<LLVMFuncOp>(it))
223973ddb7dSMehdi Amini       ++it;
224973ddb7dSMehdi Amini     return it;
2256b534ecbSJames Molloy   }
2266b534ecbSJames Molloy 
2276b534ecbSJames Molloy   /// Functions are always inserted before the module terminator.
getFuncInsertPt()2286b534ecbSJames Molloy   Block::iterator getFuncInsertPt() {
2296b534ecbSJames Molloy     return std::prev(module.getBody()->end());
2306b534ecbSJames Molloy   }
2316b534ecbSJames Molloy 
2326b534ecbSJames Molloy   /// Remapped blocks, for the current function.
2336b534ecbSJames Molloy   DenseMap<llvm::BasicBlock *, Block *> blocks;
2346b534ecbSJames Molloy   /// Remapped values. These are function-local.
235e62a6956SRiver Riddle   DenseMap<llvm::Value *, Value> instMap;
2366b534ecbSJames Molloy   /// Instructions that had not been defined when first encountered as a use.
2376b534ecbSJames Molloy   /// Maps to the dummy Operation that was created in processValue().
2386b534ecbSJames Molloy   DenseMap<llvm::Value *, Operation *> unknownInstMap;
2396b534ecbSJames Molloy   /// Uniquing map of GlobalVariables.
2406b534ecbSJames Molloy   DenseMap<llvm::GlobalVariable *, GlobalOp> globals;
2416b534ecbSJames Molloy   /// Cached FileLineColLoc::get("imported-bitcode", 0, 0).
2426b534ecbSJames Molloy   Location unknownLoc;
243b2ab375dSAlex Zinenko   /// The stateful type translator (contains named structs).
244b2ab375dSAlex Zinenko   LLVM::TypeFromLLVMIRTranslator typeTranslator;
2456b534ecbSJames Molloy };
2466b534ecbSJames Molloy } // namespace
2476b534ecbSJames Molloy 
processDebugLoc(const llvm::DebugLoc & loc,llvm::Instruction * inst)2486b534ecbSJames Molloy Location Importer::processDebugLoc(const llvm::DebugLoc &loc,
2496b534ecbSJames Molloy                                    llvm::Instruction *inst) {
2506b534ecbSJames Molloy   if (!loc && inst) {
2516b534ecbSJames Molloy     std::string s;
2526b534ecbSJames Molloy     llvm::raw_string_ostream os(s);
2536b534ecbSJames Molloy     os << "llvm-imported-inst-%";
2546b534ecbSJames Molloy     inst->printAsOperand(os, /*PrintType=*/false);
255a4bb667dSRiver Riddle     return FileLineColLoc::get(context, os.str(), 0, 0);
25602b6fb21SMehdi Amini   }
25702b6fb21SMehdi Amini   if (!loc) {
2586b534ecbSJames Molloy     return unknownLoc;
2596b534ecbSJames Molloy   }
2606b534ecbSJames Molloy   // FIXME: Obtain the filename from DILocationInfo.
261a4bb667dSRiver Riddle   return FileLineColLoc::get(context, "imported-bitcode", loc.getLine(),
262a4bb667dSRiver Riddle                              loc.getCol());
2636b534ecbSJames Molloy }
2646b534ecbSJames Molloy 
processType(llvm::Type * type)265c69c9e0fSAlex Zinenko Type Importer::processType(llvm::Type *type) {
266c69c9e0fSAlex Zinenko   if (Type result = typeTranslator.translateType(type))
267b2ab375dSAlex Zinenko     return result;
26884c3f05cSAlex Zinenko 
2696b534ecbSJames Molloy   // FIXME: Diagnostic should be able to natively handle types that have
2706b534ecbSJames Molloy   // operator<<(raw_ostream&) defined.
2716b534ecbSJames Molloy   std::string s;
2726b534ecbSJames Molloy   llvm::raw_string_ostream os(s);
2736b534ecbSJames Molloy   os << *type;
2746b534ecbSJames Molloy   emitError(unknownLoc) << "unhandled type: " << os.str();
27584c3f05cSAlex Zinenko   return nullptr;
2766b534ecbSJames Molloy }
2776b534ecbSJames Molloy 
27807328944SAlex Zinenko // We only need integers, floats, doubles, and vectors and tensors thereof for
27907328944SAlex Zinenko // attributes. Scalar and vector types are converted to the standard
28007328944SAlex Zinenko // equivalents. Array types are converted to ranked tensors; nested array types
28107328944SAlex Zinenko // are converted to multi-dimensional tensors or vectors, depending on the
28207328944SAlex Zinenko // innermost type being a scalar or a vector.
getStdTypeForAttr(Type type)283c69c9e0fSAlex Zinenko Type Importer::getStdTypeForAttr(Type type) {
28407328944SAlex Zinenko   if (!type)
28507328944SAlex Zinenko     return nullptr;
28607328944SAlex Zinenko 
287dd5165a9SAlex Zinenko   if (type.isa<IntegerType, FloatType>())
288dd5165a9SAlex Zinenko     return type;
28907328944SAlex Zinenko 
29007328944SAlex Zinenko   // LLVM vectors can only contain scalars.
291bd30a796SAlex Zinenko   if (LLVM::isCompatibleVectorType(type)) {
292bd30a796SAlex Zinenko     auto numElements = LLVM::getVectorNumElements(type);
2934b1a55a9SDavid Sherwood     if (numElements.isScalable()) {
29407328944SAlex Zinenko       emitError(unknownLoc) << "scalable vectors not supported";
29584c3f05cSAlex Zinenko       return nullptr;
29684c3f05cSAlex Zinenko     }
297bd30a796SAlex Zinenko     Type elementType = getStdTypeForAttr(LLVM::getVectorElementType(type));
29884c3f05cSAlex Zinenko     if (!elementType)
29984c3f05cSAlex Zinenko       return nullptr;
3004b1a55a9SDavid Sherwood     return VectorType::get(numElements.getKnownMinValue(), elementType);
30107328944SAlex Zinenko   }
30207328944SAlex Zinenko 
30307328944SAlex Zinenko   // LLVM arrays can contain other arrays or vectors.
3048de43b92SAlex Zinenko   if (auto arrayType = type.dyn_cast<LLVMArrayType>()) {
30507328944SAlex Zinenko     // Recover the nested array shape.
30607328944SAlex Zinenko     SmallVector<int64_t, 4> shape;
3078de43b92SAlex Zinenko     shape.push_back(arrayType.getNumElements());
3088de43b92SAlex Zinenko     while (arrayType.getElementType().isa<LLVMArrayType>()) {
3098de43b92SAlex Zinenko       arrayType = arrayType.getElementType().cast<LLVMArrayType>();
3108de43b92SAlex Zinenko       shape.push_back(arrayType.getNumElements());
31107328944SAlex Zinenko     }
31207328944SAlex Zinenko 
31307328944SAlex Zinenko     // If the innermost type is a vector, use the multi-dimensional vector as
31407328944SAlex Zinenko     // attribute type.
315bd30a796SAlex Zinenko     if (LLVM::isCompatibleVectorType(arrayType.getElementType())) {
316bd30a796SAlex Zinenko       auto numElements = LLVM::getVectorNumElements(arrayType.getElementType());
3174b1a55a9SDavid Sherwood       if (numElements.isScalable()) {
31807328944SAlex Zinenko         emitError(unknownLoc) << "scalable vectors not supported";
31984c3f05cSAlex Zinenko         return nullptr;
32084c3f05cSAlex Zinenko       }
3214b1a55a9SDavid Sherwood       shape.push_back(numElements.getKnownMinValue());
32207328944SAlex Zinenko 
323bd30a796SAlex Zinenko       Type elementType = getStdTypeForAttr(
324bd30a796SAlex Zinenko           LLVM::getVectorElementType(arrayType.getElementType()));
32584c3f05cSAlex Zinenko       if (!elementType)
32684c3f05cSAlex Zinenko         return nullptr;
32784c3f05cSAlex Zinenko       return VectorType::get(shape, elementType);
32807328944SAlex Zinenko     }
32907328944SAlex Zinenko 
33007328944SAlex Zinenko     // Otherwise use a tensor.
3318de43b92SAlex Zinenko     Type elementType = getStdTypeForAttr(arrayType.getElementType());
33284c3f05cSAlex Zinenko     if (!elementType)
33384c3f05cSAlex Zinenko       return nullptr;
33484c3f05cSAlex Zinenko     return RankedTensorType::get(shape, elementType);
33507328944SAlex Zinenko   }
33607328944SAlex Zinenko 
33784c3f05cSAlex Zinenko   return nullptr;
33807328944SAlex Zinenko }
33907328944SAlex Zinenko 
3406b534ecbSJames Molloy // Get the given constant as an attribute. Not all constants can be represented
3416b534ecbSJames Molloy // as attributes.
getConstantAsAttr(llvm::Constant * value)3426b534ecbSJames Molloy Attribute Importer::getConstantAsAttr(llvm::Constant *value) {
3436b534ecbSJames Molloy   if (auto *ci = dyn_cast<llvm::ConstantInt>(value))
3446b534ecbSJames Molloy     return b.getIntegerAttr(
3451b97cdf8SRiver Riddle         IntegerType::get(context, ci->getType()->getBitWidth()),
3466b534ecbSJames Molloy         ci->getValue());
3476b534ecbSJames Molloy   if (auto *c = dyn_cast<llvm::ConstantDataArray>(value))
3486b534ecbSJames Molloy     if (c->isString())
3496b534ecbSJames Molloy       return b.getStringAttr(c->getAsString());
350cda94d3eSAlex Zinenko   if (auto *c = dyn_cast<llvm::ConstantFP>(value)) {
351e927a336SMin-Yih Hsu     auto *type = c->getType();
352e927a336SMin-Yih Hsu     FloatType floatTy;
353e927a336SMin-Yih Hsu     if (type->isBFloatTy())
354e927a336SMin-Yih Hsu       floatTy = FloatType::getBF16(context);
355e927a336SMin-Yih Hsu     else
356e927a336SMin-Yih Hsu       floatTy = getDLFloatType(*context, type->getScalarSizeInBits());
357e927a336SMin-Yih Hsu     assert(floatTy && "unsupported floating point type");
358e927a336SMin-Yih Hsu     return b.getFloatAttr(floatTy, c->getValueAPF());
359cda94d3eSAlex Zinenko   }
360dc553ce6SAlex Zinenko   if (auto *f = dyn_cast<llvm::Function>(value))
361faf1c224SChris Lattner     return SymbolRefAttr::get(b.getContext(), f->getName());
36207328944SAlex Zinenko 
36307328944SAlex Zinenko   // Convert constant data to a dense elements attribute.
36407328944SAlex Zinenko   if (auto *cd = dyn_cast<llvm::ConstantDataSequential>(value)) {
365c69c9e0fSAlex Zinenko     Type type = processType(cd->getElementType());
36684c3f05cSAlex Zinenko     if (!type)
36784c3f05cSAlex Zinenko       return nullptr;
36884c3f05cSAlex Zinenko 
36907328944SAlex Zinenko     auto attrType = getStdTypeForAttr(processType(cd->getType()))
37007328944SAlex Zinenko                         .dyn_cast_or_null<ShapedType>();
37107328944SAlex Zinenko     if (!attrType)
37207328944SAlex Zinenko       return nullptr;
37307328944SAlex Zinenko 
3742230bf99SAlex Zinenko     if (type.isa<IntegerType>()) {
37507328944SAlex Zinenko       SmallVector<APInt, 8> values;
37607328944SAlex Zinenko       values.reserve(cd->getNumElements());
37707328944SAlex Zinenko       for (unsigned i = 0, e = cd->getNumElements(); i < e; ++i)
37807328944SAlex Zinenko         values.push_back(cd->getElementAsAPInt(i));
37907328944SAlex Zinenko       return DenseElementsAttr::get(attrType, values);
38007328944SAlex Zinenko     }
38107328944SAlex Zinenko 
382dd5165a9SAlex Zinenko     if (type.isa<Float32Type, Float64Type>()) {
38307328944SAlex Zinenko       SmallVector<APFloat, 8> values;
38407328944SAlex Zinenko       values.reserve(cd->getNumElements());
38507328944SAlex Zinenko       for (unsigned i = 0, e = cd->getNumElements(); i < e; ++i)
38607328944SAlex Zinenko         values.push_back(cd->getElementAsAPFloat(i));
38707328944SAlex Zinenko       return DenseElementsAttr::get(attrType, values);
38807328944SAlex Zinenko     }
38907328944SAlex Zinenko 
39007328944SAlex Zinenko     return nullptr;
39107328944SAlex Zinenko   }
39207328944SAlex Zinenko 
39307328944SAlex Zinenko   // Unpack constant aggregates to create dense elements attribute whenever
39407328944SAlex Zinenko   // possible. Return nullptr (failure) otherwise.
395ea4652ebSMehdi Amini   if (isa<llvm::ConstantAggregate>(value)) {
39607328944SAlex Zinenko     auto outerType = getStdTypeForAttr(processType(value->getType()))
39707328944SAlex Zinenko                          .dyn_cast_or_null<ShapedType>();
39807328944SAlex Zinenko     if (!outerType)
39907328944SAlex Zinenko       return nullptr;
40007328944SAlex Zinenko 
40107328944SAlex Zinenko     SmallVector<Attribute, 8> values;
40207328944SAlex Zinenko     SmallVector<int64_t, 8> shape;
40307328944SAlex Zinenko 
40407328944SAlex Zinenko     for (unsigned i = 0, e = value->getNumOperands(); i < e; ++i) {
40507328944SAlex Zinenko       auto nested = getConstantAsAttr(value->getAggregateElement(i))
40607328944SAlex Zinenko                         .dyn_cast_or_null<DenseElementsAttr>();
40707328944SAlex Zinenko       if (!nested)
40807328944SAlex Zinenko         return nullptr;
40907328944SAlex Zinenko 
4100cb5d7fcSRiver Riddle       values.append(nested.value_begin<Attribute>(),
4110cb5d7fcSRiver Riddle                     nested.value_end<Attribute>());
41207328944SAlex Zinenko     }
41307328944SAlex Zinenko 
41407328944SAlex Zinenko     return DenseElementsAttr::get(outerType, values);
41507328944SAlex Zinenko   }
41607328944SAlex Zinenko 
41707328944SAlex Zinenko   return nullptr;
4186b534ecbSJames Molloy }
4196b534ecbSJames Molloy 
processGlobal(llvm::GlobalVariable * gv)42002b6fb21SMehdi Amini GlobalOp Importer::processGlobal(llvm::GlobalVariable *gv) {
42102b6fb21SMehdi Amini   auto it = globals.find(gv);
4226b534ecbSJames Molloy   if (it != globals.end())
4236b534ecbSJames Molloy     return it->second;
4246b534ecbSJames Molloy 
4256b534ecbSJames Molloy   OpBuilder b(module.getBody(), getGlobalInsertPt());
4266b534ecbSJames Molloy   Attribute valueAttr;
42702b6fb21SMehdi Amini   if (gv->hasInitializer())
42802b6fb21SMehdi Amini     valueAttr = getConstantAsAttr(gv->getInitializer());
42902b6fb21SMehdi Amini   Type type = processType(gv->getValueType());
43084c3f05cSAlex Zinenko   if (!type)
43184c3f05cSAlex Zinenko     return nullptr;
4329a0ea599SDumitru Potop 
4339a0ea599SDumitru Potop   uint64_t alignment = 0;
43402b6fb21SMehdi Amini   llvm::MaybeAlign maybeAlign = gv->getAlign();
435491d2701SKazu Hirata   if (maybeAlign.has_value()) {
436*c27d8152SKazu Hirata     llvm::Align align = maybeAlign.value();
4379a0ea599SDumitru Potop     alignment = align.value();
4389a0ea599SDumitru Potop   }
4399a0ea599SDumitru Potop 
440f0ba32d6SShraiysh Vaishay   GlobalOp op = b.create<GlobalOp>(
441f0ba32d6SShraiysh Vaishay       UnknownLoc::get(context), type, gv->isConstant(),
442f0ba32d6SShraiysh Vaishay       convertLinkageFromLLVM(gv->getLinkage()), gv->getName(), valueAttr,
443f0ba32d6SShraiysh Vaishay       alignment, /*addr_space=*/gv->getAddressSpace(),
444f0ba32d6SShraiysh Vaishay       /*dso_local=*/gv->isDSOLocal(), /*thread_local=*/gv->isThreadLocal());
4459a0ea599SDumitru Potop 
44602b6fb21SMehdi Amini   if (gv->hasInitializer() && !valueAttr) {
447250a11aeSJames Molloy     Region &r = op.getInitializerRegion();
448250a11aeSJames Molloy     currentEntryBlock = b.createBlock(&r);
449250a11aeSJames Molloy     b.setInsertionPoint(currentEntryBlock, currentEntryBlock->begin());
45002b6fb21SMehdi Amini     Value v = processConstant(gv->getInitializer());
45184c3f05cSAlex Zinenko     if (!v)
45284c3f05cSAlex Zinenko       return nullptr;
453e62a6956SRiver Riddle     b.create<ReturnOp>(op.getLoc(), ArrayRef<Value>({v}));
454250a11aeSJames Molloy   }
45502b6fb21SMehdi Amini   if (gv->hasAtLeastLocalUnnamedAddr())
456cfb72fd3SJacques Pienaar     op.setUnnamedAddrAttr(UnnamedAddrAttr::get(
45702b6fb21SMehdi Amini         context, convertUnnamedAddrFromLLVM(gv->getUnnamedAddr())));
45802b6fb21SMehdi Amini   if (gv->hasSection())
45902b6fb21SMehdi Amini     op.setSectionAttr(b.getStringAttr(gv->getSection()));
4609a0ea599SDumitru Potop 
46102b6fb21SMehdi Amini   return globals[gv] = op;
4626b534ecbSJames Molloy }
4636b534ecbSJames Molloy 
processConstant(llvm::Constant * c)464e62a6956SRiver Riddle Value Importer::processConstant(llvm::Constant *c) {
465d242aa24SShraiysh Vaishay   OpBuilder bEntry(currentEntryBlock, currentEntryBlock->begin());
466250a11aeSJames Molloy   if (Attribute attr = getConstantAsAttr(c)) {
4676b534ecbSJames Molloy     // These constants can be represented as attributes.
4686b534ecbSJames Molloy     OpBuilder b(currentEntryBlock, currentEntryBlock->begin());
469c69c9e0fSAlex Zinenko     Type type = processType(c->getType());
47084c3f05cSAlex Zinenko     if (!type)
47184c3f05cSAlex Zinenko       return nullptr;
472cba733edSAlex Zinenko     if (auto symbolRef = attr.dyn_cast<FlatSymbolRefAttr>())
473a75657d6SMin-Yih Hsu       return bEntry.create<AddressOfOp>(unknownLoc, type, symbolRef.getValue());
474a75657d6SMin-Yih Hsu     return bEntry.create<ConstantOp>(unknownLoc, type, attr);
4756b534ecbSJames Molloy   }
4766b534ecbSJames Molloy   if (auto *cn = dyn_cast<llvm::ConstantPointerNull>(c)) {
477c69c9e0fSAlex Zinenko     Type type = processType(cn->getType());
47884c3f05cSAlex Zinenko     if (!type)
47984c3f05cSAlex Zinenko       return nullptr;
480a75657d6SMin-Yih Hsu     return bEntry.create<NullOp>(unknownLoc, type);
4816b534ecbSJames Molloy   }
48202b6fb21SMehdi Amini   if (auto *gv = dyn_cast<llvm::GlobalVariable>(c))
483d242aa24SShraiysh Vaishay     return bEntry.create<AddressOfOp>(UnknownLoc::get(context),
48402b6fb21SMehdi Amini                                       processGlobal(gv));
485d242aa24SShraiysh Vaishay 
4866b534ecbSJames Molloy   if (auto *ce = dyn_cast<llvm::ConstantExpr>(c)) {
4876b534ecbSJames Molloy     llvm::Instruction *i = ce->getAsInstruction();
4886b534ecbSJames Molloy     OpBuilder::InsertionGuard guard(b);
4896b534ecbSJames Molloy     b.setInsertionPoint(currentEntryBlock, currentEntryBlock->begin());
4906b534ecbSJames Molloy     if (failed(processInstruction(i)))
4916b534ecbSJames Molloy       return nullptr;
4926b534ecbSJames Molloy     assert(instMap.count(i));
4936b534ecbSJames Molloy 
494ea9bcb8bSMin-Yih Hsu     // If we don't remove entry of `i` here, it's totally possible that the
495ea9bcb8bSMin-Yih Hsu     // next time llvm::ConstantExpr::getAsInstruction is called again, which
496ea9bcb8bSMin-Yih Hsu     // always allocates a new Instruction, memory address of the newly
497ea9bcb8bSMin-Yih Hsu     // created Instruction might be the same as `i`. Making processInstruction
498ea9bcb8bSMin-Yih Hsu     // falsely believe that the new Instruction has been processed before
499ea9bcb8bSMin-Yih Hsu     // and raised an assertion error.
500ea9bcb8bSMin-Yih Hsu     Value value = instMap[i];
501ea9bcb8bSMin-Yih Hsu     instMap.erase(i);
5026b534ecbSJames Molloy     // Remove this zombie LLVM instruction now, leaving us only with the MLIR
5036b534ecbSJames Molloy     // op.
5046b534ecbSJames Molloy     i->deleteValue();
505a75657d6SMin-Yih Hsu     return value;
5066b534ecbSJames Molloy   }
507d85821dfSSagar Jain   if (auto *ue = dyn_cast<llvm::UndefValue>(c)) {
508c69c9e0fSAlex Zinenko     Type type = processType(ue->getType());
509d85821dfSSagar Jain     if (!type)
510d85821dfSSagar Jain       return nullptr;
511a75657d6SMin-Yih Hsu     return bEntry.create<UndefOp>(UnknownLoc::get(context), type);
512d85821dfSSagar Jain   }
51300fcf9e9SMin-Yih Hsu 
51400fcf9e9SMin-Yih Hsu   if (isa<llvm::ConstantAggregate>(c) || isa<llvm::ConstantAggregateZero>(c)) {
51500fcf9e9SMin-Yih Hsu     unsigned numElements = c->getNumOperands();
51600fcf9e9SMin-Yih Hsu     std::function<llvm::Constant *(unsigned)> getElement =
51700fcf9e9SMin-Yih Hsu         [&](unsigned index) -> llvm::Constant * {
51800fcf9e9SMin-Yih Hsu       return c->getAggregateElement(index);
51900fcf9e9SMin-Yih Hsu     };
52000fcf9e9SMin-Yih Hsu     // llvm::ConstantAggregateZero doesn't take any operand
52100fcf9e9SMin-Yih Hsu     // so its getNumOperands is always zero.
52200fcf9e9SMin-Yih Hsu     if (auto *caz = dyn_cast<llvm::ConstantAggregateZero>(c)) {
52300fcf9e9SMin-Yih Hsu       numElements = caz->getElementCount().getFixedValue();
52400fcf9e9SMin-Yih Hsu       // We want to capture the pointer rather than reference
52500fcf9e9SMin-Yih Hsu       // to the pointer since the latter will become dangling upon
52600fcf9e9SMin-Yih Hsu       // exiting the scope.
52700fcf9e9SMin-Yih Hsu       getElement = [=](unsigned index) -> llvm::Constant * {
52800fcf9e9SMin-Yih Hsu         return caz->getElementValue(index);
52900fcf9e9SMin-Yih Hsu       };
53000fcf9e9SMin-Yih Hsu     }
53100fcf9e9SMin-Yih Hsu 
53200fcf9e9SMin-Yih Hsu     // Generate a llvm.undef as the root value first.
53300fcf9e9SMin-Yih Hsu     Type rootType = processType(c->getType());
53400fcf9e9SMin-Yih Hsu     if (!rootType)
53500fcf9e9SMin-Yih Hsu       return nullptr;
536dcdd5d31SMin-Yih Hsu     bool useInsertValue = rootType.isa<LLVMArrayType, LLVMStructType>();
537dcdd5d31SMin-Yih Hsu     assert((useInsertValue || LLVM::isCompatibleVectorType(rootType)) &&
538dcdd5d31SMin-Yih Hsu            "unrecognized aggregate type");
53900fcf9e9SMin-Yih Hsu     Value root = bEntry.create<UndefOp>(unknownLoc, rootType);
54000fcf9e9SMin-Yih Hsu     for (unsigned i = 0; i < numElements; ++i) {
54100fcf9e9SMin-Yih Hsu       llvm::Constant *element = getElement(i);
54200fcf9e9SMin-Yih Hsu       Value elementValue = processConstant(element);
54300fcf9e9SMin-Yih Hsu       if (!elementValue)
54400fcf9e9SMin-Yih Hsu         return nullptr;
545dcdd5d31SMin-Yih Hsu       if (useInsertValue) {
54600fcf9e9SMin-Yih Hsu         ArrayAttr indexAttr = bEntry.getI32ArrayAttr({static_cast<int32_t>(i)});
54700fcf9e9SMin-Yih Hsu         root = bEntry.create<InsertValueOp>(UnknownLoc::get(context), rootType,
54800fcf9e9SMin-Yih Hsu                                             root, elementValue, indexAttr);
549dcdd5d31SMin-Yih Hsu       } else {
550dcdd5d31SMin-Yih Hsu         Attribute indexAttr = bEntry.getI32IntegerAttr(static_cast<int32_t>(i));
551dcdd5d31SMin-Yih Hsu         Value indexValue = bEntry.create<ConstantOp>(
552dcdd5d31SMin-Yih Hsu             unknownLoc, bEntry.getI32Type(), indexAttr);
553dcdd5d31SMin-Yih Hsu         if (!indexValue)
554dcdd5d31SMin-Yih Hsu           return nullptr;
555dcdd5d31SMin-Yih Hsu         root = bEntry.create<InsertElementOp>(
556dcdd5d31SMin-Yih Hsu             UnknownLoc::get(context), rootType, root, elementValue, indexValue);
557dcdd5d31SMin-Yih Hsu       }
55800fcf9e9SMin-Yih Hsu     }
55900fcf9e9SMin-Yih Hsu     return root;
56000fcf9e9SMin-Yih Hsu   }
56100fcf9e9SMin-Yih Hsu 
5626b534ecbSJames Molloy   emitError(unknownLoc) << "unhandled constant: " << diag(*c);
5636b534ecbSJames Molloy   return nullptr;
5646b534ecbSJames Molloy }
5656b534ecbSJames Molloy 
processValue(llvm::Value * value)566e62a6956SRiver Riddle Value Importer::processValue(llvm::Value *value) {
5676b534ecbSJames Molloy   auto it = instMap.find(value);
5686b534ecbSJames Molloy   if (it != instMap.end())
5696b534ecbSJames Molloy     return it->second;
5706b534ecbSJames Molloy 
5716b534ecbSJames Molloy   // We don't expect to see instructions in dominator order. If we haven't seen
5726b534ecbSJames Molloy   // this instruction yet, create an unknown op and remap it later.
5736b534ecbSJames Molloy   if (isa<llvm::Instruction>(value)) {
574c69c9e0fSAlex Zinenko     Type type = processType(value->getType());
57584c3f05cSAlex Zinenko     if (!type)
57684c3f05cSAlex Zinenko       return nullptr;
57714ecafd0SChia-hung Duan     unknownInstMap[value] =
57814ecafd0SChia-hung Duan         b.create(UnknownLoc::get(context), b.getStringAttr("llvm.unknown"),
57914ecafd0SChia-hung Duan                  /*operands=*/{}, type);
5806b534ecbSJames Molloy     return unknownInstMap[value]->getResult(0);
5816b534ecbSJames Molloy   }
5826b534ecbSJames Molloy 
5836b534ecbSJames Molloy   if (auto *c = dyn_cast<llvm::Constant>(value))
5846b534ecbSJames Molloy     return processConstant(c);
5856b534ecbSJames Molloy 
5866b534ecbSJames Molloy   emitError(unknownLoc) << "unhandled value: " << diag(*value);
5876b534ecbSJames Molloy   return nullptr;
5886b534ecbSJames Molloy }
5896b534ecbSJames Molloy 
59067bdda63SRiver Riddle /// Return the MLIR OperationName for the given LLVM opcode.
lookupOperationNameFromOpcode(unsigned opcode)59167bdda63SRiver Riddle static StringRef lookupOperationNameFromOpcode(unsigned opcode) {
5926b534ecbSJames Molloy // Maps from LLVM opcode to MLIR OperationName. This is deliberately ordered
5936b534ecbSJames Molloy // as in llvm/IR/Instructions.def to aid comprehension and spot missing
5946b534ecbSJames Molloy // instructions.
5956b534ecbSJames Molloy #define INST(llvm_n, mlir_n)                                                   \
5966b534ecbSJames Molloy   { llvm::Instruction::llvm_n, LLVM::mlir_n##Op::getOperationName() }
5976b534ecbSJames Molloy   static const DenseMap<unsigned, StringRef> opcMap = {
5983b91657cSMin-Yih Hsu       // clang-format off
5993b91657cSMin-Yih Hsu       INST(Ret, Return),
6006b534ecbSJames Molloy       // Br is handled specially.
601857eb4a1SMin-Yih Hsu       // Switch is handled specially.
6026b534ecbSJames Molloy       // FIXME: indirectbr
6033b91657cSMin-Yih Hsu       // Invoke is handled specially.
604ff77397fSShraiysh Vaishay       INST(Resume, Resume),
6053b91657cSMin-Yih Hsu       INST(Unreachable, Unreachable),
6066b534ecbSJames Molloy       // FIXME: cleanupret
6076b534ecbSJames Molloy       // FIXME: catchret
6086b534ecbSJames Molloy       // FIXME: catchswitch
6096b534ecbSJames Molloy       // FIXME: callbr
6103b91657cSMin-Yih Hsu       INST(FNeg, FNeg),
6113b91657cSMin-Yih Hsu       INST(Add, Add),
6123b91657cSMin-Yih Hsu       INST(FAdd, FAdd),
6133b91657cSMin-Yih Hsu       INST(Sub, Sub),
6143b91657cSMin-Yih Hsu       INST(FSub, FSub),
6153b91657cSMin-Yih Hsu       INST(Mul, Mul),
6163b91657cSMin-Yih Hsu       INST(FMul, FMul),
6173b91657cSMin-Yih Hsu       INST(UDiv, UDiv),
6183b91657cSMin-Yih Hsu       INST(SDiv, SDiv),
6193b91657cSMin-Yih Hsu       INST(FDiv, FDiv),
6203b91657cSMin-Yih Hsu       INST(URem, URem),
6213b91657cSMin-Yih Hsu       INST(SRem, SRem),
6223b91657cSMin-Yih Hsu       INST(FRem, FRem),
6233b91657cSMin-Yih Hsu       INST(Shl, Shl),
6243b91657cSMin-Yih Hsu       INST(LShr, LShr),
6253b91657cSMin-Yih Hsu       INST(AShr, AShr),
6263b91657cSMin-Yih Hsu       INST(And, And),
6273b91657cSMin-Yih Hsu       INST(Or, Or),
6283b91657cSMin-Yih Hsu       INST(Xor, XOr),
6293b91657cSMin-Yih Hsu       INST(ExtractElement, ExtractElement),
6303b91657cSMin-Yih Hsu       INST(InsertElement, InsertElement),
6313b91657cSMin-Yih Hsu       // ShuffleVector is handled specially.
6323b91657cSMin-Yih Hsu       // ExtractValue is handled specially.
6333b91657cSMin-Yih Hsu       // InsertValue is handled specially.
6343b91657cSMin-Yih Hsu       INST(Alloca, Alloca),
6353b91657cSMin-Yih Hsu       INST(Load, Load),
6366b534ecbSJames Molloy       INST(Store, Store),
6373b91657cSMin-Yih Hsu       INST(Fence, Fence),
6386b534ecbSJames Molloy       // FIXME: atomiccmpxchg
6396b534ecbSJames Molloy       // FIXME: atomicrmw
6403b91657cSMin-Yih Hsu       // Getelementptr is handled specially.
6413b91657cSMin-Yih Hsu       INST(Trunc, Trunc),
6423b91657cSMin-Yih Hsu       INST(ZExt, ZExt),
6433b91657cSMin-Yih Hsu       INST(SExt, SExt),
6443b91657cSMin-Yih Hsu       INST(FPToUI, FPToUI),
6453b91657cSMin-Yih Hsu       INST(FPToSI, FPToSI),
6463b91657cSMin-Yih Hsu       INST(UIToFP, UIToFP),
6473b91657cSMin-Yih Hsu       INST(SIToFP, SIToFP),
6483b91657cSMin-Yih Hsu       INST(FPTrunc, FPTrunc),
6493b91657cSMin-Yih Hsu       INST(FPExt, FPExt),
6503b91657cSMin-Yih Hsu       INST(PtrToInt, PtrToInt),
6513b91657cSMin-Yih Hsu       INST(IntToPtr, IntToPtr),
6523b91657cSMin-Yih Hsu       INST(BitCast, Bitcast),
6533b91657cSMin-Yih Hsu       INST(AddrSpaceCast, AddrSpaceCast),
6546b534ecbSJames Molloy       // ICmp is handled specially.
655e927a336SMin-Yih Hsu       // FCmp is handled specially.
6566b534ecbSJames Molloy       // PHI is handled specially.
6573b91657cSMin-Yih Hsu       INST(Select, Select),
6583b91657cSMin-Yih Hsu       INST(Freeze, Freeze),
6593b91657cSMin-Yih Hsu       INST(Call, Call),
6606b534ecbSJames Molloy       // FIXME: vaarg
6616b534ecbSJames Molloy       // FIXME: landingpad
6623b91657cSMin-Yih Hsu       // FIXME: catchpad
6633b91657cSMin-Yih Hsu       // FIXME: cleanuppad
6643b91657cSMin-Yih Hsu       // clang-format on
6656b534ecbSJames Molloy   };
6666b534ecbSJames Molloy #undef INST
6676b534ecbSJames Molloy 
66867bdda63SRiver Riddle   return opcMap.lookup(opcode);
66967bdda63SRiver Riddle }
67067bdda63SRiver Riddle 
67142c17073Sjacquesguan /// Return the MLIR OperationName for the given LLVM intrinsic ID.
lookupOperationNameFromIntrinsicID(unsigned id)67242c17073Sjacquesguan static StringRef lookupOperationNameFromIntrinsicID(unsigned id) {
67342c17073Sjacquesguan   // Maps from LLVM intrinsic ID to MLIR OperationName.
67442c17073Sjacquesguan   static const DenseMap<unsigned, StringRef> intrMap = {
67542c17073Sjacquesguan #include "mlir/Dialect/LLVMIR/LLVMIntrinsicToLLVMIROpPairs.inc"
67642c17073Sjacquesguan   };
67742c17073Sjacquesguan   return intrMap.lookup(id);
67842c17073Sjacquesguan }
67942c17073Sjacquesguan 
getICmpPredicate(llvm::CmpInst::Predicate p)6806b534ecbSJames Molloy static ICmpPredicate getICmpPredicate(llvm::CmpInst::Predicate p) {
6816b534ecbSJames Molloy   switch (p) {
6826b534ecbSJames Molloy   default:
6836b534ecbSJames Molloy     llvm_unreachable("incorrect comparison predicate");
6846b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_EQ:
6856b534ecbSJames Molloy     return LLVM::ICmpPredicate::eq;
6866b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_NE:
6876b534ecbSJames Molloy     return LLVM::ICmpPredicate::ne;
6886b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_SLT:
6896b534ecbSJames Molloy     return LLVM::ICmpPredicate::slt;
6906b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_SLE:
6916b534ecbSJames Molloy     return LLVM::ICmpPredicate::sle;
6926b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_SGT:
6936b534ecbSJames Molloy     return LLVM::ICmpPredicate::sgt;
6946b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_SGE:
6956b534ecbSJames Molloy     return LLVM::ICmpPredicate::sge;
6966b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_ULT:
6976b534ecbSJames Molloy     return LLVM::ICmpPredicate::ult;
6986b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_ULE:
6996b534ecbSJames Molloy     return LLVM::ICmpPredicate::ule;
7006b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_UGT:
7016b534ecbSJames Molloy     return LLVM::ICmpPredicate::ugt;
7026b534ecbSJames Molloy   case llvm::CmpInst::Predicate::ICMP_UGE:
7036b534ecbSJames Molloy     return LLVM::ICmpPredicate::uge;
7046b534ecbSJames Molloy   }
705e927a336SMin-Yih Hsu   llvm_unreachable("incorrect integer comparison predicate");
706e927a336SMin-Yih Hsu }
707e927a336SMin-Yih Hsu 
getFCmpPredicate(llvm::CmpInst::Predicate p)708e927a336SMin-Yih Hsu static FCmpPredicate getFCmpPredicate(llvm::CmpInst::Predicate p) {
709e927a336SMin-Yih Hsu   switch (p) {
710e927a336SMin-Yih Hsu   default:
7116b534ecbSJames Molloy     llvm_unreachable("incorrect comparison predicate");
712e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_FALSE:
713e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::_false;
714e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_TRUE:
715e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::_true;
716e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_OEQ:
717e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::oeq;
718e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_ONE:
719e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::one;
720e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_OLT:
721e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::olt;
722e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_OLE:
723e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::ole;
724e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_OGT:
725e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::ogt;
726e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_OGE:
727e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::oge;
728e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_ORD:
729e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::ord;
730e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_ULT:
731e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::ult;
732e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_ULE:
733e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::ule;
734e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_UGT:
735e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::ugt;
736e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_UGE:
737e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::uge;
738e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_UNO:
739e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::uno;
740e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_UEQ:
741e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::ueq;
742e927a336SMin-Yih Hsu   case llvm::CmpInst::Predicate::FCMP_UNE:
743e927a336SMin-Yih Hsu     return LLVM::FCmpPredicate::une;
744e927a336SMin-Yih Hsu   }
745e927a336SMin-Yih Hsu   llvm_unreachable("incorrect floating point comparison predicate");
7466b534ecbSJames Molloy }
7476b534ecbSJames Molloy 
getLLVMAtomicOrdering(llvm::AtomicOrdering ordering)74876cf1403SSagar Jain static AtomicOrdering getLLVMAtomicOrdering(llvm::AtomicOrdering ordering) {
74976cf1403SSagar Jain   switch (ordering) {
75076cf1403SSagar Jain   case llvm::AtomicOrdering::NotAtomic:
75176cf1403SSagar Jain     return LLVM::AtomicOrdering::not_atomic;
75276cf1403SSagar Jain   case llvm::AtomicOrdering::Unordered:
75376cf1403SSagar Jain     return LLVM::AtomicOrdering::unordered;
75476cf1403SSagar Jain   case llvm::AtomicOrdering::Monotonic:
75576cf1403SSagar Jain     return LLVM::AtomicOrdering::monotonic;
75676cf1403SSagar Jain   case llvm::AtomicOrdering::Acquire:
75776cf1403SSagar Jain     return LLVM::AtomicOrdering::acquire;
75876cf1403SSagar Jain   case llvm::AtomicOrdering::Release:
75976cf1403SSagar Jain     return LLVM::AtomicOrdering::release;
76076cf1403SSagar Jain   case llvm::AtomicOrdering::AcquireRelease:
76176cf1403SSagar Jain     return LLVM::AtomicOrdering::acq_rel;
76276cf1403SSagar Jain   case llvm::AtomicOrdering::SequentiallyConsistent:
76376cf1403SSagar Jain     return LLVM::AtomicOrdering::seq_cst;
76476cf1403SSagar Jain   }
76576cf1403SSagar Jain   llvm_unreachable("incorrect atomic ordering");
76676cf1403SSagar Jain }
76776cf1403SSagar Jain 
7686b534ecbSJames Molloy // `br` branches to `target`. Return the branch arguments to `br`, in the
7696b534ecbSJames Molloy // same order of the PHIs in `target`.
77084c3f05cSAlex Zinenko LogicalResult
processBranchArgs(llvm::Instruction * br,llvm::BasicBlock * target,SmallVectorImpl<Value> & blockArguments)771d242aa24SShraiysh Vaishay Importer::processBranchArgs(llvm::Instruction *br, llvm::BasicBlock *target,
77284c3f05cSAlex Zinenko                             SmallVectorImpl<Value> &blockArguments) {
7736b534ecbSJames Molloy   for (auto inst = target->begin(); isa<llvm::PHINode>(inst); ++inst) {
77402b6fb21SMehdi Amini     auto *pn = cast<llvm::PHINode>(&*inst);
77502b6fb21SMehdi Amini     Value value = processValue(pn->getIncomingValueForBlock(br->getParent()));
77684c3f05cSAlex Zinenko     if (!value)
77784c3f05cSAlex Zinenko       return failure();
77884c3f05cSAlex Zinenko     blockArguments.push_back(value);
7796b534ecbSJames Molloy   }
78084c3f05cSAlex Zinenko   return success();
7816b534ecbSJames Molloy }
7826b534ecbSJames Molloy 
processInstruction(llvm::Instruction * inst)7836b534ecbSJames Molloy LogicalResult Importer::processInstruction(llvm::Instruction *inst) {
7846b534ecbSJames Molloy   // FIXME: Support uses of SubtargetData. Currently inbounds GEPs, fast-math
7856b534ecbSJames Molloy   // flags and call / operand attributes are not supported.
7866b534ecbSJames Molloy   Location loc = processDebugLoc(inst->getDebugLoc(), inst);
787794c4218SMin-Yih Hsu   assert(!instMap.count(inst) &&
788794c4218SMin-Yih Hsu          "processInstruction must be called only once per instruction!");
7896b534ecbSJames Molloy   switch (inst->getOpcode()) {
7906b534ecbSJames Molloy   default:
7916b534ecbSJames Molloy     return emitError(loc) << "unknown instruction: " << diag(*inst);
7926b534ecbSJames Molloy   case llvm::Instruction::Add:
7936b534ecbSJames Molloy   case llvm::Instruction::FAdd:
7946b534ecbSJames Molloy   case llvm::Instruction::Sub:
7956b534ecbSJames Molloy   case llvm::Instruction::FSub:
7966b534ecbSJames Molloy   case llvm::Instruction::Mul:
7976b534ecbSJames Molloy   case llvm::Instruction::FMul:
7986b534ecbSJames Molloy   case llvm::Instruction::UDiv:
7996b534ecbSJames Molloy   case llvm::Instruction::SDiv:
8006b534ecbSJames Molloy   case llvm::Instruction::FDiv:
8016b534ecbSJames Molloy   case llvm::Instruction::URem:
8026b534ecbSJames Molloy   case llvm::Instruction::SRem:
8036b534ecbSJames Molloy   case llvm::Instruction::FRem:
8046b534ecbSJames Molloy   case llvm::Instruction::Shl:
8056b534ecbSJames Molloy   case llvm::Instruction::LShr:
8066b534ecbSJames Molloy   case llvm::Instruction::AShr:
8076b534ecbSJames Molloy   case llvm::Instruction::And:
8086b534ecbSJames Molloy   case llvm::Instruction::Or:
8096b534ecbSJames Molloy   case llvm::Instruction::Xor:
8106b534ecbSJames Molloy   case llvm::Instruction::Load:
8116b534ecbSJames Molloy   case llvm::Instruction::Store:
8126b534ecbSJames Molloy   case llvm::Instruction::Ret:
813ff77397fSShraiysh Vaishay   case llvm::Instruction::Resume:
8146b534ecbSJames Molloy   case llvm::Instruction::Trunc:
8156b534ecbSJames Molloy   case llvm::Instruction::ZExt:
8166b534ecbSJames Molloy   case llvm::Instruction::SExt:
8176b534ecbSJames Molloy   case llvm::Instruction::FPToUI:
8186b534ecbSJames Molloy   case llvm::Instruction::FPToSI:
8196b534ecbSJames Molloy   case llvm::Instruction::UIToFP:
8206b534ecbSJames Molloy   case llvm::Instruction::SIToFP:
8216b534ecbSJames Molloy   case llvm::Instruction::FPTrunc:
8226b534ecbSJames Molloy   case llvm::Instruction::FPExt:
8236b534ecbSJames Molloy   case llvm::Instruction::PtrToInt:
8246b534ecbSJames Molloy   case llvm::Instruction::IntToPtr:
8256b534ecbSJames Molloy   case llvm::Instruction::AddrSpaceCast:
826d85821dfSSagar Jain   case llvm::Instruction::Freeze:
8279b519f41Sjacquesguan   case llvm::Instruction::BitCast:
8289b519f41Sjacquesguan   case llvm::Instruction::ExtractElement:
8293b91657cSMin-Yih Hsu   case llvm::Instruction::InsertElement:
8303b91657cSMin-Yih Hsu   case llvm::Instruction::Select:
8313b91657cSMin-Yih Hsu   case llvm::Instruction::FNeg:
8323b91657cSMin-Yih Hsu   case llvm::Instruction::Unreachable: {
83367bdda63SRiver Riddle     OperationState state(loc, lookupOperationNameFromOpcode(inst->getOpcode()));
834e62a6956SRiver Riddle     SmallVector<Value, 4> ops;
8356b534ecbSJames Molloy     ops.reserve(inst->getNumOperands());
83684c3f05cSAlex Zinenko     for (auto *op : inst->operand_values()) {
83784c3f05cSAlex Zinenko       Value value = processValue(op);
83884c3f05cSAlex Zinenko       if (!value)
83984c3f05cSAlex Zinenko         return failure();
84084c3f05cSAlex Zinenko       ops.push_back(value);
84184c3f05cSAlex Zinenko     }
8426b534ecbSJames Molloy     state.addOperands(ops);
84384c3f05cSAlex Zinenko     if (!inst->getType()->isVoidTy()) {
844c69c9e0fSAlex Zinenko       Type type = processType(inst->getType());
84584c3f05cSAlex Zinenko       if (!type)
84684c3f05cSAlex Zinenko         return failure();
84784c3f05cSAlex Zinenko       state.addTypes(type);
84884c3f05cSAlex Zinenko     }
84914ecafd0SChia-hung Duan     Operation *op = b.create(state);
8506b534ecbSJames Molloy     if (!inst->getType()->isVoidTy())
851794c4218SMin-Yih Hsu       instMap[inst] = op->getResult(0);
8526b534ecbSJames Molloy     return success();
8536b534ecbSJames Molloy   }
8546c5ae8e9SAlex Zinenko   case llvm::Instruction::Alloca: {
8556c5ae8e9SAlex Zinenko     Value size = processValue(inst->getOperand(0));
8566c5ae8e9SAlex Zinenko     if (!size)
8576c5ae8e9SAlex Zinenko       return failure();
8586c5ae8e9SAlex Zinenko 
8596c5ae8e9SAlex Zinenko     auto *allocaInst = cast<llvm::AllocaInst>(inst);
860794c4218SMin-Yih Hsu     instMap[inst] =
861794c4218SMin-Yih Hsu         b.create<AllocaOp>(loc, processType(inst->getType()),
8626c5ae8e9SAlex Zinenko                            processType(allocaInst->getAllocatedType()), size,
8636c5ae8e9SAlex Zinenko                            allocaInst->getAlign().value());
8646c5ae8e9SAlex Zinenko     return success();
8656c5ae8e9SAlex Zinenko   }
8666b534ecbSJames Molloy   case llvm::Instruction::ICmp: {
86784c3f05cSAlex Zinenko     Value lhs = processValue(inst->getOperand(0));
86884c3f05cSAlex Zinenko     Value rhs = processValue(inst->getOperand(1));
86984c3f05cSAlex Zinenko     if (!lhs || !rhs)
87084c3f05cSAlex Zinenko       return failure();
871794c4218SMin-Yih Hsu     instMap[inst] = b.create<ICmpOp>(
87284c3f05cSAlex Zinenko         loc, getICmpPredicate(cast<llvm::ICmpInst>(inst)->getPredicate()), lhs,
87384c3f05cSAlex Zinenko         rhs);
8746b534ecbSJames Molloy     return success();
8756b534ecbSJames Molloy   }
876e927a336SMin-Yih Hsu   case llvm::Instruction::FCmp: {
877e927a336SMin-Yih Hsu     Value lhs = processValue(inst->getOperand(0));
878e927a336SMin-Yih Hsu     Value rhs = processValue(inst->getOperand(1));
879e927a336SMin-Yih Hsu     if (!lhs || !rhs)
880e927a336SMin-Yih Hsu       return failure();
881e927a336SMin-Yih Hsu     instMap[inst] = b.create<FCmpOp>(
882e927a336SMin-Yih Hsu         loc, b.getI1Type(),
883e927a336SMin-Yih Hsu         getFCmpPredicate(cast<llvm::FCmpInst>(inst)->getPredicate()), lhs, rhs);
884e927a336SMin-Yih Hsu     return success();
885e927a336SMin-Yih Hsu   }
8866b534ecbSJames Molloy   case llvm::Instruction::Br: {
8876b534ecbSJames Molloy     auto *brInst = cast<llvm::BranchInst>(inst);
8886b534ecbSJames Molloy     OperationState state(loc,
8896b534ecbSJames Molloy                          brInst->isConditional() ? "llvm.cond_br" : "llvm.br");
89084c3f05cSAlex Zinenko     if (brInst->isConditional()) {
89184c3f05cSAlex Zinenko       Value condition = processValue(brInst->getCondition());
89284c3f05cSAlex Zinenko       if (!condition)
89384c3f05cSAlex Zinenko         return failure();
894cb177712SRiver Riddle       state.addOperands(condition);
89584c3f05cSAlex Zinenko     }
896cb177712SRiver Riddle 
897cb177712SRiver Riddle     std::array<int32_t, 3> operandSegmentSizes = {1, 0, 0};
898cb177712SRiver Riddle     for (int i : llvm::seq<int>(0, brInst->getNumSuccessors())) {
899cb177712SRiver Riddle       auto *succ = brInst->getSuccessor(i);
90084c3f05cSAlex Zinenko       SmallVector<Value, 4> blockArguments;
90184c3f05cSAlex Zinenko       if (failed(processBranchArgs(brInst, succ, blockArguments)))
90284c3f05cSAlex Zinenko         return failure();
903cb177712SRiver Riddle       state.addSuccessors(blocks[succ]);
904cb177712SRiver Riddle       state.addOperands(blockArguments);
905cb177712SRiver Riddle       operandSegmentSizes[i + 1] = blockArguments.size();
90684c3f05cSAlex Zinenko     }
907cb177712SRiver Riddle 
908cb177712SRiver Riddle     if (brInst->isConditional()) {
909cb177712SRiver Riddle       state.addAttribute(LLVM::CondBrOp::getOperandSegmentSizeAttr(),
910cb177712SRiver Riddle                          b.getI32VectorAttr(operandSegmentSizes));
911cb177712SRiver Riddle     }
912cb177712SRiver Riddle 
91314ecafd0SChia-hung Duan     b.create(state);
9146b534ecbSJames Molloy     return success();
9156b534ecbSJames Molloy   }
916857eb4a1SMin-Yih Hsu   case llvm::Instruction::Switch: {
917857eb4a1SMin-Yih Hsu     auto *swInst = cast<llvm::SwitchInst>(inst);
918857eb4a1SMin-Yih Hsu     // Process the condition value.
919857eb4a1SMin-Yih Hsu     Value condition = processValue(swInst->getCondition());
920857eb4a1SMin-Yih Hsu     if (!condition)
921857eb4a1SMin-Yih Hsu       return failure();
922857eb4a1SMin-Yih Hsu 
923857eb4a1SMin-Yih Hsu     SmallVector<Value> defaultBlockArgs;
924857eb4a1SMin-Yih Hsu     // Process the default case.
925857eb4a1SMin-Yih Hsu     llvm::BasicBlock *defaultBB = swInst->getDefaultDest();
926857eb4a1SMin-Yih Hsu     if (failed(processBranchArgs(swInst, defaultBB, defaultBlockArgs)))
927857eb4a1SMin-Yih Hsu       return failure();
928857eb4a1SMin-Yih Hsu 
929857eb4a1SMin-Yih Hsu     // Process the cases.
930857eb4a1SMin-Yih Hsu     unsigned numCases = swInst->getNumCases();
931857eb4a1SMin-Yih Hsu     SmallVector<SmallVector<Value>> caseOperands(numCases);
932857eb4a1SMin-Yih Hsu     SmallVector<ValueRange> caseOperandRefs(numCases);
933857eb4a1SMin-Yih Hsu     SmallVector<int32_t> caseValues(numCases);
934857eb4a1SMin-Yih Hsu     SmallVector<Block *> caseBlocks(numCases);
935857eb4a1SMin-Yih Hsu     for (const auto &en : llvm::enumerate(swInst->cases())) {
936857eb4a1SMin-Yih Hsu       const llvm::SwitchInst::CaseHandle &caseHandle = en.value();
937857eb4a1SMin-Yih Hsu       unsigned i = en.index();
938857eb4a1SMin-Yih Hsu       llvm::BasicBlock *succBB = caseHandle.getCaseSuccessor();
939857eb4a1SMin-Yih Hsu       if (failed(processBranchArgs(swInst, succBB, caseOperands[i])))
940857eb4a1SMin-Yih Hsu         return failure();
941857eb4a1SMin-Yih Hsu       caseOperandRefs[i] = caseOperands[i];
942857eb4a1SMin-Yih Hsu       caseValues[i] = caseHandle.getCaseValue()->getSExtValue();
943857eb4a1SMin-Yih Hsu       caseBlocks[i] = blocks[succBB];
944857eb4a1SMin-Yih Hsu     }
945857eb4a1SMin-Yih Hsu 
946857eb4a1SMin-Yih Hsu     b.create<SwitchOp>(loc, condition, blocks[defaultBB], defaultBlockArgs,
947857eb4a1SMin-Yih Hsu                        caseValues, caseBlocks, caseOperandRefs);
948857eb4a1SMin-Yih Hsu     return success();
949857eb4a1SMin-Yih Hsu   }
9506b534ecbSJames Molloy   case llvm::Instruction::PHI: {
951c69c9e0fSAlex Zinenko     Type type = processType(inst->getType());
95284c3f05cSAlex Zinenko     if (!type)
95384c3f05cSAlex Zinenko       return failure();
954794c4218SMin-Yih Hsu     instMap[inst] = b.getInsertionBlock()->addArgument(
955e084679fSRiver Riddle         type, processDebugLoc(inst->getDebugLoc(), inst));
9566b534ecbSJames Molloy     return success();
9576b534ecbSJames Molloy   }
9586b534ecbSJames Molloy   case llvm::Instruction::Call: {
9596b534ecbSJames Molloy     llvm::CallInst *ci = cast<llvm::CallInst>(inst);
960e62a6956SRiver Riddle     SmallVector<Value, 4> ops;
9616b534ecbSJames Molloy     ops.reserve(inst->getNumOperands());
96280e39366SKazu Hirata     for (auto &op : ci->args()) {
96384c3f05cSAlex Zinenko       Value arg = processValue(op.get());
96484c3f05cSAlex Zinenko       if (!arg)
96584c3f05cSAlex Zinenko         return failure();
96684c3f05cSAlex Zinenko       ops.push_back(arg);
96784c3f05cSAlex Zinenko     }
9686b534ecbSJames Molloy 
9696b534ecbSJames Molloy     SmallVector<Type, 2> tys;
97084c3f05cSAlex Zinenko     if (!ci->getType()->isVoidTy()) {
971c69c9e0fSAlex Zinenko       Type type = processType(inst->getType());
97284c3f05cSAlex Zinenko       if (!type)
97384c3f05cSAlex Zinenko         return failure();
97484c3f05cSAlex Zinenko       tys.push_back(type);
97584c3f05cSAlex Zinenko     }
9766b534ecbSJames Molloy     Operation *op;
9776b534ecbSJames Molloy     if (llvm::Function *callee = ci->getCalledFunction()) {
97842c17073Sjacquesguan       // For all intrinsics, try to generate to the corresponding op.
97942c17073Sjacquesguan       if (callee->isIntrinsic()) {
98042c17073Sjacquesguan         auto id = callee->getIntrinsicID();
98142c17073Sjacquesguan         StringRef opName = lookupOperationNameFromIntrinsicID(id);
98242c17073Sjacquesguan         if (!opName.empty()) {
98342c17073Sjacquesguan           OperationState state(loc, opName);
98442c17073Sjacquesguan           state.addOperands(ops);
98542c17073Sjacquesguan           state.addTypes(tys);
98642c17073Sjacquesguan           Operation *op = b.create(state);
98742c17073Sjacquesguan           if (!inst->getType()->isVoidTy())
98842c17073Sjacquesguan             instMap[inst] = op->getResult(0);
98942c17073Sjacquesguan           return success();
99042c17073Sjacquesguan         }
99142c17073Sjacquesguan       }
992faf1c224SChris Lattner       op = b.create<CallOp>(
993faf1c224SChris Lattner           loc, tys, SymbolRefAttr::get(b.getContext(), callee->getName()), ops);
9946b534ecbSJames Molloy     } else {
995a58b62b4SCraig Topper       Value calledValue = processValue(ci->getCalledOperand());
99684c3f05cSAlex Zinenko       if (!calledValue)
99784c3f05cSAlex Zinenko         return failure();
99884c3f05cSAlex Zinenko       ops.insert(ops.begin(), calledValue);
9990d988da6SRahul Joshi       op = b.create<CallOp>(loc, tys, ops);
10006b534ecbSJames Molloy     }
10016b534ecbSJames Molloy     if (!ci->getType()->isVoidTy())
1002794c4218SMin-Yih Hsu       instMap[inst] = op->getResult(0);
10036b534ecbSJames Molloy     return success();
10046b534ecbSJames Molloy   }
1005d242aa24SShraiysh Vaishay   case llvm::Instruction::LandingPad: {
1006d242aa24SShraiysh Vaishay     llvm::LandingPadInst *lpi = cast<llvm::LandingPadInst>(inst);
1007d242aa24SShraiysh Vaishay     SmallVector<Value, 4> ops;
1008d242aa24SShraiysh Vaishay 
1009d242aa24SShraiysh Vaishay     for (unsigned i = 0, ie = lpi->getNumClauses(); i < ie; i++)
1010d242aa24SShraiysh Vaishay       ops.push_back(processConstant(lpi->getClause(i)));
1011d242aa24SShraiysh Vaishay 
1012ff77397fSShraiysh Vaishay     Type ty = processType(lpi->getType());
1013ff77397fSShraiysh Vaishay     if (!ty)
1014ff77397fSShraiysh Vaishay       return failure();
1015ff77397fSShraiysh Vaishay 
1016794c4218SMin-Yih Hsu     instMap[inst] = b.create<LandingpadOp>(loc, ty, lpi->isCleanup(), ops);
1017d242aa24SShraiysh Vaishay     return success();
1018d242aa24SShraiysh Vaishay   }
1019d242aa24SShraiysh Vaishay   case llvm::Instruction::Invoke: {
1020d242aa24SShraiysh Vaishay     llvm::InvokeInst *ii = cast<llvm::InvokeInst>(inst);
1021d242aa24SShraiysh Vaishay 
1022d242aa24SShraiysh Vaishay     SmallVector<Type, 2> tys;
1023d242aa24SShraiysh Vaishay     if (!ii->getType()->isVoidTy())
1024d242aa24SShraiysh Vaishay       tys.push_back(processType(inst->getType()));
1025d242aa24SShraiysh Vaishay 
1026d242aa24SShraiysh Vaishay     SmallVector<Value, 4> ops;
1027d242aa24SShraiysh Vaishay     ops.reserve(inst->getNumOperands() + 1);
102880e39366SKazu Hirata     for (auto &op : ii->args())
1029d242aa24SShraiysh Vaishay       ops.push_back(processValue(op.get()));
1030d242aa24SShraiysh Vaishay 
1031d242aa24SShraiysh Vaishay     SmallVector<Value, 4> normalArgs, unwindArgs;
1032e21adfa3SRiver Riddle     (void)processBranchArgs(ii, ii->getNormalDest(), normalArgs);
1033e21adfa3SRiver Riddle     (void)processBranchArgs(ii, ii->getUnwindDest(), unwindArgs);
1034d242aa24SShraiysh Vaishay 
1035d242aa24SShraiysh Vaishay     Operation *op;
1036d242aa24SShraiysh Vaishay     if (llvm::Function *callee = ii->getCalledFunction()) {
1037faf1c224SChris Lattner       op = b.create<InvokeOp>(
1038faf1c224SChris Lattner           loc, tys, SymbolRefAttr::get(b.getContext(), callee->getName()), ops,
1039faf1c224SChris Lattner           blocks[ii->getNormalDest()], normalArgs, blocks[ii->getUnwindDest()],
1040faf1c224SChris Lattner           unwindArgs);
1041d242aa24SShraiysh Vaishay     } else {
1042a58b62b4SCraig Topper       ops.insert(ops.begin(), processValue(ii->getCalledOperand()));
1043d242aa24SShraiysh Vaishay       op = b.create<InvokeOp>(loc, tys, ops, blocks[ii->getNormalDest()],
1044d242aa24SShraiysh Vaishay                               normalArgs, blocks[ii->getUnwindDest()],
1045d242aa24SShraiysh Vaishay                               unwindArgs);
1046d242aa24SShraiysh Vaishay     }
1047d242aa24SShraiysh Vaishay 
1048d242aa24SShraiysh Vaishay     if (!ii->getType()->isVoidTy())
1049794c4218SMin-Yih Hsu       instMap[inst] = op->getResult(0);
1050d242aa24SShraiysh Vaishay     return success();
1051d242aa24SShraiysh Vaishay   }
105276cf1403SSagar Jain   case llvm::Instruction::Fence: {
105376cf1403SSagar Jain     StringRef syncscope;
105476cf1403SSagar Jain     SmallVector<StringRef, 4> ssNs;
105516b02253SAlex Zinenko     llvm::LLVMContext &llvmContext = inst->getContext();
105676cf1403SSagar Jain     llvm::FenceInst *fence = cast<llvm::FenceInst>(inst);
105776cf1403SSagar Jain     llvmContext.getSyncScopeNames(ssNs);
105876cf1403SSagar Jain     int fenceSyncScopeID = fence->getSyncScopeID();
105976cf1403SSagar Jain     for (unsigned i = 0, e = ssNs.size(); i != e; i++) {
106076cf1403SSagar Jain       if (fenceSyncScopeID == llvmContext.getOrInsertSyncScopeID(ssNs[i])) {
106176cf1403SSagar Jain         syncscope = ssNs[i];
106276cf1403SSagar Jain         break;
106376cf1403SSagar Jain       }
106476cf1403SSagar Jain     }
106576cf1403SSagar Jain     b.create<FenceOp>(loc, getLLVMAtomicOrdering(fence->getOrdering()),
106676cf1403SSagar Jain                       syncscope);
106776cf1403SSagar Jain     return success();
106876cf1403SSagar Jain   }
10696b534ecbSJames Molloy   case llvm::Instruction::GetElementPtr: {
10706b534ecbSJames Molloy     // FIXME: Support inbounds GEPs.
10716b534ecbSJames Molloy     llvm::GetElementPtrInst *gep = cast<llvm::GetElementPtrInst>(inst);
10726c5ae8e9SAlex Zinenko     Value basePtr = processValue(gep->getOperand(0));
10736c5ae8e9SAlex Zinenko     Type sourceElementType = processType(gep->getSourceElementType());
10746c5ae8e9SAlex Zinenko 
10750b168a49SMin-Yih Hsu     SmallVector<Value> indices;
10760b168a49SMin-Yih Hsu     for (llvm::Value *operand : llvm::drop_begin(gep->operand_values())) {
10770b168a49SMin-Yih Hsu       indices.push_back(processValue(operand));
10780b168a49SMin-Yih Hsu       if (!indices.back())
107984c3f05cSAlex Zinenko         return failure();
108084c3f05cSAlex Zinenko     }
10810b168a49SMin-Yih Hsu     // Treat every indices as dynamic since GEPOp::build will refine those
10820b168a49SMin-Yih Hsu     // indices into static attributes later. One small downside of this
10830b168a49SMin-Yih Hsu     // approach is that many unused `llvm.mlir.constant` would be emitted
10840b168a49SMin-Yih Hsu     // at first place.
10850b168a49SMin-Yih Hsu     SmallVector<int32_t> structIndices(indices.size(),
10860b168a49SMin-Yih Hsu                                        LLVM::GEPOp::kDynamicIndex);
10876c5ae8e9SAlex Zinenko 
108884c3f05cSAlex Zinenko     Type type = processType(inst->getType());
108984c3f05cSAlex Zinenko     if (!type)
109084c3f05cSAlex Zinenko       return failure();
1091794c4218SMin-Yih Hsu     instMap[inst] = b.create<GEPOp>(loc, type, sourceElementType, basePtr,
10920b168a49SMin-Yih Hsu                                     indices, structIndices);
10936b534ecbSJames Molloy     return success();
10946b534ecbSJames Molloy   }
1095b8f52c08SMin-Yih Hsu   case llvm::Instruction::InsertValue: {
1096b8f52c08SMin-Yih Hsu     auto *ivInst = cast<llvm::InsertValueInst>(inst);
1097b8f52c08SMin-Yih Hsu     Value inserted = processValue(ivInst->getInsertedValueOperand());
1098b8f52c08SMin-Yih Hsu     if (!inserted)
1099b8f52c08SMin-Yih Hsu       return failure();
1100b8f52c08SMin-Yih Hsu     Value aggOperand = processValue(ivInst->getAggregateOperand());
1101b8f52c08SMin-Yih Hsu     if (!aggOperand)
1102b8f52c08SMin-Yih Hsu       return failure();
1103b8f52c08SMin-Yih Hsu 
1104b8f52c08SMin-Yih Hsu     SmallVector<int32_t> idxValues;
1105b8f52c08SMin-Yih Hsu     for (unsigned idx : ivInst->getIndices())
1106b8f52c08SMin-Yih Hsu       idxValues.push_back(static_cast<int32_t>(idx));
1107b8f52c08SMin-Yih Hsu     ArrayAttr indices = b.getI32ArrayAttr(idxValues);
1108b8f52c08SMin-Yih Hsu 
1109b8f52c08SMin-Yih Hsu     instMap[inst] = b.create<InsertValueOp>(loc, aggOperand, inserted, indices);
1110b8f52c08SMin-Yih Hsu     return success();
1111b8f52c08SMin-Yih Hsu   }
1112b8f52c08SMin-Yih Hsu   case llvm::Instruction::ExtractValue: {
1113b8f52c08SMin-Yih Hsu     auto *evInst = cast<llvm::ExtractValueInst>(inst);
1114b8f52c08SMin-Yih Hsu     Value aggOperand = processValue(evInst->getAggregateOperand());
1115b8f52c08SMin-Yih Hsu     if (!aggOperand)
1116b8f52c08SMin-Yih Hsu       return failure();
1117b8f52c08SMin-Yih Hsu 
1118b8f52c08SMin-Yih Hsu     Type type = processType(inst->getType());
1119b8f52c08SMin-Yih Hsu     if (!type)
1120b8f52c08SMin-Yih Hsu       return failure();
1121b8f52c08SMin-Yih Hsu 
1122b8f52c08SMin-Yih Hsu     SmallVector<int32_t> idxValues;
1123b8f52c08SMin-Yih Hsu     for (unsigned idx : evInst->getIndices())
1124b8f52c08SMin-Yih Hsu       idxValues.push_back(static_cast<int32_t>(idx));
1125b8f52c08SMin-Yih Hsu     ArrayAttr indices = b.getI32ArrayAttr(idxValues);
1126b8f52c08SMin-Yih Hsu 
1127b8f52c08SMin-Yih Hsu     instMap[inst] = b.create<ExtractValueOp>(loc, type, aggOperand, indices);
1128b8f52c08SMin-Yih Hsu     return success();
1129b8f52c08SMin-Yih Hsu   }
11303da65c4cSMin-Yih Hsu   case llvm::Instruction::ShuffleVector: {
11313da65c4cSMin-Yih Hsu     auto *svInst = cast<llvm::ShuffleVectorInst>(inst);
11323da65c4cSMin-Yih Hsu     Value vec1 = processValue(svInst->getOperand(0));
11333da65c4cSMin-Yih Hsu     if (!vec1)
11343da65c4cSMin-Yih Hsu       return failure();
11353da65c4cSMin-Yih Hsu     Value vec2 = processValue(svInst->getOperand(1));
11363da65c4cSMin-Yih Hsu     if (!vec2)
11373da65c4cSMin-Yih Hsu       return failure();
11383da65c4cSMin-Yih Hsu 
11393da65c4cSMin-Yih Hsu     ArrayAttr mask = b.getI32ArrayAttr(svInst->getShuffleMask());
11403da65c4cSMin-Yih Hsu 
11413da65c4cSMin-Yih Hsu     instMap[inst] = b.create<ShuffleVectorOp>(loc, vec1, vec2, mask);
11423da65c4cSMin-Yih Hsu     return success();
11433da65c4cSMin-Yih Hsu   }
11446b534ecbSJames Molloy   }
11456b534ecbSJames Molloy }
11466b534ecbSJames Molloy 
getPersonalityAsAttr(llvm::Function * f)1147ff77397fSShraiysh Vaishay FlatSymbolRefAttr Importer::getPersonalityAsAttr(llvm::Function *f) {
1148ff77397fSShraiysh Vaishay   if (!f->hasPersonalityFn())
1149ff77397fSShraiysh Vaishay     return nullptr;
1150ff77397fSShraiysh Vaishay 
1151ff77397fSShraiysh Vaishay   llvm::Constant *pf = f->getPersonalityFn();
1152ff77397fSShraiysh Vaishay 
1153ff77397fSShraiysh Vaishay   // If it directly has a name, we can use it.
1154ff77397fSShraiysh Vaishay   if (pf->hasName())
1155faf1c224SChris Lattner     return SymbolRefAttr::get(b.getContext(), pf->getName());
1156ff77397fSShraiysh Vaishay 
1157ff77397fSShraiysh Vaishay   // If it doesn't have a name, currently, only function pointers that are
1158ff77397fSShraiysh Vaishay   // bitcast to i8* are parsed.
115902b6fb21SMehdi Amini   if (auto *ce = dyn_cast<llvm::ConstantExpr>(pf)) {
1160ff77397fSShraiysh Vaishay     if (ce->getOpcode() == llvm::Instruction::BitCast &&
116116b02253SAlex Zinenko         ce->getType() == llvm::Type::getInt8PtrTy(f->getContext())) {
116202b6fb21SMehdi Amini       if (auto *func = dyn_cast<llvm::Function>(ce->getOperand(0)))
1163faf1c224SChris Lattner         return SymbolRefAttr::get(b.getContext(), func->getName());
1164ff77397fSShraiysh Vaishay     }
1165ff77397fSShraiysh Vaishay   }
1166ff77397fSShraiysh Vaishay   return FlatSymbolRefAttr();
1167ff77397fSShraiysh Vaishay }
1168ff77397fSShraiysh Vaishay 
processFunction(llvm::Function * f)11696b534ecbSJames Molloy LogicalResult Importer::processFunction(llvm::Function *f) {
11706b534ecbSJames Molloy   blocks.clear();
11716b534ecbSJames Molloy   instMap.clear();
11726b534ecbSJames Molloy   unknownInstMap.clear();
11736b534ecbSJames Molloy 
11748de43b92SAlex Zinenko   auto functionType =
11758de43b92SAlex Zinenko       processType(f->getFunctionType()).dyn_cast<LLVMFunctionType>();
117684c3f05cSAlex Zinenko   if (!functionType)
117784c3f05cSAlex Zinenko     return failure();
117884c3f05cSAlex Zinenko 
117942c17073Sjacquesguan   if (f->isIntrinsic()) {
118042c17073Sjacquesguan     StringRef opName = lookupOperationNameFromIntrinsicID(f->getIntrinsicID());
118142c17073Sjacquesguan     // Skip the intrinsic decleration if we could found a corresponding op.
118242c17073Sjacquesguan     if (!opName.empty())
118342c17073Sjacquesguan       return success();
118442c17073Sjacquesguan   }
118542c17073Sjacquesguan 
11860252357bSAlexander Batashev   bool dsoLocal = f->hasLocalLinkage();
11870252357bSAlexander Batashev   CConv cconv = convertCConvFromLLVM(f->getCallingConv());
11880252357bSAlexander Batashev 
11896b534ecbSJames Molloy   b.setInsertionPoint(module.getBody(), getFuncInsertPt());
11900252357bSAlexander Batashev   LLVMFuncOp fop = b.create<LLVMFuncOp>(
11910252357bSAlexander Batashev       UnknownLoc::get(context), f->getName(), functionType,
11920252357bSAlexander Batashev       convertLinkageFromLLVM(f->getLinkage()), dsoLocal, cconv);
1193ff77397fSShraiysh Vaishay 
1194ff77397fSShraiysh Vaishay   if (FlatSymbolRefAttr personality = getPersonalityAsAttr(f))
1195195730a6SRiver Riddle     fop->setAttr(b.getStringAttr("personality"), personality);
1196ff77397fSShraiysh Vaishay   else if (f->hasPersonalityFn())
1197ff77397fSShraiysh Vaishay     emitWarning(UnknownLoc::get(context),
1198ff77397fSShraiysh Vaishay                 "could not deduce personality, skipping it");
1199ff77397fSShraiysh Vaishay 
12001bf79213SMarkus Böck   if (f->hasGC())
12011bf79213SMarkus Böck     fop.setGarbageCollectorAttr(b.getStringAttr(f->getGC()));
12021bf79213SMarkus Böck 
12036b534ecbSJames Molloy   if (f->isDeclaration())
12046b534ecbSJames Molloy     return success();
12056b534ecbSJames Molloy 
12066b534ecbSJames Molloy   // Eagerly create all blocks.
12076b534ecbSJames Molloy   SmallVector<Block *, 4> blockList;
12086b534ecbSJames Molloy   for (llvm::BasicBlock &bb : *f) {
1209dde96363SJacques Pienaar     blockList.push_back(b.createBlock(&fop.getBody(), fop.getBody().end()));
12106b534ecbSJames Molloy     blocks[&bb] = blockList.back();
12116b534ecbSJames Molloy   }
12126b534ecbSJames Molloy   currentEntryBlock = blockList[0];
12136b534ecbSJames Molloy 
12146b534ecbSJames Molloy   // Add function arguments to the entry block.
1215e084679fSRiver Riddle   for (const auto &kv : llvm::enumerate(f->args())) {
1216e084679fSRiver Riddle     instMap[&kv.value()] = blockList[0]->addArgument(
1217e084679fSRiver Riddle         functionType.getParamType(kv.index()), fop.getLoc());
1218e084679fSRiver Riddle   }
12196b534ecbSJames Molloy 
12206b534ecbSJames Molloy   for (auto bbs : llvm::zip(*f, blockList)) {
12216b534ecbSJames Molloy     if (failed(processBasicBlock(&std::get<0>(bbs), std::get<1>(bbs))))
12226b534ecbSJames Molloy       return failure();
12236b534ecbSJames Molloy   }
12246b534ecbSJames Molloy 
12256b534ecbSJames Molloy   // Now that all instructions are guaranteed to have been visited, ensure
12266b534ecbSJames Molloy   // any unknown uses we encountered are remapped.
12276b534ecbSJames Molloy   for (auto &llvmAndUnknown : unknownInstMap) {
12286b534ecbSJames Molloy     assert(instMap.count(llvmAndUnknown.first));
1229e62a6956SRiver Riddle     Value newValue = instMap[llvmAndUnknown.first];
1230e62a6956SRiver Riddle     Value oldValue = llvmAndUnknown.second->getResult(0);
12312bdf33ccSRiver Riddle     oldValue.replaceAllUsesWith(newValue);
12326b534ecbSJames Molloy     llvmAndUnknown.second->erase();
12336b534ecbSJames Molloy   }
12346b534ecbSJames Molloy   return success();
12356b534ecbSJames Molloy }
12366b534ecbSJames Molloy 
processBasicBlock(llvm::BasicBlock * bb,Block * block)12376b534ecbSJames Molloy LogicalResult Importer::processBasicBlock(llvm::BasicBlock *bb, Block *block) {
12386b534ecbSJames Molloy   b.setInsertionPointToStart(block);
12396b534ecbSJames Molloy   for (llvm::Instruction &inst : *bb) {
12406b534ecbSJames Molloy     if (failed(processInstruction(&inst)))
12416b534ecbSJames Molloy       return failure();
12426b534ecbSJames Molloy   }
12436b534ecbSJames Molloy   return success();
12446b534ecbSJames Molloy }
12456b534ecbSJames Molloy 
12468f66ab1cSSanjoy Das OwningOpRef<ModuleOp>
translateLLVMIRToModule(std::unique_ptr<llvm::Module> llvmModule,MLIRContext * context)12476b534ecbSJames Molloy mlir::translateLLVMIRToModule(std::unique_ptr<llvm::Module> llvmModule,
12486b534ecbSJames Molloy                               MLIRContext *context) {
1249f9dc2b70SMehdi Amini   context->loadDialect<LLVMDialect>();
1250ea998709SAlex Zinenko   context->loadDialect<DLTIDialect>();
12518f66ab1cSSanjoy Das   OwningOpRef<ModuleOp> module(ModuleOp::create(
1252a4bb667dSRiver Riddle       FileLineColLoc::get(context, "", /*line=*/0, /*column=*/0)));
12536b534ecbSJames Molloy 
1254ea998709SAlex Zinenko   DataLayoutSpecInterface dlSpec =
1255ea998709SAlex Zinenko       translateDataLayout(llvmModule->getDataLayout(), context);
1256ea998709SAlex Zinenko   if (!dlSpec) {
1257ea998709SAlex Zinenko     emitError(UnknownLoc::get(context), "can't translate data layout");
1258ea998709SAlex Zinenko     return {};
1259ea998709SAlex Zinenko   }
1260ea998709SAlex Zinenko 
1261ea998709SAlex Zinenko   module.get()->setAttr(DLTIDialect::kDataLayoutAttrName, dlSpec);
1262ea998709SAlex Zinenko 
12636b534ecbSJames Molloy   Importer deserializer(context, module.get());
12646b534ecbSJames Molloy   for (llvm::GlobalVariable &gv : llvmModule->globals()) {
12656b534ecbSJames Molloy     if (!deserializer.processGlobal(&gv))
12666b534ecbSJames Molloy       return {};
12676b534ecbSJames Molloy   }
12686b534ecbSJames Molloy   for (llvm::Function &f : llvmModule->functions()) {
12696b534ecbSJames Molloy     if (failed(deserializer.processFunction(&f)))
12706b534ecbSJames Molloy       return {};
12716b534ecbSJames Molloy   }
12726b534ecbSJames Molloy 
12736b534ecbSJames Molloy   return module;
12746b534ecbSJames Molloy }
12756b534ecbSJames Molloy 
12766b534ecbSJames Molloy // Deserializes the LLVM bitcode stored in `input` into an MLIR module in the
12776b534ecbSJames Molloy // LLVM dialect.
translateLLVMIRToModule(llvm::SourceMgr & sourceMgr,MLIRContext * context)12788f66ab1cSSanjoy Das OwningOpRef<ModuleOp> translateLLVMIRToModule(llvm::SourceMgr &sourceMgr,
12796b534ecbSJames Molloy                                               MLIRContext *context) {
12806b534ecbSJames Molloy   llvm::SMDiagnostic err;
128116b02253SAlex Zinenko   llvm::LLVMContext llvmContext;
128216b02253SAlex Zinenko   std::unique_ptr<llvm::Module> llvmModule = llvm::parseIR(
128316b02253SAlex Zinenko       *sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID()), err, llvmContext);
12846b534ecbSJames Molloy   if (!llvmModule) {
12856b534ecbSJames Molloy     std::string errStr;
12866b534ecbSJames Molloy     llvm::raw_string_ostream errStream(errStr);
12876b534ecbSJames Molloy     err.print(/*ProgName=*/"", errStream);
12886b534ecbSJames Molloy     emitError(UnknownLoc::get(context)) << errStream.str();
12896b534ecbSJames Molloy     return {};
12906b534ecbSJames Molloy   }
12916b534ecbSJames Molloy   return translateLLVMIRToModule(std::move(llvmModule), context);
12926b534ecbSJames Molloy }
12936b534ecbSJames Molloy 
1294223154d2SJonathan Roelofs namespace mlir {
registerFromLLVMIRTranslation()1295223154d2SJonathan Roelofs void registerFromLLVMIRTranslation() {
1296223154d2SJonathan Roelofs   TranslateToMLIRRegistration fromLLVM(
1297223154d2SJonathan Roelofs       "import-llvm", [](llvm::SourceMgr &sourceMgr, MLIRContext *context) {
1298223154d2SJonathan Roelofs         return ::translateLLVMIRToModule(sourceMgr, context);
12996b534ecbSJames Molloy       });
1300223154d2SJonathan Roelofs }
1301223154d2SJonathan Roelofs } // namespace mlir
1302