1//===- Translation.cpp - Translation registry -----------------------------===//
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// Definitions of the translation registry.
10//
11//===----------------------------------------------------------------------===//
12
13#include "mlir/Tools/mlir-translate/Translation.h"
14#include "mlir/IR/AsmState.h"
15#include "mlir/IR/BuiltinOps.h"
16#include "mlir/IR/Dialect.h"
17#include "mlir/IR/Verifier.h"
18#include "mlir/Parser/Parser.h"
19#include "mlir/Tools/ParseUtilities.h"
20#include "llvm/Support/SourceMgr.h"
21#include <optional>
22
23using namespace mlir;
24
25//===----------------------------------------------------------------------===//
26// Translation CommandLine Options
27//===----------------------------------------------------------------------===//
28
29struct TranslationOptions {
30 llvm::cl::opt<bool> noImplicitModule{
31 "no-implicit-module",
32 llvm::cl::desc("Disable the parsing of an implicit top-level module op"),
33 llvm::cl::init(Val: false)};
34};
35
36static llvm::ManagedStatic<TranslationOptions> clOptions;
37
38void mlir::registerTranslationCLOptions() { *clOptions; }
39
40//===----------------------------------------------------------------------===//
41// Translation Registry
42//===----------------------------------------------------------------------===//
43
44/// Get the mutable static map between registered file-to-file MLIR
45/// translations.
46static llvm::StringMap<Translation> &getTranslationRegistry() {
47 static llvm::StringMap<Translation> translationBundle;
48 return translationBundle;
49}
50
51/// Register the given translation.
52static void registerTranslation(StringRef name, StringRef description,
53 std::optional<llvm::Align> inputAlignment,
54 const TranslateFunction &function) {
55 auto &registry = getTranslationRegistry();
56 if (registry.count(Key: name))
57 llvm::report_fatal_error(
58 reason: "Attempting to overwrite an existing <file-to-file> function");
59 assert(function &&
60 "Attempting to register an empty translate <file-to-file> function");
61 registry[name] = Translation(function, description, inputAlignment);
62}
63
64TranslateRegistration::TranslateRegistration(
65 StringRef name, StringRef description, const TranslateFunction &function) {
66 registerTranslation(name, description, /*inputAlignment=*/std::nullopt,
67 function);
68}
69
70//===----------------------------------------------------------------------===//
71// Translation to MLIR
72//===----------------------------------------------------------------------===//
73
74// Puts `function` into the to-MLIR translation registry unless there is already
75// a function registered for the same name.
76static void registerTranslateToMLIRFunction(
77 StringRef name, StringRef description,
78 const DialectRegistrationFunction &dialectRegistration,
79 std::optional<llvm::Align> inputAlignment,
80 const TranslateSourceMgrToMLIRFunction &function) {
81 auto wrappedFn = [function, dialectRegistration](
82 const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
83 raw_ostream &output, MLIRContext *context) {
84 DialectRegistry registry;
85 dialectRegistration(registry);
86 context->appendDialectRegistry(registry);
87 OwningOpRef<Operation *> op = function(sourceMgr, context);
88 if (!op || failed(result: verify(op: *op)))
89 return failure();
90 op.get()->print(os&: output);
91 return success();
92 };
93 registerTranslation(name, description, inputAlignment, function: wrappedFn);
94}
95
96TranslateToMLIRRegistration::TranslateToMLIRRegistration(
97 StringRef name, StringRef description,
98 const TranslateSourceMgrToMLIRFunction &function,
99 const DialectRegistrationFunction &dialectRegistration,
100 std::optional<llvm::Align> inputAlignment) {
101 registerTranslateToMLIRFunction(name, description, dialectRegistration,
102 inputAlignment, function);
103}
104TranslateToMLIRRegistration::TranslateToMLIRRegistration(
105 StringRef name, StringRef description,
106 const TranslateRawSourceMgrToMLIRFunction &function,
107 const DialectRegistrationFunction &dialectRegistration,
108 std::optional<llvm::Align> inputAlignment) {
109 registerTranslateToMLIRFunction(
110 name, description, dialectRegistration, inputAlignment,
111 function: [function](const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
112 MLIRContext *ctx) { return function(*sourceMgr, ctx); });
113}
114/// Wraps `function` with a lambda that extracts a StringRef from a source
115/// manager and registers the wrapper lambda as a to-MLIR conversion.
116TranslateToMLIRRegistration::TranslateToMLIRRegistration(
117 StringRef name, StringRef description,
118 const TranslateStringRefToMLIRFunction &function,
119 const DialectRegistrationFunction &dialectRegistration,
120 std::optional<llvm::Align> inputAlignment) {
121 registerTranslateToMLIRFunction(
122 name, description, dialectRegistration, inputAlignment,
123 function: [function](const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
124 MLIRContext *ctx) {
125 const llvm::MemoryBuffer *buffer =
126 sourceMgr->getMemoryBuffer(i: sourceMgr->getMainFileID());
127 return function(buffer->getBuffer(), ctx);
128 });
129}
130
131//===----------------------------------------------------------------------===//
132// Translation from MLIR
133//===----------------------------------------------------------------------===//
134
135TranslateFromMLIRRegistration::TranslateFromMLIRRegistration(
136 StringRef name, StringRef description,
137 const TranslateFromMLIRFunction &function,
138 const DialectRegistrationFunction &dialectRegistration) {
139 registerTranslation(
140 name, description, /*inputAlignment=*/std::nullopt,
141 function: [function,
142 dialectRegistration](const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
143 raw_ostream &output, MLIRContext *context) {
144 DialectRegistry registry;
145 dialectRegistration(registry);
146 context->appendDialectRegistry(registry);
147 bool implicitModule =
148 (!clOptions.isConstructed() || !clOptions->noImplicitModule);
149 OwningOpRef<Operation *> op =
150 parseSourceFileForTool(sourceMgr, config: context, insertImplicitModule: implicitModule);
151 if (!op || failed(result: verify(op: *op)))
152 return failure();
153 return function(op.get(), output);
154 });
155}
156
157//===----------------------------------------------------------------------===//
158// Translation Parser
159//===----------------------------------------------------------------------===//
160
161TranslationParser::TranslationParser(llvm::cl::Option &opt)
162 : llvm::cl::parser<const Translation *>(opt) {
163 for (const auto &kv : getTranslationRegistry())
164 addLiteralOption(Name: kv.first(), V: &kv.second, HelpStr: kv.second.getDescription());
165}
166
167void TranslationParser::printOptionInfo(const llvm::cl::Option &o,
168 size_t globalWidth) const {
169 TranslationParser *tp = const_cast<TranslationParser *>(this);
170 llvm::array_pod_sort(Start: tp->Values.begin(), End: tp->Values.end(),
171 Compare: [](const TranslationParser::OptionInfo *lhs,
172 const TranslationParser::OptionInfo *rhs) {
173 return lhs->Name.compare(RHS: rhs->Name);
174 });
175 llvm::cl::parser<const Translation *>::printOptionInfo(O: o, GlobalWidth: globalWidth);
176}
177

source code of mlir/lib/Tools/mlir-translate/Translation.cpp