1//===- TestToLLVMIRTranslation.cpp - Translate Test 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 Test dialect and LLVM IR.
10//
11//===----------------------------------------------------------------------===//
12
13#include "TestDialect.h"
14#include "TestOps.h"
15#include "mlir/IR/Builders.h"
16#include "mlir/IR/BuiltinAttributes.h"
17#include "mlir/IR/BuiltinOps.h"
18#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
19#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
20#include "mlir/Target/LLVMIR/LLVMTranslationInterface.h"
21#include "mlir/Target/LLVMIR/ModuleTranslation.h"
22#include "mlir/Tools/mlir-translate/Translation.h"
23#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/TypeSwitch.h"
25
26using namespace mlir;
27
28namespace {
29
30class TestDialectLLVMIRTranslationInterface
31 : public LLVMTranslationDialectInterface {
32public:
33 using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
34
35 LogicalResult
36 amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
37 NamedAttribute attribute,
38 LLVM::ModuleTranslation &moduleTranslation) const final;
39
40 LogicalResult
41 convertOperation(Operation *op, llvm::IRBuilderBase &builder,
42 LLVM::ModuleTranslation &moduleTranslation) const final;
43};
44
45} // namespace
46
47LogicalResult TestDialectLLVMIRTranslationInterface::amendOperation(
48 Operation *op, ArrayRef<llvm::Instruction *> instructions,
49 NamedAttribute attribute,
50 LLVM::ModuleTranslation &moduleTranslation) const {
51 return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
52 attribute.getName())
53 // The `test.discardable_mod_attr` attribute, if present and set to
54 // `true`, results in the addition of a `test.symbol` in the module it is
55 // attached to with name "sym_from_attr".
56 .Case(S: "test.discardable_mod_attr",
57 Value: [&](Attribute attr) {
58 if (!isa<ModuleOp>(Val: op)) {
59 op->emitOpError(message: "attribute 'test.discardable_mod_attr' only "
60 "supported in modules");
61 return failure();
62 }
63
64 bool createSymbol = false;
65 if (auto boolAttr = dyn_cast<BoolAttr>(Val&: attr))
66 createSymbol = boolAttr.getValue();
67
68 if (createSymbol) {
69 OpBuilder builder(op->getRegion(index: 0));
70 builder.create<test::SymbolOp>(
71 op->getLoc(),
72 StringAttr::get(op->getContext(), "sym_from_attr"),
73 /*sym_visibility=*/nullptr);
74 }
75
76 return success();
77 })
78 .Case(S: "test.add_annotation",
79 Value: [&](Attribute attr) {
80 for (llvm::Instruction *instruction : instructions) {
81 if (auto strAttr = dyn_cast<StringAttr>(attr)) {
82 instruction->addAnnotationMetadata("annotation_from_test: " +
83 strAttr.getValue().str());
84 } else {
85 instruction->addAnnotationMetadata(Annotation: "annotation_from_test");
86 }
87 }
88 return success();
89 })
90 .Default(Value: [](Attribute) {
91 // Skip other discardable dialect attributes.
92 return success();
93 })(attribute.getValue());
94}
95
96LogicalResult TestDialectLLVMIRTranslationInterface::convertOperation(
97 Operation *op, llvm::IRBuilderBase &builder,
98 LLVM::ModuleTranslation &moduleTranslation) const {
99 return llvm::TypeSwitch<Operation *, LogicalResult>(op)
100 // `test.symbol`s are translated into global integers in LLVM IR, with a
101 // name equal to the symbol they are translated from.
102 .Case(caseFn: [&](test::SymbolOp symOp) {
103 llvm::Module *mod = moduleTranslation.getLLVMModule();
104 llvm::IntegerType *i32Type =
105 llvm::IntegerType::get(C&: moduleTranslation.getLLVMContext(), NumBits: 32);
106 mod->getOrInsertGlobal(symOp.getSymName(), i32Type);
107 return success();
108 })
109 .Default(defaultFn: [&](Operation *) {
110 return op->emitOpError(message: "unsupported translation of test operation");
111 });
112}
113
114namespace mlir {
115
116void registerTestToLLVMIR() {
117 TranslateFromMLIRRegistration registration(
118 "test-to-llvmir", "test dialect to LLVM IR",
119 [](Operation *op, raw_ostream &output) {
120 llvm::LLVMContext llvmContext;
121 auto llvmModule = translateModuleToLLVMIR(module: op, llvmContext);
122 if (!llvmModule)
123 return failure();
124
125 llvmModule->print(OS&: output, AAW: nullptr);
126 return success();
127 },
128 [](DialectRegistry &registry) {
129 registry.insert<test::TestDialect>();
130 registerBuiltinDialectTranslation(registry);
131 registerLLVMDialectTranslation(registry);
132 registry.addExtension(
133 extensionFn: +[](MLIRContext *ctx, test::TestDialect *dialect) {
134 dialect->addInterfaces<TestDialectLLVMIRTranslationInterface>();
135 });
136 });
137}
138
139} // namespace mlir
140

source code of mlir/test/lib/Dialect/Test/TestToLLVMIRTranslation.cpp