xref: /llvm-project/mlir/test/lib/Dialect/Test/TestToLLVMIRTranslation.cpp (revision 48f8d95f337a9c97c5d00eb15eb43fdaa9b23235)
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 #include "llvm/IR/DebugProgramInstruction.h"
26 
27 extern llvm::cl::opt<bool> WriteNewDbgInfoFormat;
28 
29 using namespace mlir;
30 
31 namespace {
32 
33 class TestDialectLLVMIRTranslationInterface
34     : public LLVMTranslationDialectInterface {
35 public:
36   using LLVMTranslationDialectInterface::LLVMTranslationDialectInterface;
37 
38   LogicalResult
39   amendOperation(Operation *op, ArrayRef<llvm::Instruction *> instructions,
40                  NamedAttribute attribute,
41                  LLVM::ModuleTranslation &moduleTranslation) const final;
42 
43   LogicalResult
44   convertOperation(Operation *op, llvm::IRBuilderBase &builder,
45                    LLVM::ModuleTranslation &moduleTranslation) const final;
46 };
47 
48 } // namespace
49 
amendOperation(Operation * op,ArrayRef<llvm::Instruction * > instructions,NamedAttribute attribute,LLVM::ModuleTranslation & moduleTranslation) const50 LogicalResult TestDialectLLVMIRTranslationInterface::amendOperation(
51     Operation *op, ArrayRef<llvm::Instruction *> instructions,
52     NamedAttribute attribute,
53     LLVM::ModuleTranslation &moduleTranslation) const {
54   return llvm::StringSwitch<llvm::function_ref<LogicalResult(Attribute)>>(
55              attribute.getName())
56       // The `test.discardable_mod_attr` attribute, if present and set to
57       // `true`, results in the addition of a `test.symbol` in the module it is
58       // attached to with name "sym_from_attr".
59       .Case("test.discardable_mod_attr",
60             [&](Attribute attr) {
61               if (!isa<ModuleOp>(op)) {
62                 op->emitOpError("attribute 'test.discardable_mod_attr' only "
63                                 "supported in modules");
64                 return failure();
65               }
66 
67               bool createSymbol = false;
68               if (auto boolAttr = dyn_cast<BoolAttr>(attr))
69                 createSymbol = boolAttr.getValue();
70 
71               if (createSymbol) {
72                 OpBuilder builder(op->getRegion(0));
73                 builder.create<test::SymbolOp>(
74                     op->getLoc(),
75                     StringAttr::get(op->getContext(), "sym_from_attr"),
76                     /*sym_visibility=*/nullptr);
77               }
78 
79               return success();
80             })
81       .Case("test.add_annotation",
82             [&](Attribute attr) {
83               for (llvm::Instruction *instruction : instructions) {
84                 if (auto strAttr = dyn_cast<StringAttr>(attr)) {
85                   instruction->addAnnotationMetadata("annotation_from_test: " +
86                                                      strAttr.getValue().str());
87                 } else {
88                   instruction->addAnnotationMetadata("annotation_from_test");
89                 }
90               }
91               return success();
92             })
93       .Default([](Attribute) {
94         // Skip other discardable dialect attributes.
95         return success();
96       })(attribute.getValue());
97 }
98 
convertOperation(Operation * op,llvm::IRBuilderBase & builder,LLVM::ModuleTranslation & moduleTranslation) const99 LogicalResult TestDialectLLVMIRTranslationInterface::convertOperation(
100     Operation *op, llvm::IRBuilderBase &builder,
101     LLVM::ModuleTranslation &moduleTranslation) const {
102   return llvm::TypeSwitch<Operation *, LogicalResult>(op)
103       // `test.symbol`s are translated into global integers in LLVM IR, with a
104       // name equal to the symbol they are translated from.
105       .Case([&](test::SymbolOp symOp) {
106         llvm::Module *mod = moduleTranslation.getLLVMModule();
107         llvm::IntegerType *i32Type =
108             llvm::IntegerType::get(moduleTranslation.getLLVMContext(), 32);
109         mod->getOrInsertGlobal(symOp.getSymName(), i32Type);
110         return success();
111       })
112       .Default([&](Operation *) {
113         return op->emitOpError("unsupported translation of test operation");
114       });
115 }
116 
117 namespace mlir {
118 
registerTestToLLVMIR()119 void registerTestToLLVMIR() {
120   TranslateFromMLIRRegistration registration(
121       "test-to-llvmir", "test dialect to LLVM IR",
122       [](Operation *op, raw_ostream &output) {
123         llvm::LLVMContext llvmContext;
124         auto llvmModule = translateModuleToLLVMIR(op, llvmContext);
125         if (!llvmModule)
126           return failure();
127 
128         // When printing LLVM IR, we should convert the module to the debug info
129         // format that LLVM expects us to print.
130         // See https://llvm.org/docs/RemoveDIsDebugInfo.html
131         llvm::ScopedDbgInfoFormatSetter formatSetter(*llvmModule,
132                                                      WriteNewDbgInfoFormat);
133         if (WriteNewDbgInfoFormat)
134           llvmModule->removeDebugIntrinsicDeclarations();
135         llvmModule->print(output, nullptr);
136         return success();
137       },
138       [](DialectRegistry &registry) {
139         registry.insert<test::TestDialect>();
140         registerBuiltinDialectTranslation(registry);
141         registerLLVMDialectTranslation(registry);
142         registry.addExtension(
143             +[](MLIRContext *ctx, test::TestDialect *dialect) {
144               dialect->addInterfaces<TestDialectLLVMIRTranslationInterface>();
145             });
146       });
147 }
148 
149 } // namespace mlir
150