|
| 1 | +# Debug Actions |
| 2 | + |
| 3 | +[TOC] |
| 4 | + |
| 5 | +This file documents the infrastructure for `Debug Actions`. This is a DEBUG only |
| 6 | +API that allows for external entities to control various aspects of compiler |
| 7 | +execution. This is conceptually similar to something like `DebugCounters` in |
| 8 | +LLVM, but at a lower level. This framework doesn't make any assumptions about |
| 9 | +how the higher level driver is controlling the execution, it merely provides a |
| 10 | +framework for connecting the two together. A high level overview of the workflow |
| 11 | +surrounding debug actions is shown below: |
| 12 | + |
| 13 | +* Compiler developer defines an [`action`](#debug-action) that is taken by the |
| 14 | + a pass, transformation, utility that they are developing. |
| 15 | +* Depending on the needs, the developer dispatches various queries, pertaining |
| 16 | + to this action, to an [`action manager`](#debug-action-manager) that will |
| 17 | + provide an answer as to what behavior the action should take. |
| 18 | +* An external entity registers an [`action handler`](#debug-action-handler) |
| 19 | + with the action manager, and provides the logic to resolve queries on |
| 20 | + actions. |
| 21 | + |
| 22 | +The exact definition of an `external entity` is left opaque, to allow for more |
| 23 | +interesting handlers. The set of possible action queries is detailed in the |
| 24 | +[`action manager`](#debug-action-manager) section below. |
| 25 | + |
| 26 | +(TODO: Add connection to existing handlers when they are added) |
| 27 | + |
| 28 | +## Debug Action |
| 29 | + |
| 30 | +A `debug action` is essentially a marker for a type of action that may be |
| 31 | +performed within the compiler. There are no constraints on the granularity of an |
| 32 | +“action”, it can be as simple as “perform this fold” and as complex as “run this |
| 33 | +pass pipeline”. An action is comprised of the following: |
| 34 | + |
| 35 | +* Tag: |
| 36 | + |
| 37 | + - A unique string identifier, similar to a command line flag or |
| 38 | + DEBUG_TYPE. |
| 39 | + |
| 40 | +* Description: |
| 41 | + |
| 42 | + - A short description of what the action represents. |
| 43 | + |
| 44 | +* Parameter Types: |
| 45 | + |
| 46 | + - The types of values that are passed to queries related to this action, |
| 47 | + to help guide decisions. |
| 48 | + |
| 49 | +Below is an example action that may be provided by the |
| 50 | +[pattern rewriter](PatternRewriter.md) framework to control the application of |
| 51 | +rewrite patterns. |
| 52 | + |
| 53 | +```c++ |
| 54 | +/// A debug action that allows for controlling the application of patterns. |
| 55 | +/// A new action type can be defined by inheriting from `DebugAction`. |
| 56 | +/// * The Tag is specified via a static `StringRef getTag()` method. |
| 57 | +/// * The Description is specified via a static `StringRef getDescription()` |
| 58 | +/// method. |
| 59 | +/// * The parameters for the action are provided via template parameters when |
| 60 | +/// inheriting from `DebugAction`. |
| 61 | +struct ApplyPatternAction |
| 62 | + : public DebugAction<Operation *, const Pattern &> { |
| 63 | + static StringRef getTag() { return "apply-pattern"; } |
| 64 | + static StringRef getDescription() { |
| 65 | + return "Control the application of rewrite patterns"; |
| 66 | + } |
| 67 | +}; |
| 68 | +``` |
| 69 | +
|
| 70 | +## Debug Action Manager |
| 71 | +
|
| 72 | +The `DebugActionManager` orchestrates the various different queries relating to |
| 73 | +debug actions, and is accessible via the `MLIRContext`. These queries allow for |
| 74 | +external entities to control various aspects of the compiler via |
| 75 | +[action handlers](#debug-action-handler). When resolving a query for an action, |
| 76 | +the result from the most recently registered handler is used. |
| 77 | +
|
| 78 | +TODO: It may be interesting to support merging results from multiple action |
| 79 | +handlers, but this is left for future work when driven by a real use case. |
| 80 | +
|
| 81 | +The set of available queries are shown below: |
| 82 | +
|
| 83 | +```c++ |
| 84 | +class DebugActionManager { |
| 85 | +public: |
| 86 | + /// Returns true if the given action type should be executed, false otherwise. |
| 87 | + /// `Params` correspond to any action specific parameters that may be used to |
| 88 | + /// guide the decision. |
| 89 | + template <typename ActionType, typename... Params> |
| 90 | + bool shouldExecute(Params &&... params); |
| 91 | +}; |
| 92 | +``` |
| 93 | + |
| 94 | +Building on the example from the [previous section](#debug-action), an example |
| 95 | +usage of the `shouldExecute` query is shown below: |
| 96 | + |
| 97 | +```c++ |
| 98 | +/// A debug action that allows for controlling the application of patterns. |
| 99 | +struct ApplyPatternAction |
| 100 | + : public DebugAction<Operation *, const Pattern &> { |
| 101 | + static StringRef getTag() { return "apply-pattern"; } |
| 102 | + static StringRef getDescription() { |
| 103 | + return "Control the application of rewrite patterns"; |
| 104 | + } |
| 105 | +}; |
| 106 | + |
| 107 | +// ... |
| 108 | + |
| 109 | +bool shouldApplyPattern(Operation *currentOp, const Pattern ¤tPattern) { |
| 110 | + MLIRContext *context = currentOp->getContext(); |
| 111 | + DebugActionManager &manager = context->getDebugActionManager(); |
| 112 | + |
| 113 | + // Query the action manager to see if `currentPattern` should be applied to |
| 114 | + // `currentOp`. |
| 115 | + return manager.shouldExecute<ApplyPatternAction>(currentOp, currentPattern); |
| 116 | +} |
| 117 | +``` |
| 118 | +
|
| 119 | +## Debug Action Handler |
| 120 | +
|
| 121 | +A debug action handler provides the internal implementation for the various |
| 122 | +action related queries within the [`DebugActionManager`](debug-action-manager). |
| 123 | +Action handlers allow for external entities to control and inject external |
| 124 | +information into the compiler. Handlers can be registered with the |
| 125 | +`DebugActionManager` using `registerActionHandler`. There are two types of |
| 126 | +handlers; action-specific handlers and generic handlers. |
| 127 | +
|
| 128 | +### Action Specific Handlers |
| 129 | +
|
| 130 | +Action specific handlers handle a specific debug action type, with the |
| 131 | +parameters to its query methods mapping 1-1 to the parameter types of the action |
| 132 | +type. An action specific handler can be defined by inheriting from the handler |
| 133 | +base class defined at `ActionType::Handler` where `ActionType` is the specific |
| 134 | +action that should be handled. An example using our running pattern example is |
| 135 | +shown below: |
| 136 | +
|
| 137 | +```c++ |
| 138 | +struct MyPatternHandler : public ApplyPatternAction::Handler { |
| 139 | + /// A variant of `shouldExecute` shown in the `DebugActionManager` class |
| 140 | + /// above. |
| 141 | + /// This method returns a FailureOr<bool>, where failure signifies that the |
| 142 | + /// action was not handled (allowing for other handlers to process it), or the |
| 143 | + /// boolean true/false signifying if the action should execute or not. |
| 144 | + FailureOr<bool> shouldExecute(Operation *op, |
| 145 | + const RewritePattern &pattern) final; |
| 146 | +}; |
| 147 | +``` |
| 148 | + |
| 149 | +### Generic Handlers |
| 150 | + |
| 151 | +A generic handler allows for handling queries on any action type. These types of |
| 152 | +handlers are useful for implementing general functionality that doesn’t |
| 153 | +necessarily need to interpret the exact action parameters, or can rely on an |
| 154 | +external interpreter (such as the user). As these handlers are generic, they |
| 155 | +take a set of opaque parameters that try to map the context of the action type |
| 156 | +in a generic way. A generic handler can be defined by inheriting from |
| 157 | +`DebugActionManager::GenericHandler`. An example is shown below: |
| 158 | + |
| 159 | +```c++ |
| 160 | +struct MyPatternHandler : public DebugActionManager::GenericHandler { |
| 161 | + /// The return type of this method is the same as the action-specific handler. |
| 162 | + /// The arguments to this method map the concepts of an action type in an |
| 163 | + /// opaque way. The arguments are provided in such a way so that the context |
| 164 | + /// of the action is still somewhat user readable, or at least loggable as |
| 165 | + /// such. |
| 166 | + /// - actionTag: The tag specified by the action type. |
| 167 | + /// - actionDesc: The description specified by the action type. |
| 168 | + virtual FailureOr<bool> shouldExecute(StringRef actionTag, |
| 169 | + StringRef actionDesc); |
| 170 | +}; |
| 171 | +``` |
0 commit comments