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