blob: fbea5fdf6b4bbc96f36a7b4203cb554f58075820 [file] [log] [blame]
//===- CLOptionsSetup.cpp - Helpers to setup debug CL options ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "mlir/Debug/CLOptionsSetup.h"
#include "mlir/Debug/Counter.h"
#include "mlir/Debug/DebuggerExecutionContextHook.h"
#include "mlir/Debug/ExecutionContext.h"
#include "mlir/Debug/Observers/ActionLogging.h"
#include "mlir/Debug/Observers/ActionProfiler.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/Support/FileUtilities.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ToolOutputFile.h"
using namespace mlir;
using namespace mlir::tracing;
using namespace llvm;
namespace {
struct DebugConfigCLOptions : public DebugConfig {
DebugConfigCLOptions() {
static cl::opt<std::string, /*ExternalStorage=*/true> logActionsTo{
"log-actions-to",
cl::desc("Log action execution to a file, or stderr if "
" '-' is passed"),
cl::location(logActionsToFlag)};
static cl::opt<std::string, /*ExternalStorage=*/true> profileActionsTo{
"profile-actions-to",
cl::desc("Profile action execution to a file, or stderr if "
" '-' is passed"),
cl::location(profileActionsToFlag)};
static cl::list<std::string> logActionLocationFilter(
"log-mlir-actions-filter",
cl::desc(
"Comma separated list of locations to filter actions from logging"),
cl::CommaSeparated,
cl::cb<void, std::string>([&](const std::string &location) {
static bool registerOnce = [&] {
addLogActionLocFilter(&locBreakpointManager);
return true;
}();
(void)registerOnce;
static std::vector<std::string> locations;
locations.push_back(location);
StringRef locStr = locations.back();
// Parse the individual location filters and set the breakpoints.
auto diag = [](Twine msg) { llvm::errs() << msg << "\n"; };
auto locBreakpoint =
tracing::FileLineColLocBreakpoint::parseFromString(locStr, diag);
if (failed(locBreakpoint)) {
llvm::errs() << "Invalid location filter: " << locStr << "\n";
exit(1);
}
auto [file, line, col] = *locBreakpoint;
locBreakpointManager.addBreakpoint(file, line, col);
}));
}
tracing::FileLineColLocBreakpointManager locBreakpointManager;
};
} // namespace
static ManagedStatic<DebugConfigCLOptions> clOptionsConfig;
void DebugConfig::registerCLOptions() { *clOptionsConfig; }
DebugConfig DebugConfig::createFromCLOptions() { return *clOptionsConfig; }
class InstallDebugHandler::Impl {
public:
Impl(MLIRContext &context, const DebugConfig &config) {
if (config.getLogActionsTo().empty() &&
config.getProfileActionsTo().empty() &&
!config.isDebuggerActionHookEnabled()) {
if (tracing::DebugCounter::isActivated())
context.registerActionHandler(tracing::DebugCounter());
return;
}
errs() << "ExecutionContext registered on the context";
if (tracing::DebugCounter::isActivated())
emitError(UnknownLoc::get(&context),
"Debug counters are incompatible with --log-actions-to and "
"--mlir-enable-debugger-hook options and are disabled");
if (!config.getLogActionsTo().empty()) {
std::string errorMessage;
logActionsFile = openOutputFile(config.getLogActionsTo(), &errorMessage);
if (!logActionsFile) {
emitError(UnknownLoc::get(&context),
"Opening file for --log-actions-to failed: ")
<< errorMessage << "\n";
return;
}
logActionsFile->keep();
raw_fd_ostream &logActionsStream = logActionsFile->os();
actionLogger = std::make_unique<tracing::ActionLogger>(logActionsStream);
for (const auto *locationBreakpoint : config.getLogActionsLocFilters())
actionLogger->addBreakpointManager(locationBreakpoint);
executionContext.registerObserver(actionLogger.get());
}
if (!config.getProfileActionsTo().empty()) {
std::string errorMessage;
profileActionsFile =
openOutputFile(config.getProfileActionsTo(), &errorMessage);
if (!profileActionsFile) {
emitError(UnknownLoc::get(&context),
"Opening file for --profile-actions-to failed: ")
<< errorMessage << "\n";
return;
}
profileActionsFile->keep();
raw_fd_ostream &profileActionsStream = profileActionsFile->os();
actionProfiler =
std::make_unique<tracing::ActionProfiler>(profileActionsStream);
executionContext.registerObserver(actionProfiler.get());
}
if (config.isDebuggerActionHookEnabled()) {
errs() << " (with Debugger hook)";
setupDebuggerExecutionContextHook(executionContext);
}
errs() << "\n";
context.registerActionHandler(executionContext);
}
private:
std::unique_ptr<ToolOutputFile> logActionsFile;
tracing::ExecutionContext executionContext;
std::unique_ptr<tracing::ActionLogger> actionLogger;
std::vector<std::unique_ptr<tracing::FileLineColLocBreakpoint>>
locationBreakpoints;
std::unique_ptr<ToolOutputFile> profileActionsFile;
std::unique_ptr<tracing::ActionProfiler> actionProfiler;
};
InstallDebugHandler::InstallDebugHandler(MLIRContext &context,
const DebugConfig &config)
: impl(std::make_unique<Impl>(context, config)) {}
InstallDebugHandler::~InstallDebugHandler() = default;