MLIR 22.0.0git
MlirTranslateMain.cpp
Go to the documentation of this file.
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
10#include "mlir/IR/AsmState.h"
11#include "mlir/Parser/Parser.h"
13#include "mlir/Support/Timing.h"
16#include "llvm/Support/InitLLVM.h"
17#include "llvm/Support/SourceMgr.h"
18#include "llvm/Support/ToolOutputFile.h"
19
20using namespace mlir;
21
22//===----------------------------------------------------------------------===//
23// Diagnostic Filter
24//===----------------------------------------------------------------------===//
25
26namespace {
27/// A scoped diagnostic handler that marks non-error diagnostics as handled. As
28/// a result, the main diagnostic handler does not print non-error diagnostics.
29class ErrorDiagnosticFilter : public ScopedDiagnosticHandler {
30public:
31 ErrorDiagnosticFilter(MLIRContext *ctx) : ScopedDiagnosticHandler(ctx) {
32 setHandler([](Diagnostic &diag) {
33 if (diag.getSeverity() != DiagnosticSeverity::Error)
34 return success();
35 return failure();
36 });
37 }
38};
39} // namespace
40
41//===----------------------------------------------------------------------===//
42// Translate Entry Point
43//===----------------------------------------------------------------------===//
44
45LogicalResult mlir::mlirTranslateMain(int argc, char **argv,
46 llvm::StringRef toolName) {
47
48 static llvm::cl::opt<std::string> inputFilename(
49 llvm::cl::Positional, llvm::cl::desc("<input file>"),
50 llvm::cl::init("-"));
51
52 static llvm::cl::opt<std::string> outputFilename(
53 "o", llvm::cl::desc("Output filename"), llvm::cl::value_desc("filename"),
54 llvm::cl::init("-"));
55
56 static llvm::cl::opt<bool> allowUnregisteredDialects(
57 "allow-unregistered-dialect",
58 llvm::cl::desc("Allow operation with no registered dialects (discouraged: testing only!)"),
59 llvm::cl::init(false));
60
61 static llvm::cl::opt<std::string> inputSplitMarker{
62 "split-input-file", llvm::cl::ValueOptional,
63 llvm::cl::callback([&](const std::string &str) {
64 // Implicit value: use default marker if flag was used without value.
65 if (str.empty())
66 inputSplitMarker.setValue(kDefaultSplitMarker);
67 }),
68 llvm::cl::desc("Split the input file into chunks using the given or "
69 "default marker and process each chunk independently"),
70 llvm::cl::init("")};
71
72 static llvm::cl::opt<SourceMgrDiagnosticVerifierHandler::Level>
73 verifyDiagnostics{
74 "verify-diagnostics", llvm::cl::ValueOptional,
75 llvm::cl::desc("Check that emitted diagnostics match expected-* "
76 "lines on the corresponding line"),
77 llvm::cl::values(
78 clEnumValN(
80 "Check all diagnostics (expected, unexpected, near-misses)"),
81 // Implicit value: when passed with no arguments, e.g.
82 // `--verify-diagnostics` or `--verify-diagnostics=`.
83 clEnumValN(
85 "Check all diagnostics (expected, unexpected, near-misses)"),
86 clEnumValN(
88 "only-expected", "Check only expected diagnostics"))};
89
90 static llvm::cl::opt<bool> errorDiagnosticsOnly(
91 "error-diagnostics-only",
92 llvm::cl::desc("Filter all non-error diagnostics "
93 "(discouraged: testing only!)"),
94 llvm::cl::init(false));
95
96 static llvm::cl::opt<std::string> outputSplitMarker(
97 "output-split-marker",
98 llvm::cl::desc("Split marker to use for merging the ouput"),
99 llvm::cl::init(""));
100
101 llvm::InitLLVM y(argc, argv);
102
103 // Add flags for all the registered translations.
104 llvm::cl::list<const Translation *, bool, TranslationParser>
105 translationsRequested("", llvm::cl::desc("Translations to perform"),
106 llvm::cl::Required);
111 llvm::cl::ParseCommandLineOptions(argc, argv, toolName);
112
113 // Initialize the timing manager.
116 TimingScope timing = tm.getRootScope();
117
118 std::string errorMessage;
119 std::unique_ptr<llvm::MemoryBuffer> input;
120 if (auto inputAlignment = translationsRequested[0]->getInputAlignment())
121 input = openInputFile(inputFilename, *inputAlignment, &errorMessage);
122 else
123 input = openInputFile(inputFilename, &errorMessage);
124 if (!input) {
125 llvm::errs() << errorMessage << "\n";
126 return failure();
127 }
128
129 auto output = openOutputFile(outputFilename, &errorMessage);
130 if (!output) {
131 llvm::errs() << errorMessage << "\n";
132 return failure();
133 }
134
135 // Processes the memory buffer with a new MLIRContext.
136 auto processBuffer = [&](std::unique_ptr<llvm::MemoryBuffer> ownedBuffer,
137 raw_ostream &os) {
138 // Many of the translations expect a null-terminated buffer while splitting
139 // the buffer does not guarantee null-termination. Make a copy of the buffer
140 // to ensure null-termination.
141 if (!ownedBuffer->getBuffer().ends_with('\0')) {
142 ownedBuffer = llvm::MemoryBuffer::getMemBufferCopy(
143 ownedBuffer->getBuffer(), ownedBuffer->getBufferIdentifier());
144 }
145 // Temporary buffers for chained translation processing.
146 std::string dataIn;
147 std::string dataOut;
148 LogicalResult result = LogicalResult::success();
149
150 for (size_t i = 0, e = translationsRequested.size(); i < e; ++i) {
151 llvm::raw_ostream *stream;
152 llvm::raw_string_ostream dataStream(dataOut);
153
154 if (i == e - 1) {
155 // Output last translation to output.
156 stream = &os;
157 } else {
158 // Output translation to temporary data buffer.
159 stream = &dataStream;
160 }
161
162 const Translation *translationRequested = translationsRequested[i];
163 TimingScope translationTiming =
164 timing.nest(translationRequested->getDescription());
165
166 MLIRContext context;
167 context.allowUnregisteredDialects(allowUnregisteredDialects);
168 context.printOpOnDiagnostic(verifyDiagnostics.getNumOccurrences() == 0);
169 auto sourceMgr = std::make_shared<llvm::SourceMgr>();
170 sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());
171
172 if (verifyDiagnostics.getNumOccurrences()) {
173 // In the diagnostic verification flow, we ignore whether the
174 // translation failed (in most cases, it is expected to fail) and we do
175 // not filter non-error diagnostics even if `errorDiagnosticsOnly` is
176 // set. Instead, we check if the diagnostics were produced as expected.
177 SourceMgrDiagnosticVerifierHandler sourceMgrHandler(
178 *sourceMgr, &context, verifyDiagnostics);
179 (void)(*translationRequested)(sourceMgr, os, &context);
180 result = sourceMgrHandler.verify();
181 } else if (errorDiagnosticsOnly) {
182 SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);
183 ErrorDiagnosticFilter diagnosticFilter(&context);
184 result = (*translationRequested)(sourceMgr, *stream, &context);
185 } else {
186 SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);
187 result = (*translationRequested)(sourceMgr, *stream, &context);
188 }
189 if (failed(result))
190 return result;
191
192 if (i < e - 1) {
193 // If there are further translations, create a new buffer with the
194 // output data.
195 dataIn = dataOut;
196 dataOut.clear();
197 ownedBuffer = llvm::MemoryBuffer::getMemBuffer(dataIn);
198 }
199 }
200 return result;
201 };
202
203 if (failed(splitAndProcessBuffer(std::move(input), processBuffer,
204 output->os(), inputSplitMarker,
205 outputSplitMarker)))
206 return failure();
207
208 output->keep();
209 return success();
210}
return success()
static LogicalResult processBuffer(raw_ostream &os, std::unique_ptr< MemoryBuffer > ownedBuffer, llvm::MemoryBufferRef sourceBuffer, const MlirOptMainConfig &config, DialectRegistry &registry, SourceMgrDiagnosticVerifierHandler *verifyHandler, llvm::ThreadPoolInterface *threadPool)
Parses the memory buffer.
static std::string diag(const llvm::Value &value)
Facilities for time measurement and report printing to an output stream.
Definition Timing.h:388
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
void printOpOnDiagnostic(bool enable)
Set the flag specifying if we should attach the operation to diagnostics emitted via Operation::emit.
void allowUnregisteredDialects(bool allow=true)
Enables creating operations in unregistered dialects.
This diagnostic handler is a simple RAII class that registers and erases a diagnostic handler on a gi...
This class is a utility diagnostic handler for use with llvm::SourceMgr.
This class is a utility diagnostic handler for use with llvm::SourceMgr that verifies that emitted di...
TimingScope getRootScope()
Get the root timer of this timing manager wrapped in a TimingScope for convenience.
Definition Timing.cpp:73
An RAII-style wrapper around a timer that ensures the timer is properly started and stopped.
Definition Timing.h:272
TimingScope nest(Args... args)
Create a nested timing scope.
Definition Timing.h:311
This class contains all of the components necessary for performing a translation.
Definition Translation.h:61
StringRef getDescription() const
Return the description of this translation.
Definition Translation.h:70
detail::InFlightRemark failed(Location loc, RemarkOpts opts)
Report an optimization remark that failed.
Definition Remarks.h:561
Include the generated interface declarations.
const char *const kDefaultSplitMarker
void registerDefaultTimingManagerCLOptions()
Register a set of useful command-line options that can be used to configure a DefaultTimingManager.
Definition Timing.cpp:612
std::unique_ptr< llvm::ToolOutputFile > openOutputFile(llvm::StringRef outputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for writing.
void registerTranslationCLOptions()
Register command-line options used by the translation registry.
void registerMLIRContextCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
std::unique_ptr< llvm::MemoryBuffer > openInputFile(llvm::StringRef inputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for reading.
LogicalResult splitAndProcessBuffer(std::unique_ptr< llvm::MemoryBuffer > originalBuffer, ChunkBufferHandler processChunkBuffer, raw_ostream &os, llvm::StringRef inputSplitMarker=kDefaultSplitMarker, llvm::StringRef outputSplitMarker="")
Splits the specified buffer on a marker (// ----- by default), processes each chunk independently acc...
void registerAsmPrinterCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
void applyDefaultTimingManagerCLOptions(DefaultTimingManager &tm)
Apply any values that were registered with 'registerDefaultTimingManagerOptions' to a DefaultTimingMa...
Definition Timing.cpp:617
LogicalResult mlirTranslateMain(int argc, char **argv, StringRef toolName)
Translate to/from an MLIR module from/to an external representation (e.g.