MLIR  18.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/IR/BuiltinOps.h"
12 #include "mlir/IR/Dialect.h"
13 #include "mlir/IR/Verifier.h"
14 #include "mlir/Parser/Parser.h"
17 #include "mlir/Support/Timing.h"
20 #include "llvm/Support/InitLLVM.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Support/ToolOutputFile.h"
23 
24 using namespace mlir;
25 
26 //===----------------------------------------------------------------------===//
27 // Diagnostic Filter
28 //===----------------------------------------------------------------------===//
29 
30 namespace {
31 /// A scoped diagnostic handler that marks non-error diagnostics as handled. As
32 /// a result, the main diagnostic handler does not print non-error diagnostics.
33 class ErrorDiagnosticFilter : public ScopedDiagnosticHandler {
34 public:
35  ErrorDiagnosticFilter(MLIRContext *ctx) : ScopedDiagnosticHandler(ctx) {
36  setHandler([](Diagnostic &diag) {
37  if (diag.getSeverity() != DiagnosticSeverity::Error)
38  return success();
39  return failure();
40  });
41  }
42 };
43 } // namespace
44 
45 //===----------------------------------------------------------------------===//
46 // Translate Entry Point
47 //===----------------------------------------------------------------------===//
48 
49 LogicalResult mlir::mlirTranslateMain(int argc, char **argv,
50  llvm::StringRef toolName) {
51 
52  static llvm::cl::opt<std::string> inputFilename(
53  llvm::cl::Positional, llvm::cl::desc("<input file>"),
54  llvm::cl::init("-"));
55 
56  static llvm::cl::opt<std::string> outputFilename(
57  "o", llvm::cl::desc("Output filename"), llvm::cl::value_desc("filename"),
58  llvm::cl::init("-"));
59 
60  static llvm::cl::opt<bool> allowUnregisteredDialects(
61  "allow-unregistered-dialect",
62  llvm::cl::desc("Allow operation with no registered dialects (discouraged: testing only!)"),
63  llvm::cl::init(false));
64 
65  static llvm::cl::opt<bool> splitInputFile(
66  "split-input-file",
67  llvm::cl::desc("Split the input file into pieces and "
68  "process each chunk independently"),
69  llvm::cl::init(false));
70 
71  static llvm::cl::opt<bool> verifyDiagnostics(
72  "verify-diagnostics",
73  llvm::cl::desc("Check that emitted diagnostics match "
74  "expected-* lines on the corresponding line"),
75  llvm::cl::init(false));
76 
77  static llvm::cl::opt<bool> errorDiagnosticsOnly(
78  "error-diagnostics-only",
79  llvm::cl::desc("Filter all non-error diagnostics "
80  "(discouraged: testing only!)"),
81  llvm::cl::init(false));
82 
83  llvm::InitLLVM y(argc, argv);
84 
85  // Add flags for all the registered translations.
86  llvm::cl::list<const Translation *, bool, TranslationParser>
87  translationsRequested("", llvm::cl::desc("Translations to perform"),
88  llvm::cl::Required);
93  llvm::cl::ParseCommandLineOptions(argc, argv, toolName);
94 
95  // Initialize the timing manager.
98  TimingScope timing = tm.getRootScope();
99 
100  std::string errorMessage;
101  std::unique_ptr<llvm::MemoryBuffer> input;
102  if (auto inputAlignment = translationsRequested[0]->getInputAlignment())
103  input = openInputFile(inputFilename, *inputAlignment, &errorMessage);
104  else
105  input = openInputFile(inputFilename, &errorMessage);
106  if (!input) {
107  llvm::errs() << errorMessage << "\n";
108  return failure();
109  }
110 
111  auto output = openOutputFile(outputFilename, &errorMessage);
112  if (!output) {
113  llvm::errs() << errorMessage << "\n";
114  return failure();
115  }
116 
117  // Processes the memory buffer with a new MLIRContext.
118  auto processBuffer = [&](std::unique_ptr<llvm::MemoryBuffer> ownedBuffer,
119  raw_ostream &os) {
120  // Temporary buffers for chained translation processing.
121  std::string dataIn;
122  std::string dataOut;
124 
125  for (size_t i = 0, e = translationsRequested.size(); i < e; ++i) {
126  llvm::raw_ostream *stream;
127  llvm::raw_string_ostream dataStream(dataOut);
128 
129  if (i == e - 1) {
130  // Output last translation to output.
131  stream = &os;
132  } else {
133  // Output translation to temporary data buffer.
134  stream = &dataStream;
135  }
136 
137  const Translation *translationRequested = translationsRequested[i];
138  TimingScope translationTiming =
139  timing.nest(translationRequested->getDescription());
140 
141  MLIRContext context;
142  context.allowUnregisteredDialects(allowUnregisteredDialects);
143  context.printOpOnDiagnostic(!verifyDiagnostics);
144  auto sourceMgr = std::make_shared<llvm::SourceMgr>();
145  sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());
146 
147  if (verifyDiagnostics) {
148  // In the diagnostic verification flow, we ignore whether the
149  // translation failed (in most cases, it is expected to fail) and we do
150  // not filter non-error diagnostics even if `errorDiagnosticsOnly` is
151  // set. Instead, we check if the diagnostics were produced as expected.
152  SourceMgrDiagnosticVerifierHandler sourceMgrHandler(*sourceMgr,
153  &context);
154  (void)(*translationRequested)(sourceMgr, os, &context);
155  result = sourceMgrHandler.verify();
156  } else if (errorDiagnosticsOnly) {
157  SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);
158  ErrorDiagnosticFilter diagnosticFilter(&context);
159  result = (*translationRequested)(sourceMgr, *stream, &context);
160  } else {
161  SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context);
162  result = (*translationRequested)(sourceMgr, *stream, &context);
163  }
164  if (failed(result))
165  return result;
166 
167  if (i < e - 1) {
168  // If there are further translations, create a new buffer with the
169  // output data.
170  dataIn = dataOut;
171  dataOut.clear();
172  ownedBuffer = llvm::MemoryBuffer::getMemBuffer(dataIn);
173  }
174  }
175  return result;
176  };
177 
178  if (failed(splitAndProcessBuffer(std::move(input), processBuffer,
179  output->os(), splitInputFile)))
180  return failure();
181 
182  output->keep();
183  return success();
184 }
static LogicalResult processBuffer(raw_ostream &os, std::unique_ptr< MemoryBuffer > ownedBuffer, const MlirOptMainConfig &config, DialectRegistry &registry, llvm::ThreadPool *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:341
This class contains all of the information necessary to report a diagnostic to the DiagnosticEngine.
Definition: Diagnostics.h:156
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:60
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...
Definition: Diagnostics.h:516
This class is a utility diagnostic handler for use with llvm::SourceMgr.
Definition: Diagnostics.h:553
This class is a utility diagnostic handler for use with llvm::SourceMgr that verifies that emitted di...
Definition: Diagnostics.h:619
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
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:62
std::unique_ptr< llvm::MemoryBuffer > openInputFile(llvm::StringRef inputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for reading.
void registerDefaultTimingManagerCLOptions()
Register a set of useful command-line options that can be used to configure a DefaultTimingManager.
Definition: Timing.cpp:557
void registerTranslationCLOptions()
Register command-line options used by the translation registry.
Definition: Translation.cpp:38
std::unique_ptr< llvm::ToolOutputFile > openOutputFile(llvm::StringRef outputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for writing.
void registerMLIRContextCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
Definition: MLIRContext.cpp:90
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
Definition: LogicalResult.h:56
void registerAsmPrinterCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
Definition: AsmPrinter.cpp:193
void applyDefaultTimingManagerCLOptions(DefaultTimingManager &tm)
Apply any values that were registered with 'registerDefaultTimingManagerOptions' to a DefaultTimingMa...
Definition: Timing.cpp:562
LogicalResult mlirTranslateMain(int argc, char **argv, StringRef toolName)
Translate to/from an MLIR module from/to an external representation (e.g.
LogicalResult splitAndProcessBuffer(std::unique_ptr< llvm::MemoryBuffer > originalBuffer, ChunkBufferHandler processChunkBuffer, raw_ostream &os, bool enableSplitting=true, bool insertMarkerInOutput=false)
Splits the specified buffer on a marker (// -----), processes each chunk independently according to t...
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
Definition: LogicalResult.h:72
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
static LogicalResult success(bool isSuccess=true)
If isSuccess is true a success result is generated, otherwise a 'failure' result is generated.
Definition: LogicalResult.h:30