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
21using namespace mlir;
22using namespace mlir::tracing;
23using namespace llvm;
24
25namespace {
26struct 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
72static ManagedStatic<DebugConfigCLOptions> clOptionsConfig;
73void DebugConfig::registerCLOptions() { *clOptionsConfig; }
74
75DebugConfig DebugConfig::createFromCLOptions() { return *clOptionsConfig; }
76
77class InstallDebugHandler::Impl {
78public:
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
134private:
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
144InstallDebugHandler::InstallDebugHandler(MLIRContext &context,
145 const DebugConfig &config)
146 : impl(std::make_unique<Impl>(args&: context, args: config)) {}
147
148InstallDebugHandler::~InstallDebugHandler() = default;
149

source code of mlir/lib/Debug/CLOptionsSetup.cpp