3f20caa31c5fc652fe2cddf3f8ad82cb40d88dfc
[oota-llvm.git] / lib / DebugInfo / CodeView / TypeTableBuilder.cpp
1 //===-- TypeTableBuilder.cpp ----------------------------------------------===//
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 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
13 #include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
14 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
15 #include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
16 #include "llvm/support/raw_ostream.h"
17
18 using namespace llvm;
19 using namespace codeview;
20
21 namespace {
22
23 const uint32_t PointerKindMask = 0x0000001f;
24 const int PointerKindShift = 0;
25 const uint32_t PointerModeMask = 0x000000e0;
26 const int PointerModeShift = 5;
27 const uint32_t PointerSizeMask = 0x0007e000;
28 const int PointerSizeShift = 13;
29 const uint32_t PointerOptionsMask = 0x00081f00;
30
31 const int ClassHfaKindShift = 11;
32 const int ClassWindowsRTClassKindShift = 14;
33
34 void writePointerBase(TypeRecordBuilder &Builder,
35                       const PointerRecordBase &Record) {
36   Builder.writeTypeIndex(Record.getReferentType());
37   uint32_t flags =
38       static_cast<uint32_t>(Record.getOptions()) |
39       (Record.getSize() << PointerSizeShift) |
40       (static_cast<uint32_t>(Record.getMode()) << PointerModeShift) |
41       (static_cast<uint32_t>(Record.getPointerKind()) << PointerKindShift);
42   Builder.writeUInt32(flags);
43 }
44 }
45
46 TypeTableBuilder::TypeTableBuilder() {}
47
48 TypeTableBuilder::~TypeTableBuilder() {}
49
50 TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
51   TypeRecordBuilder Builder(TypeRecordKind::Modifier);
52
53   Builder.writeTypeIndex(Record.getModifiedType());
54   Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
55
56   return writeRecord(Builder);
57 }
58
59 TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
60   TypeRecordBuilder Builder(TypeRecordKind::Procedure);
61
62   Builder.writeTypeIndex(Record.getReturnType());
63   Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
64   Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
65   Builder.writeUInt16(Record.getParameterCount());
66   Builder.writeTypeIndex(Record.getArgumentList());
67
68   return writeRecord(Builder);
69 }
70
71 TypeIndex
72 TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
73   TypeRecordBuilder Builder(TypeRecordKind::MemberFunction);
74
75   Builder.writeTypeIndex(Record.getReturnType());
76   Builder.writeTypeIndex(Record.getClassType());
77   Builder.writeTypeIndex(Record.getThisType());
78   Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
79   Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
80   Builder.writeUInt16(Record.getParameterCount());
81   Builder.writeTypeIndex(Record.getArgumentList());
82   Builder.writeInt32(Record.getThisPointerAdjustment());
83
84   return writeRecord(Builder);
85 }
86
87 TypeIndex
88 TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
89   TypeRecordBuilder Builder(TypeRecordKind::ArgumentList);
90
91   Builder.writeUInt32(Record.getArgumentTypes().size());
92   for (TypeIndex TI : Record.getArgumentTypes()) {
93     Builder.writeTypeIndex(TI);
94   }
95
96   return writeRecord(Builder);
97 }
98
99 TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
100   TypeRecordBuilder Builder(TypeRecordKind::Pointer);
101
102   writePointerBase(Builder, Record);
103
104   return writeRecord(Builder);
105 }
106
107 TypeIndex
108 TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) {
109   TypeRecordBuilder Builder(TypeRecordKind::Pointer);
110
111   writePointerBase(Builder, Record);
112
113   Builder.writeTypeIndex(Record.getContainingType());
114   Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation()));
115
116   return writeRecord(Builder);
117 }
118
119 TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
120   TypeRecordBuilder Builder(TypeRecordKind::Array);
121
122   Builder.writeTypeIndex(Record.getElementType());
123   Builder.writeTypeIndex(Record.getIndexType());
124   Builder.writeEncodedUnsignedInteger(Record.getSize());
125   Builder.writeNullTerminatedString(Record.getName());
126
127   return writeRecord(Builder);
128 }
129
130 TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
131   assert((Record.getKind() == TypeRecordKind::Structure) ||
132          (Record.getKind() == TypeRecordKind::Class) ||
133          (Record.getKind() == TypeRecordKind::Union));
134
135   TypeRecordBuilder Builder(Record.getKind());
136
137   Builder.writeUInt16(Record.getMemberCount());
138   uint16_t Flags =
139       static_cast<uint16_t>(Record.getOptions()) |
140       (static_cast<uint16_t>(Record.getHfa()) << ClassHfaKindShift) |
141       (static_cast<uint16_t>(Record.getWinRTKind())
142        << ClassWindowsRTClassKindShift);
143   Builder.writeUInt16(Flags);
144   Builder.writeTypeIndex(Record.getFieldList());
145   if (Record.getKind() != TypeRecordKind::Union) {
146     Builder.writeTypeIndex(Record.getDerivationList());
147     Builder.writeTypeIndex(Record.getVTableShape());
148   } else {
149     assert(Record.getDerivationList() == TypeIndex());
150     assert(Record.getVTableShape() == TypeIndex());
151   }
152   Builder.writeEncodedUnsignedInteger(Record.getSize());
153   Builder.writeNullTerminatedString(Record.getName());
154   if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
155       ClassOptions::None) {
156     Builder.writeNullTerminatedString(Record.getUniqueName());
157   }
158
159   return writeRecord(Builder);
160 }
161
162 TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
163   TypeRecordBuilder Builder(TypeRecordKind::Enum);
164
165   Builder.writeUInt16(Record.getMemberCount());
166   Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
167   Builder.writeTypeIndex(Record.getUnderlyingType());
168   Builder.writeTypeIndex(Record.getFieldList());
169   Builder.writeNullTerminatedString(Record.getName());
170   if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
171       ClassOptions::None) {
172     Builder.writeNullTerminatedString(Record.getUniqueName());
173   }
174
175   return writeRecord(Builder);
176 }
177
178 TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
179   TypeRecordBuilder Builder(TypeRecordKind::BitField);
180
181   Builder.writeTypeIndex(Record.getType());
182   Builder.writeUInt8(Record.getBitSize());
183   Builder.writeUInt8(Record.getBitOffset());
184
185   return writeRecord(Builder);
186 }
187
188 TypeIndex TypeTableBuilder::writeVirtualTableShape(
189     const VirtualTableShapeRecord &Record) {
190   TypeRecordBuilder Builder(TypeRecordKind::VirtualTableShape);
191
192   ArrayRef<VirtualTableSlotKind> Slots = Record.getSlots();
193
194   Builder.writeUInt16(Slots.size());
195   for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
196     uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
197     if ((SlotIndex + 1) < Slots.size()) {
198       Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
199     }
200     Builder.writeUInt8(Byte);
201   }
202
203   return writeRecord(Builder);
204 }
205
206 TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
207   return writeRecord(Builder.str());
208 }
209
210 TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
211   // TODO: Split the list into multiple records if it's longer than 64KB, using
212   // a subrecord of TypeRecordKind::Index to chain the records together.
213   return writeRecord(FieldList.str());
214 }
215
216 TypeIndex
217 TypeTableBuilder::writeMethodList(MethodListRecordBuilder &MethodList) {
218   // TODO: Split the list into multiple records if it's longer than 64KB, using
219   // a subrecord of TypeRecordKind::Index to chain the records together.
220   return writeRecord(MethodList.str());
221 }