Line data Source code
1 : //===- TypeTableBuilder.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_TYPETABLEBUILDER_H
11 : #define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
12 :
13 : #include "llvm/ADT/ArrayRef.h"
14 : #include "llvm/DebugInfo/CodeView/CodeView.h"
15 : #include "llvm/DebugInfo/CodeView/TypeIndex.h"
16 : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
17 : #include "llvm/DebugInfo/CodeView/TypeSerializer.h"
18 : #include "llvm/Support/Allocator.h"
19 : #include "llvm/Support/Error.h"
20 : #include <algorithm>
21 : #include <cassert>
22 : #include <cstdint>
23 : #include <type_traits>
24 :
25 : namespace llvm {
26 : namespace codeview {
27 :
28 4865 : class TypeTableBuilder {
29 : private:
30 0 : TypeIndex handleError(Error EC) const {
31 : assert(false && "Couldn't write Type!");
32 0 : consumeError(std::move(EC));
33 0 : return TypeIndex();
34 : }
35 :
36 : BumpPtrAllocator &Allocator;
37 : TypeSerializer Serializer;
38 :
39 : public:
40 : explicit TypeTableBuilder(BumpPtrAllocator &Allocator,
41 : bool WriteUnique = true)
42 4865 : : Allocator(Allocator), Serializer(Allocator, WriteUnique) {}
43 : TypeTableBuilder(const TypeTableBuilder &) = delete;
44 : TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
45 :
46 93 : bool empty() const { return Serializer.records().empty(); }
47 :
48 : BumpPtrAllocator &getAllocator() const { return Allocator; }
49 :
50 1614 : template <typename T> TypeIndex writeKnownType(T &Record) {
51 : static_assert(!std::is_same<T, FieldListRecord>::value,
52 : "Can't serialize FieldList!");
53 :
54 3228 : CVType Type;
55 3228 : Type.Type = static_cast<TypeLeafKind>(Record.getKind());
56 4842 : if (auto EC = Serializer.visitTypeBegin(Type))
57 0 : return handleError(std::move(EC));
58 6456 : if (auto EC = Serializer.visitKnownRecord(Type, Record))
59 0 : return handleError(std::move(EC));
60 :
61 1614 : auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type);
62 1614 : if (!ExpectedIndex)
63 0 : return handleError(ExpectedIndex.takeError());
64 :
65 1614 : return *ExpectedIndex;
66 : }
67 :
68 : TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) {
69 138 : return Serializer.insertRecordBytes(Record);
70 : }
71 :
72 : TypeIndex writeSerializedRecord(const RemappedType &Record) {
73 1002 : return Serializer.insertRecord(Record);
74 : }
75 :
76 90 : template <typename TFunc> void ForEachRecord(TFunc Func) {
77 90 : uint32_t Index = TypeIndex::FirstNonSimpleIndex;
78 :
79 871 : for (auto Record : Serializer.records()) {
80 920 : Func(TypeIndex(Index), Record);
81 691 : ++Index;
82 : }
83 90 : }
84 :
85 1167 : ArrayRef<ArrayRef<uint8_t>> records() const { return Serializer.records(); }
86 : };
87 :
88 320 : class FieldListRecordBuilder {
89 : TypeTableBuilder &TypeTable;
90 : BumpPtrAllocator Allocator;
91 : TypeSerializer TempSerializer;
92 : CVType Type;
93 :
94 : public:
95 160 : explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable)
96 480 : : TypeTable(TypeTable), TempSerializer(Allocator, false) {
97 160 : Type.Type = TypeLeafKind::LF_FIELDLIST;
98 160 : }
99 :
100 134 : void begin() {
101 134 : TempSerializer.reset();
102 :
103 402 : if (auto EC = TempSerializer.visitTypeBegin(Type))
104 0 : consumeError(std::move(EC));
105 134 : }
106 :
107 6183 : template <typename T> void writeMemberType(T &Record) {
108 6183 : CVMemberRecord CVMR;
109 12366 : CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind());
110 18549 : if (auto EC = TempSerializer.visitMemberBegin(CVMR))
111 0 : consumeError(std::move(EC));
112 24732 : if (auto EC = TempSerializer.visitKnownMember(CVMR, Record))
113 0 : consumeError(std::move(EC));
114 18549 : if (auto EC = TempSerializer.visitMemberEnd(CVMR))
115 0 : consumeError(std::move(EC));
116 6183 : }
117 :
118 134 : TypeIndex end(bool Write) {
119 134 : TypeIndex Index;
120 402 : if (auto EC = TempSerializer.visitTypeEnd(Type)) {
121 0 : consumeError(std::move(EC));
122 0 : return TypeIndex();
123 : }
124 :
125 134 : if (Write) {
126 406 : for (auto Record : TempSerializer.records())
127 276 : Index = TypeTable.writeSerializedRecord(Record);
128 : }
129 :
130 134 : return Index;
131 : }
132 : };
133 :
134 : } // end namespace codeview
135 : } // end namespace llvm
136 :
137 : #endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
|