xref: /llvm-project/mlir/include/mlir/Tools/mlir-translate/Translation.h (revision 0a81ace0047a2de93e71c82cdf0977fc989660df)
1 //===- Translation.h - Translation registry ---------------------*- C++ -*-===//
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 // Registry for user-provided translations.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef MLIR_TOOLS_MLIRTRANSLATE_TRANSLATION_H
14 #define MLIR_TOOLS_MLIRTRANSLATE_TRANSLATION_H
15 
16 #include "mlir/IR/Operation.h"
17 #include "llvm/Support/CommandLine.h"
18 #include <optional>
19 
20 namespace mlir {
21 template <typename OpTy>
22 class OwningOpRef;
23 
24 /// Interface of the function that translates the sources managed by `sourceMgr`
25 /// to MLIR. The source manager has at least one buffer. The implementation
26 /// should create a new MLIR Operation in the given context and return a
27 /// pointer to it, or a nullptr in case of any error.
28 using TranslateSourceMgrToMLIRFunction = std::function<OwningOpRef<Operation *>(
29     const std::shared_ptr<llvm::SourceMgr> &sourceMgr, MLIRContext *)>;
30 using TranslateRawSourceMgrToMLIRFunction =
31     std::function<OwningOpRef<Operation *>(llvm::SourceMgr &sourceMgr,
32                                            MLIRContext *)>;
33 
34 /// Interface of the function that translates the given string to MLIR. The
35 /// implementation should create a new MLIR Operation in the given context. If
36 /// source-related error reporting is required from within the function, use
37 /// TranslateSourceMgrToMLIRFunction instead.
38 using TranslateStringRefToMLIRFunction =
39     std::function<OwningOpRef<Operation *>(llvm::StringRef, MLIRContext *)>;
40 
41 /// Interface of the function that translates MLIR to a different format and
42 /// outputs the result to a stream. It is allowed to modify the operation.
43 using TranslateFromMLIRFunction =
44     std::function<LogicalResult(Operation *, llvm::raw_ostream &output)>;
45 
46 /// Interface of the function that performs file-to-file translation involving
47 /// MLIR. The input file is held in the given MemoryBuffer; the output file
48 /// should be written to the given raw_ostream. The implementation should create
49 /// all MLIR constructs needed during the process inside the given context. This
50 /// can be used for round-tripping external formats through the MLIR system.
51 using TranslateFunction = std::function<LogicalResult(
52     const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
53     llvm::raw_ostream &output, MLIRContext *)>;
54 
55 /// Interface of the function that adds all dialects and dialect extensions used
56 /// for the translation to the given DialectRegistry.
57 using DialectRegistrationFunction = std::function<void(DialectRegistry &)>;
58 
59 /// This class contains all of the components necessary for performing a
60 /// translation.
61 class Translation {
62 public:
63   Translation() = default;
Translation(TranslateFunction function,StringRef description,std::optional<llvm::Align> inputAlignment)64   Translation(TranslateFunction function, StringRef description,
65               std::optional<llvm::Align> inputAlignment)
66       : function(std::move(function)), description(description),
67         inputAlignment(inputAlignment) {}
68 
69   /// Return the description of this translation.
getDescription()70   StringRef getDescription() const { return description; }
71 
72   /// Return the optional alignment desired for the input of the translation.
getInputAlignment()73   std::optional<llvm::Align> getInputAlignment() const {
74     return inputAlignment;
75   }
76 
77   /// Invoke the translation function with the given input and output streams.
operator()78   LogicalResult operator()(const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
79                            llvm::raw_ostream &output,
80                            MLIRContext *context) const {
81     return function(sourceMgr, output, context);
82   }
83 
84 private:
85   /// The underlying translation function.
86   TranslateFunction function;
87 
88   /// The description of the translation.
89   StringRef description;
90 
91   /// An optional alignment desired for the input of the translation.
92   std::optional<llvm::Align> inputAlignment;
93 };
94 
95 /// Use Translate[ToMLIR|FromMLIR]Registration as an initializer that
96 /// registers a function and associates it with name. This requires that a
97 /// translation has not been registered to a given name. `inputAlign` is an
98 /// optional expected alignment for the input data.
99 ///
100 /// Usage:
101 ///
102 ///   // At file scope.
103 ///   namespace mlir {
104 ///   void registerTRexToMLIRRegistration() {
105 ///     TranslateToMLIRRegistration Unused(&MySubCommand, [] { ... });
106 ///   }
107 ///   } // namespace mlir
108 ///
109 /// \{
110 struct TranslateToMLIRRegistration {
111   TranslateToMLIRRegistration(
112       llvm::StringRef name, llvm::StringRef description,
113       const TranslateSourceMgrToMLIRFunction &function,
114       const DialectRegistrationFunction &dialectRegistration =
115           [](DialectRegistry &) {},
116       std::optional<llvm::Align> inputAlignment = std::nullopt);
117   TranslateToMLIRRegistration(
118       llvm::StringRef name, llvm::StringRef description,
119       const TranslateRawSourceMgrToMLIRFunction &function,
120       const DialectRegistrationFunction &dialectRegistration =
121           [](DialectRegistry &) {},
122       std::optional<llvm::Align> inputAlignment = std::nullopt);
123   TranslateToMLIRRegistration(
124       llvm::StringRef name, llvm::StringRef description,
125       const TranslateStringRefToMLIRFunction &function,
126       const DialectRegistrationFunction &dialectRegistration =
127           [](DialectRegistry &) {},
128       std::optional<llvm::Align> inputAlignment = std::nullopt);
129 };
130 
131 struct TranslateFromMLIRRegistration {
132   TranslateFromMLIRRegistration(
133       llvm::StringRef name, llvm::StringRef description,
134       const TranslateFromMLIRFunction &function,
135       const DialectRegistrationFunction &dialectRegistration =
136           [](DialectRegistry &) {});
137 
138   template <typename FuncTy, typename OpTy = detail::first_argument<FuncTy>,
139             typename = std::enable_if_t<!std::is_same_v<OpTy, Operation *>>>
140   TranslateFromMLIRRegistration(
141       llvm::StringRef name, llvm::StringRef description, FuncTy function,
142       const DialectRegistrationFunction &dialectRegistration =
143           [](DialectRegistry &) {})
144       : TranslateFromMLIRRegistration(
145             name, description,
146             [function](Operation *op, raw_ostream &os) -> LogicalResult {
147               if (auto casted = dyn_cast<OpTy>(op))
148                 return function(casted, os);
149               return emitError(op->getLoc())
150                      << "expected a '" << OpTy::getOperationName()
151                      << "' op, got '" << op->getName().getStringRef() << "'";
152             },
153             dialectRegistration) {}
154 };
155 struct TranslateRegistration {
156   TranslateRegistration(llvm::StringRef name, llvm::StringRef description,
157                         const TranslateFunction &function);
158 };
159 /// \}
160 
161 /// A command line parser for translation functions.
162 struct TranslationParser : public llvm::cl::parser<const Translation *> {
163   TranslationParser(llvm::cl::Option &opt);
164 
165   void printOptionInfo(const llvm::cl::Option &o,
166                        size_t globalWidth) const override;
167 };
168 
169 /// Register command-line options used by the translation registry.
170 void registerTranslationCLOptions();
171 
172 } // namespace mlir
173 
174 #endif // MLIR_TOOLS_MLIRTRANSLATE_TRANSLATION_H
175