Home | History | Annotate | Download | only in CodeView
      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 
     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>
     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>
     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