1 | //===- TypeRecord.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_TYPERECORD_H |
10 | #define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H |
11 | |
12 | #include "llvm/ADT/APSInt.h" |
13 | #include "llvm/ADT/ArrayRef.h" |
14 | #include "llvm/ADT/SmallVector.h" |
15 | #include "llvm/ADT/StringRef.h" |
16 | #include "llvm/DebugInfo/CodeView/CVRecord.h" |
17 | #include "llvm/DebugInfo/CodeView/CodeView.h" |
18 | #include "llvm/DebugInfo/CodeView/GUID.h" |
19 | #include "llvm/DebugInfo/CodeView/TypeIndex.h" |
20 | #include "llvm/Support/BinaryStreamArray.h" |
21 | #include "llvm/Support/Endian.h" |
22 | #include <algorithm> |
23 | #include <cstdint> |
24 | #include <optional> |
25 | #include <vector> |
26 | |
27 | namespace llvm { |
28 | namespace codeview { |
29 | |
30 | using support::little32_t; |
31 | using support::ulittle16_t; |
32 | using support::ulittle32_t; |
33 | |
34 | struct CVMemberRecord { |
35 | TypeLeafKind Kind; |
36 | ArrayRef<uint8_t> Data; |
37 | }; |
38 | |
39 | /// Equvalent to CV_fldattr_t in cvinfo.h. |
40 | struct MemberAttributes { |
41 | uint16_t Attrs = 0; |
42 | |
43 | enum { |
44 | MethodKindShift = 2, |
45 | }; |
46 | |
47 | MemberAttributes() = default; |
48 | |
49 | explicit MemberAttributes(MemberAccess Access) |
50 | : Attrs(static_cast<uint16_t>(Access)) {} |
51 | |
52 | MemberAttributes(MemberAccess Access, MethodKind Kind, MethodOptions Flags) { |
53 | Attrs = static_cast<uint16_t>(Access); |
54 | Attrs |= (static_cast<uint16_t>(Kind) << MethodKindShift); |
55 | Attrs |= static_cast<uint16_t>(Flags); |
56 | } |
57 | |
58 | /// Get the access specifier. Valid for any kind of member. |
59 | MemberAccess getAccess() const { |
60 | return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask)); |
61 | } |
62 | |
63 | /// Indicates if a method is defined with friend, virtual, static, etc. |
64 | MethodKind getMethodKind() const { |
65 | return MethodKind( |
66 | (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >> |
67 | MethodKindShift); |
68 | } |
69 | |
70 | /// Get the flags that are not included in access control or method |
71 | /// properties. |
72 | MethodOptions getFlags() const { |
73 | return MethodOptions( |
74 | unsigned(Attrs) & |
75 | ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask)); |
76 | } |
77 | |
78 | /// Is this method virtual. |
79 | bool isVirtual() const { |
80 | auto MP = getMethodKind(); |
81 | return MP != MethodKind::Vanilla && MP != MethodKind::Friend && |
82 | MP != MethodKind::Static; |
83 | } |
84 | |
85 | /// Does this member introduce a new virtual method. |
86 | bool isIntroducedVirtual() const { |
87 | auto MP = getMethodKind(); |
88 | return MP == MethodKind::IntroducingVirtual || |
89 | MP == MethodKind::PureIntroducingVirtual; |
90 | } |
91 | |
92 | /// Is this method static. |
93 | bool isStatic() const { |
94 | return getMethodKind() == MethodKind::Static; |
95 | } |
96 | }; |
97 | |
98 | // Does not correspond to any tag, this is the tail of an LF_POINTER record |
99 | // if it represents a member pointer. |
100 | class MemberPointerInfo { |
101 | public: |
102 | MemberPointerInfo() = default; |
103 | |
104 | MemberPointerInfo(TypeIndex ContainingType, |
105 | PointerToMemberRepresentation Representation) |
106 | : ContainingType(ContainingType), Representation(Representation) {} |
107 | |
108 | TypeIndex getContainingType() const { return ContainingType; } |
109 | PointerToMemberRepresentation getRepresentation() const { |
110 | return Representation; |
111 | } |
112 | |
113 | TypeIndex ContainingType; |
114 | PointerToMemberRepresentation Representation = |
115 | PointerToMemberRepresentation::Unknown; |
116 | }; |
117 | |
118 | class TypeRecord { |
119 | protected: |
120 | TypeRecord() = default; |
121 | explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {} |
122 | |
123 | public: |
124 | TypeRecordKind getKind() const { return Kind; } |
125 | |
126 | TypeRecordKind Kind; |
127 | }; |
128 | |
129 | // LF_MODIFIER |
130 | class ModifierRecord : public TypeRecord { |
131 | public: |
132 | ModifierRecord() = default; |
133 | explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
134 | ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers) |
135 | : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType), |
136 | Modifiers(Modifiers) {} |
137 | |
138 | TypeIndex getModifiedType() const { return ModifiedType; } |
139 | ModifierOptions getModifiers() const { return Modifiers; } |
140 | |
141 | TypeIndex ModifiedType; |
142 | ModifierOptions Modifiers = ModifierOptions::None; |
143 | }; |
144 | |
145 | // LF_PROCEDURE |
146 | class ProcedureRecord : public TypeRecord { |
147 | public: |
148 | ProcedureRecord() = default; |
149 | explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
150 | ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv, |
151 | FunctionOptions Options, uint16_t ParameterCount, |
152 | TypeIndex ArgumentList) |
153 | : TypeRecord(TypeRecordKind::Procedure), ReturnType(ReturnType), |
154 | CallConv(CallConv), Options(Options), ParameterCount(ParameterCount), |
155 | ArgumentList(ArgumentList) {} |
156 | |
157 | TypeIndex getReturnType() const { return ReturnType; } |
158 | CallingConvention getCallConv() const { return CallConv; } |
159 | FunctionOptions getOptions() const { return Options; } |
160 | uint16_t getParameterCount() const { return ParameterCount; } |
161 | TypeIndex getArgumentList() const { return ArgumentList; } |
162 | |
163 | TypeIndex ReturnType; |
164 | CallingConvention CallConv = CallingConvention::NearC; |
165 | FunctionOptions Options = FunctionOptions::None; |
166 | uint16_t ParameterCount = 0; |
167 | TypeIndex ArgumentList; |
168 | }; |
169 | |
170 | // LF_MFUNCTION |
171 | class MemberFunctionRecord : public TypeRecord { |
172 | public: |
173 | MemberFunctionRecord() = default; |
174 | explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
175 | |
176 | MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType, |
177 | TypeIndex ThisType, CallingConvention CallConv, |
178 | FunctionOptions Options, uint16_t ParameterCount, |
179 | TypeIndex ArgumentList, int32_t ThisPointerAdjustment) |
180 | : TypeRecord(TypeRecordKind::MemberFunction), ReturnType(ReturnType), |
181 | ClassType(ClassType), ThisType(ThisType), CallConv(CallConv), |
182 | Options(Options), ParameterCount(ParameterCount), |
183 | ArgumentList(ArgumentList), |
184 | ThisPointerAdjustment(ThisPointerAdjustment) {} |
185 | |
186 | TypeIndex getReturnType() const { return ReturnType; } |
187 | TypeIndex getClassType() const { return ClassType; } |
188 | TypeIndex getThisType() const { return ThisType; } |
189 | CallingConvention getCallConv() const { return CallConv; } |
190 | FunctionOptions getOptions() const { return Options; } |
191 | uint16_t getParameterCount() const { return ParameterCount; } |
192 | TypeIndex getArgumentList() const { return ArgumentList; } |
193 | int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; } |
194 | |
195 | TypeIndex ReturnType; |
196 | TypeIndex ClassType; |
197 | TypeIndex ThisType; |
198 | CallingConvention CallConv = CallingConvention::NearC; |
199 | FunctionOptions Options = FunctionOptions::None; |
200 | uint16_t ParameterCount = 0; |
201 | TypeIndex ArgumentList; |
202 | int32_t ThisPointerAdjustment = 0; |
203 | }; |
204 | |
205 | // LF_LABEL |
206 | class LabelRecord : public TypeRecord { |
207 | public: |
208 | LabelRecord() = default; |
209 | explicit LabelRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
210 | |
211 | LabelRecord(LabelType Mode) : TypeRecord(TypeRecordKind::Label), Mode(Mode) {} |
212 | |
213 | LabelType Mode = LabelType::Near; |
214 | }; |
215 | |
216 | // LF_MFUNC_ID |
217 | class MemberFuncIdRecord : public TypeRecord { |
218 | public: |
219 | MemberFuncIdRecord() = default; |
220 | explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
221 | MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType, |
222 | StringRef Name) |
223 | : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType), |
224 | FunctionType(FunctionType), Name(Name) {} |
225 | |
226 | TypeIndex getClassType() const { return ClassType; } |
227 | TypeIndex getFunctionType() const { return FunctionType; } |
228 | StringRef getName() const { return Name; } |
229 | |
230 | TypeIndex ClassType; |
231 | TypeIndex FunctionType; |
232 | StringRef Name; |
233 | }; |
234 | |
235 | // LF_ARGLIST |
236 | class ArgListRecord : public TypeRecord { |
237 | public: |
238 | ArgListRecord() = default; |
239 | explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
240 | |
241 | ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices) |
242 | : TypeRecord(Kind), ArgIndices(Indices) {} |
243 | |
244 | ArrayRef<TypeIndex> getIndices() const { return ArgIndices; } |
245 | |
246 | std::vector<TypeIndex> ArgIndices; |
247 | }; |
248 | |
249 | // LF_SUBSTR_LIST |
250 | class StringListRecord : public TypeRecord { |
251 | public: |
252 | StringListRecord() = default; |
253 | explicit StringListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
254 | |
255 | StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices) |
256 | : TypeRecord(Kind), StringIndices(Indices) {} |
257 | |
258 | ArrayRef<TypeIndex> getIndices() const { return StringIndices; } |
259 | |
260 | std::vector<TypeIndex> StringIndices; |
261 | }; |
262 | |
263 | // LF_POINTER |
264 | class PointerRecord : public TypeRecord { |
265 | public: |
266 | // ---------------------------XXXXX |
267 | static const uint32_t PointerKindShift = 0; |
268 | static const uint32_t PointerKindMask = 0x1F; |
269 | |
270 | // ------------------------XXX----- |
271 | static const uint32_t PointerModeShift = 5; |
272 | static const uint32_t PointerModeMask = 0x07; |
273 | |
274 | // ----------XXX------XXXXX-------- |
275 | static const uint32_t PointerOptionMask = 0x381f00; |
276 | |
277 | // -------------XXXXXX------------ |
278 | static const uint32_t PointerSizeShift = 13; |
279 | static const uint32_t PointerSizeMask = 0xFF; |
280 | |
281 | PointerRecord() = default; |
282 | explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
283 | |
284 | PointerRecord(TypeIndex ReferentType, uint32_t Attrs) |
285 | : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), |
286 | Attrs(Attrs) {} |
287 | |
288 | PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM, |
289 | PointerOptions PO, uint8_t Size) |
290 | : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), |
291 | Attrs(calcAttrs(PK, PM, PO, Size)) {} |
292 | |
293 | PointerRecord(TypeIndex ReferentType, PointerKind PK, PointerMode PM, |
294 | PointerOptions PO, uint8_t Size, const MemberPointerInfo &MPI) |
295 | : TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType), |
296 | Attrs(calcAttrs(PK, PM, PO, Size)), MemberInfo(MPI) {} |
297 | |
298 | TypeIndex getReferentType() const { return ReferentType; } |
299 | |
300 | PointerKind getPointerKind() const { |
301 | return static_cast<PointerKind>((Attrs >> PointerKindShift) & |
302 | PointerKindMask); |
303 | } |
304 | |
305 | PointerMode getMode() const { |
306 | return static_cast<PointerMode>((Attrs >> PointerModeShift) & |
307 | PointerModeMask); |
308 | } |
309 | |
310 | PointerOptions getOptions() const { |
311 | return static_cast<PointerOptions>(Attrs & PointerOptionMask); |
312 | } |
313 | |
314 | uint8_t getSize() const { |
315 | return (Attrs >> PointerSizeShift) & PointerSizeMask; |
316 | } |
317 | |
318 | MemberPointerInfo getMemberInfo() const { return *MemberInfo; } |
319 | |
320 | bool isPointerToMember() const { |
321 | return getMode() == PointerMode::PointerToDataMember || |
322 | getMode() == PointerMode::PointerToMemberFunction; |
323 | } |
324 | |
325 | bool isFlat() const { return !!(Attrs & uint32_t(PointerOptions::Flat32)); } |
326 | bool isConst() const { return !!(Attrs & uint32_t(PointerOptions::Const)); } |
327 | |
328 | bool isVolatile() const { |
329 | return !!(Attrs & uint32_t(PointerOptions::Volatile)); |
330 | } |
331 | |
332 | bool isUnaligned() const { |
333 | return !!(Attrs & uint32_t(PointerOptions::Unaligned)); |
334 | } |
335 | |
336 | bool isRestrict() const { |
337 | return !!(Attrs & uint32_t(PointerOptions::Restrict)); |
338 | } |
339 | |
340 | bool isLValueReferenceThisPtr() const { |
341 | return !!(Attrs & uint32_t(PointerOptions::LValueRefThisPointer)); |
342 | } |
343 | |
344 | bool isRValueReferenceThisPtr() const { |
345 | return !!(Attrs & uint32_t(PointerOptions::RValueRefThisPointer)); |
346 | } |
347 | |
348 | TypeIndex ReferentType; |
349 | uint32_t Attrs = 0; |
350 | std::optional<MemberPointerInfo> MemberInfo; |
351 | |
352 | void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO, |
353 | uint8_t Size) { |
354 | Attrs = calcAttrs(PK, PM, PO, Size); |
355 | } |
356 | |
357 | private: |
358 | static uint32_t calcAttrs(PointerKind PK, PointerMode PM, PointerOptions PO, |
359 | uint8_t Size) { |
360 | uint32_t A = 0; |
361 | A |= static_cast<uint32_t>(PK); |
362 | A |= static_cast<uint32_t>(PO); |
363 | A |= (static_cast<uint32_t>(PM) << PointerModeShift); |
364 | A |= (static_cast<uint32_t>(Size) << PointerSizeShift); |
365 | return A; |
366 | } |
367 | }; |
368 | |
369 | // LF_NESTTYPE |
370 | class NestedTypeRecord : public TypeRecord { |
371 | public: |
372 | NestedTypeRecord() = default; |
373 | explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
374 | NestedTypeRecord(TypeIndex Type, StringRef Name) |
375 | : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {} |
376 | |
377 | TypeIndex getNestedType() const { return Type; } |
378 | StringRef getName() const { return Name; } |
379 | |
380 | TypeIndex Type; |
381 | StringRef Name; |
382 | }; |
383 | |
384 | // LF_FIELDLIST |
385 | class FieldListRecord : public TypeRecord { |
386 | public: |
387 | FieldListRecord() = default; |
388 | explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
389 | explicit FieldListRecord(ArrayRef<uint8_t> Data) |
390 | : TypeRecord(TypeRecordKind::FieldList), Data(Data) {} |
391 | |
392 | ArrayRef<uint8_t> Data; |
393 | }; |
394 | |
395 | // LF_ARRAY |
396 | class ArrayRecord : public TypeRecord { |
397 | public: |
398 | ArrayRecord() = default; |
399 | explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
400 | ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size, |
401 | StringRef Name) |
402 | : TypeRecord(TypeRecordKind::Array), ElementType(ElementType), |
403 | IndexType(IndexType), Size(Size), Name(Name) {} |
404 | |
405 | TypeIndex getElementType() const { return ElementType; } |
406 | TypeIndex getIndexType() const { return IndexType; } |
407 | uint64_t getSize() const { return Size; } |
408 | StringRef getName() const { return Name; } |
409 | |
410 | TypeIndex ElementType; |
411 | TypeIndex IndexType; |
412 | uint64_t Size = 0; |
413 | StringRef Name; |
414 | }; |
415 | |
416 | class TagRecord : public TypeRecord { |
417 | protected: |
418 | TagRecord() = default; |
419 | explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
420 | TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, |
421 | TypeIndex FieldList, StringRef Name, StringRef UniqueName) |
422 | : TypeRecord(Kind), MemberCount(MemberCount), Options(Options), |
423 | FieldList(FieldList), Name(Name), UniqueName(UniqueName) {} |
424 | |
425 | public: |
426 | static const int HfaKindShift = 11; |
427 | static const int HfaKindMask = 0x1800; |
428 | static const int WinRTKindShift = 14; |
429 | static const int WinRTKindMask = 0xC000; |
430 | |
431 | bool hasUniqueName() const { |
432 | return (Options & ClassOptions::HasUniqueName) != ClassOptions::None; |
433 | } |
434 | |
435 | bool isNested() const { |
436 | return (Options & ClassOptions::Nested) != ClassOptions::None; |
437 | } |
438 | |
439 | bool isForwardRef() const { |
440 | return (Options & ClassOptions::ForwardReference) != ClassOptions::None; |
441 | } |
442 | |
443 | bool containsNestedClass() const { |
444 | return (Options & ClassOptions::ContainsNestedClass) != ClassOptions::None; |
445 | } |
446 | |
447 | bool isScoped() const { |
448 | return (Options & ClassOptions::Scoped) != ClassOptions::None; |
449 | } |
450 | |
451 | uint16_t getMemberCount() const { return MemberCount; } |
452 | ClassOptions getOptions() const { return Options; } |
453 | TypeIndex getFieldList() const { return FieldList; } |
454 | StringRef getName() const { return Name; } |
455 | StringRef getUniqueName() const { return UniqueName; } |
456 | |
457 | uint16_t MemberCount = 0; |
458 | ClassOptions Options = ClassOptions::None; |
459 | TypeIndex FieldList; |
460 | StringRef Name; |
461 | StringRef UniqueName; |
462 | }; |
463 | |
464 | // LF_CLASS, LF_STRUCTURE, LF_INTERFACE |
465 | class ClassRecord : public TagRecord { |
466 | public: |
467 | ClassRecord() = default; |
468 | explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {} |
469 | ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options, |
470 | TypeIndex FieldList, TypeIndex DerivationList, |
471 | TypeIndex VTableShape, uint64_t Size, StringRef Name, |
472 | StringRef UniqueName) |
473 | : TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName), |
474 | DerivationList(DerivationList), VTableShape(VTableShape), Size(Size) {} |
475 | |
476 | HfaKind getHfa() const { |
477 | uint16_t Value = static_cast<uint16_t>(Options); |
478 | Value = (Value & HfaKindMask) >> HfaKindShift; |
479 | return static_cast<HfaKind>(Value); |
480 | } |
481 | |
482 | WindowsRTClassKind getWinRTKind() const { |
483 | uint16_t Value = static_cast<uint16_t>(Options); |
484 | Value = (Value & WinRTKindMask) >> WinRTKindShift; |
485 | return static_cast<WindowsRTClassKind>(Value); |
486 | } |
487 | |
488 | TypeIndex getDerivationList() const { return DerivationList; } |
489 | TypeIndex getVTableShape() const { return VTableShape; } |
490 | uint64_t getSize() const { return Size; } |
491 | |
492 | TypeIndex DerivationList; |
493 | TypeIndex VTableShape; |
494 | uint64_t Size = 0; |
495 | }; |
496 | |
497 | // LF_UNION |
498 | struct UnionRecord : public TagRecord { |
499 | UnionRecord() = default; |
500 | explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {} |
501 | UnionRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, |
502 | uint64_t Size, StringRef Name, StringRef UniqueName) |
503 | : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name, |
504 | UniqueName), |
505 | Size(Size) {} |
506 | |
507 | HfaKind getHfa() const { |
508 | uint16_t Value = static_cast<uint16_t>(Options); |
509 | Value = (Value & HfaKindMask) >> HfaKindShift; |
510 | return static_cast<HfaKind>(Value); |
511 | } |
512 | |
513 | uint64_t getSize() const { return Size; } |
514 | |
515 | uint64_t Size = 0; |
516 | }; |
517 | |
518 | // LF_ENUM |
519 | class EnumRecord : public TagRecord { |
520 | public: |
521 | EnumRecord() = default; |
522 | explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {} |
523 | EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList, |
524 | StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType) |
525 | : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name, |
526 | UniqueName), |
527 | UnderlyingType(UnderlyingType) {} |
528 | |
529 | TypeIndex getUnderlyingType() const { return UnderlyingType; } |
530 | |
531 | TypeIndex UnderlyingType; |
532 | }; |
533 | |
534 | // LF_BITFIELD |
535 | class BitFieldRecord : public TypeRecord { |
536 | public: |
537 | BitFieldRecord() = default; |
538 | explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
539 | BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset) |
540 | : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize), |
541 | BitOffset(BitOffset) {} |
542 | |
543 | TypeIndex getType() const { return Type; } |
544 | uint8_t getBitOffset() const { return BitOffset; } |
545 | uint8_t getBitSize() const { return BitSize; } |
546 | |
547 | TypeIndex Type; |
548 | uint8_t BitSize = 0; |
549 | uint8_t BitOffset = 0; |
550 | }; |
551 | |
552 | // LF_VTSHAPE |
553 | class VFTableShapeRecord : public TypeRecord { |
554 | public: |
555 | VFTableShapeRecord() = default; |
556 | explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
557 | explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots) |
558 | : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {} |
559 | explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots) |
560 | : TypeRecord(TypeRecordKind::VFTableShape), Slots(std::move(Slots)) {} |
561 | |
562 | ArrayRef<VFTableSlotKind> getSlots() const { |
563 | if (!SlotsRef.empty()) |
564 | return SlotsRef; |
565 | return Slots; |
566 | } |
567 | |
568 | uint32_t getEntryCount() const { return getSlots().size(); } |
569 | |
570 | ArrayRef<VFTableSlotKind> SlotsRef; |
571 | std::vector<VFTableSlotKind> Slots; |
572 | }; |
573 | |
574 | // LF_TYPESERVER2 |
575 | class TypeServer2Record : public TypeRecord { |
576 | public: |
577 | TypeServer2Record() = default; |
578 | explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {} |
579 | TypeServer2Record(StringRef GuidStr, uint32_t Age, StringRef Name) |
580 | : TypeRecord(TypeRecordKind::TypeServer2), Age(Age), Name(Name) { |
581 | assert(GuidStr.size() == 16 && "guid isn't 16 bytes" ); |
582 | ::memcpy(dest: Guid.Guid, src: GuidStr.data(), n: 16); |
583 | } |
584 | |
585 | const GUID &getGuid() const { return Guid; } |
586 | uint32_t getAge() const { return Age; } |
587 | StringRef getName() const { return Name; } |
588 | |
589 | GUID Guid = {}; |
590 | uint32_t Age = 0; |
591 | StringRef Name; |
592 | }; |
593 | |
594 | // LF_STRING_ID |
595 | class StringIdRecord : public TypeRecord { |
596 | public: |
597 | StringIdRecord() = default; |
598 | explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
599 | StringIdRecord(TypeIndex Id, StringRef String) |
600 | : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {} |
601 | |
602 | TypeIndex getId() const { return Id; } |
603 | StringRef getString() const { return String; } |
604 | |
605 | TypeIndex Id; |
606 | StringRef String; |
607 | }; |
608 | |
609 | // LF_FUNC_ID |
610 | class FuncIdRecord : public TypeRecord { |
611 | public: |
612 | FuncIdRecord() = default; |
613 | explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
614 | FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name) |
615 | : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope), |
616 | FunctionType(FunctionType), Name(Name) {} |
617 | |
618 | TypeIndex getParentScope() const { return ParentScope; } |
619 | TypeIndex getFunctionType() const { return FunctionType; } |
620 | StringRef getName() const { return Name; } |
621 | |
622 | TypeIndex ParentScope; |
623 | TypeIndex FunctionType; |
624 | StringRef Name; |
625 | }; |
626 | |
627 | // LF_UDT_SRC_LINE |
628 | class UdtSourceLineRecord : public TypeRecord { |
629 | public: |
630 | UdtSourceLineRecord() = default; |
631 | explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
632 | UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber) |
633 | : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), |
634 | SourceFile(SourceFile), LineNumber(LineNumber) {} |
635 | |
636 | TypeIndex getUDT() const { return UDT; } |
637 | TypeIndex getSourceFile() const { return SourceFile; } |
638 | uint32_t getLineNumber() const { return LineNumber; } |
639 | |
640 | TypeIndex UDT; |
641 | TypeIndex SourceFile; |
642 | uint32_t LineNumber = 0; |
643 | }; |
644 | |
645 | // LF_UDT_MOD_SRC_LINE |
646 | class UdtModSourceLineRecord : public TypeRecord { |
647 | public: |
648 | UdtModSourceLineRecord() = default; |
649 | explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
650 | UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, |
651 | uint32_t LineNumber, uint16_t Module) |
652 | : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT), |
653 | SourceFile(SourceFile), LineNumber(LineNumber), Module(Module) {} |
654 | |
655 | TypeIndex getUDT() const { return UDT; } |
656 | TypeIndex getSourceFile() const { return SourceFile; } |
657 | uint32_t getLineNumber() const { return LineNumber; } |
658 | uint16_t getModule() const { return Module; } |
659 | |
660 | TypeIndex UDT; |
661 | TypeIndex SourceFile; |
662 | uint32_t LineNumber = 0; |
663 | uint16_t Module = 0; |
664 | }; |
665 | |
666 | // LF_BUILDINFO |
667 | class BuildInfoRecord : public TypeRecord { |
668 | public: |
669 | BuildInfoRecord() = default; |
670 | explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
671 | BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices) |
672 | : TypeRecord(TypeRecordKind::BuildInfo), |
673 | ArgIndices(ArgIndices.begin(), ArgIndices.end()) {} |
674 | |
675 | ArrayRef<TypeIndex> getArgs() const { return ArgIndices; } |
676 | |
677 | /// Indices of known build info arguments. |
678 | enum BuildInfoArg { |
679 | CurrentDirectory, ///< Absolute CWD path |
680 | BuildTool, ///< Absolute compiler path |
681 | SourceFile, ///< Path to main source file, relative or absolute |
682 | TypeServerPDB, ///< Absolute path of type server PDB (/Fd) |
683 | CommandLine, ///< Full canonical command line (maybe -cc1) |
684 | MaxArgs |
685 | }; |
686 | |
687 | SmallVector<TypeIndex, MaxArgs> ArgIndices; |
688 | }; |
689 | |
690 | // LF_VFTABLE |
691 | class VFTableRecord : public TypeRecord { |
692 | public: |
693 | VFTableRecord() = default; |
694 | explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
695 | VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable, |
696 | uint32_t VFPtrOffset, StringRef Name, |
697 | ArrayRef<StringRef> Methods) |
698 | : TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass), |
699 | OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) { |
700 | MethodNames.push_back(x: Name); |
701 | llvm::append_range(C&: MethodNames, R&: Methods); |
702 | } |
703 | |
704 | TypeIndex getCompleteClass() const { return CompleteClass; } |
705 | TypeIndex getOverriddenVTable() const { return OverriddenVFTable; } |
706 | uint32_t getVFPtrOffset() const { return VFPtrOffset; } |
707 | StringRef getName() const { return ArrayRef(MethodNames).front(); } |
708 | |
709 | ArrayRef<StringRef> getMethodNames() const { |
710 | return ArrayRef(MethodNames).drop_front(); |
711 | } |
712 | |
713 | TypeIndex CompleteClass; |
714 | TypeIndex OverriddenVFTable; |
715 | uint32_t VFPtrOffset = 0; |
716 | std::vector<StringRef> MethodNames; |
717 | }; |
718 | |
719 | // LF_ONEMETHOD |
720 | class OneMethodRecord : public TypeRecord { |
721 | public: |
722 | OneMethodRecord() = default; |
723 | explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
724 | OneMethodRecord(TypeIndex Type, MemberAttributes Attrs, int32_t VFTableOffset, |
725 | StringRef Name) |
726 | : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Attrs(Attrs), |
727 | VFTableOffset(VFTableOffset), Name(Name) {} |
728 | OneMethodRecord(TypeIndex Type, MemberAccess Access, MethodKind MK, |
729 | MethodOptions Options, int32_t VFTableOffset, StringRef Name) |
730 | : TypeRecord(TypeRecordKind::OneMethod), Type(Type), |
731 | Attrs(Access, MK, Options), VFTableOffset(VFTableOffset), Name(Name) {} |
732 | |
733 | TypeIndex getType() const { return Type; } |
734 | MethodKind getMethodKind() const { return Attrs.getMethodKind(); } |
735 | MethodOptions getOptions() const { return Attrs.getFlags(); } |
736 | MemberAccess getAccess() const { return Attrs.getAccess(); } |
737 | int32_t getVFTableOffset() const { return VFTableOffset; } |
738 | StringRef getName() const { return Name; } |
739 | |
740 | bool isIntroducingVirtual() const { |
741 | return getMethodKind() == MethodKind::IntroducingVirtual || |
742 | getMethodKind() == MethodKind::PureIntroducingVirtual; |
743 | } |
744 | |
745 | TypeIndex Type; |
746 | MemberAttributes Attrs; |
747 | int32_t VFTableOffset = 0; |
748 | StringRef Name; |
749 | }; |
750 | |
751 | // LF_METHODLIST |
752 | class MethodOverloadListRecord : public TypeRecord { |
753 | public: |
754 | MethodOverloadListRecord() = default; |
755 | explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
756 | MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods) |
757 | : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {} |
758 | |
759 | ArrayRef<OneMethodRecord> getMethods() const { return Methods; } |
760 | |
761 | std::vector<OneMethodRecord> Methods; |
762 | }; |
763 | |
764 | /// For method overload sets. LF_METHOD |
765 | class OverloadedMethodRecord : public TypeRecord { |
766 | public: |
767 | OverloadedMethodRecord() = default; |
768 | explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
769 | OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList, |
770 | StringRef Name) |
771 | : TypeRecord(TypeRecordKind::OverloadedMethod), |
772 | NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {} |
773 | |
774 | uint16_t getNumOverloads() const { return NumOverloads; } |
775 | TypeIndex getMethodList() const { return MethodList; } |
776 | StringRef getName() const { return Name; } |
777 | |
778 | uint16_t NumOverloads = 0; |
779 | TypeIndex MethodList; |
780 | StringRef Name; |
781 | }; |
782 | |
783 | // LF_MEMBER |
784 | class DataMemberRecord : public TypeRecord { |
785 | public: |
786 | DataMemberRecord() = default; |
787 | explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
788 | DataMemberRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset, |
789 | StringRef Name) |
790 | : TypeRecord(TypeRecordKind::DataMember), Attrs(Attrs), Type(Type), |
791 | FieldOffset(Offset), Name(Name) {} |
792 | DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset, |
793 | StringRef Name) |
794 | : TypeRecord(TypeRecordKind::DataMember), Attrs(Access), Type(Type), |
795 | FieldOffset(Offset), Name(Name) {} |
796 | |
797 | MemberAccess getAccess() const { return Attrs.getAccess(); } |
798 | TypeIndex getType() const { return Type; } |
799 | uint64_t getFieldOffset() const { return FieldOffset; } |
800 | StringRef getName() const { return Name; } |
801 | |
802 | MemberAttributes Attrs; |
803 | TypeIndex Type; |
804 | uint64_t FieldOffset = 0; |
805 | StringRef Name; |
806 | }; |
807 | |
808 | // LF_STMEMBER |
809 | class StaticDataMemberRecord : public TypeRecord { |
810 | public: |
811 | StaticDataMemberRecord() = default; |
812 | explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
813 | StaticDataMemberRecord(MemberAttributes Attrs, TypeIndex Type, StringRef Name) |
814 | : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Attrs), Type(Type), |
815 | Name(Name) {} |
816 | StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name) |
817 | : TypeRecord(TypeRecordKind::StaticDataMember), Attrs(Access), Type(Type), |
818 | Name(Name) {} |
819 | |
820 | MemberAccess getAccess() const { return Attrs.getAccess(); } |
821 | TypeIndex getType() const { return Type; } |
822 | StringRef getName() const { return Name; } |
823 | |
824 | MemberAttributes Attrs; |
825 | TypeIndex Type; |
826 | StringRef Name; |
827 | }; |
828 | |
829 | // LF_ENUMERATE |
830 | class EnumeratorRecord : public TypeRecord { |
831 | public: |
832 | EnumeratorRecord() = default; |
833 | explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
834 | EnumeratorRecord(MemberAttributes Attrs, APSInt Value, StringRef Name) |
835 | : TypeRecord(TypeRecordKind::Enumerator), Attrs(Attrs), |
836 | Value(std::move(Value)), Name(Name) {} |
837 | EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name) |
838 | : TypeRecord(TypeRecordKind::Enumerator), Attrs(Access), |
839 | Value(std::move(Value)), Name(Name) {} |
840 | |
841 | MemberAccess getAccess() const { return Attrs.getAccess(); } |
842 | APSInt getValue() const { return Value; } |
843 | StringRef getName() const { return Name; } |
844 | |
845 | MemberAttributes Attrs; |
846 | APSInt Value; |
847 | StringRef Name; |
848 | }; |
849 | |
850 | // LF_VFUNCTAB |
851 | class VFPtrRecord : public TypeRecord { |
852 | public: |
853 | VFPtrRecord() = default; |
854 | explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
855 | VFPtrRecord(TypeIndex Type) |
856 | : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {} |
857 | |
858 | TypeIndex getType() const { return Type; } |
859 | |
860 | TypeIndex Type; |
861 | }; |
862 | |
863 | // LF_BCLASS, LF_BINTERFACE |
864 | class BaseClassRecord : public TypeRecord { |
865 | public: |
866 | BaseClassRecord() = default; |
867 | explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
868 | BaseClassRecord(MemberAttributes Attrs, TypeIndex Type, uint64_t Offset) |
869 | : TypeRecord(TypeRecordKind::BaseClass), Attrs(Attrs), Type(Type), |
870 | Offset(Offset) {} |
871 | BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset) |
872 | : TypeRecord(TypeRecordKind::BaseClass), Attrs(Access), Type(Type), |
873 | Offset(Offset) {} |
874 | |
875 | MemberAccess getAccess() const { return Attrs.getAccess(); } |
876 | TypeIndex getBaseType() const { return Type; } |
877 | uint64_t getBaseOffset() const { return Offset; } |
878 | |
879 | MemberAttributes Attrs; |
880 | TypeIndex Type; |
881 | uint64_t Offset = 0; |
882 | }; |
883 | |
884 | // LF_VBCLASS, LF_IVBCLASS |
885 | class VirtualBaseClassRecord : public TypeRecord { |
886 | public: |
887 | VirtualBaseClassRecord() = default; |
888 | explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
889 | VirtualBaseClassRecord(TypeRecordKind Kind, MemberAttributes Attrs, |
890 | TypeIndex BaseType, TypeIndex VBPtrType, |
891 | uint64_t Offset, uint64_t Index) |
892 | : TypeRecord(Kind), Attrs(Attrs), BaseType(BaseType), |
893 | VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {} |
894 | VirtualBaseClassRecord(TypeRecordKind Kind, MemberAccess Access, |
895 | TypeIndex BaseType, TypeIndex VBPtrType, |
896 | uint64_t Offset, uint64_t Index) |
897 | : TypeRecord(Kind), Attrs(Access), BaseType(BaseType), |
898 | VBPtrType(VBPtrType), VBPtrOffset(Offset), VTableIndex(Index) {} |
899 | |
900 | MemberAccess getAccess() const { return Attrs.getAccess(); } |
901 | TypeIndex getBaseType() const { return BaseType; } |
902 | TypeIndex getVBPtrType() const { return VBPtrType; } |
903 | uint64_t getVBPtrOffset() const { return VBPtrOffset; } |
904 | uint64_t getVTableIndex() const { return VTableIndex; } |
905 | |
906 | MemberAttributes Attrs; |
907 | TypeIndex BaseType; |
908 | TypeIndex VBPtrType; |
909 | uint64_t VBPtrOffset = 0; |
910 | uint64_t VTableIndex = 0; |
911 | }; |
912 | |
913 | /// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records |
914 | /// together. The first will end in an LF_INDEX record that points to the next. |
915 | class ListContinuationRecord : public TypeRecord { |
916 | public: |
917 | ListContinuationRecord() = default; |
918 | explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
919 | ListContinuationRecord(TypeIndex ContinuationIndex) |
920 | : TypeRecord(TypeRecordKind::ListContinuation), |
921 | ContinuationIndex(ContinuationIndex) {} |
922 | |
923 | TypeIndex getContinuationIndex() const { return ContinuationIndex; } |
924 | |
925 | TypeIndex ContinuationIndex; |
926 | }; |
927 | |
928 | // LF_PRECOMP |
929 | class PrecompRecord : public TypeRecord { |
930 | public: |
931 | PrecompRecord() = default; |
932 | explicit PrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
933 | |
934 | uint32_t getStartTypeIndex() const { return StartTypeIndex; } |
935 | uint32_t getTypesCount() const { return TypesCount; } |
936 | uint32_t getSignature() const { return Signature; } |
937 | StringRef getPrecompFilePath() const { return PrecompFilePath; } |
938 | |
939 | uint32_t StartTypeIndex = 0; |
940 | uint32_t TypesCount = 0; |
941 | uint32_t Signature = 0; |
942 | StringRef PrecompFilePath; |
943 | }; |
944 | |
945 | // LF_ENDPRECOMP |
946 | class EndPrecompRecord : public TypeRecord { |
947 | public: |
948 | EndPrecompRecord() = default; |
949 | explicit EndPrecompRecord(TypeRecordKind Kind) : TypeRecord(Kind) {} |
950 | |
951 | uint32_t getSignature() const { return Signature; } |
952 | |
953 | uint32_t Signature = 0; |
954 | }; |
955 | |
956 | } // end namespace codeview |
957 | } // end namespace llvm |
958 | |
959 | #endif // LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H |
960 | |