| //===- symbolSerializer.h ---------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H |
| #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLSERIALIZER_H |
| |
| #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" |
| #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" |
| #include "llvm/DebugInfo/MSF/ByteStream.h" |
| #include "llvm/DebugInfo/MSF/StreamWriter.h" |
| |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/iterator_range.h" |
| #include "llvm/Support/Allocator.h" |
| #include "llvm/Support/Error.h" |
| |
| namespace llvm { |
| namespace codeview { |
| |
| class SymbolSerializer : public SymbolVisitorCallbacks { |
| uint32_t RecordStart = 0; |
| msf::StreamWriter &Writer; |
| SymbolRecordMapping Mapping; |
| Optional<SymbolKind> CurrentSymbol; |
| |
| Error writeRecordPrefix(SymbolKind Kind) { |
| RecordPrefix Prefix; |
| Prefix.RecordKind = Kind; |
| Prefix.RecordLen = 0; |
| if (auto EC = Writer.writeObject(Prefix)) |
| return EC; |
| return Error::success(); |
| } |
| |
| public: |
| explicit SymbolSerializer(msf::StreamWriter &Writer) |
| : Writer(Writer), Mapping(Writer) {} |
| |
| virtual Error visitSymbolBegin(CVSymbol &Record) override { |
| assert(!CurrentSymbol.hasValue() && "Already in a symbol mapping!"); |
| |
| RecordStart = Writer.getOffset(); |
| if (auto EC = writeRecordPrefix(Record.kind())) |
| return EC; |
| |
| CurrentSymbol = Record.kind(); |
| if (auto EC = Mapping.visitSymbolBegin(Record)) |
| return EC; |
| |
| return Error::success(); |
| } |
| |
| virtual Error visitSymbolEnd(CVSymbol &Record) override { |
| assert(CurrentSymbol.hasValue() && "Not in a symbol mapping!"); |
| |
| if (auto EC = Mapping.visitSymbolEnd(Record)) |
| return EC; |
| |
| uint32_t RecordEnd = Writer.getOffset(); |
| Writer.setOffset(RecordStart); |
| uint16_t Length = RecordEnd - Writer.getOffset() - 2; |
| if (auto EC = Writer.writeInteger(Length)) |
| return EC; |
| |
| Writer.setOffset(RecordEnd); |
| CurrentSymbol.reset(); |
| |
| return Error::success(); |
| } |
| |
| #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ |
| virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ |
| return visitKnownRecordImpl(CVR, Record); \ |
| } |
| #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) |
| #include "CVSymbolTypes.def" |
| |
| private: |
| template <typename RecordKind> |
| Error visitKnownRecordImpl(CVSymbol &CVR, RecordKind &Record) { |
| return Mapping.visitKnownRecord(CVR, Record); |
| } |
| }; |
| } |
| } |
| |
| #endif |