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/DebugInfo/CodeView/CVRecord.h" 13 #include "llvm/DebugInfo/CodeView/CodeView.h" 14 #include "llvm/DebugInfo/CodeView/RecordSerialization.h" 15 #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" 16 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" 17 #include "llvm/Support/Allocator.h" 18 #include "llvm/Support/BinaryByteStream.h" 19 #include "llvm/Support/BinaryStreamWriter.h" 20 #include "llvm/Support/Endian.h" 21 #include "llvm/Support/Error.h" 22 #include <array> 23 #include <cstdint> 24 25 namespace llvm { 26 namespace codeview { 27 28 class SymbolSerializer : public SymbolVisitorCallbacks { 29 BumpPtrAllocator &Storage; 30 // Since this is a fixed size buffer, use a stack allocated buffer. This 31 // yields measurable performance increase over the repeated heap allocations 32 // when serializing many independent records via writeOneSymbol. 33 std::array<uint8_t, MaxRecordLength> RecordBuffer; 34 MutableBinaryByteStream Stream; 35 BinaryStreamWriter Writer; 36 SymbolRecordMapping Mapping; 37 std::optional<SymbolKind> CurrentSymbol; 38 writeRecordPrefix(SymbolKind Kind)39 Error writeRecordPrefix(SymbolKind Kind) { 40 RecordPrefix Prefix; 41 Prefix.RecordKind = Kind; 42 Prefix.RecordLen = 0; 43 if (auto EC = Writer.writeObject(Prefix)) 44 return EC; 45 return Error::success(); 46 } 47 48 public: 49 SymbolSerializer(BumpPtrAllocator &Storage, CodeViewContainer Container); 50 51 template <typename SymType> writeOneSymbol(SymType & Sym,BumpPtrAllocator & Storage,CodeViewContainer Container)52 static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage, 53 CodeViewContainer Container) { 54 RecordPrefix Prefix{uint16_t(Sym.Kind)}; 55 CVSymbol Result(&Prefix, sizeof(Prefix)); 56 SymbolSerializer Serializer(Storage, Container); 57 consumeError(Serializer.visitSymbolBegin(Result)); 58 consumeError(Serializer.visitKnownRecord(Result, Sym)); 59 consumeError(Serializer.visitSymbolEnd(Result)); 60 return Result; 61 } 62 63 Error visitSymbolBegin(CVSymbol &Record) override; 64 Error visitSymbolEnd(CVSymbol &Record) override; 65 66 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 67 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ 68 return visitKnownRecordImpl(CVR, Record); \ 69 } 70 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 71 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 72 73 private: 74 template <typename RecordKind> visitKnownRecordImpl(CVSymbol & CVR,RecordKind & Record)75 Error visitKnownRecordImpl(CVSymbol &CVR, RecordKind &Record) { 76 return Mapping.visitKnownRecord(CVR, Record); 77 } 78 }; 79 80 } // end namespace codeview 81 } // end namespace llvm 82 83 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H 84