1 //===---- typeBuilder.cpp --------------------------------*- C++ -*-===//
2 //
3 // type builder implementation using codeview::TypeTableBuilder
4 //
5 // Copyright (c) Microsoft. All rights reserved.
6 // Licensed under the MIT license.
7 // See LICENSE file in the project root for full license information.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include "typeBuilder.h"
12 #include "llvm/BinaryFormat/COFF.h"
13 #include <sstream>
14 #include <vector>
15
UserDefinedTypesBuilder()16 UserDefinedTypesBuilder::UserDefinedTypesBuilder()
17 : Allocator(), TypeTable(Allocator), Streamer(nullptr),
18 TargetPointerSize(0)
19 {
20 VFTableShapeRecord vfTableShape(TypeRecordKind::VFTableShape);
21 ClassVTableTypeIndex = TypeTable.writeKnownType(vfTableShape);
22 }
23
SetStreamer(MCObjectStreamer * Streamer)24 void UserDefinedTypesBuilder::SetStreamer(MCObjectStreamer *Streamer) {
25 assert(this->Streamer == nullptr);
26 assert(Streamer != nullptr);
27 this->Streamer = Streamer;
28 }
29
SetTargetPointerSize(unsigned TargetPointerSize)30 void UserDefinedTypesBuilder::SetTargetPointerSize(unsigned TargetPointerSize) {
31 assert(this->TargetPointerSize == 0);
32 assert(TargetPointerSize != 0);
33 this->TargetPointerSize = TargetPointerSize;
34 }
35
EmitCodeViewMagicVersion()36 void UserDefinedTypesBuilder::EmitCodeViewMagicVersion() {
37 Streamer->EmitValueToAlignment(4);
38 Streamer->AddComment("Debug section magic");
39 Streamer->EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
40 }
41
GetCommonClassOptions()42 ClassOptions UserDefinedTypesBuilder::GetCommonClassOptions() {
43 return ClassOptions();
44 }
45
EmitTypeInformation(MCSection * COFFDebugTypesSection)46 void UserDefinedTypesBuilder::EmitTypeInformation(
47 MCSection *COFFDebugTypesSection) {
48
49 if (TypeTable.empty())
50 return;
51
52 Streamer->SwitchSection(COFFDebugTypesSection);
53 EmitCodeViewMagicVersion();
54
55 TypeTable.ForEachRecord([&](TypeIndex FieldTypeIndex,
56 ArrayRef<uint8_t> Record) {
57 StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size());
58 Streamer->EmitBinaryData(S);
59 });
60 }
61
GetEnumFieldListType(uint64 Count,const EnumRecordTypeDescriptor * TypeRecords)62 unsigned UserDefinedTypesBuilder::GetEnumFieldListType(
63 uint64 Count, const EnumRecordTypeDescriptor *TypeRecords) {
64 FieldListRecordBuilder FLRB(TypeTable);
65 FLRB.begin();
66 #ifndef NDEBUG
67 uint64 MaxInt = (unsigned int)-1;
68 assert(Count <= MaxInt && "There are too many fields inside enum");
69 #endif
70 for (int i = 0; i < (int)Count; ++i) {
71 EnumRecordTypeDescriptor record = TypeRecords[i];
72 EnumeratorRecord ER(MemberAccess::Public, APSInt::getUnsigned(record.Value),
73 record.Name);
74 FLRB.writeMemberType(ER);
75 }
76 TypeIndex Type = FLRB.end(true);
77 return Type.getIndex();
78 }
79
GetEnumTypeIndex(const EnumTypeDescriptor & TypeDescriptor,const EnumRecordTypeDescriptor * TypeRecords)80 unsigned UserDefinedTypesBuilder::GetEnumTypeIndex(
81 const EnumTypeDescriptor &TypeDescriptor,
82 const EnumRecordTypeDescriptor *TypeRecords) {
83
84 ClassOptions CO = GetCommonClassOptions();
85 unsigned FieldListIndex =
86 GetEnumFieldListType(TypeDescriptor.ElementCount, TypeRecords);
87 TypeIndex FieldListIndexType = TypeIndex(FieldListIndex);
88 TypeIndex ElementTypeIndex = TypeIndex(TypeDescriptor.ElementType);
89
90 EnumRecord EnumRecord(TypeDescriptor.ElementCount, CO, FieldListIndexType,
91 TypeDescriptor.Name, StringRef(),
92 ElementTypeIndex);
93
94 TypeIndex Type = TypeTable.writeKnownType(EnumRecord);
95 UserDefinedTypes.push_back(std::make_pair(TypeDescriptor.Name, Type));
96 return Type.getIndex();
97 }
98
GetClassTypeIndex(const ClassTypeDescriptor & ClassDescriptor)99 unsigned UserDefinedTypesBuilder::GetClassTypeIndex(
100 const ClassTypeDescriptor &ClassDescriptor) {
101 TypeRecordKind Kind =
102 ClassDescriptor.IsStruct ? TypeRecordKind::Struct : TypeRecordKind::Class;
103 ClassOptions CO = ClassOptions::ForwardReference | GetCommonClassOptions();
104
105 TypeIndex FieldListIndex = TypeIndex();
106 uint16_t memberCount = 0;
107
108 if (!ClassDescriptor.IsStruct) {
109 FieldListRecordBuilder FLBR(TypeTable);
110 FLBR.begin();
111 memberCount++;
112 AddClassVTShape(FLBR);
113 FieldListIndex = FLBR.end(true);
114 }
115
116 ClassRecord CR(Kind, memberCount, CO, FieldListIndex, TypeIndex(), TypeIndex(), 0,
117 ClassDescriptor.Name, StringRef());
118 TypeIndex FwdDeclTI = TypeTable.writeKnownType(CR);
119 return FwdDeclTI.getIndex();
120 }
121
GetCompleteClassTypeIndex(const ClassTypeDescriptor & ClassDescriptor,const ClassFieldsTypeDescriptior & ClassFieldsDescriptor,const DataFieldDescriptor * FieldsDescriptors)122 unsigned UserDefinedTypesBuilder::GetCompleteClassTypeIndex(
123 const ClassTypeDescriptor &ClassDescriptor,
124 const ClassFieldsTypeDescriptior &ClassFieldsDescriptor,
125 const DataFieldDescriptor *FieldsDescriptors) {
126
127 FieldListRecordBuilder FLBR(TypeTable);
128 FLBR.begin();
129
130 uint16_t memberCount = 0;
131 if (!ClassDescriptor.IsStruct) {
132 memberCount++;
133 AddClassVTShape(FLBR);
134 }
135
136 if (ClassDescriptor.BaseClassId != 0) {
137 memberCount++;
138 AddBaseClass(FLBR, ClassDescriptor.BaseClassId);
139 }
140
141 for (int i = 0; i < ClassFieldsDescriptor.FieldsCount; ++i) {
142 DataFieldDescriptor desc = FieldsDescriptors[i];
143 MemberAccess Access = MemberAccess::Public;
144 TypeIndex MemberBaseType(desc.FieldTypeIndex);
145 if (desc.Offset == 0xFFFFFFFF)
146 {
147 StaticDataMemberRecord SDMR(Access, MemberBaseType, desc.Name);
148 FLBR.writeMemberType(SDMR);
149 }
150 else
151 {
152 int MemberOffsetInBytes = desc.Offset;
153 DataMemberRecord DMR(Access, MemberBaseType, MemberOffsetInBytes,
154 desc.Name);
155 FLBR.writeMemberType(DMR);
156 }
157 memberCount++;
158 }
159 TypeIndex FieldListIndex = FLBR.end(true);
160 TypeRecordKind Kind =
161 ClassDescriptor.IsStruct ? TypeRecordKind::Struct : TypeRecordKind::Class;
162 ClassOptions CO = GetCommonClassOptions();
163 ClassRecord CR(Kind, memberCount, CO, FieldListIndex,
164 TypeIndex(), TypeIndex(), ClassFieldsDescriptor.Size,
165 ClassDescriptor.Name, StringRef());
166 TypeIndex ClassIndex = TypeTable.writeKnownType(CR);
167
168 UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex));
169
170 return ClassIndex.getIndex();
171 }
172
GetArrayTypeIndex(const ClassTypeDescriptor & ClassDescriptor,const ArrayTypeDescriptor & ArrayDescriptor)173 unsigned UserDefinedTypesBuilder::GetArrayTypeIndex(
174 const ClassTypeDescriptor &ClassDescriptor,
175 const ArrayTypeDescriptor &ArrayDescriptor) {
176 FieldListRecordBuilder FLBR(TypeTable);
177 FLBR.begin();
178
179 unsigned Offset = 0;
180 unsigned FieldsCount = 0;
181
182 assert(ClassDescriptor.BaseClassId != 0);
183
184 AddClassVTShape(FLBR);
185 FieldsCount++;
186 AddBaseClass(FLBR, ClassDescriptor.BaseClassId);
187 FieldsCount++;
188 Offset += TargetPointerSize;
189
190 MemberAccess Access = MemberAccess::Public;
191 TypeIndex IndexType = TypeIndex(SimpleTypeKind::Int32);
192 DataMemberRecord CountDMR(Access, IndexType, Offset, "count");
193 FLBR.writeMemberType(CountDMR);
194 FieldsCount++;
195 Offset += TargetPointerSize;
196
197 if (ArrayDescriptor.IsMultiDimensional == 1) {
198 for (unsigned i = 0; i < ArrayDescriptor.Rank; ++i) {
199 DataMemberRecord LengthDMR(Access, TypeIndex(SimpleTypeKind::Int32),
200 Offset, ArrayDimentions.GetLengthName(i));
201 FLBR.writeMemberType(LengthDMR);
202 FieldsCount++;
203 Offset += 4;
204 }
205
206 for (unsigned i = 0; i < ArrayDescriptor.Rank; ++i) {
207 DataMemberRecord BoundsDMR(Access, TypeIndex(SimpleTypeKind::Int32),
208 Offset, ArrayDimentions.GetBoundsName(i));
209 FLBR.writeMemberType(BoundsDMR);
210 FieldsCount++;
211 Offset += 4;
212 }
213 }
214
215 TypeIndex ElementTypeIndex = TypeIndex(ArrayDescriptor.ElementType);
216 ArrayRecord AR(ElementTypeIndex, IndexType, ArrayDescriptor.Size, "");
217 TypeIndex ArrayIndex = TypeTable.writeKnownType(AR);
218 DataMemberRecord ArrayDMR(Access, ArrayIndex, Offset, "values");
219 FLBR.writeMemberType(ArrayDMR);
220 FieldsCount++;
221
222 TypeIndex FieldListIndex = FLBR.end(true);
223
224 assert(ClassDescriptor.IsStruct == false);
225 TypeRecordKind Kind = TypeRecordKind::Class;
226 ClassOptions CO = GetCommonClassOptions();
227 ClassRecord CR(Kind, FieldsCount, CO, FieldListIndex, TypeIndex(),
228 TypeIndex(), ArrayDescriptor.Size, ClassDescriptor.Name,
229 StringRef());
230 TypeIndex ClassIndex = TypeTable.writeKnownType(CR);
231
232 UserDefinedTypes.push_back(std::make_pair(ClassDescriptor.Name, ClassIndex));
233
234 return ClassIndex.getIndex();
235 }
236
GetPointerTypeIndex(const PointerTypeDescriptor & PointerDescriptor)237 unsigned UserDefinedTypesBuilder::GetPointerTypeIndex(const PointerTypeDescriptor& PointerDescriptor)
238 {
239 uint32_t elementType = PointerDescriptor.ElementType;
240 PointerKind pointerKind = PointerDescriptor.Is64Bit ? PointerKind::Near64 : PointerKind::Near32;
241 PointerMode pointerMode = PointerDescriptor.IsReference ? PointerMode::LValueReference : PointerMode::Pointer;
242 PointerOptions pointerOptions = PointerDescriptor.IsConst ? PointerOptions::Const : PointerOptions::None;
243
244 PointerRecord PointerToClass(TypeIndex(elementType), pointerKind, pointerMode, pointerOptions, 0);
245 TypeIndex PointerIndex = TypeTable.writeKnownType(PointerToClass);
246 return PointerIndex.getIndex();
247 }
248
GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor & MemberDescriptor,uint32_t const * const ArgumentTypes)249 unsigned UserDefinedTypesBuilder::GetMemberFunctionTypeIndex(const MemberFunctionTypeDescriptor& MemberDescriptor,
250 uint32_t const *const ArgumentTypes)
251 {
252 std::vector<TypeIndex> argumentTypes;
253 argumentTypes.reserve(MemberDescriptor.NumberOfArguments);
254 for (uint16_t iArgument = 0; iArgument < MemberDescriptor.NumberOfArguments; iArgument++)
255 {
256 argumentTypes.emplace_back(ArgumentTypes[iArgument]);
257 }
258
259 ArgListRecord ArgList(TypeRecordKind::ArgList, argumentTypes);
260 TypeIndex ArgumentList = TypeTable.writeKnownType(ArgList);
261
262 MemberFunctionRecord MemberFunction(TypeIndex(MemberDescriptor.ReturnType),
263 TypeIndex(MemberDescriptor.ContainingClass),
264 TypeIndex(MemberDescriptor.TypeIndexOfThisPointer),
265 CallingConvention(MemberDescriptor.CallingConvention),
266 FunctionOptions::None, MemberDescriptor.NumberOfArguments,
267 ArgumentList,
268 MemberDescriptor.ThisAdjust);
269
270 TypeIndex MemberFunctionIndex = TypeTable.writeKnownType(MemberFunction);
271 return MemberFunctionIndex.getIndex();
272 }
273
GetMemberFunctionId(const MemberFunctionIdTypeDescriptor & MemberIdDescriptor)274 unsigned UserDefinedTypesBuilder::GetMemberFunctionId(const MemberFunctionIdTypeDescriptor& MemberIdDescriptor)
275 {
276 MemberFuncIdRecord MemberFuncId(TypeIndex(MemberIdDescriptor.MemberFunction), TypeIndex(MemberIdDescriptor.ParentClass), MemberIdDescriptor.Name);
277 TypeIndex MemberFuncIdIndex = TypeTable.writeKnownType(MemberFuncId);
278 return MemberFuncIdIndex.getIndex();
279 }
280
AddBaseClass(FieldListRecordBuilder & FLBR,unsigned BaseClassId)281 void UserDefinedTypesBuilder::AddBaseClass(FieldListRecordBuilder &FLBR,
282 unsigned BaseClassId) {
283 MemberAttributes def;
284 TypeIndex BaseTypeIndex(BaseClassId);
285 BaseClassRecord BCR(def, BaseTypeIndex, 0);
286 FLBR.writeMemberType(BCR);
287 }
288
AddClassVTShape(FieldListRecordBuilder & FLBR)289 void UserDefinedTypesBuilder::AddClassVTShape(FieldListRecordBuilder &FLBR) {
290 VFPtrRecord VfPtr(ClassVTableTypeIndex);
291 FLBR.writeMemberType(VfPtr);
292 }
293
GetLengthName(unsigned index)294 const char *ArrayDimensionsDescriptor::GetLengthName(unsigned index) {
295 if (Lengths.size() <= index) {
296 Resize(index + 1);
297 }
298 return Lengths[index].c_str();
299 }
300
GetBoundsName(unsigned index)301 const char *ArrayDimensionsDescriptor::GetBoundsName(unsigned index) {
302 if (Bounds.size() <= index) {
303 Resize(index);
304 }
305 return Bounds[index].c_str();
306 }
307
Resize(unsigned NewSize)308 void ArrayDimensionsDescriptor::Resize(unsigned NewSize) {
309 unsigned OldSize = Lengths.size();
310 assert(OldSize == Bounds.size());
311 Lengths.resize(NewSize);
312 Bounds.resize(NewSize);
313 for (unsigned i = OldSize; i < NewSize; ++i) {
314 std::stringstream ss;
315 ss << "length" << i;
316 ss >> Lengths[i];
317 ss.clear();
318 ss << "bounds" << i;
319 ss >> Bounds[i];
320 }
321 }
322