1 //===- SymbolSerializer.h ---------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H 10 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H 11 12 #include "llvm/ADT/Optional.h" 13 #include "llvm/DebugInfo/CodeView/CodeView.h" 14 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 15 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 16 #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" 17 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" 18 #include "llvm/Support/Allocator.h" 19 #include "llvm/Support/BinaryByteStream.h" 20 #include "llvm/Support/BinaryStreamWriter.h" 21 #include "llvm/Support/Error.h" 22 #include <cstdint> 23 24 namespace llvm { 25 namespace codeview { 26 27 class SymbolSerializer : public SymbolVisitorCallbacks { 28 BumpPtrAllocator &Storage; 29 // Since this is a fixed size buffer, use a stack allocated buffer. This 30 // yields measurable performance increase over the repeated heap allocations 31 // when serializing many independent records via writeOneSymbol. 32 std::array<uint8_t, MaxRecordLength> RecordBuffer; 33 MutableBinaryByteStream Stream; 34 BinaryStreamWriter Writer; 35 SymbolRecordMapping Mapping; 36 Optional<SymbolKind> CurrentSymbol; 37 38 Error writeRecordPrefix(SymbolKind Kind) { 39 RecordPrefix Prefix; 40 Prefix.RecordKind = Kind; 41 Prefix.RecordLen = 0; 42 if (auto EC = Writer.writeObject(Prefix)) 43 return EC; 44 return Error::success(); 45 } 46 47 public: 48 SymbolSerializer(BumpPtrAllocator &Storage, CodeViewContainer Container); 49 50 template <typename SymType> 51 static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage, 52 CodeViewContainer Container) { 53 RecordPrefix Prefix{uint16_t(Sym.Kind)}; 54 CVSymbol Result(&Prefix, sizeof(Prefix)); 55 SymbolSerializer Serializer(Storage, Container); 56 consumeError(Serializer.visitSymbolBegin(Result)); 57 consumeError(Serializer.visitKnownRecord(Result, Sym)); 58 consumeError(Serializer.visitSymbolEnd(Result)); 59 return Result; 60 } 61 62 Error visitSymbolBegin(CVSymbol &Record) override; 63 Error visitSymbolEnd(CVSymbol &Record) override; 64 65 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 66 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ 67 return visitKnownRecordImpl(CVR, Record); \ 68 } 69 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 70 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 71 72 private: 73 template <typename RecordKind> 74 Error visitKnownRecordImpl(CVSymbol &CVR, RecordKind &Record) { 75 return Mapping.visitKnownRecord(CVR, Record); 76 } 77 }; 78 79 } // end namespace codeview 80 } // end namespace llvm 81 82 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H 83