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/Compiler.h"
21#include "llvm/Support/Endian.h"
22#include "llvm/Support/Error.h"
23#include <array>
24#include <cstdint>
25
26namespace llvm {
27namespace codeview {
28
29class LLVM_ABI 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 std::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(Obj: Prefix))
45 return EC;
46 return Error::success();
47 }
48
49public:
50 SymbolSerializer(BumpPtrAllocator &Storage, CodeViewContainer Container);
51
52 template <typename SymType>
53 static CVSymbol writeOneSymbol(SymType &Sym, BumpPtrAllocator &Storage,
54 CodeViewContainer Container) {
55 RecordPrefix Prefix{uint16_t(Sym.Kind)};
56 CVSymbol Result(&Prefix, sizeof(Prefix));
57 SymbolSerializer Serializer(Storage, Container);
58 consumeError(Err: Serializer.visitSymbolBegin(Record&: Result));
59 consumeError(Serializer.visitKnownRecord(Result, Sym));
60 consumeError(Err: Serializer.visitSymbolEnd(Record&: 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
74private:
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