MLIR  22.0.0git
ExecutionContext.cpp
Go to the documentation of this file.
1 //===- ExecutionContext.cpp - Debug Execution Context Support -------------===//
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 
10 
11 #include "llvm/ADT/ScopeExit.h"
12 #include "llvm/Support/FormatVariadic.h"
13 
14 using namespace mlir;
15 using namespace mlir::tracing;
16 
17 //===----------------------------------------------------------------------===//
18 // ActionActiveStack
19 //===----------------------------------------------------------------------===//
20 
21 void ActionActiveStack::print(raw_ostream &os, bool withContext) const {
22  os << "ActionActiveStack depth " << getDepth() << "\n";
23  const ActionActiveStack *current = this;
24  int count = 0;
25  while (current) {
26  llvm::errs() << llvm::formatv("#{0,3}: ", count++);
27  current->action.print(llvm::errs());
28  llvm::errs() << "\n";
29  ArrayRef<IRUnit> context = current->action.getContextIRUnits();
30  if (withContext && !context.empty()) {
31  llvm::errs() << "Context:\n";
32  llvm::interleave(
33  current->action.getContextIRUnits(),
34  [&](const IRUnit &unit) {
35  llvm::errs() << " - ";
36  unit.print(llvm::errs());
37  },
38  [&]() { llvm::errs() << "\n"; });
39  llvm::errs() << "\n";
40  }
41  current = current->parent;
42  }
43 }
44 
45 //===----------------------------------------------------------------------===//
46 // ExecutionContext
47 //===----------------------------------------------------------------------===//
48 
49 static const LLVM_THREAD_LOCAL ActionActiveStack *actionStack = nullptr;
50 
52  observers.push_back(observer);
53 }
54 
56  const Action &action) {
57  // Update the top of the stack with the current action.
58  int depth = 0;
59  if (actionStack)
60  depth = actionStack->getDepth() + 1;
61  ActionActiveStack info{actionStack, action, depth};
62  actionStack = &info;
63  auto raii = llvm::make_scope_exit([&]() { actionStack = info.getParent(); });
64  Breakpoint *breakpoint = nullptr;
65 
66  // Invoke the callback here and handles control requests here.
67  auto handleUserInput = [&]() -> bool {
68  if (!onBreakpointControlExecutionCallback)
69  return true;
70  auto todoNext = onBreakpointControlExecutionCallback(actionStack);
71  switch (todoNext) {
73  depthToBreak = std::nullopt;
74  return true;
76  depthToBreak = std::nullopt;
77  return false;
79  depthToBreak = depth + 1;
80  return true;
82  depthToBreak = depth;
83  return true;
85  depthToBreak = depth - 1;
86  return true;
87  }
88  llvm::report_fatal_error("Unknown control request");
89  };
90 
91  // Try to find a breakpoint that would hit on this action.
92  // Right now there is no way to collect them all, we stop at the first one.
93  for (auto *breakpointManager : breakpoints) {
94  breakpoint = breakpointManager->match(action);
95  if (breakpoint)
96  break;
97  }
98  info.setBreakpoint(breakpoint);
99 
100  bool shouldExecuteAction = true;
101  // If we have a breakpoint, or if `depthToBreak` was previously set and the
102  // current depth matches, we invoke the user-provided callback.
103  if (breakpoint || (depthToBreak && depth <= depthToBreak))
104  shouldExecuteAction = handleUserInput();
105 
106  // Notify the observers about the current action.
107  for (auto *observer : observers)
108  observer->beforeExecute(actionStack, breakpoint, shouldExecuteAction);
109 
110  if (shouldExecuteAction) {
111  // Execute the action here.
112  transform();
113 
114  // Notify the observers about completion of the action.
115  for (auto *observer : observers)
116  observer->afterExecute(actionStack);
117  }
118 
119  if (depthToBreak && depth <= depthToBreak)
120  handleUserInput();
121 }
static const LLVM_THREAD_LOCAL ActionActiveStack * actionStack
IRUnit is a union of the different types of IR objects that constitute the IR structure (other than T...
Definition: Unit.h:28
An action is a specific action that is to be taken by the compiler, that can be toggled and controlle...
Definition: Action.h:38
virtual void print(raw_ostream &os) const
Definition: Action.h:50
virtual ArrayRef< IRUnit > getContextIRUnits() const
Return the set of IR units that are associated with this action.
Definition: Action.h:55
This abstract class represents a breakpoint.
void registerObserver(Observer *observer)
Register a new Observer on this context.
void operator()(function_ref< void()> transform, const Action &action)
Process the given action.
Include the generated interface declarations.
This class is used to keep track of the active actions in the stack.
const ActionActiveStack * getParent() const
void print(raw_ostream &os, bool withContext) const
This abstract class defines the interface used to observe an Action execution.