1 //===- ExecutionContext.cpp - Debug Execution Context Support -------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "mlir/Debug/ExecutionContext.h"
11 #include "llvm/ADT/ScopeExit.h"
12 #include "llvm/Support/FormatVariadic.h"
17 using namespace mlir::tracing
;
19 //===----------------------------------------------------------------------===//
21 //===----------------------------------------------------------------------===//
23 void ActionActiveStack::print(raw_ostream
&os
, bool withContext
) const {
24 os
<< "ActionActiveStack depth " << getDepth() << "\n";
25 const ActionActiveStack
*current
= this;
28 llvm::errs() << llvm::formatv("#{0,3}: ", count
++);
29 current
->action
.print(llvm::errs());
31 ArrayRef
<IRUnit
> context
= current
->action
.getContextIRUnits();
32 if (withContext
&& !context
.empty()) {
33 llvm::errs() << "Context:\n";
35 current
->action
.getContextIRUnits(),
36 [&](const IRUnit
&unit
) {
37 llvm::errs() << " - ";
38 unit
.print(llvm::errs());
40 [&]() { llvm::errs() << "\n"; });
43 current
= current
->parent
;
47 //===----------------------------------------------------------------------===//
49 //===----------------------------------------------------------------------===//
51 static const LLVM_THREAD_LOCAL ActionActiveStack
*actionStack
= nullptr;
53 void ExecutionContext::registerObserver(Observer
*observer
) {
54 observers
.push_back(observer
);
57 void ExecutionContext::operator()(llvm::function_ref
<void()> transform
,
58 const Action
&action
) {
59 // Update the top of the stack with the current action.
62 depth
= actionStack
->getDepth() + 1;
63 ActionActiveStack info
{actionStack
, action
, depth
};
65 auto raii
= llvm::make_scope_exit([&]() { actionStack
= info
.getParent(); });
66 Breakpoint
*breakpoint
= nullptr;
68 // Invoke the callback here and handles control requests here.
69 auto handleUserInput
= [&]() -> bool {
70 if (!onBreakpointControlExecutionCallback
)
72 auto todoNext
= onBreakpointControlExecutionCallback(actionStack
);
74 case ExecutionContext::Apply
:
75 depthToBreak
= std::nullopt
;
77 case ExecutionContext::Skip
:
78 depthToBreak
= std::nullopt
;
80 case ExecutionContext::Step
:
81 depthToBreak
= depth
+ 1;
83 case ExecutionContext::Next
:
86 case ExecutionContext::Finish
:
87 depthToBreak
= depth
- 1;
90 llvm::report_fatal_error("Unknown control request");
93 // Try to find a breakpoint that would hit on this action.
94 // Right now there is no way to collect them all, we stop at the first one.
95 for (auto *breakpointManager
: breakpoints
) {
96 breakpoint
= breakpointManager
->match(action
);
100 info
.setBreakpoint(breakpoint
);
102 bool shouldExecuteAction
= true;
103 // If we have a breakpoint, or if `depthToBreak` was previously set and the
104 // current depth matches, we invoke the user-provided callback.
105 if (breakpoint
|| (depthToBreak
&& depth
<= depthToBreak
))
106 shouldExecuteAction
= handleUserInput();
108 // Notify the observers about the current action.
109 for (auto *observer
: observers
)
110 observer
->beforeExecute(actionStack
, breakpoint
, shouldExecuteAction
);
112 if (shouldExecuteAction
) {
113 // Execute the action here.
116 // Notify the observers about completion of the action.
117 for (auto *observer
: observers
)
118 observer
->afterExecute(actionStack
);
121 if (depthToBreak
&& depth
<= depthToBreak
)