diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h index ef976c1155795..19f223bf8aa84 100644 --- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h +++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h @@ -31,6 +31,13 @@ class DialectRegistry; class PassPipelineCLParser; class PassManager; +/// enum class to indicate the verbosity level of the diagnostic filter. +enum class VerbosityLevel { + ErrorsOnly = 0, + ErrorsAndWarnings, + ErrorsWarningsAndRemarks +}; + /// Configuration options for the mlir-opt tool. /// This is intended to help building tools like mlir-opt by collecting the /// supported options. @@ -74,6 +81,11 @@ class MlirOptMainConfig { dumpPassPipelineFlag = dump; return *this; } + + VerbosityLevel getDiagnosticVerbosityLevel() const { + return diagnosticVerbosityLevelFlag; + } + bool shouldDumpPassPipeline() const { return dumpPassPipelineFlag; } /// Set the output format to bytecode instead of textual IR. @@ -82,10 +94,13 @@ class MlirOptMainConfig { return *this; } bool shouldEmitBytecode() const { return emitBytecodeFlag; } + bool shouldElideResourceDataFromBytecode() const { return elideResourceDataFromBytecodeFlag; } + bool shouldShowNotes() const { return !disableDiagnosticNotesFlag; } + /// Set the IRDL file to load before processing the input. MlirOptMainConfig &setIrdlFile(StringRef file) { irdlFileFlag = file; @@ -202,6 +217,11 @@ class MlirOptMainConfig { /// Configuration for the debugging hooks. tracing::DebugConfig debugConfig; + /// Verbosity level of diagnostic information. 0: Errors only, + /// 1: Errors and warnings, 2: Errors, warnings and remarks. + VerbosityLevel diagnosticVerbosityLevelFlag = + VerbosityLevel::ErrorsWarningsAndRemarks; + /// Print the pipeline that will be run. bool dumpPassPipelineFlag = false; @@ -235,6 +255,11 @@ class MlirOptMainConfig { /// Show the registered dialects before trying to load the input file. bool showDialectsFlag = false; + /// Show the notes in diagnostic information. Notes can be included in + /// any diagnostic information, so it is not specified in the verbosity + /// level. + bool disableDiagnosticNotesFlag = true; + /// Split the input file based on the given marker into chunks and process /// each chunk independently. Input is not split if empty. std::string splitInputFileFlag = ""; diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp index 5a7b17672c518..a7cd601f5da50 100644 --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -41,6 +41,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/InitLLVM.h" +#include "llvm/Support/LogicalResult.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/Process.h" #include "llvm/Support/Regex.h" @@ -108,6 +109,23 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig { cl::desc("IRDL file to register before processing the input"), cl::location(irdlFileFlag), cl::init(""), cl::value_desc("filename")); + static cl::opt + diagnosticVerbosityLevel( + "mlir-diagnostic-verbosity-level", + cl::desc("Choose level of diagnostic information"), + cl::location(diagnosticVerbosityLevelFlag), + cl::init(VerbosityLevel::ErrorsWarningsAndRemarks), + cl::values( + clEnumValN(VerbosityLevel::ErrorsOnly, "errors", "Errors only"), + clEnumValN(VerbosityLevel::ErrorsAndWarnings, "warnings", + "Errors and warnings"), + clEnumValN(VerbosityLevel::ErrorsWarningsAndRemarks, "remarks", + "Errors, warnings and remarks"))); + + static cl::opt disableDiagnosticNotes( + "mlir-disable-diagnostic-notes", cl::desc("Disable diagnostic notes."), + cl::location(disableDiagnosticNotesFlag), cl::init(false)); + static cl::opt enableDebuggerHook( "mlir-enable-debugger-hook", cl::desc("Enable Debugger hook for debugging MLIR Actions"), @@ -133,7 +151,8 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig { cl::location(showDialectsFlag), cl::init(false)); static cl::opt splitInputFile{ - "split-input-file", llvm::cl::ValueOptional, + "split-input-file", + llvm::cl::ValueOptional, cl::callback([&](const std::string &str) { // Implicit value: use default marker if flag was used without value. if (str.empty()) @@ -141,7 +160,8 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig { }), cl::desc("Split the input file into chunks using the given or " "default marker and process each chunk independently"), - cl::location(splitInputFileFlag), cl::init("")}; + cl::location(splitInputFileFlag), + cl::init("")}; static cl::opt outputSplitMarker( "output-split-marker", @@ -202,6 +222,44 @@ struct MlirOptMainConfigCLOptions : public MlirOptMainConfig { /// setDialectPluginsCallback(DialectRegistry&). cl::list *dialectPlugins = nullptr; }; + +/// A scoped diagnostic handler that suppresses certain diagnostics based on +/// the verbosity level and whether the diagnostic is a note. +class DiagnosticFilter : public ScopedDiagnosticHandler { +public: + DiagnosticFilter(MLIRContext *ctx, VerbosityLevel verbosityLevel, + bool showNotes = true) + : ScopedDiagnosticHandler(ctx) { + setHandler([verbosityLevel, showNotes](Diagnostic &diag) { + auto severity = diag.getSeverity(); + switch (severity) { + case DiagnosticSeverity::Error: + // failure indicates that the error is not handled by the filter and + // goes through to the default handler. Therefore, the error can be + // successfully printed. + return failure(); + case DiagnosticSeverity::Warning: + if (verbosityLevel == VerbosityLevel::ErrorsOnly) + return success(); + else + return failure(); + case DiagnosticSeverity::Remark: + if (verbosityLevel == VerbosityLevel::ErrorsOnly || + verbosityLevel == VerbosityLevel::ErrorsAndWarnings) + return success(); + else + return failure(); + case DiagnosticSeverity::Note: + if (showNotes) + return failure(); + else + return success(); + default: + llvm_unreachable("Unknown diagnostic severity"); + } + }); + } +}; } // namespace ManagedStatic clOptionsConfig; @@ -474,6 +532,9 @@ static LogicalResult processBuffer(raw_ostream &os, // otherwise just perform the actions without worrying about it. if (!config.shouldVerifyDiagnostics()) { SourceMgrDiagnosticHandler sourceMgrHandler(*sourceMgr, &context); + DiagnosticFilter diagnosticFilter(&context, + config.getDiagnosticVerbosityLevel(), + config.shouldShowNotes()); return performActions(os, sourceMgr, &context, config); }