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