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