1//===- MlirTranslateMain.cpp - MLIR Translation entry point ---------------===//
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#include "mlir/Tools/mlir-translate/MlirTranslateMain.h"
10#include "mlir/IR/AsmState.h"
11#include "mlir/IR/BuiltinOps.h"
12#include "mlir/IR/Dialect.h"
13#include "mlir/IR/Verifier.h"
14#include "mlir/Parser/Parser.h"
15#include "mlir/Support/FileUtilities.h"
16#include "mlir/Support/Timing.h"
17#include "mlir/Support/ToolUtilities.h"
18#include "mlir/Tools/mlir-translate/Translation.h"
19#include "llvm/Support/InitLLVM.h"
20#include "llvm/Support/SourceMgr.h"
21#include "llvm/Support/ToolOutputFile.h"
22
23using namespace mlir;
24
25//===----------------------------------------------------------------------===//
26// Diagnostic Filter
27//===----------------------------------------------------------------------===//
28
29namespace {
30/// A scoped diagnostic handler that marks non-error diagnostics as handled. As
31/// a result, the main diagnostic handler does not print non-error diagnostics.
32class ErrorDiagnosticFilter : public ScopedDiagnosticHandler {
33public:
34 ErrorDiagnosticFilter(MLIRContext *ctx) : ScopedDiagnosticHandler(ctx) {
35 setHandler([](Diagnostic &diag) {
36 if (diag.getSeverity() != DiagnosticSeverity::Error)
37 return success();
38 return failure();
39 });
40 }
41};
42} // namespace
43
44//===----------------------------------------------------------------------===//
45// Translate Entry Point
46//===----------------------------------------------------------------------===//
47
48LogicalResult mlir::mlirTranslateMain(int argc, char **argv,
49 llvm::StringRef toolName) {
50
51 static llvm::cl::opt<std::string> inputFilename(
52 llvm::cl::Positional, llvm::cl::desc("<input file>"),
53 llvm::cl::init(Val: "-"));
54
55 static llvm::cl::opt<std::string> outputFilename(
56 "o", llvm::cl::desc("Output filename"), llvm::cl::value_desc("filename"),
57 llvm::cl::init(Val: "-"));
58
59 static llvm::cl::opt<bool> allowUnregisteredDialects(
60 "allow-unregistered-dialect",
61 llvm::cl::desc("Allow operation with no registered dialects (discouraged: testing only!)"),
62 llvm::cl::init(Val: false));
63
64 static llvm::cl::opt<std::string> inputSplitMarker{
65 "split-input-file", llvm::cl::ValueOptional,
66 llvm::cl::callback(CB: [&](const std::string &str) {
67 // Implicit value: use default marker if flag was used without value.
68 if (str.empty())
69 inputSplitMarker.setValue(V: kDefaultSplitMarker);
70 }),
71 llvm::cl::desc("Split the input file into chunks using the given or "
72 "default marker and process each chunk independently"),
73 llvm::cl::init(Val: "")};
74
75 static llvm::cl::opt<SourceMgrDiagnosticVerifierHandler::Level>
76 verifyDiagnostics{
77 "verify-diagnostics", llvm::cl::ValueOptional,
78 llvm::cl::desc("Check that emitted diagnostics match expected-* "
79 "lines on the corresponding line"),
80 llvm::cl::values(
81 clEnumValN(
82 SourceMgrDiagnosticVerifierHandler::Level::All, "all",
83 "Check all diagnostics (expected, unexpected, near-misses)"),
84 // Implicit value: when passed with no arguments, e.g.
85 // `--verify-diagnostics` or `--verify-diagnostics=`.
86 clEnumValN(
87 SourceMgrDiagnosticVerifierHandler::Level::All, "",
88 "Check all diagnostics (expected, unexpected, near-misses)"),
89 clEnumValN(
90 SourceMgrDiagnosticVerifierHandler::Level::OnlyExpected,
91 "only-expected", "Check only expected diagnostics"))};
92
93 static llvm::cl::opt<bool> errorDiagnosticsOnly(
94 "error-diagnostics-only",
95 llvm::cl::desc("Filter all non-error diagnostics "
96 "(discouraged: testing only!)"),
97 llvm::cl::init(Val: false));
98
99 static llvm::cl::opt<std::string> outputSplitMarker(
100 "output-split-marker",
101 llvm::cl::desc("Split marker to use for merging the ouput"),
102 llvm::cl::init(Val: ""));
103
104 llvm::InitLLVM y(argc, argv);
105
106 // Add flags for all the registered translations.
107 llvm::cl::list<const Translation *, bool, TranslationParser>
108 translationsRequested("", llvm::cl::desc("Translations to perform"),
109 llvm::cl::Required);
110 registerAsmPrinterCLOptions();
111 registerMLIRContextCLOptions();
112 registerTranslationCLOptions();
113 registerDefaultTimingManagerCLOptions();
114 llvm::cl::ParseCommandLineOptions(argc, argv, Overview: toolName);
115
116 // Initialize the timing manager.
117 DefaultTimingManager tm;
118 applyDefaultTimingManagerCLOptions(tm);
119 TimingScope timing = tm.getRootScope();
120
121 std::string errorMessage;
122 std::unique_ptr<llvm::MemoryBuffer> input;
123 if (auto inputAlignment = translationsRequested[0]->getInputAlignment())
124 input = openInputFile(inputFilename, alignment: *inputAlignment, errorMessage: &errorMessage);
125 else
126 input = openInputFile(inputFilename, errorMessage: &errorMessage);
127 if (!input) {
128 llvm::errs() << errorMessage << "\n";
129 return failure();
130 }
131
132 auto output = openOutputFile(outputFilename, errorMessage: &errorMessage);
133 if (!output) {
134 llvm::errs() << errorMessage << "\n";
135 return failure();
136 }
137
138 // Processes the memory buffer with a new MLIRContext.
139 auto processBuffer = [&](std::unique_ptr<llvm::MemoryBuffer> ownedBuffer,
140 raw_ostream &os) {
141 // Temporary buffers for chained translation processing.
142 std::string dataIn;
143 std::string dataOut;
144 LogicalResult result = LogicalResult::success();
145
146 for (size_t i = 0, e = translationsRequested.size(); i < e; ++i) {
147 llvm::raw_ostream *stream;
148 llvm::raw_string_ostream dataStream(dataOut);
149
150 if (i == e - 1) {
151 // Output last translation to output.
152 stream = &os;
153 } else {
154 // Output translation to temporary data buffer.
155 stream = &dataStream;
156 }
157
158 const Translation *translationRequested = translationsRequested[i];
159 TimingScope translationTiming =
160 timing.nest(args: translationRequested->getDescription());
161
162 MLIRContext context;
163 context.allowUnregisteredDialects(allow: allowUnregisteredDialects);
164 context.printOpOnDiagnostic(enable: verifyDiagnostics.getNumOccurrences() == 0);
165 auto sourceMgr = std::make_shared<llvm::SourceMgr>();
166 sourceMgr->AddNewSourceBuffer(F: std::move(ownedBuffer), IncludeLoc: SMLoc());
167
168 if (verifyDiagnostics.getNumOccurrences()) {
169 // In the diagnostic verification flow, we ignore whether the
170 // translation failed (in most cases, it is expected to fail) and we do
171 // not filter non-error diagnostics even if `errorDiagnosticsOnly` is
172 // set. Instead, we check if the diagnostics were produced as expected.
173 SourceMgrDiagnosticVerifierHandler sourceMgrHandler(
174 *sourceMgr, &context, verifyDiagnostics);
175 (void)(*translationRequested)(sourceMgr, os, &context);
176 result = sourceMgrHandler.verify();
177 } else if (errorDiagnosticsOnly) {
178 SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);
179 ErrorDiagnosticFilter diagnosticFilter(&context);
180 result = (*translationRequested)(sourceMgr, *stream, &context);
181 } else {
182 SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);
183 result = (*translationRequested)(sourceMgr, *stream, &context);
184 }
185 if (failed(Result: result))
186 return result;
187
188 if (i < e - 1) {
189 // If there are further translations, create a new buffer with the
190 // output data.
191 dataIn = dataOut;
192 dataOut.clear();
193 ownedBuffer = llvm::MemoryBuffer::getMemBuffer(InputData: dataIn);
194 }
195 }
196 return result;
197 };
198
199 if (failed(Result: splitAndProcessBuffer(originalBuffer: std::move(input), processChunkBuffer: processBuffer,
200 os&: output->os(), inputSplitMarker,
201 outputSplitMarker)))
202 return failure();
203
204 output->keep();
205 return success();
206}
207

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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