diff --git a/mlir/include/mlir/Debug/CLOptionsSetup.h b/mlir/include/mlir/Debug/CLOptionsSetup.h new file mode 100644 --- /dev/null +++ b/mlir/include/mlir/Debug/CLOptionsSetup.h @@ -0,0 +1,90 @@ +//===- CLOptionsSetup.h - Helpers to setup debug CL options -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef MLIR_DEBUG_CLOPTIONSSETUP_H +#define MLIR_DEBUG_CLOPTIONSSETUP_H + +#include "mlir/Debug/BreakpointManagers/FileLineColLocBreakpointManager.h" +#include "mlir/Support/LogicalResult.h" +#include "llvm/ADT/StringRef.h" + +#include + +namespace mlir { +class MLIRContext; +namespace tracing { +class BreakpointManager; + +class DebugConfig { +public: + /// Register the options as global LLVM command line options. + static void registerCLOptions(); + + /// Create a new config with the default set from the CL options. + static DebugConfig createFromCLOptions(); + + /// + /// Options. + /// + + /// Enable the gdb action hook: it makes GDB able to intercept MLIR Actions. + void enableGdbActionHook(bool enabled = true) { + enableGdbActionHookFlag = enabled; + } + + /// Return true if the gdb action hook is enabled. + bool isGdbActionHookEnabled() const { return enableGdbActionHookFlag; } + + /// Set the filename to use for logging actions, use "-" for stdout. + DebugConfig &logActionsTo(StringRef filename) { + logActionsToFlag = filename; + return *this; + } + /// Get the filename to use for logging actions. + StringRef getLogActionsTo() const { return logActionsToFlag; } + + /// Set the location breakpoints to use for logging actions. + /// Ownership stays with the caller. + DebugConfig & + addLogActionLocFilter(tracing::BreakpointManager *breakpointManager) { + logActionLocationFilter.push_back(breakpointManager); + return *this; + } + + /// Get the location breakpoints to use for logging actions. + ArrayRef getLogActionsLocFilters() const { + return logActionLocationFilter; + } + +protected: + /// Enable the gdb action hook: GDB can intercept MLIR Actions. + bool enableGdbActionHookFlag = false; + + /// Log action execution to the given file (or "-" for stdout) + std::string logActionsToFlag; + + /// Location Breakpoints to filter the action logging. + std::vector logActionLocationFilter; +}; + +/// This is a RAII class that installs the debug handlers on the context +/// based on the provided configuration. +class InstallDebugHandler { +public: + InstallDebugHandler(MLIRContext &context, const DebugConfig &config); + ~InstallDebugHandler(); + +private: + class Impl; + std::unique_ptr impl; +}; + +} // namespace tracing +} // namespace mlir + +#endif // MLIR_DEBUG_CLOPTIONSSETUP_H diff --git a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h --- a/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h +++ b/mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h @@ -13,7 +13,7 @@ #ifndef MLIR_TOOLS_MLIROPT_MLIROPTMAIN_H #define MLIR_TOOLS_MLIROPT_MLIROPTMAIN_H -#include "mlir/Debug/BreakpointManagers/FileLineColLocBreakpointManager.h" +#include "mlir/Debug/CLOptionsSetup.h" #include "mlir/Support/LogicalResult.h" #include "llvm/ADT/StringRef.h" @@ -30,9 +30,6 @@ class DialectRegistry; class PassPipelineCLParser; class PassManager; -namespace tracing { -class FileLineColLocBreakpointManager; -} /// Configuration options for the mlir-opt tool. /// This is intended to help building tools like mlir-opt by collecting the @@ -64,6 +61,14 @@ return allowUnregisteredDialectsFlag; } + /// Set the debug configuration to use. + MlirOptMainConfig &setDebugConfig(tracing::DebugConfig config) { + debugConfig = std::move(config); + return *this; + } + tracing::DebugConfig &getDebugConfig() { return debugConfig; } + const tracing::DebugConfig &getDebugConfig() const { return debugConfig; } + /// Print the pass-pipeline as text before executing. MlirOptMainConfig &dumpPassPipeline(bool dump) { dumpPassPipelineFlag = dump; @@ -78,33 +83,6 @@ } bool shouldEmitBytecode() const { return emitBytecodeFlag; } - /// Enable the gdb action hook: it makes GDB able to intercept MLIR Actions. - void enableGdbActionHook(bool enabled = true) { - enableGdbActionHookFlag = enabled; - } - - /// Return true if the gdb action hook is enabled. - bool isGdbActionHookEnabled() const { return enableGdbActionHookFlag; } - - /// Set the filename to use for logging actions, use "-" for stdout. - MlirOptMainConfig &logActionsTo(StringRef filename) { - logActionsToFlag = filename; - return *this; - } - /// Get the filename to use for logging actions. - StringRef getLogActionsTo() const { return logActionsToFlag; } - - /// Set the location breakpoints to use for logging actions. - /// Ownership stays with the caller. - void addLogActionLocFilter(tracing::BreakpointManager *breakpointManager) { - logActionLocationFilter.push_back(breakpointManager); - } - - /// Get the location breakpoints to use for logging actions. - ArrayRef getLogActionsLocFilters() const { - return logActionLocationFilter; - } - /// Set the callback to populate the pass manager. MlirOptMainConfig & setPassPipelineSetupFn(std::function callback) { @@ -174,6 +152,9 @@ /// general. bool allowUnregisteredDialectsFlag = false; + /// Configuration for the debugging hooks. + tracing::DebugConfig debugConfig; + /// Print the pipeline that will be run. bool dumpPassPipelineFlag = false; @@ -183,12 +164,6 @@ /// Enable the gdb action hook: GDB can intercept MLIR Actions. bool enableGdbActionHookFlag = false; - /// Log action execution to the given file (or "-" for stdout) - std::string logActionsToFlag; - - /// Location Breakpoints to filter the action logging. - std::vector logActionLocationFilter; - /// The callback to populate the pass manager. std::function passPipelineCallback; diff --git a/mlir/lib/Debug/CLOptionsSetup.cpp b/mlir/lib/Debug/CLOptionsSetup.cpp new file mode 100644 --- /dev/null +++ b/mlir/lib/Debug/CLOptionsSetup.cpp @@ -0,0 +1,118 @@ +//===- CLOptionsSetup.cpp - Helpers to setup debug CL options ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "mlir/Debug/CLOptionsSetup.h" + +#include "mlir/Debug/Counter.h" +#include "mlir/Debug/ExecutionContext.h" +#include "mlir/Debug/GdbDebugExecutionContextHook.h" +#include "mlir/Debug/Observers/ActionLogging.h" +#include "mlir/IR/MLIRContext.h" +#include "mlir/Support/FileUtilities.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/ToolOutputFile.h" + +using namespace mlir; +using namespace mlir::tracing; +using namespace llvm; + +namespace { +struct DebugConfigCLOptions : public DebugConfig { + DebugConfigCLOptions() { + static cl::opt logActionsTo{ + "log-actions-to", + cl::desc("Log action execution to a file, or stderr if " + " '-' is passed"), + cl::location(logActionsToFlag)}; + + static cl::list logActionLocationFilter( + "log-mlir-actions-filter", + cl::desc( + "Comma separated list of locations to filter actions from logging"), + cl::CommaSeparated, + cl::cb([&](const std::string &location) { + static bool register_once = [&] { + addLogActionLocFilter(&locBreakpointManager); + return true; + }(); + (void)register_once; + static std::vector locations; + locations.push_back(location); + StringRef locStr = locations.back(); + + // Parse the individual location filters and set the breakpoints. + auto diag = [](StringRef msg) { errs() << msg << "\n"; }; + auto locBreakpoint = + tracing::FileLineColLocBreakpoint::parseFromString(locStr, diag); + if (failed(locBreakpoint)) { + errs() << "Invalid location filter: " << locStr << "\n"; + exit(1); + } + auto [file, line, col] = *locBreakpoint; + locBreakpointManager.addBreakpoint(file, line, col); + })); + } + tracing::FileLineColLocBreakpointManager locBreakpointManager; +}; + +ManagedStatic clOptionsConfig; + +} // namespace + +void DebugConfig::registerCLOptions() { *clOptionsConfig; } + +DebugConfig DebugConfig::createFromCLOptions() { return *clOptionsConfig; } + +class InstallDebugHandler::Impl { +public: + Impl(MLIRContext &context, const DebugConfig &config) { + if (config.getLogActionsTo().empty() && !config.isGdbActionHookEnabled()) { + if (tracing::DebugCounter::isDebugCounterActivated()) + context.registerActionHandler(tracing::DebugCounter{}); + return; + } + errs() << "ExecutionContext registered on the context"; + if (tracing::DebugCounter::isDebugCounterActivated()) + emitError(UnknownLoc::get(&context), + "Debug counters are incompatible with --log-actions-to and " + "--mlir-enable-gdb-hook options and are disabled"); + if (!config.getLogActionsTo().empty()) { + std::string errorMessage; + logActionsFile = openOutputFile(config.getLogActionsTo(), &errorMessage); + if (!logActionsFile) { + errs() << "Error handling --log-actions-to: " << errorMessage << "\n"; + return; + } + logActionsFile->keep(); + raw_fd_ostream &logActionsStream = logActionsFile->os(); + actionLogger = std::make_unique(logActionsStream); + for (const auto *locationBreakpoint : config.getLogActionsLocFilters()) + actionLogger->addBreakpointManager(locationBreakpoint); + executionContext.registerObserver(actionLogger.get()); + } + if (config.isGdbActionHookEnabled()) { + errs() << " (with GDB hook)"; + setupGdbDebugExecutionContextHook(executionContext); + } + errs() << "\n"; + context.registerActionHandler(executionContext); + } + +private: + std::unique_ptr logActionsFile; + tracing::ExecutionContext executionContext; + std::unique_ptr actionLogger; + std::vector> + locationBreakpoints; +}; + +InstallDebugHandler::InstallDebugHandler(MLIRContext &context, + const DebugConfig &config) + : impl(std::make_unique(context, config)) {} + +InstallDebugHandler::~InstallDebugHandler() = default; diff --git a/mlir/lib/Debug/CMakeLists.txt b/mlir/lib/Debug/CMakeLists.txt --- a/mlir/lib/Debug/CMakeLists.txt +++ b/mlir/lib/Debug/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(Observers) add_mlir_library(MLIRDebug + CLOptionsSetup.cpp DebugCounter.cpp ExecutionContext.cpp BreakpointManagers/FileLineColLocBreakpointManager.cpp diff --git a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp --- a/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp +++ b/mlir/lib/Tools/mlir-opt/MlirOptMain.cpp @@ -13,6 +13,7 @@ #include "mlir/Tools/mlir-opt/MlirOptMain.h" #include "mlir/Bytecode/BytecodeWriter.h" +#include "mlir/Debug/CLOptionsSetup.h" #include "mlir/Debug/Counter.h" #include "mlir/Debug/ExecutionContext.h" #include "mlir/Debug/GdbDebugExecutionContextHook.h" @@ -76,39 +77,6 @@ "parsing"), cl::location(useExplicitModuleFlag), cl::init(false)); - static cl::opt logActionsTo{ - "log-actions-to", - cl::desc("Log action execution to a file, or stderr if " - " '-' is passed"), - cl::location(logActionsToFlag)}; - - static cl::list logActionLocationFilter( - "log-mlir-actions-filter", - cl::desc( - "Comma separated list of locations to filter actions from logging"), - cl::CommaSeparated, - cl::cb([&](const std::string &location) { - static bool register_once = [&] { - addLogActionLocFilter(&locBreakpointManager); - return true; - }(); - (void)register_once; - static std::vector locations; - locations.push_back(location); - StringRef locStr = locations.back(); - - // Parse the individual location filters and set the breakpoints. - auto diag = [](StringRef msg) { llvm::errs() << msg << "\n"; }; - auto locBreakpoint = - tracing::FileLineColLocBreakpoint::parseFromString(locStr, diag); - if (failed(locBreakpoint)) { - llvm::errs() << "Invalid location filter: " << locStr << "\n"; - exit(1); - } - auto [file, line, col] = *locBreakpoint; - locBreakpointManager.addBreakpoint(file, line, col); - })); - static cl::opt showDialects( "show-dialects", cl::desc("Print the list of registered dialects and exit"), @@ -134,16 +102,18 @@ static PassPipelineCLParser passPipeline("", "Compiler passes to run", "p"); setPassPipelineParser(passPipeline); } - - tracing::FileLineColLocBreakpointManager locBreakpointManager; }; } // namespace ManagedStatic clOptionsConfig; -void MlirOptMainConfig::registerCLOptions() { *clOptionsConfig; } +void MlirOptMainConfig::registerCLOptions() { + *clOptionsConfig; + tracing::DebugConfig::registerCLOptions(); +} MlirOptMainConfig MlirOptMainConfig::createFromCLOptions() { + clOptionsConfig->setDebugConfig(tracing::DebugConfig::createFromCLOptions()); return *clOptionsConfig; } @@ -166,51 +136,6 @@ return *this; } -/// Set the ExecutionContext on the context and handle the observers. -class InstallDebugHandler { -public: - InstallDebugHandler(MLIRContext &context, const MlirOptMainConfig &config) { - if (config.getLogActionsTo().empty() && !config.isGdbActionHookEnabled()) { - if (tracing::DebugCounter::isDebugCounterActivated()) - context.registerActionHandler(tracing::DebugCounter{}); - return; - } - llvm::errs() << "ExecutionContext registered on the context"; - if (tracing::DebugCounter::isDebugCounterActivated()) - emitError(UnknownLoc::get(&context), - "Debug counters are incompatible with --log-actions-to and " - "--mlir-enable-gdb-hook options and are disabled"); - if (!config.getLogActionsTo().empty()) { - std::string errorMessage; - logActionsFile = openOutputFile(config.getLogActionsTo(), &errorMessage); - if (!logActionsFile) { - llvm::errs() << "Error handling --log-actions-to: " << errorMessage - << "\n"; - return; - } - logActionsFile->keep(); - raw_fd_ostream &logActionsStream = logActionsFile->os(); - actionLogger = std::make_unique(logActionsStream); - for (const auto *locationBreakpoint : config.getLogActionsLocFilters()) - actionLogger->addBreakpointManager(locationBreakpoint); - executionContext.registerObserver(actionLogger.get()); - } - if (config.isGdbActionHookEnabled()) { - llvm::errs() << " (with GDB hook)"; - setupGdbDebugExecutionContextHook(executionContext); - } - llvm::errs() << "\n"; - context.registerActionHandler(executionContext); - } - -private: - std::unique_ptr logActionsFile; - tracing::ExecutionContext executionContext; - std::unique_ptr actionLogger; - std::vector> - locationBreakpoints; -}; - /// Perform the actions on the input file indicated by the command line flags /// within the specified context. /// @@ -299,7 +224,8 @@ if (config.shouldVerifyDiagnostics()) context.printOpOnDiagnostic(false); - InstallDebugHandler installDebugHandler{context, config}; + tracing::InstallDebugHandler installDebugHandler(context, + config.getDebugConfig()); // If we are in verify diagnostics mode then we have a lot of work to do, // otherwise just perform the actions without worrying about it.