LLVM  8.0.1
TypeRecordMapping.cpp
Go to the documentation of this file.
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 
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 
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 
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 
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 
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 
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 
141  error(IO.mapInteger(Record.ModifiedType));
142  error(IO.mapEnum(Record.Modifiers));
143 
144  return Error::success();
145 }
146 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
308  error(IO.mapInteger(Record.Id));
309  error(IO.mapStringZ(Record.String));
310 
311  return Error::success();
312 }
313 
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 
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 
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 
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 
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 
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 
369  FieldListRecord &Record) {
370  error(IO.mapByteVectorTail(Record.Data));
371 
372  return Error::success();
373 }
374 
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 
384  error(IO.mapEnum(Record.Mode));
385  return Error::success();
386 }
387 
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 
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 
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 
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 
428  OneMethodRecord &Record) {
429  const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
430  MapOneMethodRecord Mapper(IsFromOverloadList);
431  return Mapper(IO, Record);
432 }
433 
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 
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 
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 
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 
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 
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 
494  EndPrecompRecord &EndPrecomp) {
495  error(IO.mapInteger(EndPrecomp.Signature));
496  return Error::success();
497 }
This class represents lattice values for constants.
Definition: AllocatorList.h:24
Error mapInteger(TypeIndex &TypeInd)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Definition: StringRef.h:138
#define error(X)
ArrayRef< uint8_t > Data
Definition: TypeRecord.h:398
Error visitMemberEnd(CVMemberRecord &Record) override
bool hasUniqueName() const
Definition: TypeRecord.h:437
amdgpu Simplify well known AMD library false Value Value const Twine & Name
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:96
std::vector< TypeIndex > StringIndices
Definition: TypeRecord.h:266
* 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:149
Optional< MemberPointerInfo > MemberInfo
Definition: TypeRecord.h:356
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition: TypeRecord.h:921
std::vector< TypeIndex > ArgIndices
Definition: TypeRecord.h:252
For method overload sets. LF_METHOD.
Definition: TypeRecord.h:771
std::vector< StringRef > MethodNames
Definition: TypeRecord.h:722
static constexpr uint32_t ContinuationLength
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE 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:654
static ErrorSuccess success()
Create a success value.
Definition: Error.h:327
static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName)
CallingConvention CallConv
Definition: TypeRecord.h:170
std::vector< OneMethodRecord > Methods
Definition: TypeRecord.h:767
#define I(x, y, z)
Definition: MD5.cpp:58
#define N
uint32_t Size
Definition: Profile.cpp:47
Error mapStringZ(StringRef &Value)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::vector< VFTableSlotKind > Slots
Definition: TypeRecord.h:577
ArrayRef< VFTableSlotKind > getSlots() const
Definition: TypeRecord.h:568
Lightweight error class with error context and mandatory checking.
Definition: Error.h:158
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE 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:608
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:84
SmallVector< TypeIndex, MaxArgs > ArgIndices
Definition: TypeRecord.h:693
Error visitMemberBegin(CVMemberRecord &Record) override
PointerToMemberRepresentation Representation
Definition: TypeRecord.h:121