summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-serialize-ast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-serialize-ast.cpp')
-rw-r--r--source/slang/slang-serialize-ast.cpp166
1 files changed, 94 insertions, 72 deletions
diff --git a/source/slang/slang-serialize-ast.cpp b/source/slang/slang-serialize-ast.cpp
index a288b3bd2..be959b8a1 100644
--- a/source/slang/slang-serialize-ast.cpp
+++ b/source/slang/slang-serialize-ast.cpp
@@ -1,6 +1,7 @@
// slang-serialize-ast.cpp
#include "slang-serialize-ast.h"
+#include "core/slang-performance-profiler.h"
#include "slang-ast-dispatch.h"
#include "slang-check.h"
#include "slang-compiler.h"
@@ -84,7 +85,8 @@ namespace Slang
// they are all just getting dumped here in the AST serialization logic, because
// it is currenly the only place that cares about this stuff.
//
-void serialize(Serializer const&, RefObject&)
+template<typename S>
+void serialize(S const&, RefObject&)
{
// There's actually no data stored in a `RefObject`, since it only exists
// to make reference-counting possible for other types. This function is
@@ -136,7 +138,8 @@ struct FossilizedTypeTraits<RefObject>
// While we could include this among the types we handle using fiddle,
// let's implement it by hand here, starting with the `serialize()` function:
//
-void serialize(Serializer const& serializer, MatrixCoord& value)
+template<typename S>
+void serialize(S const& serializer, MatrixCoord& value)
{
// We start with one of the `SLANG_SCOPED_SERIALIZER_*`
// macros, which basically just handles calling
@@ -210,7 +213,8 @@ struct FossilizedTypeTraits<MatrixCoord>
// as a single scalar value. We'll define our `serialize()` function
// so that it serializes that "raw" value instead:
//
-void serialize(Serializer const& serializer, SemanticVersion& value)
+template<typename S>
+void serialize(S const& serializer, SemanticVersion& value)
{
// This function is doing something a little "clever"
// handle the fact that it might be used to either
@@ -373,33 +377,17 @@ struct ContainerDeclDirectMemberDeclsInfo
};
//
-// Okay, that's enough examples for now. Let's move on to the next big
-// topic...
-//
// Many types in the AST need additional context information to be able to
-// read or write them properly, so instead of passing around the basic
-// `Serializer` type (which wraps an `ISerializerImpl`), for those types
-// that need extra context we will be passing around an `ASTSerializer`
-// (which wraps an `IASTSerializerImpl`, with the latter interface providing
-// the callbacks to handle the data types that need special-case behavior.
+// read or write them properly, so the concrete serializer type being passed
+// around will include an additional "context" type, that will be either
+// `ASTSerialReadContext` or `ASTSerialWriteContext`, depending on the mode
+// in which serialization is being performed.
+//
+// We could define a base class or interface with `virtual` functions for
+// accessing all of the relevant context, but because we are already
+// using template specialization, it is easier to just ensure that the
+// relevant context types both provide the required operations.
//
-
-struct ASTSerialContext;
-using ASTSerializer = Serializer_<ISerializerImpl, ASTSerialContext>;
-
-/// Context interface for AST serialization
-struct ASTSerialContext : SourceLocSerialContext
-{
-public:
- virtual void handleASTNode(ASTSerializer const& serializer, NodeBase*& value) = 0;
- virtual void handleASTNodeContents(ASTSerializer const& serializer, NodeBase* value) = 0;
- virtual void handleName(ASTSerializer const& serializer, Name*& value) = 0;
- virtual void handleToken(ASTSerializer const& serializer, Token& value) = 0;
- virtual void handleContainerDeclDirectMemberDecls(
- ASTSerializer const& serializer,
- ContainerDeclDirectMemberDecls& value) = 0;
-};
-
//
// Now that we've covered some of the big-picture structure, and shown
@@ -439,7 +427,8 @@ public:
%for _,T in ipairs(enumTypeNames) do
/// Serialize a `value` of type `$T`.
-void serialize(Serializer const& serializer, $T& value)
+template<typename S>
+void serialize(S const& serializer, $T& value)
{
serializeEnum(serializer, value);
}
@@ -518,7 +507,8 @@ struct Fossilized_$T;
SLANG_DECLARE_FOSSILIZED_TYPE($T, Fossilized_$T);
/// Serialize a `$T`
-void serialize(ASTSerializer const& serializer, $T& value);
+template<typename S>
+void serialize(S const& serializer, $T& value);
%end
#else // FIDDLE OUTPUT:
#define FIDDLE_GENERATED_OUTPUT_ID 1
@@ -545,7 +535,8 @@ struct Fossilized_$T;
SLANG_DECLARE_FOSSILIZED_TYPE($T, Fossilized_$T);
/// Serialize the content of a `$T`
-void _serializeASTNodeContents(ASTSerializer const& serializer, $T* value);
+template<typename S>
+void _serializeASTNodeContents(S const& serializer, $T* value);
%end
#else // FIDDLE OUTPUT:
#define FIDDLE_GENERATED_OUTPUT_ID 2
@@ -566,9 +557,11 @@ void _serializeASTNodeContents(ASTSerializer const& serializer, $T* value);
/// lower-level serialization operations to an underlying
/// `ISerializerImpl`.
///
-struct ASTSerialWriteContext : ASTSerialContext
+struct ASTSerialWriteContext : SourceLocSerialContext
{
public:
+ using ASTSerializer = Serializer<Fossil::SerialWriter, ASTSerialWriteContext>;
+
/// Construct a context for writing a serialized AST.
///
/// * `module` is the module that is being serialized, and will be
@@ -587,21 +580,23 @@ private:
ModuleDecl* _module = nullptr;
SerialSourceLocWriter* _sourceLocWriter = nullptr;
+public:
//
// For the most part, this type just implements the methods
// of the `IASTSerializerImpl` interface, and then has some
// support routines needed by those implementations.
//
- virtual void handleName(ASTSerializer const& serializer, Name*& value) override;
- virtual void handleToken(ASTSerializer const& serializer, Token& value) override;
- virtual void handleASTNode(ASTSerializer const& serializer, NodeBase*& node) override;
- virtual void handleASTNodeContents(ASTSerializer const& serializer, NodeBase* node) override;
- virtual void handleContainerDeclDirectMemberDecls(
+ void handleName(ASTSerializer const& serializer, Name*& value);
+ void handleToken(ASTSerializer const& serializer, Token& value);
+ void handleASTNode(ASTSerializer const& serializer, NodeBase*& node);
+ void handleASTNodeContents(ASTSerializer const& serializer, NodeBase* node);
+ void handleContainerDeclDirectMemberDecls(
ASTSerializer const& serializer,
- ContainerDeclDirectMemberDecls& value) override;
- virtual SerialSourceLocWriter* getSourceLocWriter() override { return _sourceLocWriter; }
+ ContainerDeclDirectMemberDecls& value);
+ SerialSourceLocWriter* getSourceLocWriter() { return _sourceLocWriter; }
+private:
void _writeImportedModule(ASTSerializer const& serializer, ModuleDecl* moduleDecl);
void _writeImportedDecl(
ASTSerializer const& serializer,
@@ -653,9 +648,11 @@ private:
/// contexts could result in the same declaration getting turned
/// into multiple distinct `Decl*`s.
///
-struct ASTSerialReadContext : public ASTSerialContext, public RefObject
+struct ASTSerialReadContext : public SourceLocSerialContext, public RefObject
{
public:
+ using ASTSerializer = Serializer<Fossil::SerialReader, ASTSerialReadContext>;
+
/// Construct an AST deserialization context.
///
/// The `linkage`, `astBuilder`, and `sink` arguments must
@@ -729,6 +726,7 @@ private:
Count _deserializedTopLevelDeclCount = 0;
#endif
+public:
//
// Much like the `ASTSerialWriter`, for the most part this
// type just implements the `IASTSerializer` interface,
@@ -736,15 +734,16 @@ private:
// implementations.
//
- virtual void handleName(ASTSerializer const& serializer, Name*& value) override;
- virtual void handleToken(ASTSerializer const& serializer, Token& value) override;
- virtual void handleASTNode(ASTSerializer const& serializer, NodeBase*& outNode) override;
- virtual void handleASTNodeContents(ASTSerializer const& serializer, NodeBase* node) override;
- virtual void handleContainerDeclDirectMemberDecls(
+ void handleName(ASTSerializer const& serializer, Name*& value);
+ void handleToken(ASTSerializer const& serializer, Token& value);
+ void handleASTNode(ASTSerializer const& serializer, NodeBase*& outNode);
+ void handleASTNodeContents(ASTSerializer const& serializer, NodeBase* node);
+ void handleContainerDeclDirectMemberDecls(
ASTSerializer const& serializer,
- ContainerDeclDirectMemberDecls& value) override;
- virtual SerialSourceLocReader* getSourceLocReader() override { return _sourceLocReader; }
+ ContainerDeclDirectMemberDecls& value);
+ SerialSourceLocReader* getSourceLocReader() { return _sourceLocReader; }
+private:
ModuleDecl* _readImportedModule(ASTSerializer const& serializer);
NodeBase* _readImportedDecl(ASTSerializer const& serializer);
@@ -770,7 +769,8 @@ private:
SLANG_DECLARE_FOSSILIZED_AS(Name, String);
-void serializeObject(ASTSerializer const& serializer, Name*& value, Name*)
+template<typename S>
+void serializeObject(S const& serializer, Name*& value, Name*)
{
serializer.getContext()->handleName(serializer, value);
}
@@ -807,7 +807,8 @@ struct FossilizedTypeTraits<Token>
};
};
-void serialize(ASTSerializer const& serializer, Token& value)
+template<typename S>
+void serialize(S const& serializer, Token& value)
{
serializer.getContext()->handleToken(serializer, value);
}
@@ -883,8 +884,8 @@ void ASTSerialReadContext::handleToken(ASTSerializer const& serializer, Token& v
// serialize any pointers to AST nodes.
//
-template<typename T>
-void serializeObject(ASTSerializer const& serializer, T*& value, NodeBase*)
+template<typename S, typename T>
+SLANG_FORCE_INLINE void serializeObject(S const& serializer, T*& value, NodeBase*)
{
// The general-purpose serialization layer defines
// a variant as akin to a struct, but where the
@@ -912,7 +913,8 @@ void serializeObject(ASTSerializer const& serializer, T*& value, NodeBase*)
// object in the reading direction.
//
-void serializeObjectContents(ASTSerializer const& serializer, NodeBase* value, NodeBase*)
+template<typename S>
+SLANG_FORCE_INLINE void serializeObjectContents(S const& serializer, NodeBase* value, NodeBase*)
{
serializer.getContext()->handleASTNodeContents(serializer, value);
}
@@ -930,7 +932,8 @@ void serializeObjectContents(ASTSerializer const& serializer, NodeBase* value, N
SLANG_DECLARE_FOSSILIZED_AS(ContainerDeclDirectMemberDecls, ContainerDeclDirectMemberDeclsInfo);
-void serialize(ASTSerializer const& serializer, ContainerDeclDirectMemberDecls& value)
+template<typename S>
+SLANG_FORCE_INLINE void serialize(S const& serializer, ContainerDeclDirectMemberDecls& value)
{
serializer.getContext()->handleContainerDeclDirectMemberDecls(serializer, value);
}
@@ -943,7 +946,8 @@ void serialize(ASTSerializer const& serializer, ContainerDeclDirectMemberDecls&
SLANG_DECLARE_FOSSILIZED_AS(DiagnosticInfo const*, Int32);
-void serializePtr(Serializer const& serializer, DiagnosticInfo const*& value, DiagnosticInfo const*)
+template<typename S>
+void serializePtr(S const& serializer, DiagnosticInfo const*& value, DiagnosticInfo const*)
{
Int32 id = 0;
if (isWriting(serializer))
@@ -964,8 +968,8 @@ void serializePtr(Serializer const& serializer, DiagnosticInfo const*& value, Di
// and we'll serialize it as such.
//
-template<typename T>
-void serialize(ASTSerializer const& serializer, DeclRef<T>& value)
+template<typename S, typename T>
+void serialize(S const& serializer, DeclRef<T>& value)
{
serialize(serializer, value.declRefBase);
}
@@ -987,7 +991,8 @@ struct FossilizedTypeTraits<DeclRef<T>>
SLANG_DECLARE_FOSSILIZED_AS(SyntaxClass<NodeBase>, ASTNodeType);
-void serialize(Serializer const& serializer, SyntaxClass<NodeBase>& value)
+template<typename S>
+void serialize(S const& serializer, SyntaxClass<NodeBase>& value)
{
ASTNodeType raw = ASTNodeType(0);
if (isWriting(serializer))
@@ -1011,7 +1016,8 @@ void serialize(Serializer const& serializer, SyntaxClass<NodeBase>& value)
SLANG_DECLARE_FOSSILIZED_AS(Modifiers, List<Modifier*>);
-void serialize(ASTSerializer const& serializer, Modifiers& value)
+template<typename S>
+void serialize(S const& serializer, Modifiers& value)
{
SLANG_SCOPED_SERIALIZER_ARRAY(serializer);
@@ -1059,7 +1065,8 @@ void serialize(ASTSerializer const& serializer, Modifiers& value)
//
SLANG_DECLARE_FOSSILIZED_AS_MEMBER(TypeExp, type);
-void serialize(ASTSerializer const& serializer, TypeExp& value)
+template<typename S>
+void serialize(S const& serializer, TypeExp& value)
{
serialize(serializer, value.type);
}
@@ -1071,7 +1078,8 @@ void serialize(ASTSerializer const& serializer, TypeExp& value)
SLANG_DECLARE_FOSSILIZED_AS_MEMBER(CandidateExtensionList, candidateExtensions);
-void serialize(ASTSerializer const& serializer, CandidateExtensionList& value)
+template<typename S>
+void serialize(S const& serializer, CandidateExtensionList& value)
{
serialize(serializer, value.candidateExtensions);
}
@@ -1079,7 +1087,8 @@ void serialize(ASTSerializer const& serializer, CandidateExtensionList& value)
SLANG_DECLARE_FOSSILIZED_AS_MEMBER(DeclAssociationList, associations);
-void serialize(ASTSerializer const& serializer, DeclAssociationList& value)
+template<typename S>
+void serialize(S const& serializer, DeclAssociationList& value)
{
serialize(serializer, value.associations);
}
@@ -1109,7 +1118,8 @@ SLANG_DECLARE_FOSSILIZED_AS(CapabilityTargetSet, CapabilityStageSets);
//
SLANG_DECLARE_FOSSILIZED_AS(CapabilitySet, CapabilityTargetSets);
-void serialize(Serializer const& serializer, CapabilityAtomSet& value)
+template<typename S>
+void serialize(S const& serializer, CapabilityAtomSet& value)
{
SLANG_SCOPED_SERIALIZER_ARRAY(serializer);
if (isWriting(serializer))
@@ -1131,12 +1141,14 @@ void serialize(Serializer const& serializer, CapabilityAtomSet& value)
}
}
-void serialize(Serializer const& serializer, CapabilityStageSet& value)
+template<typename S>
+void serialize(S const& serializer, CapabilityStageSet& value)
{
serialize(serializer, value.atomSet);
}
-void serialize(Serializer const& serializer, CapabilityTargetSet& value)
+template<typename S>
+void serialize(S const& serializer, CapabilityTargetSet& value)
{
serialize(serializer, value.shaderStageSets);
@@ -1154,7 +1166,8 @@ void serialize(Serializer const& serializer, CapabilityTargetSet& value)
}
}
-void serialize(Serializer const& serializer, CapabilitySet& value)
+template<typename S>
+void serialize(S const& serializer, CapabilitySet& value)
{
serialize(serializer, value.getCapabilityTargetSets());
@@ -1190,7 +1203,8 @@ struct FossilizedTypeTraits<RequirementWitness>
};
};
-void serialize(ASTSerializer const& serializer, RequirementWitness& value)
+template<typename S>
+void serialize(S const& serializer, RequirementWitness& value)
{
SLANG_SCOPED_SERIALIZER_VARIANT(serializer);
serialize(serializer, value.m_flavor);
@@ -1228,7 +1242,8 @@ struct FossilizedTypeTraits<ValNodeOperand>
};
};
-void serialize(ASTSerializer const& serializer, ValNodeOperand& value)
+template<typename S>
+void serialize(S const& serializer, ValNodeOperand& value)
{
SLANG_SCOPED_SERIALIZER_VARIANT(serializer);
serialize(serializer, value.kind);
@@ -1289,7 +1304,8 @@ struct Fossilized_$T
};
/// Serialize a `value` of type `$T`
-void serialize(ASTSerializer const& serializer, $T& value)
+template<typename S>
+void serialize(S const& serializer, $T& value)
{
SLANG_UNUSED(value);
SLANG_SCOPED_SERIALIZER_STRUCT(serializer);
@@ -1346,7 +1362,8 @@ struct Fossilized_$T
};
/// Serialize the contents of an AST node of type `$T`
-void _serializeASTNodeContents(ASTSerializer const& serializer, $T* value)
+template<typename S>
+void _serializeASTNodeContents(S const& serializer, $T* value)
{
SLANG_UNUSED(serializer);
SLANG_UNUSED(value);
@@ -1372,7 +1389,8 @@ void _serializeASTNodeContents(ASTSerializer const& serializer, $T* value)
// functions, and dispatches to the correct one based on the type of the given node.
//
-void serializeASTNodeContents(ASTSerializer const& serializer, NodeBase* node)
+template<typename S>
+void serializeASTNodeContents(S const& serializer, NodeBase* node)
{
ASTNodeDispatcher<NodeBase, void>::dispatch(
node,
@@ -1894,7 +1912,7 @@ void ASTSerialReadContext::handleContainerDeclDirectMemberDecls(
// `ISerializerImpl`, whereas we *know* it has a more
// specific type, which we want to make use of.
//
- ISerializerImpl* readerImpl = serializer.getImpl();
+ auto readerImpl = serializer.getImpl();
auto fossilReader = static_cast<Fossil::SerialReader*>(readerImpl);
//
auto fossilizedInfo =
@@ -1927,6 +1945,8 @@ void writeSerializedModuleAST(
ModuleDecl* moduleDecl,
SerialSourceLocWriter* sourceLocWriter)
{
+ SLANG_PROFILE;
+
// TODO: we might want to have a more careful pass here,
// where we only encode the public declarations.
@@ -1965,7 +1985,7 @@ void writeSerializedModuleAST(
//
Fossil::SerialWriter writer(blobBuilder);
ASTSerialWriteContext context(moduleDecl, sourceLocWriter);
- ASTSerializer serializer(&writer, &context);
+ ASTSerialWriteContext::ASTSerializer serializer(&writer, &context);
// Once we have our `serializer`, we can finally invoke
// `serialize()` on the `ASTModuleInfo` to cause everything
@@ -2030,6 +2050,8 @@ ModuleDecl* readSerializedModuleAST(
SerialSourceLocReader* sourceLocReader,
SourceLoc requestingSourceLoc)
{
+ SLANG_PROFILE;
+
// We expect the `chunk` that was passed in to be a RIFF
// data chunk (matching what was written in `writeSerializedModuleAST()`,
// and to be proper fossil-format data.