1 //===- LLVMToLLVMIRTranslation.cpp - Translate LLVM dialect to LLVM IR ----===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements a translation between the MLIR LLVM dialect and LLVM IR.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
14 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
15 #include "mlir/IR/Operation.h"
16 #include "mlir/Support/LLVM.h"
17 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
18 
19 #include "llvm/IR/IRBuilder.h"
20 #include "llvm/IR/InlineAsm.h"
21 #include "llvm/IR/MDBuilder.h"
22 #include "llvm/IR/MatrixBuilder.h"
23 #include "llvm/IR/Operator.h"
24 
25 using namespace mlir;
26 using namespace mlir::LLVM;
27 using mlir::LLVM::detail::getLLVMConstant;
28 
29 #include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
30 
31 /// Convert MLIR integer comparison predicate to LLVM IR comparison predicate.
getLLVMCmpPredicate(ICmpPredicate p)32 static llvm::CmpInst::Predicate getLLVMCmpPredicate(ICmpPredicate p) {
33   switch (p) {
34   case LLVM::ICmpPredicate::eq:
35     return llvm::CmpInst::Predicate::ICMP_EQ;
36   case LLVM::ICmpPredicate::ne:
37     return llvm::CmpInst::Predicate::ICMP_NE;
38   case LLVM::ICmpPredicate::slt:
39     return llvm::CmpInst::Predicate::ICMP_SLT;
40   case LLVM::ICmpPredicate::sle:
41     return llvm::CmpInst::Predicate::ICMP_SLE;
42   case LLVM::ICmpPredicate::sgt:
43     return llvm::CmpInst::Predicate::ICMP_SGT;
44   case LLVM::ICmpPredicate::sge:
45     return llvm::CmpInst::Predicate::ICMP_SGE;
46   case LLVM::ICmpPredicate::ult:
47     return llvm::CmpInst::Predicate::ICMP_ULT;
48   case LLVM::ICmpPredicate::ule:
49     return llvm::CmpInst::Predicate::ICMP_ULE;
50   case LLVM::ICmpPredicate::ugt:
51     return llvm::CmpInst::Predicate::ICMP_UGT;
52   case LLVM::ICmpPredicate::uge:
53     return llvm::CmpInst::Predicate::ICMP_UGE;
54   }
55   llvm_unreachable("incorrect comparison predicate");
56 }
57 
getLLVMCmpPredicate(FCmpPredicate p)58 static llvm::CmpInst::Predicate getLLVMCmpPredicate(FCmpPredicate p) {
59   switch (p) {
60   case LLVM::FCmpPredicate::_false:
61     return llvm::CmpInst::Predicate::FCMP_FALSE;
62   case LLVM::FCmpPredicate::oeq:
63     return llvm::CmpInst::Predicate::FCMP_OEQ;
64   case LLVM::FCmpPredicate::ogt:
65     return llvm::CmpInst::Predicate::FCMP_OGT;
66   case LLVM::FCmpPredicate::oge:
67     return llvm::CmpInst::Predicate::FCMP_OGE;
68   case LLVM::FCmpPredicate::olt:
69     return llvm::CmpInst::Predicate::FCMP_OLT;
70   case LLVM::FCmpPredicate::ole:
71     return llvm::CmpInst::Predicate::FCMP_OLE;
72   case LLVM::FCmpPredicate::one:
73     return llvm::CmpInst::Predicate::FCMP_ONE;
74   case LLVM::FCmpPredicate::ord:
75     return llvm::CmpInst::Predicate::FCMP_ORD;
76   case LLVM::FCmpPredicate::ueq:
77     return llvm::CmpInst::Predicate::FCMP_UEQ;
78   case LLVM::FCmpPredicate::ugt:
79     return llvm::CmpInst::Predicate::FCMP_UGT;
80   case LLVM::FCmpPredicate::uge:
81     return llvm::CmpInst::Predicate::FCMP_UGE;
82   case LLVM::FCmpPredicate::ult:
83     return llvm::CmpInst::Predicate::FCMP_ULT;
84   case LLVM::FCmpPredicate::ule:
85     return llvm::CmpInst::Predicate::FCMP_ULE;
86   case LLVM::FCmpPredicate::une:
87     return llvm::CmpInst::Predicate::FCMP_UNE;
88   case LLVM::FCmpPredicate::uno:
89     return llvm::CmpInst::Predicate::FCMP_UNO;
90   case LLVM::FCmpPredicate::_true:
91     return llvm::CmpInst::Predicate::FCMP_TRUE;
92   }
93   llvm_unreachable("incorrect comparison predicate");
94 }
95 
getLLVMAtomicBinOp(AtomicBinOp op)96 static llvm::AtomicRMWInst::BinOp getLLVMAtomicBinOp(AtomicBinOp op) {
97   switch (op) {
98   case LLVM::AtomicBinOp::xchg:
99     return llvm::AtomicRMWInst::BinOp::Xchg;
100   case LLVM::AtomicBinOp::add:
101     return llvm::AtomicRMWInst::BinOp::Add;
102   case LLVM::AtomicBinOp::sub:
103     return llvm::AtomicRMWInst::BinOp::Sub;
104   case LLVM::AtomicBinOp::_and:
105     return llvm::AtomicRMWInst::BinOp::And;
106   case LLVM::AtomicBinOp::nand:
107     return llvm::AtomicRMWInst::BinOp::Nand;
108   case LLVM::AtomicBinOp::_or:
109     return llvm::AtomicRMWInst::BinOp::Or;
110   case LLVM::AtomicBinOp::_xor:
111     return llvm::AtomicRMWInst::BinOp::Xor;
112   case LLVM::AtomicBinOp::max:
113     return llvm::AtomicRMWInst::BinOp::Max;
114   case LLVM::AtomicBinOp::min:
115     return llvm::AtomicRMWInst::BinOp::Min;
116   case LLVM::AtomicBinOp::umax:
117     return llvm::AtomicRMWInst::BinOp::UMax;
118   case LLVM::AtomicBinOp::umin:
119     return llvm::AtomicRMWInst::BinOp::UMin;
120   case LLVM::AtomicBinOp::fadd:
121     return llvm::AtomicRMWInst::BinOp::FAdd;
122   case LLVM::AtomicBinOp::fsub:
123     return llvm::AtomicRMWInst::BinOp::FSub;
124   }
125   llvm_unreachable("incorrect atomic binary operator");
126 }
127 
getLLVMAtomicOrdering(AtomicOrdering ordering)128 static llvm::AtomicOrdering getLLVMAtomicOrdering(AtomicOrdering ordering) {
129   switch (ordering) {
130   case LLVM::AtomicOrdering::not_atomic:
131     return llvm::AtomicOrdering::NotAtomic;
132   case LLVM::AtomicOrdering::unordered:
133     return llvm::AtomicOrdering::Unordered;
134   case LLVM::AtomicOrdering::monotonic:
135     return llvm::AtomicOrdering::Monotonic;
136   case LLVM::AtomicOrdering::acquire:
137     return llvm::AtomicOrdering::Acquire;
138   case LLVM::AtomicOrdering::release:
139     return llvm::AtomicOrdering::Release;
140   case LLVM::AtomicOrdering::acq_rel:
141     return llvm::AtomicOrdering::AcquireRelease;
142   case LLVM::AtomicOrdering::seq_cst:
143     return llvm::AtomicOrdering::SequentiallyConsistent;
144   }
145   llvm_unreachable("incorrect atomic ordering");
146 }
147 
getFastmathFlags(FastmathFlagsInterface & op)148 static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op) {
149   using llvmFMF = llvm::FastMathFlags;
150   using FuncT = void (llvmFMF::*)(bool);
151   const std::pair<FastmathFlags, FuncT> handlers[] = {
152       // clang-format off
153       {FastmathFlags::nnan,     &llvmFMF::setNoNaNs},
154       {FastmathFlags::ninf,     &llvmFMF::setNoInfs},
155       {FastmathFlags::nsz,      &llvmFMF::setNoSignedZeros},
156       {FastmathFlags::arcp,     &llvmFMF::setAllowReciprocal},
157       {FastmathFlags::contract, &llvmFMF::setAllowContract},
158       {FastmathFlags::afn,      &llvmFMF::setApproxFunc},
159       {FastmathFlags::reassoc,  &llvmFMF::setAllowReassoc},
160       // clang-format on
161   };
162   llvm::FastMathFlags ret;
163   auto fmf = op.getFastmathFlags();
164   for (auto it : handlers)
165     if (bitEnumContains(fmf, it.first))
166       (ret.*(it.second))(true);
167   return ret;
168 }
169 
170 /// Returns an LLVM metadata node corresponding to a loop option. This metadata
171 /// is attached to an llvm.loop node.
getLoopOptionMetadata(llvm::LLVMContext & ctx,LoopOptionCase option,int64_t value)172 static llvm::MDNode *getLoopOptionMetadata(llvm::LLVMContext &ctx,
173                                            LoopOptionCase option,
174                                            int64_t value) {
175   StringRef name;
176   llvm::Constant *cstValue = nullptr;
177   switch (option) {
178   case LoopOptionCase::disable_licm:
179     name = "llvm.licm.disable";
180     cstValue = llvm::ConstantInt::getBool(ctx, value);
181     break;
182   case LoopOptionCase::disable_unroll:
183     name = "llvm.loop.unroll.disable";
184     cstValue = llvm::ConstantInt::getBool(ctx, value);
185     break;
186   case LoopOptionCase::interleave_count:
187     name = "llvm.loop.interleave.count";
188     cstValue = llvm::ConstantInt::get(
189         llvm::IntegerType::get(ctx, /*NumBits=*/32), value);
190     break;
191   case LoopOptionCase::disable_pipeline:
192     name = "llvm.loop.pipeline.disable";
193     cstValue = llvm::ConstantInt::getBool(ctx, value);
194     break;
195   case LoopOptionCase::pipeline_initiation_interval:
196     name = "llvm.loop.pipeline.initiationinterval";
197     cstValue = llvm::ConstantInt::get(
198         llvm::IntegerType::get(ctx, /*NumBits=*/32), value);
199     break;
200   }
201   return llvm::MDNode::get(ctx, {llvm::MDString::get(ctx, name),
202                                  llvm::ConstantAsMetadata::get(cstValue)});
203 }
204 
setLoopMetadata(Operation & opInst,llvm::Instruction & llvmInst,llvm::IRBuilderBase & builder,LLVM::ModuleTranslation & moduleTranslation)205 static void setLoopMetadata(Operation &opInst, llvm::Instruction &llvmInst,
206                             llvm::IRBuilderBase &builder,
207                             LLVM::ModuleTranslation &moduleTranslation) {
208   if (Attribute attr = opInst.getAttr(LLVMDialect::getLoopAttrName())) {
209     llvm::Module *module = builder.GetInsertBlock()->getModule();
210     llvm::MDNode *loopMD = moduleTranslation.lookupLoopOptionsMetadata(attr);
211     if (!loopMD) {
212       llvm::LLVMContext &ctx = module->getContext();
213 
214       SmallVector<llvm::Metadata *> loopOptions;
215       // Reserve operand 0 for loop id self reference.
216       auto dummy = llvm::MDNode::getTemporary(ctx, llvm::None);
217       loopOptions.push_back(dummy.get());
218 
219       auto loopAttr = attr.cast<DictionaryAttr>();
220       auto parallelAccessGroup =
221           loopAttr.getNamed(LLVMDialect::getParallelAccessAttrName());
222       if (parallelAccessGroup) {
223         SmallVector<llvm::Metadata *> parallelAccess;
224         parallelAccess.push_back(
225             llvm::MDString::get(ctx, "llvm.loop.parallel_accesses"));
226         for (SymbolRefAttr accessGroupRef : parallelAccessGroup->getValue()
227                                                 .cast<ArrayAttr>()
228                                                 .getAsRange<SymbolRefAttr>())
229           parallelAccess.push_back(
230               moduleTranslation.getAccessGroup(opInst, accessGroupRef));
231         loopOptions.push_back(llvm::MDNode::get(ctx, parallelAccess));
232       }
233 
234       if (auto loopOptionsAttr = loopAttr.getAs<LoopOptionsAttr>(
235               LLVMDialect::getLoopOptionsAttrName())) {
236         for (auto option : loopOptionsAttr.getOptions())
237           loopOptions.push_back(
238               getLoopOptionMetadata(ctx, option.first, option.second));
239       }
240 
241       // Create loop options and set the first operand to itself.
242       loopMD = llvm::MDNode::get(ctx, loopOptions);
243       loopMD->replaceOperandWith(0, loopMD);
244 
245       // Store a map from this Attribute to the LLVM metadata in case we
246       // encounter it again.
247       moduleTranslation.mapLoopOptionsMetadata(attr, loopMD);
248     }
249 
250     llvmInst.setMetadata(module->getMDKindID("llvm.loop"), loopMD);
251   }
252 }
253 
254 static LogicalResult
convertOperationImpl(Operation & opInst,llvm::IRBuilderBase & builder,LLVM::ModuleTranslation & moduleTranslation)255 convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
256                      LLVM::ModuleTranslation &moduleTranslation) {
257   auto extractPosition = [](ArrayAttr attr) {
258     SmallVector<unsigned, 4> position;
259     position.reserve(attr.size());
260     for (Attribute v : attr)
261       position.push_back(v.cast<IntegerAttr>().getValue().getZExtValue());
262     return position;
263   };
264 
265   llvm::IRBuilder<>::FastMathFlagGuard fmfGuard(builder);
266   if (auto fmf = dyn_cast<FastmathFlagsInterface>(opInst))
267     builder.setFastMathFlags(getFastmathFlags(fmf));
268 
269 #include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
270 #include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
271 
272   // Emit function calls.  If the "callee" attribute is present, this is a
273   // direct function call and we also need to look up the remapped function
274   // itself.  Otherwise, this is an indirect call and the callee is the first
275   // operand, look it up as a normal value.  Return the llvm::Value representing
276   // the function result, which may be of llvm::VoidTy type.
277   auto convertCall = [&](Operation &op) -> llvm::Value * {
278     auto operands = moduleTranslation.lookupValues(op.getOperands());
279     ArrayRef<llvm::Value *> operandsRef(operands);
280     if (auto attr = op.getAttrOfType<FlatSymbolRefAttr>("callee"))
281       return builder.CreateCall(
282           moduleTranslation.lookupFunction(attr.getValue()), operandsRef);
283     auto calleeType =
284         op.getOperands().front().getType().cast<LLVMPointerType>();
285     auto *calleeFunctionType = cast<llvm::FunctionType>(
286         moduleTranslation.convertType(calleeType.getElementType()));
287     return builder.CreateCall(calleeFunctionType, operandsRef.front(),
288                               operandsRef.drop_front());
289   };
290 
291   // Emit calls.  If the called function has a result, remap the corresponding
292   // value.  Note that LLVM IR dialect CallOp has either 0 or 1 result.
293   if (isa<LLVM::CallOp>(opInst)) {
294     llvm::Value *result = convertCall(opInst);
295     if (opInst.getNumResults() != 0) {
296       moduleTranslation.mapValue(opInst.getResult(0), result);
297       return success();
298     }
299     // Check that LLVM call returns void for 0-result functions.
300     return success(result->getType()->isVoidTy());
301   }
302 
303   if (auto inlineAsmOp = dyn_cast<LLVM::InlineAsmOp>(opInst)) {
304     // TODO: refactor function type creation which usually occurs in std-LLVM
305     // conversion.
306     SmallVector<Type, 8> operandTypes;
307     llvm::append_range(operandTypes, inlineAsmOp.getOperands().getTypes());
308 
309     Type resultType;
310     if (inlineAsmOp.getNumResults() == 0) {
311       resultType = LLVM::LLVMVoidType::get(&moduleTranslation.getContext());
312     } else {
313       assert(inlineAsmOp.getNumResults() == 1);
314       resultType = inlineAsmOp.getResultTypes()[0];
315     }
316     auto ft = LLVM::LLVMFunctionType::get(resultType, operandTypes);
317     llvm::InlineAsm *inlineAsmInst =
318         inlineAsmOp.getAsmDialect()
319             ? llvm::InlineAsm::get(
320                   static_cast<llvm::FunctionType *>(
321                       moduleTranslation.convertType(ft)),
322                   inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
323                   inlineAsmOp.getHasSideEffects(),
324                   inlineAsmOp.getIsAlignStack(),
325                   convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
326             : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
327                                        moduleTranslation.convertType(ft)),
328                                    inlineAsmOp.getAsmString(),
329                                    inlineAsmOp.getConstraints(),
330                                    inlineAsmOp.getHasSideEffects(),
331                                    inlineAsmOp.getIsAlignStack());
332     llvm::CallInst *inst = builder.CreateCall(
333         inlineAsmInst,
334         moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
335     if (auto maybeOperandAttrs = inlineAsmOp.getOperandAttrs()) {
336       llvm::AttributeList attrList;
337       for (const auto &it : llvm::enumerate(*maybeOperandAttrs)) {
338         Attribute attr = it.value();
339         if (!attr)
340           continue;
341         DictionaryAttr dAttr = attr.cast<DictionaryAttr>();
342         TypeAttr tAttr =
343             dAttr.get(InlineAsmOp::getElementTypeAttrName()).cast<TypeAttr>();
344         llvm::AttrBuilder b(moduleTranslation.getLLVMContext());
345         llvm::Type *ty = moduleTranslation.convertType(tAttr.getValue());
346         b.addTypeAttr(llvm::Attribute::ElementType, ty);
347         // shift to account for the returned value (this is always 1 aggregate
348         // value in LLVM).
349         int shift = (opInst.getNumResults() > 0) ? 1 : 0;
350         attrList = attrList.addAttributesAtIndex(
351             moduleTranslation.getLLVMContext(), it.index() + shift, b);
352       }
353       inst->setAttributes(attrList);
354     }
355 
356     if (opInst.getNumResults() != 0)
357       moduleTranslation.mapValue(opInst.getResult(0), inst);
358     return success();
359   }
360 
361   if (auto invOp = dyn_cast<LLVM::InvokeOp>(opInst)) {
362     auto operands = moduleTranslation.lookupValues(invOp.getCalleeOperands());
363     ArrayRef<llvm::Value *> operandsRef(operands);
364     llvm::Instruction *result;
365     if (auto attr = opInst.getAttrOfType<FlatSymbolRefAttr>("callee")) {
366       result = builder.CreateInvoke(
367           moduleTranslation.lookupFunction(attr.getValue()),
368           moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
369           moduleTranslation.lookupBlock(invOp.getSuccessor(1)), operandsRef);
370     } else {
371       auto calleeType =
372           invOp.getCalleeOperands().front().getType().cast<LLVMPointerType>();
373       auto *calleeFunctionType = cast<llvm::FunctionType>(
374           moduleTranslation.convertType(calleeType.getElementType()));
375       result = builder.CreateInvoke(
376           calleeFunctionType, operandsRef.front(),
377           moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
378           moduleTranslation.lookupBlock(invOp.getSuccessor(1)),
379           operandsRef.drop_front());
380     }
381     moduleTranslation.mapBranch(invOp, result);
382     // InvokeOp can only have 0 or 1 result
383     if (invOp->getNumResults() != 0) {
384       moduleTranslation.mapValue(opInst.getResult(0), result);
385       return success();
386     }
387     return success(result->getType()->isVoidTy());
388   }
389 
390   if (auto lpOp = dyn_cast<LLVM::LandingpadOp>(opInst)) {
391     llvm::Type *ty = moduleTranslation.convertType(lpOp.getType());
392     llvm::LandingPadInst *lpi =
393         builder.CreateLandingPad(ty, lpOp.getNumOperands());
394     lpi->setCleanup(lpOp.getCleanup());
395 
396     // Add clauses
397     for (llvm::Value *operand :
398          moduleTranslation.lookupValues(lpOp.getOperands())) {
399       // All operands should be constant - checked by verifier
400       if (auto *constOperand = dyn_cast<llvm::Constant>(operand))
401         lpi->addClause(constOperand);
402     }
403     moduleTranslation.mapValue(lpOp.getResult(), lpi);
404     return success();
405   }
406 
407   // Emit branches.  We need to look up the remapped blocks and ignore the block
408   // arguments that were transformed into PHI nodes.
409   if (auto brOp = dyn_cast<LLVM::BrOp>(opInst)) {
410     llvm::BranchInst *branch =
411         builder.CreateBr(moduleTranslation.lookupBlock(brOp.getSuccessor()));
412     moduleTranslation.mapBranch(&opInst, branch);
413     setLoopMetadata(opInst, *branch, builder, moduleTranslation);
414     return success();
415   }
416   if (auto condbrOp = dyn_cast<LLVM::CondBrOp>(opInst)) {
417     llvm::MDNode *branchWeights = nullptr;
418     if (auto weights = condbrOp.getBranchWeights()) {
419       // Map weight attributes to LLVM metadata.
420       auto weightValues = weights->getValues<APInt>();
421       auto trueWeight = weightValues[0].getSExtValue();
422       auto falseWeight = weightValues[1].getSExtValue();
423       branchWeights =
424           llvm::MDBuilder(moduleTranslation.getLLVMContext())
425               .createBranchWeights(static_cast<uint32_t>(trueWeight),
426                                    static_cast<uint32_t>(falseWeight));
427     }
428     llvm::BranchInst *branch = builder.CreateCondBr(
429         moduleTranslation.lookupValue(condbrOp.getOperand(0)),
430         moduleTranslation.lookupBlock(condbrOp.getSuccessor(0)),
431         moduleTranslation.lookupBlock(condbrOp.getSuccessor(1)), branchWeights);
432     moduleTranslation.mapBranch(&opInst, branch);
433     setLoopMetadata(opInst, *branch, builder, moduleTranslation);
434     return success();
435   }
436   if (auto switchOp = dyn_cast<LLVM::SwitchOp>(opInst)) {
437     llvm::MDNode *branchWeights = nullptr;
438     if (auto weights = switchOp.getBranchWeights()) {
439       llvm::SmallVector<uint32_t> weightValues;
440       weightValues.reserve(weights->size());
441       for (llvm::APInt weight : weights->cast<DenseIntElementsAttr>())
442         weightValues.push_back(weight.getLimitedValue());
443       branchWeights = llvm::MDBuilder(moduleTranslation.getLLVMContext())
444                           .createBranchWeights(weightValues);
445     }
446 
447     llvm::SwitchInst *switchInst = builder.CreateSwitch(
448         moduleTranslation.lookupValue(switchOp.getValue()),
449         moduleTranslation.lookupBlock(switchOp.getDefaultDestination()),
450         switchOp.getCaseDestinations().size(), branchWeights);
451 
452     auto *ty = llvm::cast<llvm::IntegerType>(
453         moduleTranslation.convertType(switchOp.getValue().getType()));
454     for (auto i :
455          llvm::zip(switchOp.getCaseValues()->cast<DenseIntElementsAttr>(),
456                    switchOp.getCaseDestinations()))
457       switchInst->addCase(
458           llvm::ConstantInt::get(ty, std::get<0>(i).getLimitedValue()),
459           moduleTranslation.lookupBlock(std::get<1>(i)));
460 
461     moduleTranslation.mapBranch(&opInst, switchInst);
462     return success();
463   }
464 
465   // Emit addressof.  We need to look up the global value referenced by the
466   // operation and store it in the MLIR-to-LLVM value mapping.  This does not
467   // emit any LLVM instruction.
468   if (auto addressOfOp = dyn_cast<LLVM::AddressOfOp>(opInst)) {
469     LLVM::GlobalOp global = addressOfOp.getGlobal();
470     LLVM::LLVMFuncOp function = addressOfOp.getFunction();
471 
472     // The verifier should not have allowed this.
473     assert((global || function) &&
474            "referencing an undefined global or function");
475 
476     moduleTranslation.mapValue(
477         addressOfOp.getResult(),
478         global ? moduleTranslation.lookupGlobal(global)
479                : moduleTranslation.lookupFunction(function.getName()));
480     return success();
481   }
482 
483   return failure();
484 }
485 
486 namespace {
487 /// Implementation of the dialect interface that converts operations belonging
488 /// to the LLVM dialect to LLVM IR.
489 class LLVMDialectLLVMIRTranslationInterface
490     : public LLVMTranslationDialectInterface {
491 public:
492   using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
493 
494   /// Translates the given operation to LLVM IR using the provided IR builder
495   /// and saving the state in `moduleTranslation`.
496   LogicalResult
convertOperation(Operation * op,llvm::IRBuilderBase & builder,LLVM::ModuleTranslation & moduleTranslation) const497   convertOperation(Operation *op, llvm::IRBuilderBase &builder,
498                    LLVM::ModuleTranslation &moduleTranslation) const final {
499     return convertOperationImpl(*op, builder, moduleTranslation);
500   }
501 };
502 } // namespace
503 
registerLLVMDialectTranslation(DialectRegistry & registry)504 void mlir::registerLLVMDialectTranslation(DialectRegistry &registry) {
505   registry.insert<LLVM::LLVMDialect>();
506   registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
507     dialect->addInterfaces<LLVMDialectLLVMIRTranslationInterface>();
508   });
509 }
510 
registerLLVMDialectTranslation(MLIRContext & context)511 void mlir::registerLLVMDialectTranslation(MLIRContext &context) {
512   DialectRegistry registry;
513   registerLLVMDialectTranslation(registry);
514   context.appendDialectRegistry(registry);
515 }
516