summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2019-12-06 13:16:03 -0800
committerGitHub <noreply@github.com>2019-12-06 13:16:03 -0800
commit895fcff7df1a71af59fad6bb31939ff370920eb4 (patch)
treea8b5b4e1158fdad56319acc89037344d1248bfff /source
parent54d3c5f6657b1099326e1ce7ec0f0692e7025442 (diff)
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
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-syntax.cpp11
-rw-r--r--source/slang/slang-syntax.h17
2 files changed, 27 insertions, 1 deletions
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<const BasicExpressionType>(type);
+ auto basicType = as<BasicExpressionType>(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<T>::getClass();
}
+ NodeBase* _dynamicCastImpl(NodeBase* node, SyntaxClassBase const& toClass);
+
+ template<typename T>
+ T* dynamicCast(NodeBase* node)
+ {
+ return (T*) _dynamicCastImpl(node, getClass<T>());
+ }
+
+ template<typename T>
+ const T* dynamicCast(const NodeBase* node) { return dynamicCast<T>(const_cast<NodeBase*>(node)); }
+
+ template<typename T>
+ T* as(NodeBase* node) { return dynamicCast<T>(node); }
+
+ template<typename T>
+ const T* as(const NodeBase* node) { return dynamicCast<T>(const_cast<NodeBase*>(node)); }
+
struct SubstitutionSet
{
RefPtr<Substitutions> substitutions;