LLVM: lib/DebugInfo/CodeView/ContinuationRecordBuilder.cpp Source File (original) (raw)
2
3using namespace llvm;
5
6namespace {
7struct ContinuationRecord {
8 ulittle16_t Kind{uint16_t(TypeLeafKind::LF_INDEX)};
11};
12
13struct SegmentInjection {
14 SegmentInjection(TypeLeafKind Kind) { Prefix.RecordKind = Kind; }
15
16 ContinuationRecord Cont;
17 RecordPrefix Prefix;
18};
19}
20
24 return;
25
26 int PaddingBytes = 4 - Align;
27 while (PaddingBytes > 0) {
28 uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes);
30 --PaddingBytes;
31 }
32}
33
34static SegmentInjection InjectFieldList(TypeLeafKind::LF_FIELDLIST);
36
40
45
47 : SegmentWriter(Buffer), Mapping(SegmentWriter) {}
48
50
53 Kind = RecordKind;
54 Buffer.clear();
55 SegmentWriter.setOffset(0);
56 SegmentOffsets.clear();
57 SegmentOffsets.push_back(0);
58 assert(SegmentWriter.getOffset() == 0);
59 assert(SegmentWriter.getLength() == 0);
60
61 const SegmentInjection *FLI =
65 const uint8_t *FLIB = reinterpret_cast<const uint8_t *>(FLI);
66 InjectedSegmentBytes =
68
69
73
74 cantFail(SegmentWriter.writeObject(Prefix));
75}
76
77template
80
81 uint32_t OriginalOffset = SegmentWriter.getOffset();
84
85
86
88
89
90 cantFail(Mapping.visitMemberBegin(CVMR));
92 cantFail(Mapping.visitMemberEnd(CVMR));
93
94
96 assert(getCurrentSegmentLength() % 4 == 0);
97
98
99
100
101
102
104
105
106
107 uint32_t MemberLength = SegmentWriter.getOffset() - OriginalOffset;
108 (void) MemberLength;
109 insertSegmentEnd(OriginalOffset);
110
111
112
113
114 assert(getCurrentSegmentLength() == MemberLength + sizeof(RecordPrefix));
115 }
116
117 assert(getCurrentSegmentLength() % 4 == 0);
119}
120
121uint32_t ContinuationRecordBuilder::getCurrentSegmentLength() const {
122 return SegmentWriter.getOffset() - SegmentOffsets.back();
123}
124
125void ContinuationRecordBuilder::insertSegmentEnd(uint32_t Offset) {
126 uint32_t SegmentBegin = SegmentOffsets.back();
127 (void)SegmentBegin;
130
131
132
133
135
137 uint32_t SegmentLength = NewSegmentBegin - SegmentOffsets.back();
138 (void) SegmentLength;
139
140 assert(SegmentLength % 4 == 0);
142 SegmentOffsets.push_back(NewSegmentBegin);
143
144
147}
148
149CVType ContinuationRecordBuilder::createSegmentRecord(
150 uint32_t OffBegin, uint32_t OffEnd, std::optional RefersTo) {
151 assert(OffEnd - OffBegin <= USHRT_MAX);
152
154 Data = Data.slice(OffBegin, OffEnd - OffBegin);
155
156
157
160
161 if (RefersTo) {
163 ContinuationRecord *CR =
164 reinterpret_cast<ContinuationRecord *>(Continuation.data());
165 assert(CR->Kind == TypeLeafKind::LF_INDEX);
166 assert(CR->IndexRef == 0xB0C0B0C0);
167 CR->IndexRef = RefersTo->getIndex();
168 }
169
171}
172
175 CVType Type(&Prefix, sizeof(Prefix));
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 std::vector Types;
225 Types.reserve(SegmentOffsets.size());
226
227 ArrayRef SO = SegmentOffsets;
228
229 uint32_t End = SegmentWriter.getOffset();
230
231 std::optional RefersTo;
233 Types.push_back(createSegmentRecord(Offset, End, RefersTo));
234
236 RefersTo = Index++;
237 }
238
239 Kind.reset();
240 return Types;
241}
242
243
244
245#define TYPE_RECORD(EnumName, EnumVal, Name)
246#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
247#define MEMBER_RECORD(EnumName, EnumVal, Name) \
248 template LLVM_ABI void \
249 llvm::codeview::ContinuationRecordBuilder::writeMemberType( \
250 Name##Record &Record);
251#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
252#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static constexpr uint32_t ContinuationLength
Definition ContinuationRecordBuilder.cpp:37
static TypeLeafKind getTypeLeafKind(ContinuationRecordKind CK)
Definition ContinuationRecordBuilder.cpp:41
static constexpr uint32_t MaxSegmentLength
Definition ContinuationRecordBuilder.cpp:38
static SegmentInjection InjectFieldList(TypeLeafKind::LF_FIELDLIST)
static SegmentInjection InjectMethodOverloadList(TypeLeafKind::LF_METHODLIST)
static void addPadding(BinaryStreamWriter &Writer)
Definition ContinuationRecordBuilder.cpp:21
FunctionLoweringInfo::StatepointRelocationRecord RecordType
MutableArrayRef< uint8_t > data()
void insert(uint64_t Offset, ArrayRef< uint8_t > Bytes)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Provides write only access to a subclass of WritableBinaryStream.
uint64_t getOffset() const
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
uint64_t bytesRemaining() const
uint64_t getLength() const
void setOffset(uint64_t Off)
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
void push_back(const T &Elt)
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI void begin(ContinuationRecordKind RecordKind)
Definition ContinuationRecordBuilder.cpp:51
LLVM_ABI std::vector< CVType > end(TypeIndex Index)
Definition ContinuationRecordBuilder.cpp:173
LLVM_ABI ~ContinuationRecordBuilder()
LLVM_ABI ContinuationRecordBuilder()
Definition ContinuationRecordBuilder.cpp:46
void writeMemberType(RecordType &Record)
Definition ContinuationRecordBuilder.cpp:78
CVRecord< TypeLeafKind > CVType
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
detail::packed_endian_specific_integral< uint16_t, llvm::endianness::little, unaligned > ulittle16_t
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
FunctionAddr VTableAddr uintptr_t uintptr_t Data
This struct is a compact representation of a valid (non-zero power of two) alignment.