39 #include "llvm/ADT/StringRef.h"
40 #include "llvm/Support/CommandLine.h"
41 #include "llvm/Support/FileUtilities.h"
42 #include "llvm/Support/InitLLVM.h"
43 #include "llvm/Support/ManagedStatic.h"
44 #include "llvm/Support/Process.h"
45 #include "llvm/Support/Regex.h"
46 #include "llvm/Support/SourceMgr.h"
47 #include "llvm/Support/StringSaver.h"
48 #include "llvm/Support/ThreadPool.h"
49 #include "llvm/Support/ToolOutputFile.h"
55 class BytecodeVersionParser :
public cl::parser<std::optional<int64_t>> {
57 BytecodeVersionParser(cl::Option &O)
58 : cl::parser<std::optional<int64_t>>(O) {}
60 bool parse(cl::Option &O, StringRef , StringRef arg,
61 std::optional<int64_t> &v) {
63 if (getAsSignedInteger(arg, 10, w))
64 return O.error(
"Invalid argument '" + arg +
65 "', only integer is supported.");
74 MlirOptMainConfigCLOptions() {
80 static cl::opt<bool,
true> allowUnregisteredDialects(
81 "allow-unregistered-dialect",
82 cl::desc(
"Allow operation with no registered dialects"),
83 cl::location(allowUnregisteredDialectsFlag), cl::init(
false));
85 static cl::opt<bool,
true> dumpPassPipeline(
86 "dump-pass-pipeline", cl::desc(
"Print the pipeline that will be run"),
87 cl::location(dumpPassPipelineFlag), cl::init(
false));
89 static cl::opt<bool,
true> emitBytecode(
90 "emit-bytecode", cl::desc(
"Emit bytecode when generating output"),
91 cl::location(emitBytecodeFlag), cl::init(
false));
93 static cl::opt<bool,
true> elideResourcesFromBytecode(
94 "elide-resource-data-from-bytecode",
95 cl::desc(
"Elide resources when generating bytecode"),
96 cl::location(elideResourceDataFromBytecodeFlag), cl::init(
false));
98 static cl::opt<std::optional<int64_t>,
true,
99 BytecodeVersionParser>
101 "emit-bytecode-version",
102 cl::desc(
"Use specified bytecode when generating output"),
103 cl::location(emitBytecodeVersion), cl::init(std::nullopt));
105 static cl::opt<std::string,
true> irdlFile(
107 cl::desc(
"IRDL file to register before processing the input"),
108 cl::location(irdlFileFlag), cl::init(
""), cl::value_desc(
"filename"));
110 static cl::opt<bool,
true> enableDebuggerHook(
111 "mlir-enable-debugger-hook",
112 cl::desc(
"Enable Debugger hook for debugging MLIR Actions"),
113 cl::location(enableDebuggerActionHookFlag), cl::init(
false));
115 static cl::opt<bool,
true> explicitModule(
116 "no-implicit-module",
117 cl::desc(
"Disable implicit addition of a top-level module op during "
119 cl::location(useExplicitModuleFlag), cl::init(
false));
121 static cl::opt<bool,
true> runReproducer(
122 "run-reproducer", cl::desc(
"Run the pipeline stored in the reproducer"),
123 cl::location(runReproducerFlag), cl::init(
false));
125 static cl::opt<bool,
true> showDialects(
127 cl::desc(
"Print the list of registered dialects and exit"),
128 cl::location(showDialectsFlag), cl::init(
false));
130 static cl::opt<bool,
true> splitInputFile(
132 cl::desc(
"Split the input file into pieces and process each "
133 "chunk independently"),
134 cl::location(splitInputFileFlag), cl::init(
false));
136 static cl::opt<bool,
true> verifyDiagnostics(
137 "verify-diagnostics",
138 cl::desc(
"Check that emitted diagnostics match "
139 "expected-* lines on the corresponding line"),
140 cl::location(verifyDiagnosticsFlag), cl::init(
false));
142 static cl::opt<bool,
true> verifyPasses(
144 cl::desc(
"Run the verifier after each transformation pass"),
145 cl::location(verifyPassesFlag), cl::init(
true));
147 static cl::opt<bool,
true> verifyRoundtrip(
149 cl::desc(
"Round-trip the IR after parsing and ensure it succeeds"),
150 cl::location(verifyRoundtripFlag), cl::init(
false));
152 static cl::list<std::string> passPlugins(
153 "load-pass-plugin", cl::desc(
"Load passes from plugin library"));
155 passPlugins.setCallback([&](
const std::string &pluginPath) {
158 errs() <<
"Failed to load passes from '" << pluginPath
159 <<
"'. Request ignored.\n";
162 plugin.get().registerPassRegistryCallbacks();
165 static cl::list<std::string> dialectPlugins(
166 "load-dialect-plugin", cl::desc(
"Load dialects from plugin library"));
167 this->dialectPlugins = std::addressof(dialectPlugins);
170 setPassPipelineParser(passPipeline);
178 cl::list<std::string> *dialectPlugins =
nullptr;
197 auto errorHandler = [&](
const Twine &msg) {
203 if (this->shouldDumpPassPipeline()) {
206 llvm::errs() <<
"\n";
213 void MlirOptMainConfigCLOptions::setDialectPluginsCallback(
215 dialectPlugins->setCallback([&](
const std::string &pluginPath) {
218 errs() <<
"Failed to load dialect plugin from '" << pluginPath
219 <<
"'. Request ignored.\n";
222 plugin.get().registerDialectRegistryCallbacks(registry);
228 registry.
insert<irdl::IRDLDialect>();
232 std::string errorMessage;
233 std::unique_ptr<MemoryBuffer> file =
openInputFile(irdlFile, &errorMessage);
242 sourceMgr.AddNewSourceBuffer(std::move(file), SMLoc());
273 llvm::raw_string_ostream ostream(buffer);
277 <<
"failed to write bytecode, cannot verify round-trip.\n";
286 &fallbackResourceMap);
288 parseSourceString<Operation *>(ostream.str(), parseConfig);
289 if (!roundtripModule) {
291 <<
"failed to parse bytecode back, cannot verify round-trip.\n";
298 std::string reference, roundtrip;
300 llvm::raw_string_ostream ostreamref(reference);
301 op->
print(ostreamref,
303 llvm::raw_string_ostream ostreamrndtrip(roundtrip);
304 roundtripModule.
get()->print(
308 if (reference != roundtrip) {
310 return op->
emitOpError() <<
"roundTrip testing roundtripped module differs "
311 "from reference:\n<<<<<<Reference\n"
312 << reference <<
"\n=====\n"
313 << roundtrip <<
"\n>>>>>roundtripped\n";
335 const std::shared_ptr<llvm::SourceMgr> &sourceMgr,
353 &fallbackResourceMap);
400 <<
"bytecode version while not emitting bytecode";
402 &fallbackResourceMap);
403 op.get()->
print(os, asmState);
411 std::unique_ptr<MemoryBuffer> ownedBuffer,
414 llvm::ThreadPool *threadPool) {
416 auto sourceMgr = std::make_shared<SourceMgr>();
417 sourceMgr->AddNewSourceBuffer(std::move(ownedBuffer), SMLoc());
453 return sourceMgrHandler.
verify();
456 std::pair<std::string, std::string>
458 llvm::StringRef toolName,
460 static cl::opt<std::string> inputFilename(
461 cl::Positional, cl::desc(
"<input file>"), cl::init(
"-"));
463 static cl::opt<std::string> outputFilename(
"o", cl::desc(
"Output filename"),
464 cl::value_desc(
"filename"),
475 std::string helpHeader = (toolName +
"\nAvailable Dialects: ").str();
477 llvm::raw_string_ostream os(helpHeader);
479 [&](
auto name) { os << name; });
482 cl::ParseCommandLineOptions(argc, argv, helpHeader);
483 return std::make_pair(inputFilename.getValue(), outputFilename.getValue());
487 std::unique_ptr<llvm::MemoryBuffer> buffer,
491 llvm::outs() <<
"Available Dialects: ";
493 llvm::outs() <<
"\n";
500 ThreadPool *threadPool =
nullptr;
510 auto chunkFn = [&](std::unique_ptr<MemoryBuffer> chunkBuffer,
512 return processBuffer(os, std::move(chunkBuffer), config, registry,
521 llvm::StringRef inputFilename,
522 llvm::StringRef outputFilename,
525 InitLLVM y(argc, argv);
532 if (inputFilename ==
"-" &&
533 sys::Process::FileDescriptorIsDisplayed(fileno(stdin)))
534 llvm::errs() <<
"(processing input from stdin now, hit ctrl-c/ctrl-d to "
538 std::string errorMessage;
541 llvm::errs() << errorMessage <<
"\n";
547 llvm::errs() << errorMessage <<
"\n";
562 std::string inputFilename, outputFilename;
563 std::tie(inputFilename, outputFilename) =
566 return MlirOptMain(argc, argv, inputFilename, outputFilename, registry);
LogicalResult loadIRDLDialects(StringRef irdlFile, MLIRContext &ctx)
static LogicalResult doVerifyRoundTrip(Operation *op, const MlirOptMainConfig &config, bool useBytecode)
static LogicalResult processBuffer(raw_ostream &os, std::unique_ptr< MemoryBuffer > ownedBuffer, const MlirOptMainConfig &config, DialectRegistry ®istry, llvm::ThreadPool *threadPool)
Parses the memory buffer.
ManagedStatic< MlirOptMainConfigCLOptions > clOptionsConfig
static LogicalResult performActions(raw_ostream &os, const std::shared_ptr< llvm::SourceMgr > &sourceMgr, MLIRContext *context, const MlirOptMainConfig &config)
Perform the actions on the input file indicated by the command line flags within the specified contex...
This class provides management for the lifetime of the state used when printing the IR.
This class contains the configuration used for the bytecode writer.
void setElideResourceDataFlag(bool shouldElideResourceData=true)
Set a boolean flag to skip emission of resources into the bytecode file.
void setDesiredBytecodeVersion(int64_t bytecodeVersion)
Set the desired bytecode version to emit.
Facilities for time measurement and report printing to an output stream.
static llvm::Expected< DialectPlugin > load(const std::string &filename)
Attempts to load a dialect plugin from a given file.
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
auto getDialectNames() const
Return the names of dialects known to this registry.
A fallback map containing external resources not explicitly handled by another parser/printer.
MLIRContext is the top-level object for a collection of MLIR operations.
void appendDialectRegistry(const DialectRegistry ®istry)
Append the contents of the given dialect registry to the registry associated with this context.
void disableMultithreading(bool disable=true)
Set the flag specifying if multi-threading is disabled by the context.
void setThreadPool(llvm::ThreadPool &pool)
Set a new thread pool to be used in this context.
void enableMultithreading(bool enable=true)
void printOpOnDiagnostic(bool enable)
Set the flag specifying if we should attach the operation to diagnostics emitted via Operation::emit.
const DialectRegistry & getDialectRegistry()
Return the dialect registry associated with this context.
llvm::ThreadPool & getThreadPool()
Return the thread pool used by this context.
bool isMultithreadingEnabled()
Return true if multi-threading is enabled by the context.
void allowUnregisteredDialects(bool allow=true)
Enables creating operations in unregistered dialects.
bool allowsUnregisteredDialects()
Return true if we allow to create operation for unregistered dialects.
Configuration options for the mlir-opt tool.
tracing::DebugConfig & getDebugConfig()
static MlirOptMainConfig createFromCLOptions()
Create a new config with the default set from the CL options.
bool shouldVerifyPasses() const
bool shouldSplitInputFile() const
bool shouldVerifyRoundtrip() const
std::optional< int64_t > bytecodeVersionToEmit() const
bool shouldShowDialects() const
bool shouldElideResourceDataFromBytecode() const
bool shouldEmitBytecode() const
LogicalResult setupPassPipeline(PassManager &pm) const
Populate the passmanager, if any callback was set.
static void registerCLOptions(DialectRegistry &dialectRegistry)
Register the options as global LLVM command line options.
bool shouldAllowUnregisteredDialects() const
bool shouldUseExplicitModule() const
bool shouldRunReproducer() const
Return true if the reproducer should be run.
bool shouldVerifyDiagnostics() const
StringRef getIrdlFile() const
MlirOptMainConfig & setPassPipelineParser(const PassPipelineCLParser &parser)
Set the parser to use to populate the pass manager.
@ Implicit
Implicit nesting behavior.
Set of flags used to control the behavior of the various IR print methods (e.g.
Operation is the basic unit of execution within MLIR.
void print(raw_ostream &os, const OpPrintingFlags &flags=std::nullopt)
MLIRContext * getContext()
Return the context this operation is associated with.
OperationName getName()
The name of an operation is the key identifier for it.
InFlightDiagnostic emitOpError(const Twine &message={})
Emit an error with the op name prefixed, like "'dim' op " which is convenient for verifiers.
OpTy get() const
Allow accessing the internal op.
This class represents a configuration for the MLIR assembly parser.
The main pass manager and pipeline builder.
MLIRContext * getContext() const
Return an instance of the context.
LogicalResult run(Operation *op)
Run the passes within this manager on the provided operation.
void enableVerifier(bool enabled=true)
Runs the verifier after each individual pass.
void enableTiming(TimingScope &timingScope)
Add an instrumentation to time the execution of passes and the computation of analyses.
This class implements a command-line parser for MLIR passes.
LogicalResult addToPipeline(OpPassManager &pm, function_ref< LogicalResult(const Twine &)> errorHandler) const
Adds the passes defined by this parser entry to the given pass manager.
static llvm::Expected< PassPlugin > load(const std::string &filename)
Attempts to load a pass plugin from a given file.
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...
LogicalResult verify()
Returns the status of the handler and verifies that all expected diagnostics were emitted.
TimingScope getRootScope()
Get the root timer of this timing manager wrapped in a TimingScope for convenience.
An RAII-style wrapper around a timer that ensures the timer is properly started and stopped.
TimingScope nest(Args... args)
Create a nested timing scope.
void stop()
Manually stop the timer early.
static DebugConfig createFromCLOptions()
Create a new config with the default set from the CL options.
static void registerCLOptions()
Register the options as global LLVM command line options.
static void registerCLOptions()
Register the command line options for debug counters.
This is a RAII class that installs the debug handlers on the context based on the provided configurat...
Include the generated interface declarations.
LogicalResult loadDialects(ModuleOp op)
Load all the dialects defined in the module.
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
Include the generated interface declarations.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
std::unique_ptr< llvm::MemoryBuffer > openInputFile(llvm::StringRef inputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for reading.
LogicalResult applyPassManagerCLOptions(PassManager &pm)
Apply any values provided to the pass manager options that were registered with 'registerPassManagerO...
void registerDefaultTimingManagerCLOptions()
Register a set of useful command-line options that can be used to configure a DefaultTimingManager.
LogicalResult MlirOptMain(llvm::raw_ostream &outputStream, std::unique_ptr< llvm::MemoryBuffer > buffer, DialectRegistry ®istry, const MlirOptMainConfig &config)
Perform the core processing behind mlir-opt.
std::unique_ptr< llvm::ToolOutputFile > openOutputFile(llvm::StringRef outputFilename, std::string *errorMessage=nullptr)
Open the file specified by its name for writing.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
void registerMLIRContextCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
OwningOpRef< Operation * > parseSourceFileForTool(const std::shared_ptr< llvm::SourceMgr > &sourceMgr, const ParserConfig &config, bool insertImplicitModule)
This parses the file specified by the indicated SourceMgr.
void registerAsmPrinterCLOptions()
Register a set of useful command-line options that can be used to configure various flags within the ...
void registerPassManagerCLOptions()
Register a set of useful command-line options that can be used to configure a pass manager.
void applyDefaultTimingManagerCLOptions(DefaultTimingManager &tm)
Apply any values that were registered with 'registerDefaultTimingManagerOptions' to a DefaultTimingMa...
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
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...
std::pair< std::string, std::string > registerAndParseCLIOptions(int argc, char **argv, llvm::StringRef toolName, DialectRegistry ®istry)
Register and parse command line options.
LogicalResult writeBytecodeToFile(Operation *op, raw_ostream &os, const BytecodeWriterConfig &config={})
Write the bytecode for the given operation to the provided output stream.
bool failed(LogicalResult result)
Utility function that returns true if the provided LogicalResult corresponds to a failure value.
This class represents an efficient way to signal success or failure.
void attachResourceParser(ParserConfig &config)
Attach an assembly resource parser to 'config' that collects the MLIR reproducer configuration into t...
LogicalResult apply(PassManager &pm) const
Apply the reproducer options to 'pm' and its context.