From 895fcff7df1a71af59fad6bb31939ff370920eb4 Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Fri, 6 Dec 2019 13:16:03 -0800 Subject: Add a custom RTTI implementation for the AST (#1148) * Add a custom RTTI implementation for the AST Profiling was showing that the internal routines behind `dynamic_cast` were the worst offenders in the whole codebase, and a lot of this was being driven by casting inside the semantic checking logic. This change takes advantage of the fact that we *already* had a custom RTTI structure built up for the classes of syntax nodes that was previously being used to implement string->class lookup and factory services to support "magic" types and modifier in the stdlib (e.g., the way that a modifier declaration in the stdlib just lists the *name* of a C++ class that should be instantiated for it). That RTTI information already included a pointer from each syntax class to its base class (if any), based on the restriction that the AST node types form a single-inheritance hierarchy. The existing code already had a virtual `getClass()` routine on AST nodes, and an `isSubClassOf` query on the class information. Putting those pieces together to implement the `dynamicCast` and `as` routines was a cinch. The work in previous PRs to layer an abstraction over all the existing `dynamic_cast` call sites and to support type-specific `dynamicCast` implementations inside `RefPtr<>` pays off greatly here. * fixup: refactor implementation to appease more pedantic/correct compilers --- source/slang/slang-syntax.cpp | 11 ++++++++++- source/slang/slang-syntax.h | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) (limited to 'source') diff --git a/source/slang/slang-syntax.cpp b/source/slang/slang-syntax.cpp index e41e5517c..d74e3a993 100644 --- a/source/slang/slang-syntax.cpp +++ b/source/slang/slang-syntax.cpp @@ -12,7 +12,7 @@ namespace Slang bool BasicExpressionType::EqualsImpl(Type * type) { - auto basicType = dynamicCast(type); + auto basicType = as(type); return basicType && basicType->baseType == this->baseType; } @@ -85,6 +85,15 @@ bool SyntaxClassBase::isSubClassOfImpl(SyntaxClassBase const& super) const return false; } +NodeBase* _dynamicCastImpl(NodeBase* node, SyntaxClassBase const& toClass) +{ + if(!node) return nullptr; + if(node->getClass().isSubClassOfImpl(toClass)) + return node; + return nullptr; +} + + void Type::accept(IValVisitor* visitor, void* extra) { accept((ITypeVisitor*)visitor, extra); diff --git a/source/slang/slang-syntax.h b/source/slang/slang-syntax.h index 86cc4b902..35c21227c 100644 --- a/source/slang/slang-syntax.h +++ b/source/slang/slang-syntax.h @@ -541,6 +541,23 @@ namespace Slang return SyntaxClass::getClass(); } + NodeBase* _dynamicCastImpl(NodeBase* node, SyntaxClassBase const& toClass); + + template + T* dynamicCast(NodeBase* node) + { + return (T*) _dynamicCastImpl(node, getClass()); + } + + template + const T* dynamicCast(const NodeBase* node) { return dynamicCast(const_cast(node)); } + + template + T* as(NodeBase* node) { return dynamicCast(node); } + + template + const T* as(const NodeBase* node) { return dynamicCast(const_cast(node)); } + struct SubstitutionSet { RefPtr substitutions; -- cgit v1.2.3