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
27namespace llvm {
28namespace codeview {
29
30using support::little32_t;
31using support::ulittle16_t;
32using support::ulittle32_t;
33
34struct CVMemberRecord {
35 TypeLeafKind Kind;
36 ArrayRef<uint8_t> Data;
37};
38
39/// Equvalent to CV_fldattr_t in cvinfo.h.
40struct 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.
100class MemberPointerInfo {
101public:
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
118class TypeRecord {
119protected:
120 TypeRecord() = default;
121 explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
122
123public:
124 TypeRecordKind getKind() const { return Kind; }
125
126 TypeRecordKind Kind;
127};
128
129// LF_MODIFIER
130class ModifierRecord : public TypeRecord {
131public:
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
146class ProcedureRecord : public TypeRecord {
147public:
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
171class MemberFunctionRecord : public TypeRecord {
172public:
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
206class LabelRecord : public TypeRecord {
207public:
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
217class MemberFuncIdRecord : public TypeRecord {
218public:
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
236class ArgListRecord : public TypeRecord {
237public:
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
250class StringListRecord : public TypeRecord {
251public:
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
264class PointerRecord : public TypeRecord {
265public:
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
357private:
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
370class NestedTypeRecord : public TypeRecord {
371public:
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
385class FieldListRecord : public TypeRecord {
386public:
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
396class ArrayRecord : public TypeRecord {
397public:
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
416class TagRecord : public TypeRecord {
417protected:
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
425public:
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
465class ClassRecord : public TagRecord {
466public:
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
498struct 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
519class EnumRecord : public TagRecord {
520public:
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
535class BitFieldRecord : public TypeRecord {
536public:
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
553class VFTableShapeRecord : public TypeRecord {
554public:
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
575class TypeServer2Record : public TypeRecord {
576public:
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
595class StringIdRecord : public TypeRecord {
596public:
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
610class FuncIdRecord : public TypeRecord {
611public:
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
628class UdtSourceLineRecord : public TypeRecord {
629public:
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
646class UdtModSourceLineRecord : public TypeRecord {
647public:
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
667class BuildInfoRecord : public TypeRecord {
668public:
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
691class VFTableRecord : public TypeRecord {
692public:
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
720class OneMethodRecord : public TypeRecord {
721public:
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
752class MethodOverloadListRecord : public TypeRecord {
753public:
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
765class OverloadedMethodRecord : public TypeRecord {
766public:
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
784class DataMemberRecord : public TypeRecord {
785public:
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
809class StaticDataMemberRecord : public TypeRecord {
810public:
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
830class EnumeratorRecord : public TypeRecord {
831public:
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
851class VFPtrRecord : public TypeRecord {
852public:
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
864class BaseClassRecord : public TypeRecord {
865public:
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
885class VirtualBaseClassRecord : public TypeRecord {
886public:
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.
915class ListContinuationRecord : public TypeRecord {
916public:
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
929class PrecompRecord : public TypeRecord {
930public:
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
946class EndPrecompRecord : public TypeRecord {
947public:
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

source code of llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h