]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r304222, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / DebugInfo / CodeView / SymbolRecord.h
1 //===- SymbolRecord.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_SYMBOLRECORD_H
11 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H
12
13 #include "llvm/ADT/APSInt.h"
14 #include "llvm/ADT/ArrayRef.h"
15 #include "llvm/ADT/Optional.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/iterator_range.h"
18 #include "llvm/DebugInfo/CodeView/CVRecord.h"
19 #include "llvm/DebugInfo/CodeView/CodeView.h"
20 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
21 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
22 #include "llvm/Support/BinaryStreamArray.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/Error.h"
25 #include <cstddef>
26 #include <cstdint>
27 #include <vector>
28
29 namespace llvm {
30 namespace codeview {
31
32 class SymbolRecord {
33 protected:
34   explicit SymbolRecord(SymbolRecordKind Kind) : Kind(Kind) {}
35
36 public:
37   SymbolRecordKind getKind() const { return Kind; }
38
39 private:
40   SymbolRecordKind Kind;
41 };
42
43 // S_GPROC32, S_LPROC32, S_GPROC32_ID, S_LPROC32_ID, S_LPROC32_DPC or
44 // S_LPROC32_DPC_ID
45 class ProcSym : public SymbolRecord {
46   static constexpr uint32_t RelocationOffset = 32;
47
48 public:
49   explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
50   ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset)
51       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
52
53   uint32_t getRelocationOffset() const {
54     return RecordOffset + RelocationOffset;
55   }
56
57   uint32_t Parent = 0;
58   uint32_t End = 0;
59   uint32_t Next = 0;
60   uint32_t CodeSize = 0;
61   uint32_t DbgStart = 0;
62   uint32_t DbgEnd = 0;
63   TypeIndex FunctionType;
64   uint32_t CodeOffset = 0;
65   uint16_t Segment = 0;
66   ProcSymFlags Flags = ProcSymFlags::None;
67   StringRef Name;
68
69   uint32_t RecordOffset = 0;
70 };
71
72 // S_THUNK32
73 class Thunk32Sym : public SymbolRecord {
74 public:
75   explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
76   Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
77       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
78
79   uint32_t Parent;
80   uint32_t End;
81   uint32_t Next;
82   uint32_t Offset;
83   uint16_t Segment;
84   uint16_t Length;
85   ThunkOrdinal Thunk;
86   StringRef Name;
87   ArrayRef<uint8_t> VariantData;
88
89   uint32_t RecordOffset;
90 };
91
92 // S_TRAMPOLINE
93 class TrampolineSym : public SymbolRecord {
94 public:
95   explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
96   TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset)
97       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
98
99   TrampolineType Type;
100   uint16_t Size;
101   uint32_t ThunkOffset;
102   uint32_t TargetOffset;
103   uint16_t ThunkSection;
104   uint16_t TargetSection;
105
106   uint32_t RecordOffset;
107 };
108
109 // S_SECTION
110 class SectionSym : public SymbolRecord {
111 public:
112   explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
113   SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
114       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
115
116   uint16_t SectionNumber;
117   uint8_t Alignment;
118   uint32_t Rva;
119   uint32_t Length;
120   uint32_t Characteristics;
121   StringRef Name;
122
123   uint32_t RecordOffset;
124 };
125
126 // S_COFFGROUP
127 class CoffGroupSym : public SymbolRecord {
128 public:
129   explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
130   CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
131       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
132
133   uint32_t Size;
134   uint32_t Characteristics;
135   uint32_t Offset;
136   uint16_t Segment;
137   StringRef Name;
138
139   uint32_t RecordOffset;
140 };
141
142 class ScopeEndSym : public SymbolRecord {
143 public:
144   explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
145   ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
146       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
147
148   uint32_t RecordOffset;
149 };
150
151 class CallerSym : public SymbolRecord {
152 public:
153   explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
154   CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset)
155       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
156
157   std::vector<TypeIndex> Indices;
158   uint32_t RecordOffset;
159 };
160
161 struct BinaryAnnotationIterator {
162   struct AnnotationData {
163     BinaryAnnotationsOpCode OpCode;
164     StringRef Name;
165     uint32_t U1;
166     uint32_t U2;
167     int32_t S1;
168   };
169
170   BinaryAnnotationIterator(ArrayRef<uint8_t> Annotations) : Data(Annotations) {}
171   BinaryAnnotationIterator() = default;
172   BinaryAnnotationIterator(const BinaryAnnotationIterator &Other)
173       : Data(Other.Data) {}
174
175   bool operator==(BinaryAnnotationIterator Other) const {
176     return Data == Other.Data;
177   }
178
179   bool operator!=(const BinaryAnnotationIterator &Other) const {
180     return !(*this == Other);
181   }
182
183   BinaryAnnotationIterator &operator=(const BinaryAnnotationIterator Other) {
184     Data = Other.Data;
185     return *this;
186   }
187
188   BinaryAnnotationIterator &operator++() {
189     if (!ParseCurrentAnnotation()) {
190       *this = BinaryAnnotationIterator();
191       return *this;
192     }
193     Data = Next;
194     Next = ArrayRef<uint8_t>();
195     Current.reset();
196     return *this;
197   }
198
199   BinaryAnnotationIterator operator++(int) {
200     BinaryAnnotationIterator Orig(*this);
201     ++(*this);
202     return Orig;
203   }
204
205   const AnnotationData &operator*() {
206     ParseCurrentAnnotation();
207     return Current.getValue();
208   }
209
210 private:
211   static uint32_t GetCompressedAnnotation(ArrayRef<uint8_t> &Annotations) {
212     if (Annotations.empty())
213       return -1;
214
215     uint8_t FirstByte = Annotations.front();
216     Annotations = Annotations.drop_front();
217
218     if ((FirstByte & 0x80) == 0x00)
219       return FirstByte;
220
221     if (Annotations.empty())
222       return -1;
223
224     uint8_t SecondByte = Annotations.front();
225     Annotations = Annotations.drop_front();
226
227     if ((FirstByte & 0xC0) == 0x80)
228       return ((FirstByte & 0x3F) << 8) | SecondByte;
229
230     if (Annotations.empty())
231       return -1;
232
233     uint8_t ThirdByte = Annotations.front();
234     Annotations = Annotations.drop_front();
235
236     if (Annotations.empty())
237       return -1;
238
239     uint8_t FourthByte = Annotations.front();
240     Annotations = Annotations.drop_front();
241
242     if ((FirstByte & 0xE0) == 0xC0)
243       return ((FirstByte & 0x1F) << 24) | (SecondByte << 16) |
244              (ThirdByte << 8) | FourthByte;
245
246     return -1;
247   };
248
249   static int32_t DecodeSignedOperand(uint32_t Operand) {
250     if (Operand & 1)
251       return -(Operand >> 1);
252     return Operand >> 1;
253   };
254
255   static int32_t DecodeSignedOperand(ArrayRef<uint8_t> &Annotations) {
256     return DecodeSignedOperand(GetCompressedAnnotation(Annotations));
257   };
258
259   bool ParseCurrentAnnotation() {
260     if (Current.hasValue())
261       return true;
262
263     Next = Data;
264     uint32_t Op = GetCompressedAnnotation(Next);
265     AnnotationData Result;
266     Result.OpCode = static_cast<BinaryAnnotationsOpCode>(Op);
267     switch (Result.OpCode) {
268     case BinaryAnnotationsOpCode::Invalid:
269       Result.Name = "Invalid";
270       Next = ArrayRef<uint8_t>();
271       break;
272     case BinaryAnnotationsOpCode::CodeOffset:
273       Result.Name = "CodeOffset";
274       Result.U1 = GetCompressedAnnotation(Next);
275       break;
276     case BinaryAnnotationsOpCode::ChangeCodeOffsetBase:
277       Result.Name = "ChangeCodeOffsetBase";
278       Result.U1 = GetCompressedAnnotation(Next);
279       break;
280     case BinaryAnnotationsOpCode::ChangeCodeOffset:
281       Result.Name = "ChangeCodeOffset";
282       Result.U1 = GetCompressedAnnotation(Next);
283       break;
284     case BinaryAnnotationsOpCode::ChangeCodeLength:
285       Result.Name = "ChangeCodeLength";
286       Result.U1 = GetCompressedAnnotation(Next);
287       break;
288     case BinaryAnnotationsOpCode::ChangeFile:
289       Result.Name = "ChangeFile";
290       Result.U1 = GetCompressedAnnotation(Next);
291       break;
292     case BinaryAnnotationsOpCode::ChangeLineEndDelta:
293       Result.Name = "ChangeLineEndDelta";
294       Result.U1 = GetCompressedAnnotation(Next);
295       break;
296     case BinaryAnnotationsOpCode::ChangeRangeKind:
297       Result.Name = "ChangeRangeKind";
298       Result.U1 = GetCompressedAnnotation(Next);
299       break;
300     case BinaryAnnotationsOpCode::ChangeColumnStart:
301       Result.Name = "ChangeColumnStart";
302       Result.U1 = GetCompressedAnnotation(Next);
303       break;
304     case BinaryAnnotationsOpCode::ChangeColumnEnd:
305       Result.Name = "ChangeColumnEnd";
306       Result.U1 = GetCompressedAnnotation(Next);
307       break;
308     case BinaryAnnotationsOpCode::ChangeLineOffset:
309       Result.Name = "ChangeLineOffset";
310       Result.S1 = DecodeSignedOperand(Next);
311       break;
312     case BinaryAnnotationsOpCode::ChangeColumnEndDelta:
313       Result.Name = "ChangeColumnEndDelta";
314       Result.S1 = DecodeSignedOperand(Next);
315       break;
316     case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: {
317       Result.Name = "ChangeCodeOffsetAndLineOffset";
318       uint32_t Annotation = GetCompressedAnnotation(Next);
319       Result.S1 = DecodeSignedOperand(Annotation >> 4);
320       Result.U1 = Annotation & 0xf;
321       break;
322     }
323     case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: {
324       Result.Name = "ChangeCodeLengthAndCodeOffset";
325       Result.U1 = GetCompressedAnnotation(Next);
326       Result.U2 = GetCompressedAnnotation(Next);
327       break;
328     }
329     }
330     Current = Result;
331     return true;
332   }
333
334   Optional<AnnotationData> Current;
335   ArrayRef<uint8_t> Data;
336   ArrayRef<uint8_t> Next;
337 };
338
339 // S_INLINESITE
340 class InlineSiteSym : public SymbolRecord {
341 public:
342   explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
343   InlineSiteSym(uint32_t RecordOffset)
344       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
345         RecordOffset(RecordOffset) {}
346
347   llvm::iterator_range<BinaryAnnotationIterator> annotations() const {
348     return llvm::make_range(BinaryAnnotationIterator(AnnotationData),
349                             BinaryAnnotationIterator());
350   }
351
352   uint32_t Parent;
353   uint32_t End;
354   TypeIndex Inlinee;
355   std::vector<uint8_t> AnnotationData;
356
357   uint32_t RecordOffset;
358 };
359
360 // S_PUB32
361 class PublicSym32 : public SymbolRecord {
362 public:
363   explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
364   explicit PublicSym32(uint32_t RecordOffset)
365       : SymbolRecord(SymbolRecordKind::PublicSym32),
366         RecordOffset(RecordOffset) {}
367
368   uint32_t Index;
369   uint32_t Offset;
370   uint16_t Segment;
371   StringRef Name;
372
373   uint32_t RecordOffset;
374 };
375
376 // S_REGISTER
377 class RegisterSym : public SymbolRecord {
378 public:
379   explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
380   RegisterSym(uint32_t RecordOffset)
381       : SymbolRecord(SymbolRecordKind::RegisterSym),
382         RecordOffset(RecordOffset) {}
383
384   uint32_t Index;
385   RegisterId Register;
386   StringRef Name;
387
388   uint32_t RecordOffset;
389 };
390
391 // S_PROCREF, S_LPROCREF
392 class ProcRefSym : public SymbolRecord {
393 public:
394   explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
395   explicit ProcRefSym(uint32_t RecordOffset)
396       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
397   }
398
399   uint32_t SumName;
400   uint32_t SymOffset;
401   uint16_t Module;
402   StringRef Name;
403
404   uint32_t RecordOffset;
405 };
406
407 // S_LOCAL
408 class LocalSym : public SymbolRecord {
409 public:
410   explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
411   explicit LocalSym(uint32_t RecordOffset)
412       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
413
414   TypeIndex Type;
415   LocalSymFlags Flags;
416   StringRef Name;
417
418   uint32_t RecordOffset;
419 };
420
421 struct LocalVariableAddrRange {
422   uint32_t OffsetStart;
423   uint16_t ISectStart;
424   uint16_t Range;
425 };
426
427 struct LocalVariableAddrGap {
428   uint16_t GapStartOffset;
429   uint16_t Range;
430 };
431
432 enum : uint16_t { MaxDefRange = 0xf000 };
433
434 // S_DEFRANGE
435 class DefRangeSym : public SymbolRecord {
436   static constexpr uint32_t RelocationOffset = 8;
437
438 public:
439   explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
440   explicit DefRangeSym(uint32_t RecordOffset)
441       : SymbolRecord(SymbolRecordKind::DefRangeSym),
442         RecordOffset(RecordOffset) {}
443
444   uint32_t getRelocationOffset() const {
445     return RecordOffset + RelocationOffset;
446   }
447
448   uint32_t Program;
449   LocalVariableAddrRange Range;
450   std::vector<LocalVariableAddrGap> Gaps;
451
452   uint32_t RecordOffset;
453 };
454
455 // S_DEFRANGE_SUBFIELD
456 class DefRangeSubfieldSym : public SymbolRecord {
457   static constexpr uint32_t RelocationOffset = 12;
458
459 public:
460   explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
461   DefRangeSubfieldSym(uint32_t RecordOffset)
462       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
463         RecordOffset(RecordOffset) {}
464
465   uint32_t getRelocationOffset() const {
466     return RecordOffset + RelocationOffset;
467   }
468
469   uint32_t Program;
470   uint16_t OffsetInParent;
471   LocalVariableAddrRange Range;
472   std::vector<LocalVariableAddrGap> Gaps;
473
474   uint32_t RecordOffset;
475 };
476
477 // S_DEFRANGE_REGISTER
478 class DefRangeRegisterSym : public SymbolRecord {
479 public:
480   struct Header {
481     ulittle16_t Register;
482     ulittle16_t MayHaveNoName;
483   };
484   explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
485   DefRangeRegisterSym(uint32_t RecordOffset)
486       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
487         RecordOffset(RecordOffset) {}
488
489   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
490
491   Header Hdr;
492   LocalVariableAddrRange Range;
493   std::vector<LocalVariableAddrGap> Gaps;
494
495   uint32_t RecordOffset;
496 };
497
498 // S_DEFRANGE_SUBFIELD_REGISTER
499 class DefRangeSubfieldRegisterSym : public SymbolRecord {
500 public:
501   struct Header {
502     ulittle16_t Register;
503     ulittle16_t MayHaveNoName;
504     ulittle32_t OffsetInParent;
505   };
506   explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
507       : SymbolRecord(Kind) {}
508   DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
509       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
510         RecordOffset(RecordOffset) {}
511
512   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
513
514   Header Hdr;
515   LocalVariableAddrRange Range;
516   std::vector<LocalVariableAddrGap> Gaps;
517
518   uint32_t RecordOffset;
519 };
520
521 // S_DEFRANGE_FRAMEPOINTER_REL
522 class DefRangeFramePointerRelSym : public SymbolRecord {
523   static constexpr uint32_t RelocationOffset = 8;
524
525 public:
526   explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
527       : SymbolRecord(Kind) {}
528   DefRangeFramePointerRelSym(uint32_t RecordOffset)
529       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
530         RecordOffset(RecordOffset) {}
531
532   uint32_t getRelocationOffset() const {
533     return RecordOffset + RelocationOffset;
534   }
535
536   int32_t Offset;
537   LocalVariableAddrRange Range;
538   std::vector<LocalVariableAddrGap> Gaps;
539
540   uint32_t RecordOffset;
541 };
542
543 // S_DEFRANGE_REGISTER_REL
544 class DefRangeRegisterRelSym : public SymbolRecord {
545 public:
546   struct Header {
547     ulittle16_t Register;
548     ulittle16_t Flags;
549     little32_t BasePointerOffset;
550   };
551   explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
552   explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
553       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
554         RecordOffset(RecordOffset) {}
555
556   // The flags implement this notional bitfield:
557   //   uint16_t IsSubfield : 1;
558   //   uint16_t Padding : 3;
559   //   uint16_t OffsetInParent : 12;
560   enum : uint16_t {
561     IsSubfieldFlag = 1,
562     OffsetInParentShift = 4,
563   };
564
565   bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
566   uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
567
568   uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
569
570   Header Hdr;
571   LocalVariableAddrRange Range;
572   std::vector<LocalVariableAddrGap> Gaps;
573
574   uint32_t RecordOffset;
575 };
576
577 // S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
578 class DefRangeFramePointerRelFullScopeSym : public SymbolRecord {
579 public:
580   explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
581       : SymbolRecord(Kind) {}
582   explicit DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset)
583       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
584         RecordOffset(RecordOffset) {}
585
586   int32_t Offset;
587
588   uint32_t RecordOffset;
589 };
590
591 // S_BLOCK32
592 class BlockSym : public SymbolRecord {
593   static constexpr uint32_t RelocationOffset = 16;
594
595 public:
596   explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
597   explicit BlockSym(uint32_t RecordOffset)
598       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset) {}
599
600   uint32_t getRelocationOffset() const {
601     return RecordOffset + RelocationOffset;
602   }
603
604   uint32_t Parent;
605   uint32_t End;
606   uint32_t CodeSize;
607   uint32_t CodeOffset;
608   uint16_t Segment;
609   StringRef Name;
610
611   uint32_t RecordOffset;
612 };
613
614 // S_LABEL32
615 class LabelSym : public SymbolRecord {
616   static constexpr uint32_t RelocationOffset = 4;
617
618 public:
619   explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
620   explicit LabelSym(uint32_t RecordOffset)
621       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset) {}
622
623   uint32_t getRelocationOffset() const {
624     return RecordOffset + RelocationOffset;
625   }
626
627   uint32_t CodeOffset;
628   uint16_t Segment;
629   ProcSymFlags Flags;
630   StringRef Name;
631
632   uint32_t RecordOffset;
633 };
634
635 // S_OBJNAME
636 class ObjNameSym : public SymbolRecord {
637 public:
638   explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
639   ObjNameSym(uint32_t RecordOffset)
640       : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
641   }
642
643   uint32_t Signature;
644   StringRef Name;
645
646   uint32_t RecordOffset;
647 };
648
649 // S_ENVBLOCK
650 class EnvBlockSym : public SymbolRecord {
651 public:
652   explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
653   EnvBlockSym(uint32_t RecordOffset)
654       : SymbolRecord(SymbolRecordKind::EnvBlockSym),
655         RecordOffset(RecordOffset) {}
656
657   std::vector<StringRef> Fields;
658
659   uint32_t RecordOffset;
660 };
661
662 // S_EXPORT
663 class ExportSym : public SymbolRecord {
664 public:
665   explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
666   ExportSym(uint32_t RecordOffset)
667       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
668
669   uint16_t Ordinal;
670   ExportFlags Flags;
671   StringRef Name;
672
673   uint32_t RecordOffset;
674 };
675
676 // S_FILESTATIC
677 class FileStaticSym : public SymbolRecord {
678 public:
679   explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
680   FileStaticSym(uint32_t RecordOffset)
681       : SymbolRecord(SymbolRecordKind::FileStaticSym),
682         RecordOffset(RecordOffset) {}
683
684   uint32_t Index;
685   uint32_t ModFilenameOffset;
686   LocalSymFlags Flags;
687   StringRef Name;
688
689   uint32_t RecordOffset;
690 };
691
692 // S_COMPILE2
693 class Compile2Sym : public SymbolRecord {
694 public:
695   explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
696   Compile2Sym(uint32_t RecordOffset)
697       : SymbolRecord(SymbolRecordKind::Compile2Sym),
698         RecordOffset(RecordOffset) {}
699
700   CompileSym2Flags Flags;
701   CPUType Machine;
702   uint16_t VersionFrontendMajor;
703   uint16_t VersionFrontendMinor;
704   uint16_t VersionFrontendBuild;
705   uint16_t VersionBackendMajor;
706   uint16_t VersionBackendMinor;
707   uint16_t VersionBackendBuild;
708   StringRef Version;
709   std::vector<StringRef> ExtraStrings;
710
711   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
712   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
713
714   uint32_t RecordOffset;
715 };
716
717 // S_COMPILE3
718 class Compile3Sym : public SymbolRecord {
719 public:
720   explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
721   Compile3Sym(uint32_t RecordOffset)
722       : SymbolRecord(SymbolRecordKind::Compile3Sym),
723         RecordOffset(RecordOffset) {}
724
725   CompileSym3Flags Flags;
726   CPUType Machine;
727   uint16_t VersionFrontendMajor;
728   uint16_t VersionFrontendMinor;
729   uint16_t VersionFrontendBuild;
730   uint16_t VersionFrontendQFE;
731   uint16_t VersionBackendMajor;
732   uint16_t VersionBackendMinor;
733   uint16_t VersionBackendBuild;
734   uint16_t VersionBackendQFE;
735   StringRef Version;
736
737   uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
738   uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
739
740   uint32_t RecordOffset;
741 };
742
743 // S_FRAMEPROC
744 class FrameProcSym : public SymbolRecord {
745 public:
746   explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
747   explicit FrameProcSym(uint32_t RecordOffset)
748       : SymbolRecord(SymbolRecordKind::FrameProcSym),
749         RecordOffset(RecordOffset) {}
750
751   uint32_t TotalFrameBytes;
752   uint32_t PaddingFrameBytes;
753   uint32_t OffsetToPadding;
754   uint32_t BytesOfCalleeSavedRegisters;
755   uint32_t OffsetOfExceptionHandler;
756   uint16_t SectionIdOfExceptionHandler;
757   FrameProcedureOptions Flags;
758
759   uint32_t RecordOffset;
760 };
761
762 // S_CALLSITEINFO
763 class CallSiteInfoSym : public SymbolRecord {
764   static constexpr uint32_t RelocationOffset = 4;
765
766 public:
767   explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
768   explicit CallSiteInfoSym(uint32_t RecordOffset)
769       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym) {}
770
771   uint32_t getRelocationOffset() const {
772     return RecordOffset + RelocationOffset;
773   }
774
775   uint32_t CodeOffset;
776   uint16_t Segment;
777   TypeIndex Type;
778
779   uint32_t RecordOffset;
780 };
781
782 // S_HEAPALLOCSITE
783 class HeapAllocationSiteSym : public SymbolRecord {
784   static constexpr uint32_t RelocationOffset = 4;
785
786 public:
787   explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
788   explicit HeapAllocationSiteSym(uint32_t RecordOffset)
789       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
790         RecordOffset(RecordOffset) {}
791
792   uint32_t getRelocationOffset() const {
793     return RecordOffset + RelocationOffset;
794   }
795
796   uint32_t CodeOffset;
797   uint16_t Segment;
798   uint16_t CallInstructionSize;
799   TypeIndex Type;
800
801   uint32_t RecordOffset;
802 };
803
804 // S_FRAMECOOKIE
805 class FrameCookieSym : public SymbolRecord {
806   static constexpr uint32_t RelocationOffset = 4;
807
808 public:
809   explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
810   explicit FrameCookieSym(uint32_t RecordOffset)
811       : SymbolRecord(SymbolRecordKind::FrameCookieSym) {}
812
813   uint32_t getRelocationOffset() const {
814     return RecordOffset + RelocationOffset;
815   }
816
817   uint32_t CodeOffset;
818   uint16_t Register;
819   uint8_t CookieKind;
820   uint8_t Flags;
821
822   uint32_t RecordOffset;
823 };
824
825 // S_UDT, S_COBOLUDT
826 class UDTSym : public SymbolRecord {
827 public:
828   explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
829   explicit UDTSym(uint32_t RecordOffset)
830       : SymbolRecord(SymbolRecordKind::UDTSym) {}
831
832   TypeIndex Type;
833   StringRef Name;
834
835   uint32_t RecordOffset;
836 };
837
838 // S_BUILDINFO
839 class BuildInfoSym : public SymbolRecord {
840 public:
841   explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
842   BuildInfoSym(uint32_t RecordOffset)
843       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
844         RecordOffset(RecordOffset) {}
845
846   uint32_t BuildId;
847
848   uint32_t RecordOffset;
849 };
850
851 // S_BPREL32
852 class BPRelativeSym : public SymbolRecord {
853 public:
854   explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
855   explicit BPRelativeSym(uint32_t RecordOffset)
856       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
857         RecordOffset(RecordOffset) {}
858
859   int32_t Offset;
860   TypeIndex Type;
861   StringRef Name;
862
863   uint32_t RecordOffset;
864 };
865
866 // S_REGREL32
867 class RegRelativeSym : public SymbolRecord {
868 public:
869   explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
870   explicit RegRelativeSym(uint32_t RecordOffset)
871       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
872         RecordOffset(RecordOffset) {}
873
874   uint32_t Offset;
875   TypeIndex Type;
876   uint16_t Register;
877   StringRef Name;
878
879   uint32_t RecordOffset;
880 };
881
882 // S_CONSTANT, S_MANCONSTANT
883 class ConstantSym : public SymbolRecord {
884 public:
885   explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
886   ConstantSym(uint32_t RecordOffset)
887       : SymbolRecord(SymbolRecordKind::ConstantSym),
888         RecordOffset(RecordOffset) {}
889
890   TypeIndex Type;
891   APSInt Value;
892   StringRef Name;
893
894   uint32_t RecordOffset;
895 };
896
897 // S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
898 class DataSym : public SymbolRecord {
899   static constexpr uint32_t RelocationOffset = 8;
900
901 public:
902   explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
903   DataSym(uint32_t RecordOffset)
904       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
905
906   uint32_t getRelocationOffset() const {
907     return RecordOffset + RelocationOffset;
908   }
909
910   TypeIndex Type;
911   uint32_t DataOffset;
912   uint16_t Segment;
913   StringRef Name;
914
915   uint32_t RecordOffset;
916 };
917
918 // S_LTHREAD32, S_GTHREAD32
919 class ThreadLocalDataSym : public SymbolRecord {
920   static constexpr uint32_t RelocationOffset = 8;
921
922 public:
923   explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
924   explicit ThreadLocalDataSym(uint32_t RecordOffset)
925       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
926         RecordOffset(RecordOffset) {}
927
928   uint32_t getRelocationOffset() const {
929     return RecordOffset + RelocationOffset;
930   }
931
932   TypeIndex Type;
933   uint32_t DataOffset;
934   uint16_t Segment;
935   StringRef Name;
936
937   uint32_t RecordOffset;
938 };
939
940 typedef CVRecord<SymbolKind> CVSymbol;
941 typedef VarStreamArray<CVSymbol> CVSymbolArray;
942
943 } // end namespace codeview
944 } // end namespace llvm
945
946 #endif // LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORD_H