]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / DebugInfo / CodeView / TypeRecordMapping.cpp
1 //===- TypeRecordMapping.cpp ------------------------------------*- 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 #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
11
12 using namespace llvm;
13 using namespace llvm::codeview;
14
15 #define error(X)                                                               \
16   if (auto EC = X)                                                             \
17     return EC;
18
19 namespace {
20 struct MapOneMethodRecord {
21   explicit MapOneMethodRecord(bool IsFromOverloadList)
22       : IsFromOverloadList(IsFromOverloadList) {}
23
24   Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
25     error(IO.mapInteger(Method.Attrs.Attrs));
26     if (IsFromOverloadList) {
27       uint16_t Padding = 0;
28       error(IO.mapInteger(Padding));
29     }
30     error(IO.mapInteger(Method.Type));
31     if (Method.isIntroducingVirtual()) {
32       error(IO.mapInteger(Method.VFTableOffset));
33     } else if (!IO.isWriting())
34       Method.VFTableOffset = -1;
35
36     if (!IsFromOverloadList)
37       error(IO.mapStringZ(Method.Name));
38
39     return Error::success();
40   }
41
42 private:
43   bool IsFromOverloadList;
44 };
45 }
46
47 static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name,
48                                   StringRef &UniqueName, bool HasUniqueName) {
49   if (IO.isWriting()) {
50     // Try to be smart about what we write here.  We can't write anything too
51     // large, so if we're going to go over the limit, truncate both the name
52     // and unique name by the same amount.
53     size_t BytesLeft = IO.maxFieldLength();
54     if (HasUniqueName) {
55       size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
56       StringRef N = Name;
57       StringRef U = UniqueName;
58       if (BytesNeeded > BytesLeft) {
59         size_t BytesToDrop = (BytesNeeded - BytesLeft);
60         size_t DropN = std::min(N.size(), BytesToDrop / 2);
61         size_t DropU = std::min(U.size(), BytesToDrop - DropN);
62
63         N = N.drop_back(DropN);
64         U = U.drop_back(DropU);
65       }
66
67       error(IO.mapStringZ(N));
68       error(IO.mapStringZ(U));
69     } else {
70       // Cap the length of the string at however many bytes we have available,
71       // plus one for the required null terminator.
72       auto N = StringRef(Name).take_front(BytesLeft - 1);
73       error(IO.mapStringZ(N));
74     }
75   } else {
76     error(IO.mapStringZ(Name));
77     if (HasUniqueName)
78       error(IO.mapStringZ(UniqueName));
79   }
80
81   return Error::success();
82 }
83
84 Error TypeRecordMapping::visitTypeBegin(CVType &CVR) {
85   assert(!TypeKind.hasValue() && "Already in a type mapping!");
86   assert(!MemberKind.hasValue() && "Already in a member mapping!");
87
88   // FieldList and MethodList records can be any length because they can be
89   // split with continuation records.  All other record types cannot be
90   // longer than the maximum record length.
91   Optional<uint32_t> MaxLen;
92   if (CVR.Type != TypeLeafKind::LF_FIELDLIST &&
93       CVR.Type != TypeLeafKind::LF_METHODLIST)
94     MaxLen = MaxRecordLength - sizeof(RecordPrefix);
95   error(IO.beginRecord(MaxLen));
96   TypeKind = CVR.Type;
97   return Error::success();
98 }
99
100 Error TypeRecordMapping::visitTypeEnd(CVType &Record) {
101   assert(TypeKind.hasValue() && "Not in a type mapping!");
102   assert(!MemberKind.hasValue() && "Still in a member mapping!");
103
104   error(IO.endRecord());
105
106   TypeKind.reset();
107   return Error::success();
108 }
109
110 Error TypeRecordMapping::visitMemberBegin(CVMemberRecord &Record) {
111   assert(TypeKind.hasValue() && "Not in a type mapping!");
112   assert(!MemberKind.hasValue() && "Already in a member mapping!");
113
114   // The largest possible subrecord is one in which there is a record prefix,
115   // followed by the subrecord, followed by a continuation, and that entire
116   // sequence spaws `MaxRecordLength` bytes.  So the record's length is
117   // calculated as follows.
118   constexpr uint32_t ContinuationLength = 8;
119   error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
120                        ContinuationLength));
121
122   MemberKind = Record.Kind;
123   return Error::success();
124 }
125
126 Error TypeRecordMapping::visitMemberEnd(CVMemberRecord &Record) {
127   assert(TypeKind.hasValue() && "Not in a type mapping!");
128   assert(MemberKind.hasValue() && "Not in a member mapping!");
129
130   if (!IO.isWriting()) {
131     if (auto EC = IO.skipPadding())
132       return EC;
133   }
134
135   MemberKind.reset();
136   error(IO.endRecord());
137   return Error::success();
138 }
139
140 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
141   error(IO.mapInteger(Record.ModifiedType));
142   error(IO.mapEnum(Record.Modifiers));
143
144   return Error::success();
145 }
146
147 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
148                                           ProcedureRecord &Record) {
149   error(IO.mapInteger(Record.ReturnType));
150   error(IO.mapEnum(Record.CallConv));
151   error(IO.mapEnum(Record.Options));
152   error(IO.mapInteger(Record.ParameterCount));
153   error(IO.mapInteger(Record.ArgumentList));
154
155   return Error::success();
156 }
157
158 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
159                                           MemberFunctionRecord &Record) {
160   error(IO.mapInteger(Record.ReturnType));
161   error(IO.mapInteger(Record.ClassType));
162   error(IO.mapInteger(Record.ThisType));
163   error(IO.mapEnum(Record.CallConv));
164   error(IO.mapEnum(Record.Options));
165   error(IO.mapInteger(Record.ParameterCount));
166   error(IO.mapInteger(Record.ArgumentList));
167   error(IO.mapInteger(Record.ThisPointerAdjustment));
168
169   return Error::success();
170 }
171
172 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
173   error(IO.mapVectorN<uint32_t>(
174       Record.ArgIndices,
175       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
176
177   return Error::success();
178 }
179
180 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
181                                           StringListRecord &Record) {
182   error(IO.mapVectorN<uint32_t>(
183       Record.StringIndices,
184       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
185
186   return Error::success();
187 }
188
189 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
190   error(IO.mapInteger(Record.ReferentType));
191   error(IO.mapInteger(Record.Attrs));
192
193   if (Record.isPointerToMember()) {
194     if (!IO.isWriting())
195       Record.MemberInfo.emplace();
196
197     MemberPointerInfo &M = *Record.MemberInfo;
198     error(IO.mapInteger(M.ContainingType));
199     error(IO.mapEnum(M.Representation));
200   }
201
202   return Error::success();
203 }
204
205 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
206   error(IO.mapInteger(Record.ElementType));
207   error(IO.mapInteger(Record.IndexType));
208   error(IO.mapEncodedInteger(Record.Size));
209   error(IO.mapStringZ(Record.Name));
210
211   return Error::success();
212 }
213
214 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
215   assert((CVR.Type == TypeLeafKind::LF_STRUCTURE) ||
216          (CVR.Type == TypeLeafKind::LF_CLASS) ||
217          (CVR.Type == TypeLeafKind::LF_INTERFACE));
218
219   error(IO.mapInteger(Record.MemberCount));
220   error(IO.mapEnum(Record.Options));
221   error(IO.mapInteger(Record.FieldList));
222   error(IO.mapInteger(Record.DerivationList));
223   error(IO.mapInteger(Record.VTableShape));
224   error(IO.mapEncodedInteger(Record.Size));
225   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
226                              Record.hasUniqueName()));
227
228   return Error::success();
229 }
230
231 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
232   error(IO.mapInteger(Record.MemberCount));
233   error(IO.mapEnum(Record.Options));
234   error(IO.mapInteger(Record.FieldList));
235   error(IO.mapEncodedInteger(Record.Size));
236   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
237                              Record.hasUniqueName()));
238
239   return Error::success();
240 }
241
242 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
243   error(IO.mapInteger(Record.MemberCount));
244   error(IO.mapEnum(Record.Options));
245   error(IO.mapInteger(Record.UnderlyingType));
246   error(IO.mapInteger(Record.FieldList));
247   error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
248                              Record.hasUniqueName()));
249
250   return Error::success();
251 }
252
253 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
254   error(IO.mapInteger(Record.Type));
255   error(IO.mapInteger(Record.BitSize));
256   error(IO.mapInteger(Record.BitOffset));
257
258   return Error::success();
259 }
260
261 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
262                                           VFTableShapeRecord &Record) {
263   uint16_t Size;
264   if (IO.isWriting()) {
265     ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
266     Size = Slots.size();
267     error(IO.mapInteger(Size));
268
269     for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
270       uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
271       if ((SlotIndex + 1) < Slots.size()) {
272         Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
273       }
274       error(IO.mapInteger(Byte));
275     }
276   } else {
277     error(IO.mapInteger(Size));
278     for (uint16_t I = 0; I < Size; I += 2) {
279       uint8_t Byte;
280       error(IO.mapInteger(Byte));
281       Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
282       if ((I + 1) < Size)
283         Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
284     }
285   }
286
287   return Error::success();
288 }
289
290 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
291   error(IO.mapInteger(Record.CompleteClass));
292   error(IO.mapInteger(Record.OverriddenVFTable));
293   error(IO.mapInteger(Record.VFPtrOffset));
294   uint32_t NamesLen = 0;
295   if (IO.isWriting()) {
296     for (auto Name : Record.MethodNames)
297       NamesLen += Name.size() + 1;
298   }
299   error(IO.mapInteger(NamesLen));
300   error(IO.mapVectorTail(
301       Record.MethodNames,
302       [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
303
304   return Error::success();
305 }
306
307 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
308   error(IO.mapInteger(Record.Id));
309   error(IO.mapStringZ(Record.String));
310
311   return Error::success();
312 }
313
314 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
315                                           UdtSourceLineRecord &Record) {
316   error(IO.mapInteger(Record.UDT));
317   error(IO.mapInteger(Record.SourceFile));
318   error(IO.mapInteger(Record.LineNumber));
319
320   return Error::success();
321 }
322
323 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
324                                           UdtModSourceLineRecord &Record) {
325   error(IO.mapInteger(Record.UDT));
326   error(IO.mapInteger(Record.SourceFile));
327   error(IO.mapInteger(Record.LineNumber));
328   error(IO.mapInteger(Record.Module));
329
330   return Error::success();
331 }
332
333 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
334   error(IO.mapInteger(Record.ParentScope));
335   error(IO.mapInteger(Record.FunctionType));
336   error(IO.mapStringZ(Record.Name));
337
338   return Error::success();
339 }
340
341 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
342                                           MemberFuncIdRecord &Record) {
343   error(IO.mapInteger(Record.ClassType));
344   error(IO.mapInteger(Record.FunctionType));
345   error(IO.mapStringZ(Record.Name));
346
347   return Error::success();
348 }
349
350 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
351                                           BuildInfoRecord &Record) {
352   error(IO.mapVectorN<uint16_t>(
353       Record.ArgIndices,
354       [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
355
356   return Error::success();
357 }
358
359 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
360                                           MethodOverloadListRecord &Record) {
361   // TODO: Split the list into multiple records if it's longer than 64KB, using
362   // a subrecord of TypeRecordKind::Index to chain the records together.
363   error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
364
365   return Error::success();
366 }
367
368 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
369                                           FieldListRecord &Record) {
370   error(IO.mapByteVectorTail(Record.Data));
371
372   return Error::success();
373 }
374
375 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
376                                           TypeServer2Record &Record) {
377   error(IO.mapGuid(Record.Guid));
378   error(IO.mapInteger(Record.Age));
379   error(IO.mapStringZ(Record.Name));
380   return Error::success();
381 }
382
383 Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
384   error(IO.mapEnum(Record.Mode));
385   return Error::success();
386 }
387
388 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
389                                           BaseClassRecord &Record) {
390   error(IO.mapInteger(Record.Attrs.Attrs));
391   error(IO.mapInteger(Record.Type));
392   error(IO.mapEncodedInteger(Record.Offset));
393
394   return Error::success();
395 }
396
397 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
398                                           EnumeratorRecord &Record) {
399   error(IO.mapInteger(Record.Attrs.Attrs));
400
401   // FIXME: Handle full APInt such as __int128.
402   error(IO.mapEncodedInteger(Record.Value));
403   error(IO.mapStringZ(Record.Name));
404
405   return Error::success();
406 }
407
408 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
409                                           DataMemberRecord &Record) {
410   error(IO.mapInteger(Record.Attrs.Attrs));
411   error(IO.mapInteger(Record.Type));
412   error(IO.mapEncodedInteger(Record.FieldOffset));
413   error(IO.mapStringZ(Record.Name));
414
415   return Error::success();
416 }
417
418 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
419                                           OverloadedMethodRecord &Record) {
420   error(IO.mapInteger(Record.NumOverloads));
421   error(IO.mapInteger(Record.MethodList));
422   error(IO.mapStringZ(Record.Name));
423
424   return Error::success();
425 }
426
427 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
428                                           OneMethodRecord &Record) {
429   const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
430   MapOneMethodRecord Mapper(IsFromOverloadList);
431   return Mapper(IO, Record);
432 }
433
434 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
435                                           NestedTypeRecord &Record) {
436   uint16_t Padding = 0;
437   error(IO.mapInteger(Padding));
438   error(IO.mapInteger(Record.Type));
439   error(IO.mapStringZ(Record.Name));
440
441   return Error::success();
442 }
443
444 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
445                                           StaticDataMemberRecord &Record) {
446
447   error(IO.mapInteger(Record.Attrs.Attrs));
448   error(IO.mapInteger(Record.Type));
449   error(IO.mapStringZ(Record.Name));
450
451   return Error::success();
452 }
453
454 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
455                                           VirtualBaseClassRecord &Record) {
456
457   error(IO.mapInteger(Record.Attrs.Attrs));
458   error(IO.mapInteger(Record.BaseType));
459   error(IO.mapInteger(Record.VBPtrType));
460   error(IO.mapEncodedInteger(Record.VBPtrOffset));
461   error(IO.mapEncodedInteger(Record.VTableIndex));
462
463   return Error::success();
464 }
465
466 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
467                                           VFPtrRecord &Record) {
468   uint16_t Padding = 0;
469   error(IO.mapInteger(Padding));
470   error(IO.mapInteger(Record.Type));
471
472   return Error::success();
473 }
474
475 Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
476                                           ListContinuationRecord &Record) {
477   uint16_t Padding = 0;
478   error(IO.mapInteger(Padding));
479   error(IO.mapInteger(Record.ContinuationIndex));
480
481   return Error::success();
482 }
483
484 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
485                                           PrecompRecord &Precomp) {
486   error(IO.mapInteger(Precomp.StartTypeIndex));
487   error(IO.mapInteger(Precomp.TypesCount));
488   error(IO.mapInteger(Precomp.Signature));
489   error(IO.mapStringZ(Precomp.PrecompFilePath));
490   return Error::success();
491 }
492
493 Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
494                                           EndPrecompRecord &EndPrecomp) {
495   error(IO.mapInteger(EndPrecomp.Signature));
496   return Error::success();
497 }