diff options
Diffstat (limited to 'source/slang/slang-serialize-ast.cpp')
| -rw-r--r-- | source/slang/slang-serialize-ast.cpp | 166 |
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. |
