/// * The Tag is specified via a static `StringRef getTag()` method.
/// * The Description is specified via a static `StringRef getDescription()`
/// method.
-/// * The parameters for the action are provided via template parameters when
-/// inheriting from `DebugAction`.
+/// * `DebugAction` is a CRTP class, so the first template parameter is the
+/// action type class itself.
+/// * The parameters for the action are provided via additional template
+/// parameters when inheriting from `DebugAction`.
struct ApplyPatternAction
- : public DebugAction<Operation *, const Pattern &> {
+ : public DebugAction<ApplyPatternAction, Operation *, const Pattern &> {
static StringRef getTag() { return "apply-pattern"; }
static StringRef getDescription() {
return "Control the application of rewrite patterns";
```c++
/// A debug action that allows for controlling the application of patterns.
struct ApplyPatternAction
- : public DebugAction<Operation *, const Pattern &> {
+ : public DebugAction<ApplyPatternAction, Operation *, const Pattern &> {
static StringRef getTag() { return "apply-pattern"; }
static StringRef getDescription() {
return "Control the application of rewrite patterns";
/// This class provides a handler class that can be derived from to handle
/// instances of this action. The parameters to its query methods map 1-1 to the
/// types on the action type.
-template <typename... ParameterTs>
+template <typename Derived, typename... ParameterTs>
class DebugAction {
public:
class Handler : public DebugActionManager::HandlerBase {
public:
- Handler()
- : HandlerBase(
- TypeID::get<typename DebugAction<ParameterTs...>::Handler>()) {}
+ Handler() : HandlerBase(TypeID::get<Derived>()) {}
/// This hook allows for controlling whether an action should execute or
/// not. `parameters` correspond to the set of values provided by the
/// Provide classof to allow casting between handler types.
static bool classof(const DebugActionManager::HandlerBase *handler) {
- return handler->getHandlerID() ==
- TypeID::get<typename DebugAction<ParameterTs...>::Handler>();
+ return handler->getHandlerID() == TypeID::get<Derived>();
}
};
//===----------------------------------------------------------------------===//
#include "mlir/Support/DebugAction.h"
+#include "mlir/Support/TypeID.h"
#include "gmock/gmock.h"
// DebugActionManager is only enabled in DEBUG mode.
using namespace mlir;
namespace {
-struct SimpleAction : public DebugAction<> {
+struct SimpleAction : DebugAction<SimpleAction> {
+ MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(SimpleAction)
static StringRef getTag() { return "simple-action"; }
static StringRef getDescription() { return "simple-action-description"; }
};
-struct ParametricAction : public DebugAction<bool> {
+struct OtherSimpleAction : DebugAction<OtherSimpleAction> {
+ MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(OtherSimpleAction)
+ static StringRef getTag() { return "other-simple-action"; }
+ static StringRef getDescription() {
+ return "other-simple-action-description";
+ }
+};
+struct ParametricAction : DebugAction<ParametricAction, bool> {
+ MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(ParametricAction)
static StringRef getTag() { return "param-action"; }
static StringRef getDescription() { return "param-action-description"; }
};
// A generic handler that always executes the simple action, but not the
// parametric action.
- struct GenericHandler : public DebugActionManager::GenericHandler {
+ struct GenericHandler : DebugActionManager::GenericHandler {
FailureOr<bool> shouldExecute(StringRef tag, StringRef desc) final {
if (tag == SimpleAction::getTag()) {
EXPECT_EQ(desc, SimpleAction::getDescription());
DebugActionManager manager;
// Handler that simply uses the input as the decider.
- struct ActionSpecificHandler : public ParametricAction::Handler {
+ struct ActionSpecificHandler : ParametricAction::Handler {
FailureOr<bool> shouldExecute(bool shouldExecuteParam) final {
return shouldExecuteParam;
}
DebugActionManager manager;
// Handler that uses the number of action executions as the decider.
- struct DebugCounterHandler : public SimpleAction::Handler {
+ struct DebugCounterHandler : SimpleAction::Handler {
FailureOr<bool> shouldExecute() final { return numExecutions++ < 3; }
unsigned numExecutions = 0;
};
EXPECT_FALSE(manager.shouldExecute<SimpleAction>());
}
+TEST(DebugActionTest, NonOverlappingActionSpecificHandlers) {
+ DebugActionManager manager;
+
+ // One handler returns true and another returns false
+ struct SimpleActionHandler : SimpleAction::Handler {
+ FailureOr<bool> shouldExecute() final { return true; }
+ };
+ struct OtherSimpleActionHandler : OtherSimpleAction::Handler {
+ FailureOr<bool> shouldExecute() final { return false; }
+ };
+ manager.registerActionHandler<SimpleActionHandler>();
+ manager.registerActionHandler<OtherSimpleActionHandler>();
+ EXPECT_TRUE(manager.shouldExecute<SimpleAction>());
+ EXPECT_FALSE(manager.shouldExecute<OtherSimpleAction>());
+}
+
} // namespace
#endif