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