155 lines · cpp
1//===- CLOptionsSetup.cpp - Helpers to setup debug CL options ---*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Debug/CLOptionsSetup.h"10 11#include "mlir/Debug/Counter.h"12#include "mlir/Debug/DebuggerExecutionContextHook.h"13#include "mlir/Debug/ExecutionContext.h"14#include "mlir/Debug/Observers/ActionLogging.h"15#include "mlir/Debug/Observers/ActionProfiler.h"16#include "mlir/IR/MLIRContext.h"17#include "mlir/Support/FileUtilities.h"18#include "llvm/Support/CommandLine.h"19#include "llvm/Support/ManagedStatic.h"20#include "llvm/Support/ToolOutputFile.h"21 22using namespace mlir;23using namespace mlir::tracing;24using namespace llvm;25 26namespace {27struct DebugConfigCLOptions : public DebugConfig {28 DebugConfigCLOptions() {29 static cl::opt<std::string, /*ExternalStorage=*/true> logActionsTo{30 "log-actions-to",31 cl::desc("Log action execution to a file, or stderr if "32 " '-' is passed"),33 cl::location(logActionsToFlag)};34 35 static cl::opt<std::string, /*ExternalStorage=*/true> profileActionsTo{36 "profile-actions-to",37 cl::desc("Profile action execution to a file, or stderr if "38 " '-' is passed"),39 cl::location(profileActionsToFlag)};40 41 static cl::list<std::string> logActionLocationFilter(42 "log-mlir-actions-filter",43 cl::desc(44 "Comma separated list of locations to filter actions from logging"),45 cl::CommaSeparated,46 cl::cb<void, std::string>([&](const std::string &location) {47 static bool registerOnce = [&] {48 addLogActionLocFilter(&locBreakpointManager);49 return true;50 }();51 (void)registerOnce;52 static std::vector<std::string> locations;53 locations.push_back(location);54 StringRef locStr = locations.back();55 56 // Parse the individual location filters and set the breakpoints.57 auto diag = [](Twine msg) { llvm::errs() << msg << "\n"; };58 auto locBreakpoint =59 tracing::FileLineColLocBreakpoint::parseFromString(locStr, diag);60 if (failed(locBreakpoint)) {61 llvm::errs() << "Invalid location filter: " << locStr << "\n";62 exit(1);63 }64 auto [file, line, col] = *locBreakpoint;65 locBreakpointManager.addBreakpoint(file, line, col);66 }));67 68 static cl::opt<bool, /*ExternalStorage=*/true> enableDebuggerHook(69 "mlir-enable-debugger-hook",70 cl::desc("Enable Debugger hook for debugging MLIR Actions"),71 cl::location(enableDebuggerActionHookFlag), cl::init(false));72 }73 tracing::FileLineColLocBreakpointManager locBreakpointManager;74};75 76} // namespace77 78static ManagedStatic<DebugConfigCLOptions> clOptionsConfig;79void DebugConfig::registerCLOptions() { *clOptionsConfig; }80 81DebugConfig DebugConfig::createFromCLOptions() { return *clOptionsConfig; }82 83class InstallDebugHandler::Impl {84public:85 Impl(MLIRContext &context, const DebugConfig &config) {86 if (config.getLogActionsTo().empty() &&87 config.getProfileActionsTo().empty() &&88 !config.isDebuggerActionHookEnabled()) {89 if (tracing::DebugCounter::isActivated())90 context.registerActionHandler(tracing::DebugCounter());91 return;92 }93 errs() << "ExecutionContext registered on the context";94 if (tracing::DebugCounter::isActivated())95 emitError(UnknownLoc::get(&context),96 "Debug counters are incompatible with --log-actions-to and "97 "--mlir-enable-debugger-hook options and are disabled");98 if (!config.getLogActionsTo().empty()) {99 std::string errorMessage;100 logActionsFile = openOutputFile(config.getLogActionsTo(), &errorMessage);101 if (!logActionsFile) {102 emitError(UnknownLoc::get(&context),103 "Opening file for --log-actions-to failed: ")104 << errorMessage << "\n";105 return;106 }107 logActionsFile->keep();108 raw_fd_ostream &logActionsStream = logActionsFile->os();109 actionLogger = std::make_unique<tracing::ActionLogger>(logActionsStream);110 for (const auto *locationBreakpoint : config.getLogActionsLocFilters())111 actionLogger->addBreakpointManager(locationBreakpoint);112 executionContext.registerObserver(actionLogger.get());113 }114 115 if (!config.getProfileActionsTo().empty()) {116 std::string errorMessage;117 profileActionsFile =118 openOutputFile(config.getProfileActionsTo(), &errorMessage);119 if (!profileActionsFile) {120 emitError(UnknownLoc::get(&context),121 "Opening file for --profile-actions-to failed: ")122 << errorMessage << "\n";123 return;124 }125 profileActionsFile->keep();126 raw_fd_ostream &profileActionsStream = profileActionsFile->os();127 actionProfiler =128 std::make_unique<tracing::ActionProfiler>(profileActionsStream);129 executionContext.registerObserver(actionProfiler.get());130 }131 132 if (config.isDebuggerActionHookEnabled()) {133 errs() << " (with Debugger hook)";134 setupDebuggerExecutionContextHook(executionContext);135 }136 errs() << "\n";137 context.registerActionHandler(executionContext);138 }139 140private:141 std::unique_ptr<ToolOutputFile> logActionsFile;142 tracing::ExecutionContext executionContext;143 std::unique_ptr<tracing::ActionLogger> actionLogger;144 std::vector<std::unique_ptr<tracing::FileLineColLocBreakpoint>>145 locationBreakpoints;146 std::unique_ptr<ToolOutputFile> profileActionsFile;147 std::unique_ptr<tracing::ActionProfiler> actionProfiler;148};149 150InstallDebugHandler::InstallDebugHandler(MLIRContext &context,151 const DebugConfig &config)152 : impl(std::make_unique<Impl>(context, config)) {}153 154InstallDebugHandler::~InstallDebugHandler() = default;155