summaryrefslogtreecommitdiff
path: root/source/slang/slang-ast-decl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-ast-decl.cpp')
-rw-r--r--source/slang/slang-ast-decl.cpp321
1 files changed, 269 insertions, 52 deletions
diff --git a/source/slang/slang-ast-decl.cpp b/source/slang/slang-ast-decl.cpp
index f37ebef48..4d9b8718f 100644
--- a/source/slang/slang-ast-decl.cpp
+++ b/source/slang/slang-ast-decl.cpp
@@ -51,80 +51,167 @@ bool isInterfaceRequirement(Decl* decl)
}
//
-// ContainerDecl
+// ContainerDeclDirectMemberDecls
//
-List<Decl*> const& ContainerDecl::getDirectMemberDecls()
+void ContainerDeclDirectMemberDecls::_initForOnDemandDeserialization(
+ RefObject* deserializationContext,
+ void const* deserializationData,
+ Count declCount)
{
- return _directMemberDecls.decls;
+ SLANG_ASSERT(deserializationContext);
+ SLANG_ASSERT(deserializationData);
+
+ SLANG_ASSERT(!decls.getCount());
+ SLANG_ASSERT(!onDemandDeserialization.context);
+
+ onDemandDeserialization.context = deserializationContext;
+ onDemandDeserialization.data = deserializationData;
+
+ for (Index i = 0; i < declCount; ++i)
+ decls.add(nullptr);
}
-Count ContainerDecl::getDirectMemberDeclCount()
+void ContainerDeclDirectMemberDecls::_readAllSerializedDecls() const
{
- return _directMemberDecls.decls.getCount();
+ SLANG_ASSERT(isUsingOnDemandDeserialization());
+
+ // We start by querying each of the contained decls
+ // by index, which should cause the entire `decls`
+ // array to be filled in.
+ //
+ auto declCount = getDeclCount();
+ for (Index i = 0; i < declCount; ++i)
+ {
+ auto decl = getDecl(i);
+ SLANG_UNUSED(decl);
+ }
+
+ // At this point, we have loaded all the information
+ // that was in the serialized representation, and
+ // don't need to keep doing on-demand loading.
+ // Thus, we clear out the pointer to the serialized
+ // data (which will cause later calls to
+ // `isDoingOnDemandSerialization()` to return `false`).
+ //
+ // Note that we do *not* clear out the `context` pointer
+ // used for on-demand deserialization, because in the
+ // case where we are storing the members of a `ModuleDecl`,
+ // that context will hold the additional state needed to
+ // look up declarations by their mangled names, and we
+ // want to retain that state. The
+ // `isUsingOnDemandDeserializationForExports()` query
+ // is based on the `context` pointer only, so it will
+ // continue to return `true`.
+ //
+ onDemandDeserialization.data = nullptr;
+
+ _invalidateLookupAccelerators();
}
-Decl* ContainerDecl::getDirectMemberDecl(Index index)
+List<Decl*> const& ContainerDeclDirectMemberDecls::getDecls() const
{
- return _directMemberDecls.decls[index];
+ if (isUsingOnDemandDeserialization())
+ {
+ _readAllSerializedDecls();
+ }
+
+ return decls;
}
-Decl* ContainerDecl::getFirstDirectMemberDecl()
+Count ContainerDeclDirectMemberDecls::getDeclCount() const
{
- if (getDirectMemberDeclCount() == 0)
- return nullptr;
- return getDirectMemberDecl(0);
+ // Note: in the case of on-demand deserialization,
+ // the number of elements in the `decls` list
+ // will be correct, although one or more of the
+ // pointers in it might be null.
+ //
+ return decls.getCount();
}
-DeclsOfNameList ContainerDecl::getDirectMemberDeclsOfName(Name* name)
+Decl* ContainerDeclDirectMemberDecls::getDecl(Index index) const
{
- return DeclsOfNameList(findLastDirectMemberDeclOfName(name));
+ auto decl = decls[index];
+ if (!decl && isUsingOnDemandDeserialization())
+ {
+ decl = _readSerializedDeclAtIndex(index);
+ decls[index] = decl;
+ }
+ return decl;
}
-Decl* ContainerDecl::findLastDirectMemberDeclOfName(Name* name)
+Decl* ContainerDeclDirectMemberDecls::findLastDeclOfName(Name* name) const
{
- _ensureLookupAcceleratorsAreValid();
- if (auto found = _directMemberDecls.accelerators.mapNameToLastDeclOfThatName.tryGetValue(name))
- return *found;
+ if (isUsingOnDemandDeserialization())
+ {
+ if (auto found = accelerators.mapNameToLastDeclOfThatName.tryGetValue(name))
+ return *found;
+
+ Decl* decl = _readSerializedDeclsOfName(name);
+ accelerators.mapNameToLastDeclOfThatName.add(name, decl);
+ return decl;
+ }
+ else
+ {
+ _ensureLookupAcceleratorsAreValid();
+ if (auto found = accelerators.mapNameToLastDeclOfThatName.tryGetValue(name))
+ return *found;
+ }
return nullptr;
}
-Decl* ContainerDecl::getPrevDirectMemberDeclWithSameName(Decl* decl)
+Dictionary<Name*, Decl*> ContainerDeclDirectMemberDecls::getMapFromNameToLastDeclOfThatName() const
{
- SLANG_ASSERT(decl);
- SLANG_ASSERT(decl->parentDecl == this);
+ if (isUsingOnDemandDeserialization())
+ {
+ // If we have been using on-demand deserialization,
+ // then the `mapNameToLastDeclOfThatName` dictionary
+ // may not accurately reflect the contained declarations.
+ // We need to force all of the declarations to be
+ // deserialized immediately, which will also have
+ // the effect of invalidating the accelerators so
+ // that they can be rebuilt to contain complete information.
+ //
+ _readAllSerializedDecls();
+ }
_ensureLookupAcceleratorsAreValid();
- return decl->_prevInContainerWithSameName;
+ return accelerators.mapNameToLastDeclOfThatName;
}
-void ContainerDecl::addDirectMemberDecl(Decl* decl)
-{
- if (!decl)
- return;
- decl->parentDecl = this;
- _directMemberDecls.decls.add(decl);
+List<Decl*> const& ContainerDeclDirectMemberDecls::getTransparentDecls() const
+{
+ if (isUsingOnDemandDeserialization())
+ {
+ if (accelerators.filteredListOfTransparentDecls.getCount() == 0)
+ {
+ _readSerializedTransparentDecls();
+ }
+ }
+ else
+ {
+ _ensureLookupAcceleratorsAreValid();
+ }
+ return accelerators.filteredListOfTransparentDecls;
}
-List<Decl*> const& ContainerDecl::getTransparentDirectMemberDecls()
+bool ContainerDeclDirectMemberDecls::isUsingOnDemandDeserialization() const
{
- _ensureLookupAcceleratorsAreValid();
- return _directMemberDecls.accelerators.filteredListOfTransparentDecls;
+ return onDemandDeserialization.data != nullptr;
}
-bool ContainerDecl::_areLookupAcceleratorsValid()
+bool ContainerDeclDirectMemberDecls::_areLookupAcceleratorsValid() const
{
- return _directMemberDecls.accelerators.declCountWhenLastUpdated ==
- _directMemberDecls.decls.getCount();
+ return accelerators.declCountWhenLastUpdated == decls.getCount();
}
-void ContainerDecl::_invalidateLookupAccelerators()
+void ContainerDeclDirectMemberDecls::_invalidateLookupAccelerators() const
{
- _directMemberDecls.accelerators.declCountWhenLastUpdated = -1;
+ accelerators.declCountWhenLastUpdated = -1;
}
-void ContainerDecl::_ensureLookupAcceleratorsAreValid()
+void ContainerDeclDirectMemberDecls::_ensureLookupAcceleratorsAreValid() const
{
if (_areLookupAcceleratorsValid())
return;
@@ -133,24 +220,28 @@ void ContainerDecl::_ensureLookupAcceleratorsAreValid()
// the accelerators are entirely invalidated, and must be rebuilt
// from scratch.
//
- if (_directMemberDecls.accelerators.declCountWhenLastUpdated < 0)
+ if (accelerators.declCountWhenLastUpdated < 0)
{
- _directMemberDecls.accelerators.declCountWhenLastUpdated = 0;
- _directMemberDecls.accelerators.mapNameToLastDeclOfThatName.clear();
- _directMemberDecls.accelerators.filteredListOfTransparentDecls.clear();
+ accelerators.declCountWhenLastUpdated = 0;
+ accelerators.mapNameToLastDeclOfThatName.clear();
+ accelerators.filteredListOfTransparentDecls.clear();
}
- // are we a generic?
- GenericDecl* genericDecl = as<GenericDecl>(this);
-
- Count memberCount = _directMemberDecls.decls.getCount();
- Count memberCountWhenLastUpdated = _directMemberDecls.accelerators.declCountWhenLastUpdated;
+ Count memberCount = decls.getCount();
+ Count memberCountWhenLastUpdated = accelerators.declCountWhenLastUpdated;
SLANG_ASSERT(memberCountWhenLastUpdated >= 0 && memberCountWhenLastUpdated <= memberCount);
+ // are we a generic?
+ GenericDecl* genericDecl = nullptr;
+ if (memberCount > 0)
+ {
+ genericDecl = as<GenericDecl>(decls[0]->parentDecl);
+ }
+
for (Index i = memberCountWhenLastUpdated; i < memberCount; ++i)
{
- Decl* memberDecl = _directMemberDecls.decls[i];
+ Decl* memberDecl = decls[i];
// Transparent member declarations will go into a separate list,
// so that they can be conveniently queried later for lookup
@@ -163,7 +254,7 @@ void ContainerDecl::_ensureLookupAcceleratorsAreValid()
//
if (memberDecl->hasModifier<TransparentModifier>())
{
- _directMemberDecls.accelerators.filteredListOfTransparentDecls.add(memberDecl);
+ accelerators.filteredListOfTransparentDecls.add(memberDecl);
}
// Members that don't have a name don't go into the lookup dictionary.
@@ -190,9 +281,7 @@ void ContainerDecl::_ensureLookupAcceleratorsAreValid()
// all of the overloaded functions with a given name.
//
Decl* prevMemberWithSameName = nullptr;
- _directMemberDecls.accelerators.mapNameToLastDeclOfThatName.tryGetValue(
- memberName,
- prevMemberWithSameName);
+ accelerators.mapNameToLastDeclOfThatName.tryGetValue(memberName, prevMemberWithSameName);
memberDecl->_prevInContainerWithSameName = prevMemberWithSameName;
// Whether or not there was a previous declaration with this
@@ -200,18 +289,131 @@ void ContainerDecl::_ensureLookupAcceleratorsAreValid()
// with that name encountered so far, and it is what we will
// store in the lookup dictionary.
//
- _directMemberDecls.accelerators.mapNameToLastDeclOfThatName[memberName] = memberDecl;
+ accelerators.mapNameToLastDeclOfThatName[memberName] = memberDecl;
}
- _directMemberDecls.accelerators.declCountWhenLastUpdated = memberCount;
+ accelerators.declCountWhenLastUpdated = memberCount;
SLANG_ASSERT(_areLookupAcceleratorsValid());
}
+
+//
+// ContainerDecl
+//
+
+List<Decl*> const& ContainerDecl::getDirectMemberDecls()
+{
+ return _directMemberDecls.getDecls();
+}
+
+Count ContainerDecl::getDirectMemberDeclCount()
+{
+ return _directMemberDecls.getDeclCount();
+}
+
+Decl* ContainerDecl::getDirectMemberDecl(Index index)
+{
+ return _directMemberDecls.getDecl(index);
+}
+
+Decl* ContainerDecl::getFirstDirectMemberDecl()
+{
+ if (getDirectMemberDeclCount() == 0)
+ return nullptr;
+ return getDirectMemberDecl(0);
+}
+
+DeclsOfNameList ContainerDecl::getDirectMemberDeclsOfName(Name* name)
+{
+ return DeclsOfNameList(findLastDirectMemberDeclOfName(name));
+}
+
+Decl* ContainerDecl::findLastDirectMemberDeclOfName(Name* name)
+{
+ return _directMemberDecls.findLastDeclOfName(name);
+}
+
+Decl* ContainerDecl::getPrevDirectMemberDeclWithSameName(Decl* decl)
+{
+ SLANG_ASSERT(decl);
+ SLANG_ASSERT(decl->parentDecl == this);
+
+ if (isUsingOnDemandDeserializationForDirectMembers())
+ {
+ // Note: in the case of on-demand deserialization,
+ // we trust that the caller has previously
+ // invoked `findLastDirectMemberDeclOfName()`
+ // in order to get `decl` (or an earlier
+ // entry in the same linked list), so that
+ // the list threaded through the declarations
+ // of the same name is already set up.
+ //
+ // If that is ever *not* the case, then this
+ // query would end up returning the wrong results.
+
+ return decl->_prevInContainerWithSameName;
+ }
+ else
+ {
+ _ensureLookupAcceleratorsAreValid();
+ return decl->_prevInContainerWithSameName;
+ }
+}
+
+void ContainerDecl::addDirectMemberDecl(Decl* decl)
+{
+ if (isUsingOnDemandDeserializationForDirectMembers())
+ {
+ SLANG_UNEXPECTED("this operation shouldn't be performed on deserialized declarations");
+ }
+
+ if (!decl)
+ return;
+
+ decl->parentDecl = this;
+ _directMemberDecls.decls.add(decl);
+}
+
+List<Decl*> const& ContainerDecl::getTransparentDirectMemberDecls()
+{
+ return _directMemberDecls.getTransparentDecls();
+}
+
+bool ContainerDecl::isUsingOnDemandDeserializationForDirectMembers()
+{
+ return _directMemberDecls.isUsingOnDemandDeserialization();
+}
+
+bool ModuleDecl::isUsingOnDemandDeserializationForExports()
+{
+ return _directMemberDecls.onDemandDeserialization.context != nullptr;
+}
+
+bool ContainerDecl::_areLookupAcceleratorsValid()
+{
+ return _directMemberDecls._areLookupAcceleratorsValid();
+}
+
+void ContainerDecl::_invalidateLookupAccelerators()
+{
+ _directMemberDecls._invalidateLookupAccelerators();
+}
+
+void ContainerDecl::_ensureLookupAcceleratorsAreValid()
+{
+ _directMemberDecls._ensureLookupAcceleratorsAreValid();
+}
+
void ContainerDecl::
_invalidateLookupAcceleratorsBecauseUnscopedEnumAttributeWillBeTurnedIntoTransparentModifier(
UnscopedEnumAttribute* unscopedEnumAttr,
TransparentModifier* transparentModifier)
{
+ if (isUsingOnDemandDeserializationForDirectMembers())
+ {
+ SLANG_UNEXPECTED("this operation shouldn't be performed on deserialized declarations");
+ }
+
SLANG_ASSERT(unscopedEnumAttr);
SLANG_ASSERT(transparentModifier);
@@ -225,6 +427,11 @@ void ContainerDecl::
_removeDirectMemberConstructorDeclBecauseSynthesizedAnotherDefaultConstructorInstead(
ConstructorDecl* decl)
{
+ if (isUsingOnDemandDeserializationForDirectMembers())
+ {
+ SLANG_UNEXPECTED("this operation shouldn't be performed on deserialized declarations");
+ }
+
SLANG_ASSERT(decl);
_invalidateLookupAccelerators();
@@ -237,6 +444,11 @@ void ContainerDecl::
VarDecl* oldDecl,
PropertyDecl* newDecl)
{
+ if (isUsingOnDemandDeserializationForDirectMembers())
+ {
+ SLANG_UNEXPECTED("this operation shouldn't be performed on deserialized declarations");
+ }
+
SLANG_ASSERT(oldDecl);
SLANG_ASSERT(newDecl);
SLANG_ASSERT(index >= 0 && index < getDirectMemberDeclCount());
@@ -251,6 +463,11 @@ void ContainerDecl::_insertDirectMemberDeclAtIndexForBitfieldPropertyBackingMemb
Index index,
VarDecl* backingVarDecl)
{
+ if (isUsingOnDemandDeserializationForDirectMembers())
+ {
+ SLANG_UNEXPECTED("this operation shouldn't be performed on deserialized declarations");
+ }
+
SLANG_ASSERT(backingVarDecl);
SLANG_ASSERT(index >= 0 && index <= getDirectMemberDeclCount());