From 35a92f382e4abcd3c4e1ccd531f1ecfba128513d Mon Sep 17 00:00:00 2001 From: =?utf8?q?=EB=B0=95=EC=A2=85=ED=98=84/On-Device=20Lab=28SR=29/Staff?= =?utf8?q?=20Engineer/=EC=82=BC=EC=84=B1=EC=A0=84=EC=9E=90?= Date: Fri, 14 Jun 2019 13:40:06 +0900 Subject: [PATCH] [loco] Canonical Node Visitor with default implementation (#3771) * [loco] Canonical Node Visitor with default implementation With this commit, users are able to implement a node visitor with their own default implementation. Signed-off-by: Jonghyun Park * Fix a typo --- contrib/loco/include/loco/IR/CanonicalNode.h | 2 +- contrib/loco/include/loco/IR/CanonicalNodeImpl.h | 2 +- .../include/loco/IR/CanonicalNodeVisitor.forward.h | 2 +- .../loco/include/loco/IR/CanonicalNodeVisitor.h | 43 +++++++++++++++++++--- contrib/loco/src/IR/CanonicalNode.test.cpp | 21 +++++++++++ 5 files changed, 62 insertions(+), 8 deletions(-) diff --git a/contrib/loco/include/loco/IR/CanonicalNode.h b/contrib/loco/include/loco/IR/CanonicalNode.h index d15855f..52239aa 100644 --- a/contrib/loco/include/loco/IR/CanonicalNode.h +++ b/contrib/loco/include/loco/IR/CanonicalNode.h @@ -32,7 +32,7 @@ struct CanonicalNode : public Node Dialect *dialect(void) const final; virtual CanonicalOpcode opcode(void) const = 0; - template T accept(CanonicalNodeVisitor *); + template T accept(CanonicalNodeVisitorBase *); }; template struct CanonicalNodeImpl : public CanonicalNode diff --git a/contrib/loco/include/loco/IR/CanonicalNodeImpl.h b/contrib/loco/include/loco/IR/CanonicalNodeImpl.h index 351276d..ed2f70a 100644 --- a/contrib/loco/include/loco/IR/CanonicalNodeImpl.h +++ b/contrib/loco/include/loco/IR/CanonicalNodeImpl.h @@ -25,7 +25,7 @@ namespace loco { -template T CanonicalNode::accept(CanonicalNodeVisitor *v) +template T CanonicalNode::accept(CanonicalNodeVisitorBase *v) { switch (this->opcode()) { diff --git a/contrib/loco/include/loco/IR/CanonicalNodeVisitor.forward.h b/contrib/loco/include/loco/IR/CanonicalNodeVisitor.forward.h index ba8da87..50bb11f 100644 --- a/contrib/loco/include/loco/IR/CanonicalNodeVisitor.forward.h +++ b/contrib/loco/include/loco/IR/CanonicalNodeVisitor.forward.h @@ -21,7 +21,7 @@ namespace loco { // NOTE This forward declaration SHOULD BE aligned with Node delcaration in "CanonicalNodeVisitor.h" -template struct CanonicalNodeVisitor; +template struct CanonicalNodeVisitorBase; } // namespace loco diff --git a/contrib/loco/include/loco/IR/CanonicalNodeVisitor.h b/contrib/loco/include/loco/IR/CanonicalNodeVisitor.h index 43e40c1..727b73f 100644 --- a/contrib/loco/include/loco/IR/CanonicalNodeVisitor.h +++ b/contrib/loco/include/loco/IR/CanonicalNodeVisitor.h @@ -24,8 +24,30 @@ namespace loco { +struct ThrowNotImplemented +{ + /** + * GCC rejects the following implementation of "CanonicalNodeVisitorImpl::visit": + * + * virtual T visit(const CLASS *) + * { + * Fallback f; + * return f.call(); + * } + * + * Let us pass "nullptr" of T * type (which serves as a type tag) as a workaround. + * + * TODO Remove this workaround if possible + */ + template T call(const T *) const + { + // Throw NYI exception + throw std::runtime_error{"Not implemented, yet"}; + } +}; + /** - * DO NOT use this class. Use CanonicalNodeVisitor instead. + * DO NOT use this class. Use CanonicalNodeVisitor or CanonicalNodeVisitorImpl instead. */ template struct CanonicalNodeVisitorBase { @@ -36,16 +58,27 @@ template struct CanonicalNodeVisitorBase #undef CANONICAL_NODE }; -template struct CanonicalNodeVisitor : public CanonicalNodeVisitorBase +template +struct CanonicalNodeVisitorImpl : public CanonicalNodeVisitorBase { - virtual ~CanonicalNodeVisitor() = default; + virtual ~CanonicalNodeVisitorImpl() = default; -#define CANONICAL_NODE(OPCODE, CLASS) \ - virtual T visit(const CLASS *) { throw std::runtime_error{"NYI"}; } +#define CANONICAL_NODE(OPCODE, CLASS) \ + virtual T visit(const CLASS *) \ + { \ + Fallback f; \ + return f.call(static_cast(nullptr)); \ + } #include "CanonicalNodes.lst" #undef CANONICAL_NODE }; +template +struct CanonicalNodeVisitor : public CanonicalNodeVisitorImpl +{ + virtual ~CanonicalNodeVisitor() = default; +}; + } // namespace loco #endif // __LOCO_IR_CANONICAL_NODE_VISITOR_H__ diff --git a/contrib/loco/src/IR/CanonicalNode.test.cpp b/contrib/loco/src/IR/CanonicalNode.test.cpp index 9f4245f..6a6ab39 100644 --- a/contrib/loco/src/IR/CanonicalNode.test.cpp +++ b/contrib/loco/src/IR/CanonicalNode.test.cpp @@ -19,6 +19,27 @@ #include +TEST(CanonicalNodeTest, visitor_with_user_default_impl) +{ + struct MyFallback + { + uint32_t call(const uint32_t *) const { return 256; } + }; + + struct MyVisitor final : public loco::CanonicalNodeVisitorImpl + { + uint32_t visit(const loco::Forward *) final { return 128; } + }; + + loco::Forward forward; + loco::ConstGen constgen; + + MyVisitor v; + + ASSERT_EQ(forward.accept(&v), 128); + ASSERT_EQ(constgen.accept(&v), 256); +} + TEST(CanonicalNodeTest, visitor) { struct CountingVisitor final : public loco::CanonicalNodeVisitor -- 2.7.4