xref: /llvm-project/mlir/lib/Debug/CLOptionsSetup.cpp (revision 0aea1f2f21b8b3984072dc2ea33857d077d91af2)
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-exception
6 //
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 
22 using namespace mlir;
23 using namespace mlir::tracing;
24 using namespace llvm;
25 
26 namespace {
27 struct DebugConfigCLOptions : public DebugConfig {
DebugConfigCLOptions__anon2c1116fe0111::DebugConfigCLOptions28   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   tracing::FileLineColLocBreakpointManager locBreakpointManager;
69 };
70 
71 } // namespace
72 
73 static ManagedStatic<DebugConfigCLOptions> clOptionsConfig;
registerCLOptions()74 void DebugConfig::registerCLOptions() { *clOptionsConfig; }
75 
createFromCLOptions()76 DebugConfig DebugConfig::createFromCLOptions() { return *clOptionsConfig; }
77 
78 class InstallDebugHandler::Impl {
79 public:
Impl(MLIRContext & context,const DebugConfig & config)80   Impl(MLIRContext &context, const DebugConfig &config) {
81     if (config.getLogActionsTo().empty() &&
82         config.getProfileActionsTo().empty() &&
83         !config.isDebuggerActionHookEnabled()) {
84       if (tracing::DebugCounter::isActivated())
85         context.registerActionHandler(tracing::DebugCounter());
86       return;
87     }
88     errs() << "ExecutionContext registered on the context";
89     if (tracing::DebugCounter::isActivated())
90       emitError(UnknownLoc::get(&context),
91                 "Debug counters are incompatible with --log-actions-to and "
92                 "--mlir-enable-debugger-hook options and are disabled");
93     if (!config.getLogActionsTo().empty()) {
94       std::string errorMessage;
95       logActionsFile = openOutputFile(config.getLogActionsTo(), &errorMessage);
96       if (!logActionsFile) {
97         emitError(UnknownLoc::get(&context),
98                   "Opening file for --log-actions-to failed: ")
99             << errorMessage << "\n";
100         return;
101       }
102       logActionsFile->keep();
103       raw_fd_ostream &logActionsStream = logActionsFile->os();
104       actionLogger = std::make_unique<tracing::ActionLogger>(logActionsStream);
105       for (const auto *locationBreakpoint : config.getLogActionsLocFilters())
106         actionLogger->addBreakpointManager(locationBreakpoint);
107       executionContext.registerObserver(actionLogger.get());
108     }
109 
110     if (!config.getProfileActionsTo().empty()) {
111       std::string errorMessage;
112       profileActionsFile =
113           openOutputFile(config.getProfileActionsTo(), &errorMessage);
114       if (!profileActionsFile) {
115         emitError(UnknownLoc::get(&context),
116                   "Opening file for --profile-actions-to failed: ")
117             << errorMessage << "\n";
118         return;
119       }
120       profileActionsFile->keep();
121       raw_fd_ostream &profileActionsStream = profileActionsFile->os();
122       actionProfiler =
123           std::make_unique<tracing::ActionProfiler>(profileActionsStream);
124       executionContext.registerObserver(actionProfiler.get());
125     }
126 
127     if (config.isDebuggerActionHookEnabled()) {
128       errs() << " (with Debugger hook)";
129       setupDebuggerExecutionContextHook(executionContext);
130     }
131     errs() << "\n";
132     context.registerActionHandler(executionContext);
133   }
134 
135 private:
136   std::unique_ptr<ToolOutputFile> logActionsFile;
137   tracing::ExecutionContext executionContext;
138   std::unique_ptr<tracing::ActionLogger> actionLogger;
139   std::vector<std::unique_ptr<tracing::FileLineColLocBreakpoint>>
140       locationBreakpoints;
141   std::unique_ptr<ToolOutputFile> profileActionsFile;
142   std::unique_ptr<tracing::ActionProfiler> actionProfiler;
143 };
144 
InstallDebugHandler(MLIRContext & context,const DebugConfig & config)145 InstallDebugHandler::InstallDebugHandler(MLIRContext &context,
146                                          const DebugConfig &config)
147     : impl(std::make_unique<Impl>(context, config)) {}
148 
149 InstallDebugHandler::~InstallDebugHandler() = default;
150