19 struct DebuggerState {
45 static LLVM_THREAD_LOCAL DebuggerState debuggerState;
57 if (!state.actionActiveStack) {
58 llvm::outs() <<
"No active action.\n";
62 state.actionActiveStack->getAction().getContextIRUnits();
63 llvm::outs() << units.size() <<
" available IRUnits:\n";
64 for (
const IRUnit &unit : units) {
65 llvm::outs() <<
" - ";
75 if (!state.actionActiveStack) {
76 llvm::outs() <<
"No active action.\n";
79 state.actionActiveStack->print(llvm::outs(), withContext);
89 llvm::outs() <<
"No active MLIR cursor, select from the context first\n";
93 .skipRegions(!withRegion)
101 if (!state.actionActiveStack) {
102 llvm::outs() <<
"No active MLIR Action stack\n";
106 state.actionActiveStack->getAction().getContextIRUnits();
107 if (index < 0 || index >=
static_cast<int>(units.size())) {
108 llvm::outs() <<
"Index invalid, bounds: [0, " << units.size()
109 <<
"] but got " << index <<
"\n";
112 state.cursor = units[index];
113 state.cursor.print(llvm::outs());
114 llvm::outs() <<
"\n";
120 llvm::outs() <<
"No active MLIR cursor, select from the context first\n";
123 IRUnit *unit = &state.cursor;
124 if (
auto *op = llvm::dyn_cast_if_present<Operation *>(*unit)) {
125 state.cursor = op->getBlock();
126 }
else if (
auto *region = llvm::dyn_cast_if_present<Region *>(*unit)) {
127 state.cursor = region->getParentOp();
128 }
else if (
auto *block = llvm::dyn_cast_if_present<Block *>(*unit)) {
129 state.cursor = block->getParent();
131 llvm::outs() <<
"Current cursor is not a valid IRUnit";
134 state.cursor.print(llvm::outs());
135 llvm::outs() <<
"\n";
141 llvm::outs() <<
"No active MLIR cursor, select from the context first\n";
144 IRUnit *unit = &state.cursor;
145 if (
auto *op = llvm::dyn_cast_if_present<Operation *>(*unit)) {
146 if (index < 0 || index >=
static_cast<int>(op->getNumRegions())) {
147 llvm::outs() <<
"Index invalid, op has " << op->getNumRegions()
148 <<
" but got " << index <<
"\n";
151 state.cursor = &op->getRegion(index);
152 }
else if (
auto *region = llvm::dyn_cast_if_present<Region *>(*unit)) {
153 auto block = region->begin();
155 while (block != region->end() && count != index) {
160 if (block == region->end()) {
161 llvm::outs() <<
"Index invalid, region has " << count <<
" block but got "
165 state.cursor = &*block;
166 }
else if (
auto *block = llvm::dyn_cast_if_present<Block *>(*unit)) {
167 auto op = block->begin();
169 while (op != block->end() && count != index) {
174 if (op == block->end()) {
175 llvm::outs() <<
"Index invalid, block has " << count
176 <<
"operations but got " << index <<
"\n";
181 llvm::outs() <<
"Current cursor is not a valid IRUnit";
184 state.cursor.print(llvm::outs());
185 llvm::outs() <<
"\n";
191 llvm::outs() <<
"No active MLIR cursor, select from the context first\n";
194 IRUnit *unit = &state.cursor;
195 if (
auto *op = llvm::dyn_cast_if_present<Operation *>(*unit)) {
198 llvm::outs() <<
"No previous operation in the current block\n";
201 state.cursor = previous;
202 }
else if (
auto *region = llvm::dyn_cast_if_present<Region *>(*unit)) {
203 llvm::outs() <<
"Has region\n";
206 llvm::outs() <<
"No parent operation for the current region\n";
209 if (region->getRegionNumber() == 0) {
210 llvm::outs() <<
"No previous region in the current operation\n";
214 ®ion->getParentOp()->getRegion(region->getRegionNumber() - 1);
215 }
else if (
auto *block = llvm::dyn_cast_if_present<Block *>(*unit)) {
216 Block *previous = block->getPrevNode();
218 llvm::outs() <<
"No previous block in the current region\n";
221 state.cursor = previous;
223 llvm::outs() <<
"Current cursor is not a valid IRUnit";
226 state.cursor.print(llvm::outs());
227 llvm::outs() <<
"\n";
233 llvm::outs() <<
"No active MLIR cursor, select from the context first\n";
236 IRUnit *unit = &state.cursor;
237 if (
auto *op = llvm::dyn_cast_if_present<Operation *>(*unit)) {
240 llvm::outs() <<
"No next operation in the current block\n";
244 }
else if (
auto *region = llvm::dyn_cast_if_present<Region *>(*unit)) {
247 llvm::outs() <<
"No parent operation for the current region\n";
250 if (region->getRegionNumber() == parent->
getNumRegions() - 1) {
251 llvm::outs() <<
"No next region in the current operation\n";
255 ®ion->getParentOp()->getRegion(region->getRegionNumber() + 1);
256 }
else if (
auto *block = llvm::dyn_cast_if_present<Block *>(*unit)) {
257 Block *next = block->getNextNode();
259 llvm::outs() <<
"No next block in the current region\n";
264 llvm::outs() <<
"Current cursor is not a valid IRUnit";
267 state.cursor.print(llvm::outs());
268 llvm::outs() <<
"\n";
276 reinterpret_cast<Breakpoint *
>(breakpoint)->enable();
280 reinterpret_cast<Breakpoint *
>(breakpoint)->disable();
286 state.tagBreakpointManager.addBreakpoint(StringRef(tag, strlen(tag)));
287 int breakpointId = state.breakpointIdsMap.size() + 1;
288 state.breakpointIdsMap[breakpointId] = breakpoint;
297 StringRef(file, strlen(file)), line, col);
303 static LLVM_THREAD_LOCAL
void *
volatile sink;
304 sink =
static_cast<void *
>(
const_cast<void **
>(&sink));
308 static void *
volatile sink;
309 static bool initialized = [&]() {
324 sink =
static_cast<void *
>(
const_cast<void **
>(&sink));
340 llvm::outs() <<
"\n";
349 bool willExecute)
override {
351 state.actionActiveStack = action;
355 state.actionActiveStack = action->
getParent();
356 state.cursor =
nullptr;
365 static DebuggerObserver observer;
void mlirDebuggerEnableBreakpoint(BreakpointHandle breakpoint)
Enable the provided breakpoint.
void mlirDebuggerCursorPrint(bool withRegion)
Print the current IR unit cursor.
void mlirDebuggerPrintActionBacktrace(bool withContext)
Print the current action backtrace.
void mlirDebuggerCursorSelectChildIRUnit(int index)
Select the child IR unit at the provided index, print an error if the index is out of bound.
static DebuggerState & getGlobalDebuggerState()
void mlirDebuggerPrintContext()
Print the available context for the current Action.
void mlirDebuggerCursorSelectIRUnitFromContext(int index)
Select the IR unit from the current context by ID.
void mlirDebuggerAddRewritePatternBreakpoint(const char *patternNameInfo)
Add a breakpoint matching a pattern by name.
static void preventLinkerDeadCodeElim()
void mlirDebuggerDisableBreakpoint(BreakpointHandle breakpoint)
Disable the provided breakpoint.
void mlirDebuggerAddFileLineColLocBreakpoint(const char *file, int line, int col)
Add a breakpoint matching a file, line and column.
LLVM_ATTRIBUTE_NOINLINE void mlirDebuggerBreakpointHook()
void mlirDebuggerSetControl(int controlOption)
This is used by the debugger to control what to do after a breakpoint is hit.
static tracing::ExecutionContext::Control debuggerCallBackFunction(const tracing::ActionActiveStack *actionStack)
void mlirDebuggerCursorSelectPreviousIRUnit()
Return the next IR unit logically in the IR.
void mlirDebuggerCursorSelectNextIRUnit()
Return the previous IR unit logically in the IR.
BreakpointHandle mlirDebuggerAddTagBreakpoint(const char *tag)
Add a breakpoint matching exactly the provided tag.
void mlirDebuggerCursorSelectParentIRUnit()
Select the parent IR unit of the provided IR unit, or print an error if the IR unit has no parent.
struct MLIRBreakpoint * BreakpointHandle
static const LLVM_THREAD_LOCAL ActionActiveStack * actionStack
Block represents an ordered list of Operations.
IRUnit is a union of the different types of IR objects that consistute the IR structure (other than T...
Set of flags used to control the behavior of the various IR print methods (e.g.
Operation is the basic unit of execution within MLIR.
unsigned getNumRegions()
Returns the number of regions held by this operation.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
virtual void print(raw_ostream &os) const
This abstract class represents a breakpoint.
The ExecutionContext is the main orchestration of the infrastructure, it acts as a handler in the MLI...
void registerObserver(Observer *observer)
Register a new Observer on this context.
Control
Enum that allows the client of the context to control the execution of the action.
void addBreakpointManager(BreakpointManager *manager)
Register a new BreakpointManager on this context.
void setCallback(CallbackTy callback)
Set the callback that is used to control the execution.
This breakpoint manager is responsible for matching FileLineColLocBreakpoint.
This is a manager to store a collection of breakpoints that trigger on tags.
Include the generated interface declarations.
void setupDebuggerExecutionContextHook(tracing::ExecutionContext &executionContext)
This class is used to keep track of the active actions in the stack.
const ActionActiveStack * getParent() const
const Action & getAction() const
This abstract class defines the interface used to observe an Action execution.