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