LLVM  4.0.0
TypeSerializer.h
Go to the documentation of this file.
1 //===- TypeSerializer.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_TYPESERIALIZER_H
11 #define LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
12 
17 
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/Allocator.h"
23 #include "llvm/Support/Error.h"
24 
25 namespace llvm {
26 
27 namespace codeview {
28 
30  struct SubRecord {
31  SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {}
32 
34  uint32_t Size = 0;
35  };
36  struct RecordSegment {
37  SmallVector<SubRecord, 16> SubRecords;
38 
39  uint32_t length() const {
40  uint32_t L = sizeof(RecordPrefix);
41  for (const auto &R : SubRecords) {
42  L += R.Size;
43  }
44  return L;
45  }
46  };
47 
49 
50  static constexpr uint8_t ContinuationLength = 8;
51  BumpPtrAllocator &RecordStorage;
52  RecordSegment CurrentSegment;
53  RecordList FieldListSegments;
54 
55  TypeIndex LastTypeIndex;
57  Optional<TypeLeafKind> MemberKind;
58  std::vector<uint8_t> RecordBuffer;
60  msf::StreamWriter Writer;
61  TypeRecordMapping Mapping;
62 
63  RecordList SeenRecords;
64  StringMap<TypeIndex> HashedRecords;
65 
66  bool isInFieldList() const;
67  TypeIndex calcNextTypeIndex() const;
68  TypeIndex incrementTypeIndex();
69  MutableArrayRef<uint8_t> getCurrentSubRecordData();
70  MutableArrayRef<uint8_t> getCurrentRecordData();
71  Error writeRecordPrefix(TypeLeafKind Kind);
72  TypeIndex insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record);
73 
75  addPadding(MutableArrayRef<uint8_t> Record);
76 
77 public:
78  explicit TypeSerializer(BumpPtrAllocator &Storage);
79 
84 
85  Error visitTypeBegin(CVType &Record) override;
86  Error visitTypeEnd(CVType &Record) override;
87  Error visitMemberBegin(CVMemberRecord &Record) override;
88  Error visitMemberEnd(CVMemberRecord &Record) override;
89 
90 #define TYPE_RECORD(EnumName, EnumVal, Name) \
91  virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
92  return visitKnownRecordImpl(CVR, Record); \
93  }
94 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
95 #define MEMBER_RECORD(EnumName, EnumVal, Name) \
96  Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
97  return visitKnownMemberImpl<Name##Record>(CVR, Record); \
98  }
99 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
100 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
101 
102 private:
103  template <typename RecordKind>
104  Error visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {
105  return Mapping.visitKnownRecord(CVR, Record);
106  }
107 
108  template <typename RecordType>
109  Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
110  assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
111 
112  if (auto EC = Writer.writeEnum(CVR.Kind))
113  return EC;
114 
115  if (auto EC = Mapping.visitKnownMember(CVR, Record))
116  return EC;
117 
118  // Get all the data that was just written and is yet to be committed to
119  // the current segment. Then pad it to 4 bytes.
120  MutableArrayRef<uint8_t> ThisRecord = getCurrentSubRecordData();
121  auto ExpectedRecord = addPadding(ThisRecord);
122  if (!ExpectedRecord)
123  return ExpectedRecord.takeError();
124  ThisRecord = *ExpectedRecord;
125 
126  CurrentSegment.SubRecords.emplace_back(CVR.Kind, ThisRecord.size());
127  CVR.Data = ThisRecord;
128 
129  // Both the last subrecord and the total length of this segment should be
130  // multiples of 4.
131  assert(ThisRecord.size() % 4 == 0);
132  assert(CurrentSegment.length() % 4 == 0);
133 
134  return Error::success();
135  }
136 };
137 }
138 }
139 
140 #endif
MachineLoop * L
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:28
Error visitMemberBegin(CVMemberRecord &Record) override
Error visitTypeEnd(CVType &Record) override
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
Tagged union holding either a T or a Error.
CVRecord< TypeLeafKind > CVType
Definition: TypeRecord.h:39
ArrayRef< MutableArrayRef< uint8_t > > records() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
A 32-bit type reference.
Definition: TypeIndex.h:89
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
Allocate memory in an ever growing pool, as if by bump-pointer.
Definition: Allocator.h:138
TypeIndex insertRecordBytes(MutableArrayRef< uint8_t > Record)
static ErrorSuccess success()
Create a success value.
TypeIndex getLastTypeIndex() const
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Definition: StringMap.h:223
Error visitMemberEnd(CVMemberRecord &Record) override
const unsigned Kind
Error writeEnum(T Num)
Definition: StreamWriter.h:44
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Lightweight error class with error context and mandatory checking.
TypeSerializer(BumpPtrAllocator &Storage)
Expected< TypeIndex > visitTypeEndGetIndex(CVType &Record)