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