MLIR 23.0.0git
LLVMToLLVMIRTranslation.cpp
Go to the documentation of this file.
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
16#include "mlir/IR/Operation.h"
18#include "mlir/Support/LLVM.h"
20
21#include "llvm/ADT/TypeSwitch.h"
22#include "llvm/IR/DIBuilder.h"
23#include "llvm/IR/IRBuilder.h"
24#include "llvm/IR/InlineAsm.h"
25#include "llvm/IR/Instructions.h"
26#include "llvm/IR/MDBuilder.h"
27#include "llvm/IR/MatrixBuilder.h"
28#include "llvm/IR/MemoryModelRelaxationAnnotations.h"
29#include "llvm/Support/LogicalResult.h"
30
31using namespace mlir;
32using namespace mlir::LLVM;
34
35#include "mlir/Dialect/LLVMIR/LLVMConversionEnumsToLLVM.inc"
36
37static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op) {
38 using llvmFMF = llvm::FastMathFlags;
39 using FuncT = void (llvmFMF::*)(bool);
40 const std::pair<FastmathFlags, FuncT> handlers[] = {
41 // clang-format off
42 {FastmathFlags::nnan, &llvmFMF::setNoNaNs},
43 {FastmathFlags::ninf, &llvmFMF::setNoInfs},
44 {FastmathFlags::nsz, &llvmFMF::setNoSignedZeros},
45 {FastmathFlags::arcp, &llvmFMF::setAllowReciprocal},
46 {FastmathFlags::contract, &llvmFMF::setAllowContract},
47 {FastmathFlags::afn, &llvmFMF::setApproxFunc},
48 {FastmathFlags::reassoc, &llvmFMF::setAllowReassoc},
49 // clang-format on
50 };
51 llvm::FastMathFlags ret;
52 ::mlir::LLVM::FastmathFlags fmfMlir = op.getFastmathAttr().getValue();
53 for (auto it : handlers)
54 if (bitEnumContainsAll(fmfMlir, it.first))
55 (ret.*(it.second))(true);
56 return ret;
57}
58
59/// Convert the value of a DenseI64ArrayAttr to a vector of unsigned indices.
61 SmallVector<unsigned> position;
62 llvm::append_range(position, indices);
63 return position;
64}
65
66/// Convert an LLVM type to a string for printing in diagnostics.
67static std::string diagStr(const llvm::Type *type) {
68 std::string str;
69 llvm::raw_string_ostream os(str);
70 type->print(os);
71 return str;
72}
73
74/// Get the declaration of an overloaded llvm intrinsic. First we get the
75/// overloaded argument types and/or result type from the CallIntrinsicOp, and
76/// then use those to get the correct declaration of the overloaded intrinsic.
77static FailureOr<llvm::Function *>
78getOverloadedDeclaration(CallIntrinsicOp op, llvm::Intrinsic::ID id,
79 llvm::Module *module,
80 LLVM::ModuleTranslation &moduleTranslation) {
82 for (Type type : op->getOperandTypes())
83 allArgTys.push_back(moduleTranslation.convertType(type));
84
85 llvm::Type *resTy;
86 if (op.getNumResults() == 0)
87 resTy = llvm::Type::getVoidTy(module->getContext());
88 else
89 resTy = moduleTranslation.convertType(op.getResult(0).getType());
90
91 // ATM we do not support variadic intrinsics.
92 llvm::FunctionType *ft = llvm::FunctionType::get(resTy, allArgTys, false);
93
95 getIntrinsicInfoTableEntries(id, table);
97
98 SmallVector<llvm::Type *, 8> overloadedArgTys;
99 if (llvm::Intrinsic::matchIntrinsicSignature(ft, tableRef,
100 overloadedArgTys) !=
101 llvm::Intrinsic::MatchIntrinsicTypesResult::MatchIntrinsicTypes_Match) {
102 return mlir::emitError(op.getLoc(), "call intrinsic signature ")
103 << diagStr(ft) << " to overloaded intrinsic " << op.getIntrinAttr()
104 << " does not match any of the overloads";
105 }
106
107 ArrayRef<llvm::Type *> overloadedArgTysRef = overloadedArgTys;
108 return llvm::Intrinsic::getOrInsertDeclaration(module, id,
109 overloadedArgTysRef);
110}
111
112static llvm::OperandBundleDef
113convertOperandBundle(OperandRange bundleOperands, StringRef bundleTag,
114 LLVM::ModuleTranslation &moduleTranslation) {
115 std::vector<llvm::Value *> operands;
116 operands.reserve(bundleOperands.size());
117 for (Value bundleArg : bundleOperands)
118 operands.push_back(moduleTranslation.lookupValue(bundleArg));
119 return llvm::OperandBundleDef(bundleTag.str(), std::move(operands));
120}
121
124 LLVM::ModuleTranslation &moduleTranslation) {
126 bundles.reserve(bundleOperands.size());
127
128 for (auto [operands, tagAttr] : llvm::zip_equal(bundleOperands, bundleTags)) {
129 StringRef tag = cast<StringAttr>(tagAttr).getValue();
130 bundles.push_back(convertOperandBundle(operands, tag, moduleTranslation));
131 }
132 return bundles;
133}
134
137 std::optional<ArrayAttr> bundleTags,
138 LLVM::ModuleTranslation &moduleTranslation) {
139 if (!bundleTags)
140 return {};
141 return convertOperandBundles(bundleOperands, *bundleTags, moduleTranslation);
142}
143
144/// Builder for LLVM_CallIntrinsicOp
145static LogicalResult
146convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
147 LLVM::ModuleTranslation &moduleTranslation) {
148 llvm::Module *module = builder.GetInsertBlock()->getModule();
149 llvm::Intrinsic::ID id =
150 llvm::Intrinsic::lookupIntrinsicID(op.getIntrinAttr());
151 if (!id)
152 return mlir::emitError(op.getLoc(), "could not find LLVM intrinsic: ")
153 << op.getIntrinAttr();
154
155 llvm::Function *fn = nullptr;
156 if (llvm::Intrinsic::isOverloaded(id)) {
157 auto fnOrFailure =
158 getOverloadedDeclaration(op, id, module, moduleTranslation);
159 if (failed(fnOrFailure))
160 return failure();
161 fn = *fnOrFailure;
162 } else {
163 fn = llvm::Intrinsic::getOrInsertDeclaration(module, id, {});
164 }
165
166 // Check the result type of the call.
167 const llvm::Type *intrinType =
168 op.getNumResults() == 0
169 ? llvm::Type::getVoidTy(module->getContext())
170 : moduleTranslation.convertType(op.getResultTypes().front());
171 if (intrinType != fn->getReturnType()) {
172 return mlir::emitError(op.getLoc(), "intrinsic call returns ")
173 << diagStr(intrinType) << " but " << op.getIntrinAttr()
174 << " actually returns " << diagStr(fn->getReturnType());
175 }
176
177 // Check the argument types of the call. If the function is variadic, check
178 // the subrange of required arguments.
179 if (!fn->getFunctionType()->isVarArg() &&
180 op.getArgs().size() != fn->arg_size()) {
181 return mlir::emitError(op.getLoc(), "intrinsic call has ")
182 << op.getArgs().size() << " operands but " << op.getIntrinAttr()
183 << " expects " << fn->arg_size();
184 }
185 if (fn->getFunctionType()->isVarArg() &&
186 op.getArgs().size() < fn->arg_size()) {
187 return mlir::emitError(op.getLoc(), "intrinsic call has ")
188 << op.getArgs().size() << " operands but variadic "
189 << op.getIntrinAttr() << " expects at least " << fn->arg_size();
190 }
191 // Check the arguments up to the number the function requires.
192 for (unsigned i = 0, e = fn->arg_size(); i != e; ++i) {
193 const llvm::Type *expected = fn->getArg(i)->getType();
194 const llvm::Type *actual =
195 moduleTranslation.convertType(op.getOperandTypes()[i]);
196 if (actual != expected) {
197 return mlir::emitError(op.getLoc(), "intrinsic call operand #")
198 << i << " has type " << diagStr(actual) << " but "
199 << op.getIntrinAttr() << " expects " << diagStr(expected);
200 }
201 }
202
203 FastmathFlagsInterface itf = op;
204 builder.setFastMathFlags(getFastmathFlags(itf));
205
206 auto *inst = builder.CreateCall(
207 fn, moduleTranslation.lookupValues(op.getArgs()),
208 convertOperandBundles(op.getOpBundleOperands(), op.getOpBundleTags(),
209 moduleTranslation));
210
211 if (failed(moduleTranslation.convertArgAndResultAttrs(op, inst)))
212 return failure();
213
214 if (op.getNumResults() == 1)
215 moduleTranslation.mapValue(op->getResults().front()) = inst;
216 return success();
217}
218
219/// Recursively converts an MLIR metadata attribute to an LLVM metadata node.
220static llvm::Metadata *
221convertMetadataAttr(Attribute attr, llvm::IRBuilderBase &builder,
222 LLVM::ModuleTranslation &moduleTranslation) {
224 .Case<LLVM::MDStringAttr>([&](auto a) -> llvm::Metadata * {
225 return llvm::MDString::get(builder.getContext(),
226 a.getValue().getValue());
227 })
228 .Case<LLVM::MDConstantAttr>([&](auto a) -> llvm::Metadata * {
229 IntegerAttr intAttr = llvm::dyn_cast<IntegerAttr>(a.getValue());
230 if (!intAttr)
231 return nullptr;
232 return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
233 llvm::Type::getIntNTy(builder.getContext(),
234 intAttr.getType().getIntOrFloatBitWidth()),
235 intAttr.getValue()));
236 })
237 .Case<LLVM::MDFuncAttr>([&](auto a) -> llvm::Metadata * {
238 if (llvm::Function *fn =
239 moduleTranslation.lookupFunction(a.getName().getValue()))
240 return llvm::ValueAsMetadata::get(fn);
241 return nullptr;
242 })
243 .Case<LLVM::MDNodeAttr>([&](auto a) -> llvm::Metadata * {
245 for (Attribute op : a.getOperands())
246 operands.push_back(
247 convertMetadataAttr(op, builder, moduleTranslation));
248 return llvm::MDNode::get(builder.getContext(), operands);
249 })
250 .Default([](auto) -> llvm::Metadata * { return nullptr; });
251}
252
253static void convertNamedMetadataOp(StringRef metadataName, ArrayAttr nodes,
254 llvm::IRBuilderBase &builder,
255 LLVM::ModuleTranslation &moduleTranslation) {
256 llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
257 llvm::NamedMDNode *namedMD =
258 llvmModule->getOrInsertNamedMetadata(metadataName);
259 for (Attribute nodeAttr : nodes) {
260 llvm::Metadata *md =
261 convertMetadataAttr(nodeAttr, builder, moduleTranslation);
262 if (auto *mdNode = llvm::dyn_cast_or_null<llvm::MDNode>(md))
263 namedMD->addOperand(mdNode);
264 }
265}
266
268 llvm::IRBuilderBase &builder,
269 LLVM::ModuleTranslation &moduleTranslation) {
270 llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
271 llvm::LLVMContext &context = llvmModule->getContext();
272 llvm::NamedMDNode *linkerMDNode =
273 llvmModule->getOrInsertNamedMetadata("llvm.linker.options");
275 mdNodes.reserve(options.size());
276 for (auto s : options.getAsRange<StringAttr>()) {
277 auto *mdNode = llvm::MDString::get(context, s.getValue());
278 mdNodes.push_back(mdNode);
279 }
280
281 auto *listMDNode = llvm::MDTuple::get(context, mdNodes);
282 linkerMDNode->addOperand(listMDNode);
283}
284
285static llvm::Metadata *
286convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr,
287 llvm::IRBuilderBase &builder,
288 LLVM::ModuleTranslation &moduleTranslation) {
289 llvm::LLVMContext &context = builder.getContext();
290 llvm::MDBuilder mdb(context);
292
293 if (key == LLVMDialect::getModuleFlagKeyCGProfileName()) {
294 for (auto entry : arrayAttr.getAsRange<ModuleFlagCGProfileEntryAttr>()) {
295 auto getFuncMetadata = [&](FlatSymbolRefAttr sym) -> llvm::Metadata * {
296 if (!sym)
297 return nullptr;
298 if (llvm::Function *fn =
299 moduleTranslation.lookupFunction(sym.getValue()))
300 return llvm::ValueAsMetadata::get(fn);
301 return nullptr;
302 };
303 llvm::Metadata *fromMetadata = getFuncMetadata(entry.getFrom());
304 llvm::Metadata *toMetadata = getFuncMetadata(entry.getTo());
305
306 llvm::Metadata *vals[] = {
307 fromMetadata, toMetadata,
308 mdb.createConstant(llvm::ConstantInt::get(
309 llvm::Type::getInt64Ty(context), entry.getCount()))};
310 nodes.push_back(llvm::MDNode::get(context, vals));
311 }
312 return llvm::MDTuple::getDistinct(context, nodes);
313 }
314 // Handle ArrayAttr of StringAttrs (e.g. "riscv-isa") by converting back to
315 // an MDTuple of MDStrings for a lossless round-trip.
316 if (llvm::all_of(arrayAttr, [](Attribute a) { return isa<StringAttr>(a); })) {
317 assert(!arrayAttr.empty() &&
318 "empty string-array is invalid per ModuleFlagAttr::verify");
319 for (StringAttr strAttr : arrayAttr.getAsRange<StringAttr>())
320 nodes.push_back(llvm::MDString::get(context, strAttr.getValue()));
321 return llvm::MDTuple::get(context, nodes);
322 }
323 return nullptr;
324}
325
327 StringRef key, ModuleFlagProfileSummaryAttr summaryAttr,
328 llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation) {
329 llvm::LLVMContext &context = builder.getContext();
330 llvm::MDBuilder mdb(context);
331
332 auto getIntTuple = [&](StringRef key, uint64_t val) -> llvm::MDTuple * {
334 mdb.createString(key), mdb.createConstant(llvm::ConstantInt::get(
335 llvm::Type::getInt64Ty(context), val))};
336 return llvm::MDTuple::get(context, tupleNodes);
337 };
338
340 mdb.createString("ProfileFormat"),
341 mdb.createString(
342 stringifyProfileSummaryFormatKind(summaryAttr.getFormat()))};
343
345 llvm::MDTuple::get(context, fmtNode),
346 getIntTuple("TotalCount", summaryAttr.getTotalCount()),
347 getIntTuple("MaxCount", summaryAttr.getMaxCount()),
348 getIntTuple("MaxInternalCount", summaryAttr.getMaxInternalCount()),
349 getIntTuple("MaxFunctionCount", summaryAttr.getMaxFunctionCount()),
350 getIntTuple("NumCounts", summaryAttr.getNumCounts()),
351 getIntTuple("NumFunctions", summaryAttr.getNumFunctions()),
352 };
353
354 if (summaryAttr.getIsPartialProfile())
355 vals.push_back(
356 getIntTuple("IsPartialProfile", *summaryAttr.getIsPartialProfile()));
357
358 if (summaryAttr.getPartialProfileRatio()) {
360 mdb.createString("PartialProfileRatio"),
361 mdb.createConstant(llvm::ConstantFP::get(
362 llvm::Type::getDoubleTy(context),
363 summaryAttr.getPartialProfileRatio().getValue()))};
364 vals.push_back(llvm::MDTuple::get(context, tupleNodes));
365 }
366
367 SmallVector<llvm::Metadata *> detailedEntries;
368 llvm::Type *llvmInt64Type = llvm::Type::getInt64Ty(context);
369 for (ModuleFlagProfileSummaryDetailedAttr detailedEntry :
370 summaryAttr.getDetailedSummary()) {
372 mdb.createConstant(
373 llvm::ConstantInt::get(llvmInt64Type, detailedEntry.getCutOff())),
374 mdb.createConstant(
375 llvm::ConstantInt::get(llvmInt64Type, detailedEntry.getMinCount())),
376 mdb.createConstant(llvm::ConstantInt::get(
377 llvmInt64Type, detailedEntry.getNumCounts()))};
378 detailedEntries.push_back(llvm::MDTuple::get(context, tupleNodes));
379 }
380 SmallVector<llvm::Metadata *> detailedSummary{
381 mdb.createString("DetailedSummary"),
382 llvm::MDTuple::get(context, detailedEntries)};
383 vals.push_back(llvm::MDTuple::get(context, detailedSummary));
384
385 return llvm::MDNode::get(context, vals);
386}
387
388static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
389 LLVM::ModuleTranslation &moduleTranslation) {
390 llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
391 for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
392 llvm::Metadata *valueMetadata =
394 .Case([&](StringAttr strAttr) {
395 return llvm::MDString::get(builder.getContext(),
396 strAttr.getValue());
397 })
398 .Case([&](IntegerAttr intAttr) {
399 return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
400 llvm::Type::getInt32Ty(builder.getContext()),
401 intAttr.getInt()));
402 })
403 .Case([&](ArrayAttr arrayAttr) {
404 return convertModuleFlagValue(flagAttr.getKey().getValue(),
405 arrayAttr, builder,
406 moduleTranslation);
407 })
408 .Case([&](ModuleFlagProfileSummaryAttr summaryAttr) {
410 flagAttr.getKey().getValue(), summaryAttr, builder,
411 moduleTranslation);
412 })
413 .Default([](auto) { return nullptr; });
414
415 assert(valueMetadata && "expected valid metadata");
416 llvmModule->addModuleFlag(
417 convertModFlagBehaviorToLLVM(flagAttr.getBehavior()),
418 flagAttr.getKey().getValue(), valueMetadata);
419 }
420}
421
422/// Looks up the GlobalValue and FunctionType for a callee symbol that is not a
423/// regular LLVM function (i.e. an alias or ifunc). Returns the lowered
424/// GlobalValue and FunctionType derived from \p calleeFuncType.
425static std::pair<llvm::GlobalValue *, llvm::FunctionType *>
427 Operation &opInst,
428 LLVM::ModuleTranslation &moduleTranslation) {
429 Operation *moduleOp = parentLLVMModule(&opInst);
430 Operation *calleeOp =
431 moduleTranslation.symbolTable().lookupSymbolIn(moduleOp, attr);
432 llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
433 moduleTranslation.convertType(calleeFuncType));
434 llvm::GlobalValue *calleeGV;
435 if (isa<LLVM::AliasOp>(calleeOp))
436 calleeGV = moduleTranslation.lookupAlias(calleeOp);
437 else
438 calleeGV = moduleTranslation.lookupIFunc(calleeOp);
439 return {calleeGV, calleeType};
440}
441
442static llvm::DILocalScope *
443getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc,
444 LLVM::ModuleTranslation &moduleTranslation) {
445 if (auto scopeLoc =
447 if (auto *localScope = llvm::dyn_cast<llvm::DILocalScope>(
448 moduleTranslation.translateDebugInfo(scopeLoc.getMetadata())))
449 return localScope;
450 return builder.GetInsertBlock()->getParent()->getSubprogram();
451}
452
453static LogicalResult
454convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
455 LLVM::ModuleTranslation &moduleTranslation) {
456
457 llvm::IRBuilder<>::FastMathFlagGuard fmfGuard(builder);
458 if (auto fmf = dyn_cast<FastmathFlagsInterface>(opInst))
459 builder.setFastMathFlags(getFastmathFlags(fmf));
460
461#include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
462#include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
463
464 // Emit function calls. If the "callee" attribute is present, this is a
465 // direct function call and we also need to look up the remapped function
466 // itself. Otherwise, this is an indirect call and the callee is the first
467 // operand, look it up as a normal value.
468 if (auto callOp = dyn_cast<LLVM::CallOp>(opInst)) {
469 auto operands = moduleTranslation.lookupValues(callOp.getCalleeOperands());
471 convertOperandBundles(callOp.getOpBundleOperands(),
472 callOp.getOpBundleTags(), moduleTranslation);
473 ArrayRef<llvm::Value *> operandsRef(operands);
474 llvm::CallInst *call;
475 if (auto attr = callOp.getCalleeAttr()) {
476 if (llvm::Function *function =
477 moduleTranslation.lookupFunction(attr.getValue())) {
478 call = builder.CreateCall(function, operandsRef, opBundles);
479 } else {
480 auto [calleeGV, calleeType] = lookupNonFunctionSymbolCallee(
481 attr, callOp.getCalleeFunctionType(), opInst, moduleTranslation);
482 call = builder.CreateCall(calleeType, calleeGV, operandsRef, opBundles);
483 }
484 } else {
485 llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
486 moduleTranslation.convertType(callOp.getCalleeFunctionType()));
487 call = builder.CreateCall(calleeType, operandsRef.front(),
488 operandsRef.drop_front(), opBundles);
489 }
490 call->setCallingConv(convertCConvToLLVM(callOp.getCConv()));
491 call->setTailCallKind(convertTailCallKindToLLVM(callOp.getTailCallKind()));
492 if (callOp.getConvergentAttr())
493 call->addFnAttr(llvm::Attribute::Convergent);
494 if (callOp.getNoUnwindAttr())
495 call->addFnAttr(llvm::Attribute::NoUnwind);
496 if (callOp.getWillReturnAttr())
497 call->addFnAttr(llvm::Attribute::WillReturn);
498 if (callOp.getNoreturnAttr())
499 call->addFnAttr(llvm::Attribute::NoReturn);
500 if (callOp.getOptsizeAttr())
501 call->addFnAttr(llvm::Attribute::OptimizeForSize);
502 if (callOp.getMinsizeAttr())
503 call->addFnAttr(llvm::Attribute::MinSize);
504 if (callOp.getSaveRegParamsAttr())
505 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
506 "save-reg-params"));
507 if (callOp.getBuiltinAttr())
508 call->addFnAttr(llvm::Attribute::Builtin);
509 if (callOp.getNobuiltinAttr())
510 call->addFnAttr(llvm::Attribute::NoBuiltin);
511 if (callOp.getReturnsTwiceAttr())
512 call->addFnAttr(llvm::Attribute::ReturnsTwice);
513 if (callOp.getColdAttr())
514 call->addFnAttr(llvm::Attribute::Cold);
515 if (callOp.getHotAttr())
516 call->addFnAttr(llvm::Attribute::Hot);
517 if (callOp.getNoduplicateAttr())
518 call->addFnAttr(llvm::Attribute::NoDuplicate);
519 if (callOp.getNoInlineAttr())
520 call->addFnAttr(llvm::Attribute::NoInline);
521 if (callOp.getAlwaysInlineAttr())
522 call->addFnAttr(llvm::Attribute::AlwaysInline);
523 if (callOp.getInlineHintAttr())
524 call->addFnAttr(llvm::Attribute::InlineHint);
525 if (callOp.getNoCallerSavedRegistersAttr())
526 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
527 "no_caller_saved_registers"));
528 if (callOp.getNocallbackAttr())
529 call->addFnAttr(llvm::Attribute::NoCallback);
530 if (StringAttr modFormat = callOp.getModularFormatAttr())
531 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
532 "modular-format",
533 modFormat.getValue()));
534 if (StringAttr zcsr = callOp.getZeroCallUsedRegsAttr())
535 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
536 "zero-call-used-regs",
537 zcsr.getValue()));
538 if (StringAttr trapFunc = callOp.getTrapFuncNameAttr())
539 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
540 "trap-func-name",
541 trapFunc.getValue()));
542
543 if (ArrayAttr noBuiltins = callOp.getNobuiltinsAttr()) {
544 if (noBuiltins.empty())
545 call->addFnAttr(llvm::Attribute::get(moduleTranslation.getLLVMContext(),
546 "no-builtins"));
547
548 moduleTranslation.convertFunctionAttrCollection(
549 noBuiltins, call, ModuleTranslation::convertNoBuiltin);
550 }
551
552 moduleTranslation.convertFunctionAttrCollection(
553 callOp.getDefaultFuncAttrsAttr(), call,
555
556 if (llvm::Attribute attr =
557 moduleTranslation.convertAllocsizeAttr(callOp.getAllocsizeAttr());
558 attr.isValid())
559 call->addFnAttr(attr);
560
561 if (failed(moduleTranslation.convertArgAndResultAttrs(callOp, call)))
562 return failure();
563
564 if (MemoryEffectsAttr memAttr = callOp.getMemoryEffectsAttr()) {
565 llvm::MemoryEffects memEffects =
566 llvm::MemoryEffects(llvm::MemoryEffects::Location::ArgMem,
567 convertModRefInfoToLLVM(memAttr.getArgMem())) |
568 llvm::MemoryEffects(
569 llvm::MemoryEffects::Location::InaccessibleMem,
570 convertModRefInfoToLLVM(memAttr.getInaccessibleMem())) |
571 llvm::MemoryEffects(llvm::MemoryEffects::Location::Other,
572 convertModRefInfoToLLVM(memAttr.getOther())) |
573 llvm::MemoryEffects(llvm::MemoryEffects::Location::ErrnoMem,
574 convertModRefInfoToLLVM(memAttr.getErrnoMem())) |
575 llvm::MemoryEffects(
576 llvm::MemoryEffects::Location::TargetMem0,
577 convertModRefInfoToLLVM(memAttr.getTargetMem0())) |
578 llvm::MemoryEffects(llvm::MemoryEffects::Location::TargetMem1,
579 convertModRefInfoToLLVM(memAttr.getTargetMem1()));
580 call->setMemoryEffects(memEffects);
581 }
582
583 moduleTranslation.setAccessGroupsMetadata(callOp, call);
584 moduleTranslation.setAliasScopeMetadata(callOp, call);
585 moduleTranslation.setTBAAMetadata(callOp, call);
586 // If the called function has a result, remap the corresponding value. Note
587 // that LLVM IR dialect CallOp has either 0 or 1 result.
588 if (opInst.getNumResults() != 0)
589 moduleTranslation.mapValue(opInst.getResult(0), call);
590 // Check that LLVM call returns void for 0-result functions.
591 else if (!call->getType()->isVoidTy())
592 return failure();
593 moduleTranslation.mapCall(callOp, call);
594 return success();
595 }
596
597 if (auto inlineAsmOp = dyn_cast<LLVM::InlineAsmOp>(opInst)) {
598 // TODO: refactor function type creation which usually occurs in std-LLVM
599 // conversion.
600 SmallVector<Type, 8> operandTypes;
601 llvm::append_range(operandTypes, inlineAsmOp.getOperands().getTypes());
602
603 Type resultType;
604 if (inlineAsmOp.getNumResults() == 0) {
605 resultType = LLVM::LLVMVoidType::get(&moduleTranslation.getContext());
606 } else {
607 assert(inlineAsmOp.getNumResults() == 1);
608 resultType = inlineAsmOp.getResultTypes()[0];
609 }
610 auto ft = LLVM::LLVMFunctionType::get(resultType, operandTypes);
611 llvm::InlineAsm *inlineAsmInst =
612 inlineAsmOp.getAsmDialect()
613 ? llvm::InlineAsm::get(
614 static_cast<llvm::FunctionType *>(
615 moduleTranslation.convertType(ft)),
616 inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
617 inlineAsmOp.getHasSideEffects(),
618 inlineAsmOp.getIsAlignStack(),
619 convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
620 : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
621 moduleTranslation.convertType(ft)),
622 inlineAsmOp.getAsmString(),
623 inlineAsmOp.getConstraints(),
624 inlineAsmOp.getHasSideEffects(),
625 inlineAsmOp.getIsAlignStack());
626 llvm::CallInst *inst = builder.CreateCall(
627 inlineAsmInst,
628 moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
629 inst->setTailCallKind(convertTailCallKindToLLVM(
630 inlineAsmOp.getTailCallKindAttr().getTailCallKind()));
631 if (auto maybeOperandAttrs = inlineAsmOp.getOperandAttrs()) {
632 llvm::AttributeList attrList;
633 for (const auto &it : llvm::enumerate(*maybeOperandAttrs)) {
634 Attribute attr = it.value();
635 if (!attr)
636 continue;
637 DictionaryAttr dAttr = cast<DictionaryAttr>(attr);
638 if (dAttr.empty())
639 continue;
640 TypeAttr tAttr =
641 cast<TypeAttr>(dAttr.get(InlineAsmOp::getElementTypeAttrName()));
642 llvm::AttrBuilder b(moduleTranslation.getLLVMContext());
643 llvm::Type *ty = moduleTranslation.convertType(tAttr.getValue());
644 b.addTypeAttr(llvm::Attribute::ElementType, ty);
645 // shift to account for the returned value (this is always 1 aggregate
646 // value in LLVM).
647 int shift = (opInst.getNumResults() > 0) ? 1 : 0;
648 attrList = attrList.addAttributesAtIndex(
649 moduleTranslation.getLLVMContext(), it.index() + shift, b);
650 }
651 inst->setAttributes(attrList);
652 }
653
654 if (opInst.getNumResults() != 0)
655 moduleTranslation.mapValue(opInst.getResult(0), inst);
656 return success();
657 }
658
659 if (auto invOp = dyn_cast<LLVM::InvokeOp>(opInst)) {
660 auto operands = moduleTranslation.lookupValues(invOp.getCalleeOperands());
662 convertOperandBundles(invOp.getOpBundleOperands(),
663 invOp.getOpBundleTags(), moduleTranslation);
664 ArrayRef<llvm::Value *> operandsRef(operands);
665 llvm::InvokeInst *result;
666 if (auto attr = opInst.getAttrOfType<FlatSymbolRefAttr>("callee")) {
667 if (llvm::Function *function =
668 moduleTranslation.lookupFunction(attr.getValue())) {
669 result = builder.CreateInvoke(
670 function, moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
671 moduleTranslation.lookupBlock(invOp.getSuccessor(1)), operandsRef,
672 opBundles);
673 } else {
674 auto [calleeGV, calleeType] = lookupNonFunctionSymbolCallee(
675 attr, invOp.getCalleeFunctionType(), opInst, moduleTranslation);
676 result = builder.CreateInvoke(
677 calleeType, calleeGV,
678 moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
679 moduleTranslation.lookupBlock(invOp.getSuccessor(1)), operandsRef,
680 opBundles);
681 }
682 } else {
683 llvm::FunctionType *calleeType = llvm::cast<llvm::FunctionType>(
684 moduleTranslation.convertType(invOp.getCalleeFunctionType()));
685 result = builder.CreateInvoke(
686 calleeType, operandsRef.front(),
687 moduleTranslation.lookupBlock(invOp.getSuccessor(0)),
688 moduleTranslation.lookupBlock(invOp.getSuccessor(1)),
689 operandsRef.drop_front(), opBundles);
690 }
691 result->setCallingConv(convertCConvToLLVM(invOp.getCConv()));
692 if (failed(moduleTranslation.convertArgAndResultAttrs(invOp, result)))
693 return failure();
694 moduleTranslation.mapBranch(invOp, result);
695 // InvokeOp can only have 0 or 1 result
696 if (invOp->getNumResults() != 0) {
697 moduleTranslation.mapValue(opInst.getResult(0), result);
698 return success();
699 }
700 return success(result->getType()->isVoidTy());
701 }
702
703 if (auto lpOp = dyn_cast<LLVM::LandingpadOp>(opInst)) {
704 llvm::Type *ty = moduleTranslation.convertType(lpOp.getType());
705 llvm::LandingPadInst *lpi =
706 builder.CreateLandingPad(ty, lpOp.getNumOperands());
707 lpi->setCleanup(lpOp.getCleanup());
708
709 // Add clauses
710 for (llvm::Value *operand :
711 moduleTranslation.lookupValues(lpOp.getOperands())) {
712 // All operands should be constant - checked by verifier
713 if (auto *constOperand = dyn_cast<llvm::Constant>(operand))
714 lpi->addClause(constOperand);
715 }
716 moduleTranslation.mapValue(lpOp.getResult(), lpi);
717 return success();
718 }
719
720 // Emit branches. We need to look up the remapped blocks and ignore the
721 // block arguments that were transformed into PHI nodes.
722 if (auto brOp = dyn_cast<LLVM::BrOp>(opInst)) {
723 llvm::UncondBrInst *branch =
724 builder.CreateBr(moduleTranslation.lookupBlock(brOp.getSuccessor()));
725 moduleTranslation.mapBranch(&opInst, branch);
726 moduleTranslation.setLoopMetadata(&opInst, branch);
727 return success();
728 }
729 if (auto condbrOp = dyn_cast<LLVM::CondBrOp>(opInst)) {
730 llvm::CondBrInst *branch = builder.CreateCondBr(
731 moduleTranslation.lookupValue(condbrOp.getOperand(0)),
732 moduleTranslation.lookupBlock(condbrOp.getSuccessor(0)),
733 moduleTranslation.lookupBlock(condbrOp.getSuccessor(1)));
734 moduleTranslation.mapBranch(&opInst, branch);
735 moduleTranslation.setLoopMetadata(&opInst, branch);
736 return success();
737 }
738 if (auto switchOp = dyn_cast<LLVM::SwitchOp>(opInst)) {
739 llvm::SwitchInst *switchInst = builder.CreateSwitch(
740 moduleTranslation.lookupValue(switchOp.getValue()),
741 moduleTranslation.lookupBlock(switchOp.getDefaultDestination()),
742 switchOp.getCaseDestinations().size());
743
744 // Handle switch with zero cases.
745 if (!switchOp.getCaseValues())
746 return success();
747
748 auto *ty = llvm::cast<llvm::IntegerType>(
749 moduleTranslation.convertType(switchOp.getValue().getType()));
750 for (auto i :
751 llvm::zip(llvm::cast<DenseIntElementsAttr>(*switchOp.getCaseValues()),
752 switchOp.getCaseDestinations()))
753 switchInst->addCase(
754 llvm::ConstantInt::get(ty, std::get<0>(i).getLimitedValue()),
755 moduleTranslation.lookupBlock(std::get<1>(i)));
756
757 moduleTranslation.mapBranch(&opInst, switchInst);
758 return success();
759 }
760 if (auto indBrOp = dyn_cast<LLVM::IndirectBrOp>(opInst)) {
761 llvm::IndirectBrInst *indBr = builder.CreateIndirectBr(
762 moduleTranslation.lookupValue(indBrOp.getAddr()),
763 indBrOp->getNumSuccessors());
764 for (auto *succ : indBrOp.getSuccessors())
765 indBr->addDestination(moduleTranslation.lookupBlock(succ));
766 moduleTranslation.mapBranch(&opInst, indBr);
767 return success();
768 }
769
770 // Emit addressof. We need to look up the global value referenced by the
771 // operation and store it in the MLIR-to-LLVM value mapping. This does not
772 // emit any LLVM instruction.
773 if (auto addressOfOp = dyn_cast<LLVM::AddressOfOp>(opInst)) {
774 LLVM::GlobalOp global =
775 addressOfOp.getGlobal(moduleTranslation.symbolTable());
776 LLVM::LLVMFuncOp function =
777 addressOfOp.getFunction(moduleTranslation.symbolTable());
778 LLVM::AliasOp alias = addressOfOp.getAlias(moduleTranslation.symbolTable());
779 LLVM::IFuncOp ifunc = addressOfOp.getIFunc(moduleTranslation.symbolTable());
780
781 // The verifier should not have allowed this.
782 assert((global || function || alias || ifunc) &&
783 "referencing an undefined global, function, alias, or ifunc");
784
785 llvm::Value *llvmValue = nullptr;
786 if (global)
787 llvmValue = moduleTranslation.lookupGlobal(global);
788 else if (alias)
789 llvmValue = moduleTranslation.lookupAlias(alias);
790 else if (function)
791 llvmValue = moduleTranslation.lookupFunction(function.getName());
792 else
793 llvmValue = moduleTranslation.lookupIFunc(ifunc);
794
795 moduleTranslation.mapValue(addressOfOp.getResult(), llvmValue);
796 return success();
797 }
798
799 // Emit dso_local_equivalent. We need to look up the global value referenced
800 // by the operation and store it in the MLIR-to-LLVM value mapping.
801 if (auto dsoLocalEquivalentOp =
802 dyn_cast<LLVM::DSOLocalEquivalentOp>(opInst)) {
803 LLVM::LLVMFuncOp function =
804 dsoLocalEquivalentOp.getFunction(moduleTranslation.symbolTable());
805 LLVM::AliasOp alias =
806 dsoLocalEquivalentOp.getAlias(moduleTranslation.symbolTable());
807
808 // The verifier should not have allowed this.
809 assert((function || alias) &&
810 "referencing an undefined function, or alias");
811
812 llvm::Value *llvmValue = nullptr;
813 if (alias)
814 llvmValue = moduleTranslation.lookupAlias(alias);
815 else
816 llvmValue = moduleTranslation.lookupFunction(function.getName());
817
818 moduleTranslation.mapValue(
819 dsoLocalEquivalentOp.getResult(),
820 llvm::DSOLocalEquivalent::get(cast<llvm::GlobalValue>(llvmValue)));
821 return success();
822 }
823
824 // Emit blockaddress. We first need to find the LLVM block referenced by this
825 // operation and then create a LLVM block address for it.
826 if (auto blockAddressOp = dyn_cast<LLVM::BlockAddressOp>(opInst)) {
827 BlockAddressAttr blockAddressAttr = blockAddressOp.getBlockAddr();
828 llvm::BasicBlock *llvmBlock =
829 moduleTranslation.lookupBlockAddress(blockAddressAttr);
830
831 llvm::Value *llvmValue = nullptr;
832 StringRef fnName = blockAddressAttr.getFunction().getValue();
833 if (llvmBlock) {
834 llvm::Function *llvmFn = moduleTranslation.lookupFunction(fnName);
835 llvmValue = llvm::BlockAddress::get(llvmFn, llvmBlock);
836 } else {
837 // The matching LLVM block is not yet emitted, a placeholder is created
838 // in its place. When the LLVM block is emitted later in translation,
839 // the llvmValue is replaced with the actual llvm::BlockAddress.
840 // A GlobalVariable is chosen as placeholder because in general LLVM
841 // constants are uniqued and are not proper for RAUW, since that could
842 // harm unrelated uses of the constant.
843 llvmValue = new llvm::GlobalVariable(
844 *moduleTranslation.getLLVMModule(),
845 llvm::PointerType::getUnqual(moduleTranslation.getLLVMContext()),
846 /*isConstant=*/true, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
847 /*Initializer=*/nullptr,
848 Twine("__mlir_block_address_")
849 .concat(Twine(fnName))
850 .concat(Twine((uint64_t)blockAddressOp.getOperation())));
851 moduleTranslation.mapUnresolvedBlockAddress(blockAddressOp, llvmValue);
852 }
853
854 moduleTranslation.mapValue(blockAddressOp.getResult(), llvmValue);
855 return success();
856 }
857
858 // Emit block label. If this label is seen before BlockAddressOp is
859 // translated, go ahead and already map it.
860 if (auto blockTagOp = dyn_cast<LLVM::BlockTagOp>(opInst)) {
861 auto funcOp = blockTagOp->getParentOfType<LLVMFuncOp>();
862 BlockAddressAttr blockAddressAttr = BlockAddressAttr::get(
863 &moduleTranslation.getContext(),
864 FlatSymbolRefAttr::get(&moduleTranslation.getContext(),
865 funcOp.getName()),
866 blockTagOp.getTag());
867 moduleTranslation.mapBlockAddress(blockAddressAttr,
868 builder.GetInsertBlock());
869 return success();
870 }
871
872 return failure();
873}
874
875static LogicalResult
877 NamedAttribute attribute,
878 LLVM::ModuleTranslation &moduleTranslation) {
879 StringRef name = attribute.getName();
880 if (name == LLVMDialect::getMmraAttrName()) {
882 if (auto oneTag = dyn_cast<LLVM::MMRATagAttr>(attribute.getValue())) {
883 tags.emplace_back(oneTag.getPrefix(), oneTag.getSuffix());
884 } else if (auto manyTags = dyn_cast<ArrayAttr>(attribute.getValue())) {
885 for (Attribute attr : manyTags) {
886 auto tag = dyn_cast<MMRATagAttr>(attr);
887 if (!tag)
888 return op.emitOpError(
889 "MMRA annotations array contains value that isn't an MMRA tag");
890 tags.emplace_back(tag.getPrefix(), tag.getSuffix());
891 }
892 } else {
893 return op.emitOpError(
894 "llvm.mmra is something other than an MMRA tag or an array of them");
895 }
896 llvm::MDTuple *mmraMd =
897 llvm::MMRAMetadata::getMD(moduleTranslation.getLLVMContext(), tags);
898 if (!mmraMd) {
899 // Empty list, canonicalizes to nothing
900 return success();
901 }
902 for (llvm::Instruction *inst : instructions)
903 inst->setMetadata(llvm::LLVMContext::MD_mmra, mmraMd);
904 return success();
905 }
906 return success();
907}
908
909namespace {
910/// Implementation of the dialect interface that converts operations belonging
911/// to the LLVM dialect to LLVM IR.
912class LLVMDialectLLVMIRTranslationInterface
913 : public LLVMTranslationDialectInterface {
914public:
915 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
916
917 /// Translates the given operation to LLVM IR using the provided IR builder
918 /// and saving the state in `moduleTranslation`.
919 LogicalResult
920 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
921 LLVM::ModuleTranslation &moduleTranslation) const final {
922 return convertOperationImpl(*op, builder, moduleTranslation);
923 }
924
925 /// Handle some metadata that is represented as a discardable attribute.
926 LogicalResult
927 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
928 NamedAttribute attribute,
929 LLVM::ModuleTranslation &moduleTranslation) const final {
930 return amendOperationImpl(*op, instructions, attribute, moduleTranslation);
931 }
932};
933} // namespace
934
936 registry.insert<LLVM::LLVMDialect>();
937 registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
938 dialect->addInterfaces<LLVMDialectLLVMIRTranslationInterface>();
939 });
940}
941
943 DialectRegistry registry;
945 context.appendDialectRegistry(registry);
946}
return success()
static std::string diagStr(const llvm::Type *type)
Convert an LLVM type to a string for printing in diagnostics.
static llvm::Metadata * convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static SmallVector< llvm::OperandBundleDef > convertOperandBundles(OperandRangeRange bundleOperands, ArrayAttr bundleTags, LLVM::ModuleTranslation &moduleTranslation)
static std::pair< llvm::GlobalValue *, llvm::FunctionType * > lookupNonFunctionSymbolCallee(FlatSymbolRefAttr attr, mlir::Type calleeFuncType, Operation &opInst, LLVM::ModuleTranslation &moduleTranslation)
Looks up the GlobalValue and FunctionType for a callee symbol that is not a regular LLVM function (i....
static FailureOr< llvm::Function * > getOverloadedDeclaration(CallIntrinsicOp op, llvm::Intrinsic::ID id, llvm::Module *module, LLVM::ModuleTranslation &moduleTranslation)
Get the declaration of an overloaded llvm intrinsic.
static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Metadata * convertMetadataAttr(Attribute attr, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Recursively converts an MLIR metadata attribute to an LLVM metadata node.
static void convertNamedMetadataOp(StringRef metadataName, ArrayAttr nodes, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static LogicalResult convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
Builder for LLVM_CallIntrinsicOp.
static LogicalResult amendOperationImpl(Operation &op, ArrayRef< llvm::Instruction * > instructions, NamedAttribute attribute, LLVM::ModuleTranslation &moduleTranslation)
static llvm::FastMathFlags getFastmathFlags(FastmathFlagsInterface &op)
static llvm::OperandBundleDef convertOperandBundle(OperandRange bundleOperands, StringRef bundleTag, LLVM::ModuleTranslation &moduleTranslation)
static SmallVector< unsigned > extractPosition(ArrayRef< int64_t > indices)
Convert the value of a DenseI64ArrayAttr to a vector of unsigned indices.
static llvm::DILocalScope * getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc, LLVM::ModuleTranslation &moduleTranslation)
static llvm::Metadata * convertModuleFlagProfileSummaryAttr(StringRef key, ModuleFlagProfileSummaryAttr summaryAttr, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
static void convertLinkerOptionsOp(ArrayAttr options, llvm::IRBuilderBase &builder, LLVM::ModuleTranslation &moduleTranslation)
b
Return true if permutation is a valid permutation of the outer_dims_perm (case OuterOrInnerPerm::Oute...
ArrayAttr()
static llvm::ManagedStatic< PassManagerOptions > options
Attributes are known-constant values of operations.
Definition Attributes.h:25
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
A symbol reference with a reference path containing a single element.
static FlatSymbolRefAttr get(StringAttr value)
Construct a symbol reference for the given value name.
This class represents a fused location whose metadata is known to be an instance of the given type.
Definition Location.h:149
Implementation class for module translation.
void mapUnresolvedBlockAddress(BlockAddressOp op, llvm::Value *cst)
Maps a blockaddress operation to its corresponding placeholder LLVM value.
void mapCall(Operation *mlir, llvm::CallInst *llvm)
Stores a mapping between an MLIR call operation and a corresponding LLVM call instruction.
llvm::BasicBlock * lookupBlock(Block *block) const
Finds an LLVM IR basic block that corresponds to the given MLIR block.
llvm::Attribute convertAllocsizeAttr(DenseI32ArrayAttr allocsizeAttr)
MLIRContext & getContext()
Returns the MLIR context of the module being translated.
void mapBranch(Operation *mlir, llvm::Instruction *llvm)
Stores the mapping between an MLIR operation with successors and a corresponding LLVM IR instruction.
SmallVector< llvm::Value * > lookupValues(ValueRange values)
Looks up remapped a list of remapped values.
void convertFunctionAttrCollection(AttrsTy attrs, Operation *op, const Converter &conv)
A template that takes a collection-like attribute, and converts it via a user provided callback,...
llvm::Value * lookupValue(Value value) const
Finds an LLVM IR value corresponding to the given MLIR value.
LogicalResult convertArgAndResultAttrs(ArgAndResultAttrsOpInterface attrsOp, llvm::CallBase *call, ArrayRef< unsigned > immArgPositions={})
Converts argument and result attributes from attrsOp to LLVM IR attributes on the call instruction.
static std::optional< llvm::Attribute > convertNoBuiltin(llvm::LLVMContext &ctx, mlir::Attribute a)
SymbolTableCollection & symbolTable()
llvm::Type * convertType(Type type)
Converts the type from MLIR LLVM dialect to LLVM.
void setTBAAMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
Sets LLVM TBAA metadata for memory operations that have TBAA attributes.
llvm::GlobalValue * lookupGlobal(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global value.
llvm::BasicBlock * lookupBlockAddress(BlockAddressAttr attr) const
Finds the LLVM basic block that corresponds to the given BlockAddressAttr.
llvm::GlobalValue * lookupIFunc(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining an IFunc.
llvm::Metadata * translateDebugInfo(LLVM::DINodeAttr attr)
Translates the given LLVM debug info metadata.
llvm::GlobalValue * lookupAlias(Operation *op)
Finds an LLVM IR global value that corresponds to the given MLIR operation defining a global alias va...
llvm::Function * lookupFunction(StringRef name) const
Finds an LLVM IR function by its name.
llvm::Module * getLLVMModule()
Returns the LLVM module in which the IR is being constructed.
static std::optional< llvm::Attribute > convertDefaultFuncAttr(llvm::LLVMContext &ctx, mlir::NamedAttribute namedAttr)
void setAliasScopeMetadata(AliasAnalysisOpInterface op, llvm::Instruction *inst)
void setAccessGroupsMetadata(AccessGroupOpInterface op, llvm::Instruction *inst)
void mapValue(Value mlir, llvm::Value *llvm)
Stores the mapping between an MLIR value and its LLVM IR counterpart.
llvm::LLVMContext & getLLVMContext() const
Returns the LLVM context in which the IR is being constructed.
void mapBlockAddress(BlockAddressAttr attr, llvm::BasicBlock *block)
Maps a BlockAddressAttr to its corresponding LLVM basic block.
void setLoopMetadata(Operation *op, llvm::Instruction *inst)
Sets LLVM loop metadata for branch operations that have a loop annotation attribute.
T findInstanceOf()
Return an instance of the given location type if one is nested under the current location.
Definition Location.h:45
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition Location.h:76
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
void appendDialectRegistry(const DialectRegistry &registry)
Append the contents of the given dialect registry to the registry associated with this context.
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
StringAttr getName() const
Return the name of the attribute.
Attribute getValue() const
Return the value of the attribute.
Definition Attributes.h:179
This class represents a contiguous range of operand ranges, e.g.
Definition ValueRange.h:85
This class implements the operand iterators for the Operation class.
Definition ValueRange.h:44
Operation is the basic unit of execution within MLIR.
Definition Operation.h:88
AttrClass getAttrOfType(StringAttr name)
Definition Operation.h:576
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition Operation.h:433
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
unsigned getNumResults()
Return the number of results held by this operation.
Definition Operation.h:430
virtual Operation * lookupSymbolIn(Operation *symbolTableOp, StringAttr symbol)
Look up a symbol with the specified name within the specified symbol table operation,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition Value.h:96
llvm::Constant * getLLVMConstant(llvm::Type *llvmType, Attribute attr, Location loc, const ModuleTranslation &moduleTranslation)
Create an LLVM IR constant of llvmType from the MLIR attribute attr.
Operation * parentLLVMModule(Operation *op)
Lookup parent Module satisfying LLVM conditions on the Module Operation.
Include the generated interface declarations.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void registerLLVMDialectTranslation(DialectRegistry &registry)
Register the LLVM dialect and the translation from it to the LLVM IR in the given registry;.