LLVM  10.0.0svn
TypeRecordMapping.cpp
Go to the documentation of this file.
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 
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 
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 
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 
103  return visitTypeBegin(CVR);
104 }
105 
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 
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 
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 
147  error(IO.mapInteger(Record.ModifiedType, "ModifiedType"));
148  error(IO.mapEnum(Record.Modifiers, "Modifiers"));
149  return Error::success();
150 }
151 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
321  error(IO.mapInteger(Record.Id, "Id"));
322  error(IO.mapStringZ(Record.String, "StringData"));
323 
324  return Error::success();
325 }
326 
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 
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 
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 
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 
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 
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 
385  FieldListRecord &Record) {
386  error(IO.mapByteVectorTail(Record.Data));
387 
388  return Error::success();
389 }
390 
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 
400  error(IO.mapEnum(Record.Mode, "Mode"));
401  return Error::success();
402 }
403 
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 
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 
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 
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 
444  OneMethodRecord &Record) {
445  const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
446  MapOneMethodRecord Mapper(IsFromOverloadList);
447  return Mapper(IO, Record);
448 }
449 
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 
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 
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 
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 
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 
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 
510  EndPrecompRecord &EndPrecomp) {
511  error(IO.mapInteger(EndPrecomp.Signature, "Signature"));
512  return Error::success();
513 }
LLVM_NODISCARD StringRef take_front(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with only the first N elements remaining.
Definition: StringRef.h:587
Kind kind() const
Definition: CVRecord.h:43
This class represents lattice values for constants.
Definition: AllocatorList.h:23
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
#define error(X)
ArrayRef< uint8_t > Data
Definition: TypeRecord.h:397
Error visitMemberEnd(CVMemberRecord &Record) override
bool hasUniqueName() const
Definition: TypeRecord.h:436
Error visitTypeEnd(CVType &Record) override
static Error visitKnownRecord(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
A 32-bit type reference.
Definition: TypeIndex.h:95
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:130
std::vector< TypeIndex > StringIndices
Definition: TypeRecord.h:265
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:148
Optional< MemberPointerInfo > MemberInfo
Definition: TypeRecord.h:355
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition: TypeRecord.h:920
std::vector< TypeIndex > ArgIndices
Definition: TypeRecord.h:251
For method overload sets. LF_METHOD.
Definition: TypeRecord.h:770
std::vector< StringRef > MethodNames
Definition: TypeRecord.h:721
static constexpr uint32_t ContinuationLength
Error mapInteger(TypeIndex &TypeInd, const Twine &Comment="")
static ErrorSuccess success()
Create a success value.
Definition: Error.h:326
static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName)
CallingConvention CallConv
Definition: TypeRecord.h:169
Error mapStringZ(StringRef &Value, const Twine &Comment="")
std::vector< OneMethodRecord > Methods
Definition: TypeRecord.h:766
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
uint32_t Size
Definition: Profile.cpp:46
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< VFTableSlotKind > Slots
Definition: TypeRecord.h:576
ArrayRef< VFTableSlotKind > getSlots() const
Definition: TypeRecord.h:567
LLVM_NODISCARD StringRef drop_back(size_t N=1) const
Return a StringRef equal to &#39;this&#39; but with the last N elements dropped.
Definition: StringRef.h:628
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:83
SmallVector< TypeIndex, MaxArgs > ArgIndices
Definition: TypeRecord.h:692
Error visitMemberBegin(CVMemberRecord &Record) override
PointerToMemberRepresentation Representation
Definition: TypeRecord.h:120