Skip to content

Commit 1020150

Browse files
committed
Add a GDB/LLDB interface for interactive debugging of MLIR Actions
This includes a small runtime acting as callback for the ExecutionEngine and a C API that makes it possible to control from the debugger. A python script for LLDB is included that hook a new `mlir` subcommand and allows to set breakpoints and inspect the current action, the context and the stack. Differential Revision: https://reviews.llvm.org/D144817
1 parent 1869a9c commit 1020150

File tree

11 files changed

+1125
-28
lines changed

11 files changed

+1125
-28
lines changed
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//===- DebuggerExecutionContextHook.h - Debugger Support --------*- 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+
// This file contains a set of C API functions that are used by the debugger to
10+
// interact with the ExecutionContext.
11+
//
12+
//===----------------------------------------------------------------------===//
13+
14+
#ifndef MLIR_SUPPORT_DEBUGGEREXECUTIONCONTEXTHOOK_H
15+
#define MLIR_SUPPORT_DEBUGGEREXECUTIONCONTEXTHOOK_H
16+
17+
#include "mlir-c/IR.h"
18+
#include "mlir/Debug/ExecutionContext.h"
19+
#include "llvm/Support/Compiler.h"
20+
21+
extern "C" {
22+
struct MLIRBreakpoint;
23+
struct MLIRIRunit;
24+
typedef struct MLIRBreakpoint *BreakpointHandle;
25+
typedef struct MLIRIRunit *irunitHandle;
26+
27+
/// This is used by the debugger to control what to do after a breakpoint is
28+
/// hit. See tracing::ExecutionContext::Control for more information.
29+
void mlirDebuggerSetControl(int controlOption);
30+
31+
/// Print the available context for the current Action.
32+
void mlirDebuggerPrintContext();
33+
34+
/// Print the current action backtrace.
35+
void mlirDebuggerPrintActionBacktrace(bool withContext);
36+
37+
//===----------------------------------------------------------------------===//
38+
// Cursor Management: The cursor is used to select an IRUnit from the context
39+
// and to navigate through the IRUnit hierarchy.
40+
//===----------------------------------------------------------------------===//
41+
42+
/// Print the current IR unit cursor.
43+
void mlirDebuggerCursorPrint(bool withRegion);
44+
45+
/// Select the IR unit from the current context by ID.
46+
void mlirDebuggerCursorSelectIRUnitFromContext(int index);
47+
48+
/// Select the parent IR unit of the provided IR unit, or print an error if the
49+
/// IR unit has no parent.
50+
void mlirDebuggerCursorSelectParentIRUnit();
51+
52+
/// Select the child IR unit at the provided index, print an error if the index
53+
/// is out of bound. For example if the irunit is an operation, the children IR
54+
/// units will be the operation's regions.
55+
void mlirDebuggerCursorSelectChildIRUnit(int index);
56+
57+
/// Return the next IR unit logically in the IR. For example if the irunit is a
58+
/// Region the next IR unit will be the next region in the parent operation or
59+
/// nullptr if there is no next region.
60+
void mlirDebuggerCursorSelectPreviousIRUnit();
61+
62+
/// Return the previous IR unit logically in the IR. For example if the irunit
63+
/// is a Region, the previous IR unit will be the previous region in the parent
64+
/// operation or nullptr if there is no previous region.
65+
void mlirDebuggerCursorSelectNextIRUnit();
66+
67+
//===----------------------------------------------------------------------===//
68+
// Breakpoint Management
69+
//===----------------------------------------------------------------------===//
70+
71+
/// Enable the provided breakpoint.
72+
void mlirDebuggerEnableBreakpoint(BreakpointHandle breakpoint);
73+
74+
/// Disable the provided breakpoint.
75+
void mlirDebuggerDisableBreakpoint(BreakpointHandle breakpoint);
76+
77+
/// Add a breakpoint matching exactly the provided tag.
78+
BreakpointHandle mlirDebuggerAddTagBreakpoint(const char *tag);
79+
80+
/// Add a breakpoint matching a pattern by name.
81+
void mlirDebuggerAddRewritePatternBreakpoint(const char *patternNameInfo);
82+
83+
/// Add a breakpoint matching a file, line and column.
84+
void mlirDebuggerAddFileLineColLocBreakpoint(const char *file, int line,
85+
int col);
86+
87+
} // extern "C"
88+
89+
namespace mlir {
90+
// Setup the debugger hooks as a callback on the provided ExecutionContext.
91+
void setupDebuggerExecutionContextHook(
92+
tracing::ExecutionContext &executionContext);
93+
94+
} // namespace mlir
95+
96+
#endif // MLIR_SUPPORT_DEBUGGEREXECUTIONCONTEXTHOOK_H

mlir/include/mlir/Debug/ExecutionContext.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,16 @@ struct ActionActiveStack {
2828
const ActionActiveStack *getParent() const { return parent; }
2929
const Action &getAction() const { return action; }
3030
int getDepth() const { return depth; }
31+
void print(raw_ostream &os, bool withContext) const;
32+
void dump() const {
33+
print(llvm::errs(), /*withContext=*/true);
34+
llvm::errs() << "\n";
35+
}
36+
Breakpoint *getBreakpoint() const { return breakpoint; }
37+
void setBreakpoint(Breakpoint *breakpoint) { this->breakpoint = breakpoint; }
3138

3239
private:
40+
Breakpoint *breakpoint = nullptr;
3341
const ActionActiveStack *parent;
3442
const Action &action;
3543
int depth;
@@ -69,7 +77,9 @@ class ExecutionContext {
6977
ExecutionContext() = default;
7078

7179
/// Set the callback that is used to control the execution.
72-
void setCallback(CallbackTy callback);
80+
void setCallback(CallbackTy callback) {
81+
onBreakpointControlExecutionCallback = callback;
82+
}
7383

7484
/// This abstract class defines the interface used to observe an Action
7585
/// execution. It allows to be notified before and after the callback is

mlir/include/mlir/IR/OperationSupport.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -835,7 +835,7 @@ class OpPrintingFlags {
835835
OpPrintingFlags &printGenericOpForm();
836836

837837
/// Skip printing regions.
838-
OpPrintingFlags &skipRegions();
838+
OpPrintingFlags &skipRegions(bool skip = true);
839839

840840
/// Do not verify the operation when using custom operation printers.
841841
OpPrintingFlags &assumeVerified();

mlir/include/mlir/Rewrite/PatternApplicator.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ class ApplyPatternAction : public tracing::ActionImpl<ApplyPatternAction> {
3737
"Encapsulate the application of rewrite patterns";
3838

3939
void print(raw_ostream &os) const override {
40-
os << "`" << tag << "`\n"
41-
<< " pattern: " << pattern.getDebugName() << '\n';
40+
os << "`" << tag << " pattern: " << pattern.getDebugName();
4241
}
4342

4443
private:

mlir/include/mlir/Tools/mlir-opt/MlirOptMain.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ class MlirOptMainConfig {
7878
}
7979
bool shouldEmitBytecode() const { return emitBytecodeFlag; }
8080

81+
/// Enable the debugger action hook: it makes the debugger able to intercept
82+
/// MLIR Actions.
83+
void enableDebuggerActionHook(bool enabled = true) {
84+
enableDebuggerActionHookFlag = enabled;
85+
}
86+
87+
/// Return true if the Debugger action hook is enabled.
88+
bool isDebuggerActionHookEnabled() const {
89+
return enableDebuggerActionHookFlag;
90+
}
91+
8192
/// Set the IRDL file to load before processing the input.
8293
MlirOptMainConfig &setIrdlFile(StringRef file) {
8394
irdlFileFlag = file;
@@ -180,6 +191,9 @@ class MlirOptMainConfig {
180191
/// Emit bytecode instead of textual assembly when generating output.
181192
bool emitBytecodeFlag = false;
182193

194+
/// Enable the Debugger action hook: Debugger can intercept MLIR Actions.
195+
bool enableDebuggerActionHookFlag = false;
196+
183197
/// IRDL file to register before processing the input.
184198
std::string irdlFileFlag = "";
185199

mlir/lib/Debug/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ add_mlir_library(MLIRDebug
44
DebugCounter.cpp
55
ExecutionContext.cpp
66
BreakpointManagers/FileLineColLocBreakpointManager.cpp
7+
DebuggerExecutionContextHook.cpp
78

89
ADDITIONAL_HEADER_DIRS
910
${MLIR_MAIN_INCLUDE_DIR}/mlir/Debug

0 commit comments

Comments
 (0)