LLVM  9.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));
25  if (IsFromOverloadList) {
26  uint16_t Padding = 0;
27  error(IO.mapInteger(Padding));
28  }
29  error(IO.mapInteger(Method.Type));
30  if (Method.isIntroducingVirtual()) {
31  error(IO.mapInteger(Method.VFTableOffset));
32  } else if (!IO.isWriting())
33  Method.VFTableOffset = -1;
34 
35  if (!IsFromOverloadList)
36  error(IO.mapStringZ(Method.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  error(IO.mapStringZ(Name));
76  if (HasUniqueName)
77  error(IO.mapStringZ(UniqueName));
78  }
79 
80  return Error::success();
81 }
82 
84  assert(!TypeKind.hasValue() && "Already in a type mapping!");
85  assert(!MemberKind.hasValue() && "Already in a member mapping!");
86 
87  // FieldList and MethodList records can be any length because they can be
88  // split with continuation records. All other record types cannot be
89  // longer than the maximum record length.
90  Optional<uint32_t> MaxLen;
91  if (CVR.kind() != TypeLeafKind::LF_FIELDLIST &&
92  CVR.kind() != TypeLeafKind::LF_METHODLIST)
93  MaxLen = MaxRecordLength - sizeof(RecordPrefix);
94  error(IO.beginRecord(MaxLen));
95  TypeKind = CVR.kind();
96  return Error::success();
97 }
98 
100  assert(TypeKind.hasValue() && "Not in a type mapping!");
101  assert(!MemberKind.hasValue() && "Still in a member mapping!");
102 
103  error(IO.endRecord());
104 
105  TypeKind.reset();
106  return Error::success();
107 }
108 
110  assert(TypeKind.hasValue() && "Not in a type mapping!");
111  assert(!MemberKind.hasValue() && "Already in a member mapping!");
112 
113  // The largest possible subrecord is one in which there is a record prefix,
114  // followed by the subrecord, followed by a continuation, and that entire
115  // sequence spaws `MaxRecordLength` bytes. So the record's length is
116  // calculated as follows.
117  constexpr uint32_t ContinuationLength = 8;
118  error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
119  ContinuationLength));
120 
121  MemberKind = Record.Kind;
122  return Error::success();
123 }
124 
126  assert(TypeKind.hasValue() && "Not in a type mapping!");
127  assert(MemberKind.hasValue() && "Not in a member mapping!");
128 
129  if (!IO.isWriting()) {
130  if (auto EC = IO.skipPadding())
131  return EC;
132  }
133 
134  MemberKind.reset();
135  error(IO.endRecord());
136  return Error::success();
137 }
138 
140  error(IO.mapInteger(Record.ModifiedType));
141  error(IO.mapEnum(Record.Modifiers));
142 
143  return Error::success();
144 }
145 
147  ProcedureRecord &Record) {
148  error(IO.mapInteger(Record.ReturnType));
149  error(IO.mapEnum(Record.CallConv));
150  error(IO.mapEnum(Record.Options));
151  error(IO.mapInteger(Record.ParameterCount));
152  error(IO.mapInteger(Record.ArgumentList));
153 
154  return Error::success();
155 }
156 
158  MemberFunctionRecord &Record) {
159  error(IO.mapInteger(Record.ReturnType));
160  error(IO.mapInteger(Record.ClassType));
161  error(IO.mapInteger(Record.ThisType));
162  error(IO.mapEnum(Record.CallConv));
163  error(IO.mapEnum(Record.Options));
164  error(IO.mapInteger(Record.ParameterCount));
165  error(IO.mapInteger(Record.ArgumentList));
166  error(IO.mapInteger(Record.ThisPointerAdjustment));
167 
168  return Error::success();
169 }
170 
172  error(IO.mapVectorN<uint32_t>(
173  Record.ArgIndices,
174  [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
175 
176  return Error::success();
177 }
178 
180  StringListRecord &Record) {
181  error(IO.mapVectorN<uint32_t>(
182  Record.StringIndices,
183  [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
184 
185  return Error::success();
186 }
187 
189  error(IO.mapInteger(Record.ReferentType));
190  error(IO.mapInteger(Record.Attrs));
191 
192  if (Record.isPointerToMember()) {
193  if (!IO.isWriting())
194  Record.MemberInfo.emplace();
195 
196  MemberPointerInfo &M = *Record.MemberInfo;
197  error(IO.mapInteger(M.ContainingType));
198  error(IO.mapEnum(M.Representation));
199  }
200 
201  return Error::success();
202 }
203 
205  error(IO.mapInteger(Record.ElementType));
206  error(IO.mapInteger(Record.IndexType));
207  error(IO.mapEncodedInteger(Record.Size));
208  error(IO.mapStringZ(Record.Name));
209 
210  return Error::success();
211 }
212 
214  assert((CVR.kind() == TypeLeafKind::LF_STRUCTURE) ||
215  (CVR.kind() == TypeLeafKind::LF_CLASS) ||
216  (CVR.kind() == TypeLeafKind::LF_INTERFACE));
217 
218  error(IO.mapInteger(Record.MemberCount));
219  error(IO.mapEnum(Record.Options));
220  error(IO.mapInteger(Record.FieldList));
221  error(IO.mapInteger(Record.DerivationList));
222  error(IO.mapInteger(Record.VTableShape));
223  error(IO.mapEncodedInteger(Record.Size));
224  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
225  Record.hasUniqueName()));
226 
227  return Error::success();
228 }
229 
231  error(IO.mapInteger(Record.MemberCount));
232  error(IO.mapEnum(Record.Options));
233  error(IO.mapInteger(Record.FieldList));
234  error(IO.mapEncodedInteger(Record.Size));
235  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
236  Record.hasUniqueName()));
237 
238  return Error::success();
239 }
240 
242  error(IO.mapInteger(Record.MemberCount));
243  error(IO.mapEnum(Record.Options));
244  error(IO.mapInteger(Record.UnderlyingType));
245  error(IO.mapInteger(Record.FieldList));
246  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
247  Record.hasUniqueName()));
248 
249  return Error::success();
250 }
251 
253  error(IO.mapInteger(Record.Type));
254  error(IO.mapInteger(Record.BitSize));
255  error(IO.mapInteger(Record.BitOffset));
256 
257  return Error::success();
258 }
259 
261  VFTableShapeRecord &Record) {
262  uint16_t Size;
263  if (IO.isWriting()) {
264  ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
265  Size = Slots.size();
266  error(IO.mapInteger(Size));
267 
268  for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
269  uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
270  if ((SlotIndex + 1) < Slots.size()) {
271  Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
272  }
273  error(IO.mapInteger(Byte));
274  }
275  } else {
276  error(IO.mapInteger(Size));
277  for (uint16_t I = 0; I < Size; I += 2) {
278  uint8_t Byte;
279  error(IO.mapInteger(Byte));
280  Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
281  if ((I + 1) < Size)
282  Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
283  }
284  }
285 
286  return Error::success();
287 }
288 
290  error(IO.mapInteger(Record.CompleteClass));
291  error(IO.mapInteger(Record.OverriddenVFTable));
292  error(IO.mapInteger(Record.VFPtrOffset));
293  uint32_t NamesLen = 0;
294  if (IO.isWriting()) {
295  for (auto Name : Record.MethodNames)
296  NamesLen += Name.size() + 1;
297  }
298  error(IO.mapInteger(NamesLen));
299  error(IO.mapVectorTail(
300  Record.MethodNames,
301  [](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
302 
303  return Error::success();
304 }
305 
307  error(IO.mapInteger(Record.Id));
308  error(IO.mapStringZ(Record.String));
309 
310  return Error::success();
311 }
312 
314  UdtSourceLineRecord &Record) {
315  error(IO.mapInteger(Record.UDT));
316  error(IO.mapInteger(Record.SourceFile));
317  error(IO.mapInteger(Record.LineNumber));
318 
319  return Error::success();
320 }
321 
323  UdtModSourceLineRecord &Record) {
324  error(IO.mapInteger(Record.UDT));
325  error(IO.mapInteger(Record.SourceFile));
326  error(IO.mapInteger(Record.LineNumber));
327  error(IO.mapInteger(Record.Module));
328 
329  return Error::success();
330 }
331 
333  error(IO.mapInteger(Record.ParentScope));
334  error(IO.mapInteger(Record.FunctionType));
335  error(IO.mapStringZ(Record.Name));
336 
337  return Error::success();
338 }
339 
341  MemberFuncIdRecord &Record) {
342  error(IO.mapInteger(Record.ClassType));
343  error(IO.mapInteger(Record.FunctionType));
344  error(IO.mapStringZ(Record.Name));
345 
346  return Error::success();
347 }
348 
350  BuildInfoRecord &Record) {
351  error(IO.mapVectorN<uint16_t>(
352  Record.ArgIndices,
353  [](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
354 
355  return Error::success();
356 }
357 
359  MethodOverloadListRecord &Record) {
360  // TODO: Split the list into multiple records if it's longer than 64KB, using
361  // a subrecord of TypeRecordKind::Index to chain the records together.
362  error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true)));
363 
364  return Error::success();
365 }
366 
368  FieldListRecord &Record) {
369  error(IO.mapByteVectorTail(Record.Data));
370 
371  return Error::success();
372 }
373 
375  TypeServer2Record &Record) {
376  error(IO.mapGuid(Record.Guid));
377  error(IO.mapInteger(Record.Age));
378  error(IO.mapStringZ(Record.Name));
379  return Error::success();
380 }
381 
383  error(IO.mapEnum(Record.Mode));
384  return Error::success();
385 }
386 
388  BaseClassRecord &Record) {
389  error(IO.mapInteger(Record.Attrs.Attrs));
390  error(IO.mapInteger(Record.Type));
391  error(IO.mapEncodedInteger(Record.Offset));
392 
393  return Error::success();
394 }
395 
397  EnumeratorRecord &Record) {
398  error(IO.mapInteger(Record.Attrs.Attrs));
399 
400  // FIXME: Handle full APInt such as __int128.
401  error(IO.mapEncodedInteger(Record.Value));
402  error(IO.mapStringZ(Record.Name));
403 
404  return Error::success();
405 }
406 
408  DataMemberRecord &Record) {
409  error(IO.mapInteger(Record.Attrs.Attrs));
410  error(IO.mapInteger(Record.Type));
411  error(IO.mapEncodedInteger(Record.FieldOffset));
412  error(IO.mapStringZ(Record.Name));
413 
414  return Error::success();
415 }
416 
418  OverloadedMethodRecord &Record) {
419  error(IO.mapInteger(Record.NumOverloads));
420  error(IO.mapInteger(Record.MethodList));
421  error(IO.mapStringZ(Record.Name));
422 
423  return Error::success();
424 }
425 
427  OneMethodRecord &Record) {
428  const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
429  MapOneMethodRecord Mapper(IsFromOverloadList);
430  return Mapper(IO, Record);
431 }
432 
434  NestedTypeRecord &Record) {
435  uint16_t Padding = 0;
436  error(IO.mapInteger(Padding));
437  error(IO.mapInteger(Record.Type));
438  error(IO.mapStringZ(Record.Name));
439 
440  return Error::success();
441 }
442 
444  StaticDataMemberRecord &Record) {
445 
446  error(IO.mapInteger(Record.Attrs.Attrs));
447  error(IO.mapInteger(Record.Type));
448  error(IO.mapStringZ(Record.Name));
449 
450  return Error::success();
451 }
452 
454  VirtualBaseClassRecord &Record) {
455 
456  error(IO.mapInteger(Record.Attrs.Attrs));
457  error(IO.mapInteger(Record.BaseType));
458  error(IO.mapInteger(Record.VBPtrType));
459  error(IO.mapEncodedInteger(Record.VBPtrOffset));
460  error(IO.mapEncodedInteger(Record.VTableIndex));
461 
462  return Error::success();
463 }
464 
466  VFPtrRecord &Record) {
467  uint16_t Padding = 0;
468  error(IO.mapInteger(Padding));
469  error(IO.mapInteger(Record.Type));
470 
471  return Error::success();
472 }
473 
475  ListContinuationRecord &Record) {
476  uint16_t Padding = 0;
477  error(IO.mapInteger(Padding));
478  error(IO.mapInteger(Record.ContinuationIndex));
479 
480  return Error::success();
481 }
482 
484  PrecompRecord &Precomp) {
485  error(IO.mapInteger(Precomp.StartTypeIndex));
486  error(IO.mapInteger(Precomp.TypesCount));
487  error(IO.mapInteger(Precomp.Signature));
488  error(IO.mapStringZ(Precomp.PrecompFilePath));
489  return Error::success();
490 }
491 
493  EndPrecompRecord &EndPrecomp) {
494  error(IO.mapInteger(EndPrecomp.Signature));
495  return Error::success();
496 }
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
Error mapInteger(TypeIndex &TypeInd)
#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
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
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
Error mapStringZ(StringRef &Value)
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