LLVM  15.0.0git
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 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Support/MD5.h"
25 
26 #include <algorithm>
27 #include <cassert>
28 #include <cstddef>
29 #include <cstdint>
30 #include <string>
31 #include <vector>
32 
33 using namespace llvm;
34 using namespace llvm::codeview;
35 
36 namespace {
37 
38 #define error(X) \
39  if (auto EC = X) \
40  return EC;
41 
42 static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
43 #define CV_TYPE(enum, val) {#enum, enum},
44 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
45 };
46 
48  switch (LT) {
49 #define TYPE_RECORD(ename, value, name) \
50  case ename: \
51  return #name;
52 #include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
53  default:
54  break;
55  }
56  return "UnknownLeaf";
57 }
58 
59 template <typename T>
60 static bool compEnumNames(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
61  return lhs.Name < rhs.Name;
62 }
63 
64 template <typename T, typename TFlag>
65 static std::string getFlagNames(CodeViewRecordIO &IO, T Value,
66  ArrayRef<EnumEntry<TFlag>> Flags) {
67  if (!IO.isStreaming())
68  return std::string("");
70  typedef SmallVector<FlagEntry, 10> FlagVector;
71  FlagVector SetFlags;
72  for (const auto &Flag : Flags) {
73  if (Flag.Value == 0)
74  continue;
75  if ((Value & Flag.Value) == Flag.Value) {
76  SetFlags.push_back(Flag);
77  }
78  }
79 
80  llvm::sort(SetFlags, &compEnumNames<TFlag>);
81 
82  std::string FlagLabel;
83  bool FirstOcc = true;
84  for (const auto &Flag : SetFlags) {
85  if (FirstOcc)
86  FirstOcc = false;
87  else
88  FlagLabel += (" | ");
89 
90  FlagLabel += (Flag.Name.str() + " (0x" + utohexstr(Flag.Value) + ")");
91  }
92 
93  if (!FlagLabel.empty()) {
94  std::string LabelWithBraces(" ( ");
95  LabelWithBraces += FlagLabel + " )";
96  return LabelWithBraces;
97  } else
98  return FlagLabel;
99 }
100 
101 template <typename T, typename TEnum>
102 static StringRef getEnumName(CodeViewRecordIO &IO, T Value,
103  ArrayRef<EnumEntry<TEnum>> EnumValues) {
104  if (!IO.isStreaming())
105  return "";
106  StringRef Name;
107  for (const auto &EnumItem : EnumValues) {
108  if (EnumItem.Value == Value) {
109  Name = EnumItem.Name;
110  break;
111  }
112  }
113 
114  return Name;
115 }
116 
117 static std::string getMemberAttributes(CodeViewRecordIO &IO,
118  MemberAccess Access, MethodKind Kind,
120  if (!IO.isStreaming())
121  return "";
122  std::string AccessSpecifier = std::string(
123  getEnumName(IO, uint8_t(Access), makeArrayRef(getMemberAccessNames())));
124  std::string MemberAttrs(AccessSpecifier);
125  if (Kind != MethodKind::Vanilla) {
126  std::string MethodKind = std::string(
127  getEnumName(IO, unsigned(Kind), makeArrayRef(getMemberKindNames())));
128  MemberAttrs += ", " + MethodKind;
129  }
130  if (Options != MethodOptions::None) {
131  std::string MethodOptions = getFlagNames(
132  IO, unsigned(Options), makeArrayRef(getMethodOptionNames()));
133  MemberAttrs += ", " + MethodOptions;
134  }
135  return MemberAttrs;
136 }
137 
138 struct MapOneMethodRecord {
139  explicit MapOneMethodRecord(bool IsFromOverloadList)
140  : IsFromOverloadList(IsFromOverloadList) {}
141 
142  Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
143  std::string Attrs = getMemberAttributes(
144  IO, Method.getAccess(), Method.getMethodKind(), Method.getOptions());
145  error(IO.mapInteger(Method.Attrs.Attrs, "Attrs: " + Attrs));
146  if (IsFromOverloadList) {
147  uint16_t Padding = 0;
148  error(IO.mapInteger(Padding));
149  }
150  error(IO.mapInteger(Method.Type, "Type"));
151  if (Method.isIntroducingVirtual()) {
152  error(IO.mapInteger(Method.VFTableOffset, "VFTableOffset"));
153  } else if (IO.isReading())
154  Method.VFTableOffset = -1;
155 
156  if (!IsFromOverloadList)
157  error(IO.mapStringZ(Method.Name, "Name"));
158 
159  return Error::success();
160  }
161 
162 private:
163  bool IsFromOverloadList;
164 };
165 } // namespace
166 
167 // Computes a string representation of a hash of the specified name, suitable
168 // for use when emitting CodeView type names.
170  SmallString<32> &StringifiedHash) {
171  llvm::MD5 Hash;
172  llvm::MD5::MD5Result Result;
173  Hash.update(Name);
174  Hash.final(Result);
175  Hash.stringifyResult(Result, StringifiedHash);
176 }
177 
179  StringRef &UniqueName, bool HasUniqueName) {
180  if (IO.isWriting()) {
181  // Try to be smart about what we write here. We can't write anything too
182  // large, so if we're going to go over the limit, replace lengthy names with
183  // a stringified hash value.
184  size_t BytesLeft = IO.maxFieldLength();
185  if (HasUniqueName) {
186  size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
187  if (BytesNeeded > BytesLeft) {
188  // The minimum space required for emitting hashes of both names.
189  assert(BytesLeft >= 70);
190 
191  // Replace the entire unique name with a hash of the unique name.
192  SmallString<32> Hash;
193  computeHashString(UniqueName, Hash);
194  std::string UniqueB = Twine("??@" + Hash + "@").str();
195  assert(UniqueB.size() == 36);
196 
197  // Truncate the name if necessary and append a hash of the name.
198  // The name length, hash included, is limited to 4096 bytes.
199  const size_t MaxTakeN = 4096;
200  size_t TakeN = std::min(MaxTakeN, BytesLeft - UniqueB.size() - 2) - 32;
201  computeHashString(Name, Hash);
202  std::string NameB = (Name.take_front(TakeN) + Hash).str();
203 
204  StringRef N = NameB;
205  StringRef U = UniqueB;
206  error(IO.mapStringZ(N));
207  error(IO.mapStringZ(U));
208  } else {
209  error(IO.mapStringZ(Name));
210  error(IO.mapStringZ(UniqueName));
211  }
212  } else {
213  // Cap the length of the string at however many bytes we have available,
214  // plus one for the required null terminator.
215  auto N = StringRef(Name).take_front(BytesLeft - 1);
216  error(IO.mapStringZ(N));
217  }
218  } else {
219  // Reading & Streaming mode come after writing mode is executed for each
220  // record. Truncating large names are done during writing, so its not
221  // necessary to do it while reading or streaming.
222  error(IO.mapStringZ(Name, "Name"));
223  if (HasUniqueName)
224  error(IO.mapStringZ(UniqueName, "LinkageName"));
225  }
226 
227  return Error::success();
228 }
229 
231  assert(!TypeKind.hasValue() && "Already in a type mapping!");
232  assert(!MemberKind.hasValue() && "Already in a member mapping!");
233 
234  // FieldList and MethodList records can be any length because they can be
235  // split with continuation records. All other record types cannot be
236  // longer than the maximum record length.
237  Optional<uint32_t> MaxLen;
238  if (CVR.kind() != TypeLeafKind::LF_FIELDLIST &&
239  CVR.kind() != TypeLeafKind::LF_METHODLIST)
240  MaxLen = MaxRecordLength - sizeof(RecordPrefix);
241  error(IO.beginRecord(MaxLen));
242  TypeKind = CVR.kind();
243 
244  if (IO.isStreaming()) {
245  auto RecordKind = CVR.kind();
246  uint16_t RecordLen = CVR.length() - 2;
247  std::string RecordKindName = std::string(
248  getEnumName(IO, unsigned(RecordKind), makeArrayRef(LeafTypeNames)));
249  error(IO.mapInteger(RecordLen, "Record length"));
250  error(IO.mapEnum(RecordKind, "Record kind: " + RecordKindName));
251  }
252  return Error::success();
253 }
254 
256  if (IO.isStreaming())
257  IO.emitRawComment(" " + getLeafTypeName(CVR.kind()) + " (0x" +
258  utohexstr(Index.getIndex()) + ")");
259  return visitTypeBegin(CVR);
260 }
261 
263  assert(TypeKind.hasValue() && "Not in a type mapping!");
264  assert(!MemberKind.hasValue() && "Still in a member mapping!");
265 
266  error(IO.endRecord());
267 
268  TypeKind.reset();
269  return Error::success();
270 }
271 
273  assert(TypeKind.hasValue() && "Not in a type mapping!");
274  assert(!MemberKind.hasValue() && "Already in a member mapping!");
275 
276  // The largest possible subrecord is one in which there is a record prefix,
277  // followed by the subrecord, followed by a continuation, and that entire
278  // sequence spawns `MaxRecordLength` bytes. So the record's length is
279  // calculated as follows.
280 
281  constexpr uint32_t ContinuationLength = 8;
284 
285  MemberKind = Record.Kind;
286  if (IO.isStreaming()) {
287  std::string MemberKindName = std::string(getLeafTypeName(Record.Kind));
288  MemberKindName +=
289  " ( " +
290  (getEnumName(IO, unsigned(Record.Kind), makeArrayRef(LeafTypeNames)))
291  .str() +
292  " )";
293  error(IO.mapEnum(Record.Kind, "Member kind: " + MemberKindName));
294  }
295  return Error::success();
296 }
297 
299  assert(TypeKind.hasValue() && "Not in a type mapping!");
300  assert(MemberKind.hasValue() && "Not in a member mapping!");
301 
302  if (IO.isReading()) {
303  if (auto EC = IO.skipPadding())
304  return EC;
305  }
306 
307  MemberKind.reset();
308  error(IO.endRecord());
309  return Error::success();
310 }
311 
313  std::string ModifierNames =
314  getFlagNames(IO, static_cast<uint16_t>(Record.Modifiers),
316  error(IO.mapInteger(Record.ModifiedType, "ModifiedType"));
317  error(IO.mapEnum(Record.Modifiers, "Modifiers" + ModifierNames));
318  return Error::success();
319 }
320 
323  std::string CallingConvName = std::string(getEnumName(
324  IO, uint8_t(Record.CallConv), makeArrayRef(getCallingConventions())));
325  std::string FuncOptionNames =
326  getFlagNames(IO, static_cast<uint16_t>(Record.Options),
328  error(IO.mapInteger(Record.ReturnType, "ReturnType"));
329  error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));
330  error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));
331  error(IO.mapInteger(Record.ParameterCount, "NumParameters"));
332  error(IO.mapInteger(Record.ArgumentList, "ArgListType"));
333 
334  return Error::success();
335 }
336 
339  std::string CallingConvName = std::string(getEnumName(
340  IO, uint8_t(Record.CallConv), makeArrayRef(getCallingConventions())));
341  std::string FuncOptionNames =
342  getFlagNames(IO, static_cast<uint16_t>(Record.Options),
344  error(IO.mapInteger(Record.ReturnType, "ReturnType"));
345  error(IO.mapInteger(Record.ClassType, "ClassType"));
346  error(IO.mapInteger(Record.ThisType, "ThisType"));
347  error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));
348  error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));
349  error(IO.mapInteger(Record.ParameterCount, "NumParameters"));
350  error(IO.mapInteger(Record.ArgumentList, "ArgListType"));
351  error(IO.mapInteger(Record.ThisPointerAdjustment, "ThisAdjustment"));
352 
353  return Error::success();
354 }
355 
358  Record.ArgIndices,
359  [](CodeViewRecordIO &IO, TypeIndex &N) {
360  return IO.mapInteger(N, "Argument");
361  },
362  "NumArgs"));
363  return Error::success();
364 }
365 
369  Record.StringIndices,
370  [](CodeViewRecordIO &IO, TypeIndex &N) {
371  return IO.mapInteger(N, "Strings");
372  },
373  "NumStrings"));
374 
375  return Error::success();
376 }
377 
379 
380  SmallString<128> Attr("Attrs: ");
381 
382  if (IO.isStreaming()) {
383  std::string PtrType =
384  std::string(getEnumName(IO, unsigned(Record.getPointerKind()),
386  Attr += "[ Type: " + PtrType;
387 
388  std::string PtrMode = std::string(getEnumName(
389  IO, unsigned(Record.getMode()), makeArrayRef(getPtrModeNames())));
390  Attr += ", Mode: " + PtrMode;
391 
392  auto PtrSizeOf = Record.getSize();
393  Attr += ", SizeOf: " + itostr(PtrSizeOf);
394 
395  if (Record.isFlat())
396  Attr += ", isFlat";
397  if (Record.isConst())
398  Attr += ", isConst";
399  if (Record.isVolatile())
400  Attr += ", isVolatile";
401  if (Record.isUnaligned())
402  Attr += ", isUnaligned";
403  if (Record.isRestrict())
404  Attr += ", isRestricted";
405  if (Record.isLValueReferenceThisPtr())
406  Attr += ", isThisPtr&";
407  if (Record.isRValueReferenceThisPtr())
408  Attr += ", isThisPtr&&";
409  Attr += " ]";
410  }
411 
412  error(IO.mapInteger(Record.ReferentType, "PointeeType"));
413  error(IO.mapInteger(Record.Attrs, Attr));
414 
415  if (Record.isPointerToMember()) {
416  if (IO.isReading())
417  Record.MemberInfo.emplace();
418 
419  MemberPointerInfo &M = *Record.MemberInfo;
420  error(IO.mapInteger(M.ContainingType, "ClassType"));
421  std::string PtrMemberGetRepresentation = std::string(getEnumName(
422  IO, uint16_t(M.Representation), makeArrayRef(getPtrMemberRepNames())));
423  error(IO.mapEnum(M.Representation,
424  "Representation: " + PtrMemberGetRepresentation));
425  }
426 
427  return Error::success();
428 }
429 
431  error(IO.mapInteger(Record.ElementType, "ElementType"));
432  error(IO.mapInteger(Record.IndexType, "IndexType"));
433  error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
434  error(IO.mapStringZ(Record.Name, "Name"));
435 
436  return Error::success();
437 }
438 
440  assert((CVR.kind() == TypeLeafKind::LF_STRUCTURE) ||
441  (CVR.kind() == TypeLeafKind::LF_CLASS) ||
442  (CVR.kind() == TypeLeafKind::LF_INTERFACE));
443 
444  std::string PropertiesNames =
445  getFlagNames(IO, static_cast<uint16_t>(Record.Options),
447  error(IO.mapInteger(Record.MemberCount, "MemberCount"));
448  error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
449  error(IO.mapInteger(Record.FieldList, "FieldList"));
450  error(IO.mapInteger(Record.DerivationList, "DerivedFrom"));
451  error(IO.mapInteger(Record.VTableShape, "VShape"));
452  error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
453  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
454  Record.hasUniqueName()));
455 
456  return Error::success();
457 }
458 
460  std::string PropertiesNames =
461  getFlagNames(IO, static_cast<uint16_t>(Record.Options),
463  error(IO.mapInteger(Record.MemberCount, "MemberCount"));
464  error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
465  error(IO.mapInteger(Record.FieldList, "FieldList"));
466  error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
467  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
468  Record.hasUniqueName()));
469 
470  return Error::success();
471 }
472 
474  std::string PropertiesNames =
475  getFlagNames(IO, static_cast<uint16_t>(Record.Options),
477  error(IO.mapInteger(Record.MemberCount, "NumEnumerators"));
478  error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
479  error(IO.mapInteger(Record.UnderlyingType, "UnderlyingType"));
480  error(IO.mapInteger(Record.FieldList, "FieldListType"));
481  error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
482  Record.hasUniqueName()));
483 
484  return Error::success();
485 }
486 
488  error(IO.mapInteger(Record.Type, "Type"));
489  error(IO.mapInteger(Record.BitSize, "BitSize"));
490  error(IO.mapInteger(Record.BitOffset, "BitOffset"));
491 
492  return Error::success();
493 }
494 
497  uint16_t Size;
498  if (!IO.isReading()) {
499  ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
500  Size = Slots.size();
501  error(IO.mapInteger(Size, "VFEntryCount"));
502 
503  for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
504  uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
505  if ((SlotIndex + 1) < Slots.size()) {
506  Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
507  }
508  error(IO.mapInteger(Byte));
509  }
510  } else {
511  error(IO.mapInteger(Size));
512  for (uint16_t I = 0; I < Size; I += 2) {
513  uint8_t Byte;
514  error(IO.mapInteger(Byte));
515  Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
516  if ((I + 1) < Size)
517  Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
518  }
519  }
520 
521  return Error::success();
522 }
523 
525  error(IO.mapInteger(Record.CompleteClass, "CompleteClass"));
526  error(IO.mapInteger(Record.OverriddenVFTable, "OverriddenVFTable"));
527  error(IO.mapInteger(Record.VFPtrOffset, "VFPtrOffset"));
528  uint32_t NamesLen = 0;
529  if (!IO.isReading()) {
530  for (auto Name : Record.MethodNames)
531  NamesLen += Name.size() + 1;
532  }
533  error(IO.mapInteger(NamesLen));
534  error(IO.mapVectorTail(
535  Record.MethodNames,
536  [](CodeViewRecordIO &IO, StringRef &S) {
537  return IO.mapStringZ(S, "MethodName");
538  },
539  "VFTableName"));
540 
541  return Error::success();
542 }
543 
545  error(IO.mapInteger(Record.Id, "Id"));
546  error(IO.mapStringZ(Record.String, "StringData"));
547 
548  return Error::success();
549 }
550 
553  error(IO.mapInteger(Record.UDT, "UDT"));
554  error(IO.mapInteger(Record.SourceFile, "SourceFile"));
555  error(IO.mapInteger(Record.LineNumber, "LineNumber"));
556 
557  return Error::success();
558 }
559 
562  error(IO.mapInteger(Record.UDT, "UDT"));
563  error(IO.mapInteger(Record.SourceFile, "SourceFile"));
564  error(IO.mapInteger(Record.LineNumber, "LineNumber"));
565  error(IO.mapInteger(Record.Module, "Module"));
566 
567  return Error::success();
568 }
569 
571  error(IO.mapInteger(Record.ParentScope, "ParentScope"));
572  error(IO.mapInteger(Record.FunctionType, "FunctionType"));
573  error(IO.mapStringZ(Record.Name, "Name"));
574 
575  return Error::success();
576 }
577 
580  error(IO.mapInteger(Record.ClassType, "ClassType"));
581  error(IO.mapInteger(Record.FunctionType, "FunctionType"));
582  error(IO.mapStringZ(Record.Name, "Name"));
583 
584  return Error::success();
585 }
586 
590  Record.ArgIndices,
591  [](CodeViewRecordIO &IO, TypeIndex &N) {
592  return IO.mapInteger(N, "Argument");
593  },
594  "NumArgs"));
595 
596  return Error::success();
597 }
598 
601  // TODO: Split the list into multiple records if it's longer than 64KB, using
602  // a subrecord of TypeRecordKind::Index to chain the records together.
603  error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true), "Method"));
604 
605  return Error::success();
606 }
607 
610  if (IO.isStreaming()) {
611  if (auto EC = codeview::visitMemberRecordStream(Record.Data, *this))
612  return EC;
613  } else
614  error(IO.mapByteVectorTail(Record.Data));
615 
616  return Error::success();
617 }
618 
621  error(IO.mapGuid(Record.Guid, "Guid"));
622  error(IO.mapInteger(Record.Age, "Age"));
623  error(IO.mapStringZ(Record.Name, "Name"));
624  return Error::success();
625 }
626 
628  std::string ModeName = std::string(
629  getEnumName(IO, uint16_t(Record.Mode), makeArrayRef(getLabelTypeEnum())));
630  error(IO.mapEnum(Record.Mode, "Mode: " + ModeName));
631  return Error::success();
632 }
633 
636  std::string Attrs = getMemberAttributes(
638  error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
639  error(IO.mapInteger(Record.Type, "BaseType"));
640  error(IO.mapEncodedInteger(Record.Offset, "BaseOffset"));
641 
642  return Error::success();
643 }
644 
647  std::string Attrs = getMemberAttributes(
649  error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
650 
651  // FIXME: Handle full APInt such as __int128.
652  error(IO.mapEncodedInteger(Record.Value, "EnumValue"));
653  error(IO.mapStringZ(Record.Name, "Name"));
654 
655  return Error::success();
656 }
657 
660  std::string Attrs = getMemberAttributes(
662  error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
663  error(IO.mapInteger(Record.Type, "Type"));
664  error(IO.mapEncodedInteger(Record.FieldOffset, "FieldOffset"));
665  error(IO.mapStringZ(Record.Name, "Name"));
666 
667  return Error::success();
668 }
669 
672  error(IO.mapInteger(Record.NumOverloads, "MethodCount"));
673  error(IO.mapInteger(Record.MethodList, "MethodListIndex"));
674  error(IO.mapStringZ(Record.Name, "Name"));
675 
676  return Error::success();
677 }
678 
681  const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
682  MapOneMethodRecord Mapper(IsFromOverloadList);
683  return Mapper(IO, Record);
684 }
685 
688  uint16_t Padding = 0;
689  error(IO.mapInteger(Padding, "Padding"));
690  error(IO.mapInteger(Record.Type, "Type"));
691  error(IO.mapStringZ(Record.Name, "Name"));
692 
693  return Error::success();
694 }
695 
698 
699  std::string Attrs = getMemberAttributes(
701  error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
702  error(IO.mapInteger(Record.Type, "Type"));
703  error(IO.mapStringZ(Record.Name, "Name"));
704 
705  return Error::success();
706 }
707 
710 
711  std::string Attrs = getMemberAttributes(
713  error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
714  error(IO.mapInteger(Record.BaseType, "BaseType"));
715  error(IO.mapInteger(Record.VBPtrType, "VBPtrType"));
716  error(IO.mapEncodedInteger(Record.VBPtrOffset, "VBPtrOffset"));
717  error(IO.mapEncodedInteger(Record.VTableIndex, "VBTableIndex"));
718 
719  return Error::success();
720 }
721 
723  VFPtrRecord &Record) {
724  uint16_t Padding = 0;
725  error(IO.mapInteger(Padding, "Padding"));
726  error(IO.mapInteger(Record.Type, "Type"));
727 
728  return Error::success();
729 }
730 
733  uint16_t Padding = 0;
734  error(IO.mapInteger(Padding, "Padding"));
735  error(IO.mapInteger(Record.ContinuationIndex, "ContinuationIndex"));
736 
737  return Error::success();
738 }
739 
741  PrecompRecord &Precomp) {
742  error(IO.mapInteger(Precomp.StartTypeIndex, "StartIndex"));
743  error(IO.mapInteger(Precomp.TypesCount, "Count"));
744  error(IO.mapInteger(Precomp.Signature, "Signature"));
745  error(IO.mapStringZ(Precomp.PrecompFilePath, "PrecompFile"));
746  return Error::success();
747 }
748 
750  EndPrecompRecord &EndPrecomp) {
751  error(IO.mapInteger(EndPrecomp.Signature, "Signature"));
752  return Error::success();
753 }
llvm::Check::Size
@ Size
Definition: FileCheck.h:77
llvm::codeview::SimpleTypeKind::Byte
@ Byte
llvm::codeview::OneMethodRecord::Type
TypeIndex Type
Definition: TypeRecord.h:745
Attrs
Function Attrs
Definition: README_ALTIVEC.txt:215
llvm::codeview::MemberAccess
MemberAccess
Source-level access specifier. (CV_access_e)
Definition: CodeView.h:265
llvm::FlagEntry
Definition: ScopedPrinter.h:60
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::codeview::getMemberKindNames
ArrayRef< EnumEntry< uint16_t > > getMemberKindNames()
Definition: EnumTables.cpp:529
llvm::MD5::update
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
Definition: MD5.cpp:189
RecordSerialization.h
llvm::MD5::stringifyResult
static void stringifyResult(MD5Result &Result, SmallVectorImpl< char > &Str)
Translates the bytes in Res to a hex string that is deposited into Str.
Definition: MD5.cpp:287
llvm::codeview::CodeViewRecordIO::isWriting
bool isWriting() const
Definition: CodeViewRecordIO.h:77
llvm::codeview::StringIdRecord
Definition: TypeRecord.h:595
StringRef.h
llvm::codeview::NestedTypeRecord
Definition: TypeRecord.h:370
ContinuationLength
static constexpr uint32_t ContinuationLength
Definition: ContinuationRecordBuilder.cpp:37
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1185
llvm::codeview::CodeViewRecordIO::mapByteVectorTail
Error mapByteVectorTail(ArrayRef< uint8_t > &Bytes, const Twine &Comment="")
Definition: CodeViewRecordIO.cpp:102
ErrorHandling.h
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:329
llvm::codeview::PrecompRecord::TypesCount
uint32_t TypesCount
Definition: TypeRecord.h:940
llvm::codeview::CodeViewRecordIO::mapStringZ
Error mapStringZ(StringRef &Value, const Twine &Comment="")
Definition: CodeViewRecordIO.cpp:209
llvm::codeview::PrecompRecord::Signature
uint32_t Signature
Definition: TypeRecord.h:941
llvm::codeview::PrecompRecord
Definition: TypeRecord.h:929
llvm::codeview::VFTableShapeRecord
Definition: TypeRecord.h:553
llvm::codeview::MethodKind::Vanilla
@ Vanilla
llvm::codeview::BaseClassRecord
Definition: TypeRecord.h:864
llvm::codeview::getTypeModifierNames
ArrayRef< EnumEntry< uint16_t > > getTypeModifierNames()
Definition: EnumTables.cpp:545
llvm::Optional< uint32_t >
llvm::codeview::CodeViewRecordIO::mapEnum
Error mapEnum(T &Value, const Twine &Comment="")
Definition: CodeViewRecordIO.h:116
llvm::codeview::TypeRecordMapping::visitTypeEnd
Error visitTypeEnd(CVType &Record) override
Definition: TypeRecordMapping.cpp:262
STLExtras.h
visitKnownRecord
static Error visitKnownRecord(CVSymbol &Record, SymbolVisitorCallbacks &Callbacks)
Definition: CVSymbolVisitor.cpp:25
llvm::codeview::PointerRecord
Definition: TypeRecord.h:264
llvm::codeview::RecordPrefix
Definition: RecordSerialization.h:32
llvm::codeview::DataMemberRecord
Definition: TypeRecord.h:784
llvm::codeview::OneMethodRecord::Attrs
MemberAttributes Attrs
Definition: TypeRecord.h:746
EnumTables.h
llvm::EnumEntry
Definition: EnumTables.h:18
llvm::Optional::hasValue
constexpr bool hasValue() const
Definition: Optional.h:312
llvm::AArch64CC::LT
@ LT
Definition: AArch64BaseInfo.h:266
llvm::codeview::CodeViewRecordIO::beginRecord
Error beginRecord(Optional< uint32_t > MaxLength)
Definition: CodeViewRecordIO.cpp:20
llvm::codeview::visitMemberRecordStream
Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)
Definition: CVTypeVisitor.cpp:271
llvm::codeview::ArgListRecord
Definition: TypeRecord.h:236
llvm::codeview::getMethodOptionNames
ArrayRef< EnumEntry< uint16_t > > getMethodOptionNames()
Definition: EnumTables.cpp:525
llvm::codeview::EnumRecord
Definition: TypeRecord.h:519
llvm::codeview::TypeRecordMapping::visitMemberEnd
Error visitMemberEnd(CVMemberRecord &Record) override
Definition: TypeRecordMapping.cpp:298
llvm::codeview::CVMemberRecord
Definition: TypeRecord.h:34
llvm::MD5::final
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
Definition: MD5.cpp:234
llvm::StringRef::take_front
LLVM_NODISCARD StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Definition: StringRef.h:624
MD5.h
SmallString.h
llvm::codeview::CodeViewRecordIO
Definition: CodeViewRecordIO.h:45
llvm::codeview::BitFieldRecord
Definition: TypeRecord.h:535
llvm::codeview::MethodOverloadListRecord
Definition: TypeRecord.h:752
llvm::codeview::MaxRecordLength
@ MaxRecordLength
Definition: RecordSerialization.h:30
llvm::dwarf::Index
Index
Definition: Dwarf.h:472
llvm::codeview::MethodKind
MethodKind
Part of member attribute flags. (CV_methodprop_e)
Definition: CodeView.h:273
llvm::codeview::UdtModSourceLineRecord
Definition: TypeRecord.h:646
llvm::codeview::EndPrecompRecord::Signature
uint32_t Signature
Definition: TypeRecord.h:953
llvm::MCID::Flag
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:147
Options
const char LLVMTargetMachineRef LLVMPassBuilderOptionsRef Options
Definition: PassBuilderBindings.cpp:48
llvm::codeview::ListContinuationRecord
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition: TypeRecord.h:915
llvm::codeview::getFunctionOptionEnum
ArrayRef< EnumEntry< uint8_t > > getFunctionOptionEnum()
Definition: EnumTables.cpp:553
llvm::codeview::CodeViewRecordIO::emitRawComment
void emitRawComment(const Twine &T)
Definition: CodeViewRecordIO.h:215
llvm::EnumEntry::Name
StringRef Name
Definition: ScopedPrinter.h:25
llvm::codeview::ModifierRecord
Definition: TypeRecord.h:130
llvm::codeview::OverloadedMethodRecord
For method overload sets. LF_METHOD.
Definition: TypeRecord.h:765
llvm::SlotIndex
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:82
llvm::codeview::MethodOptions::None
@ None
llvm::codeview::CodeViewRecordIO::mapVectorN
Error mapVectorN(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
Definition: CodeViewRecordIO.h:145
llvm::codeview::MemberFunctionRecord
Definition: TypeRecord.h:171
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::codeview::getPtrKindNames
ArrayRef< EnumEntry< uint8_t > > getPtrKindNames()
Definition: EnumTables.cpp:533
llvm::codeview::getLabelTypeEnum
ArrayRef< EnumEntry< uint16_t > > getLabelTypeEnum()
Definition: EnumTables.cpp:557
llvm::codeview::OneMethodRecord::isIntroducingVirtual
bool isIntroducingVirtual() const
Definition: TypeRecord.h:740
llvm::SmallString< 32 >
llvm::codeview::TypeRecordMapping::visitTypeBegin
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
Definition: TypeRecordMapping.cpp:230
llvm::Twine::str
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
llvm::codeview::TypeRecordMapping::visitMemberBegin
Error visitMemberBegin(CVMemberRecord &Record) override
Definition: TypeRecordMapping.cpp:272
llvm::codeview::CodeViewRecordIO::skipPadding
Error skipPadding()
Definition: CodeViewRecordIO.cpp:87
llvm::codeview::TypeServer2Record
Definition: TypeRecord.h:575
llvm::codeview::EnumeratorRecord
Definition: TypeRecord.h:830
llvm::codeview::OneMethodRecord
Definition: TypeRecord.h:720
llvm::Optional::reset
void reset()
Definition: Optional.h:301
TypeRecord.h
llvm::codeview::CVRecord::kind
Kind kind() const
Definition: CVRecord.h:42
llvm::codeview::VirtualBaseClassRecord
Definition: TypeRecord.h:885
llvm::MD5
Definition: MD5.h:41
I
#define I(x, y, z)
Definition: MD5.cpp:58
TypeRecordMapping.h
llvm::codeview::getPtrModeNames
ArrayRef< EnumEntry< uint8_t > > getPtrModeNames()
Definition: EnumTables.cpp:537
CodeViewRecordIO.h
ArrayRef.h
llvm::codeview::PrecompRecord::PrecompFilePath
StringRef PrecompFilePath
Definition: TypeRecord.h:942
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::codeview::StaticDataMemberRecord
Definition: TypeRecord.h:809
llvm::codeview::CompileSym2Flags::EC
@ EC
getLeafTypeName
static StringRef getLeafTypeName(TypeLeafKind LT)
Definition: TypeDumpVisitor.cpp:150
llvm::codeview::getPtrMemberRepNames
ArrayRef< EnumEntry< uint16_t > > getPtrMemberRepNames()
Definition: EnumTables.cpp:541
llvm::Record
Definition: Record.h:1543
llvm::codeview::getMemberAccessNames
ArrayRef< EnumEntry< uint8_t > > getMemberAccessNames()
Definition: EnumTables.cpp:521
llvm::codeview::FuncIdRecord
Definition: TypeRecord.h:610
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::codeview::FieldListRecord
Definition: TypeRecord.h:385
llvm::codeview::OneMethodRecord::getMethodKind
MethodKind getMethodKind() const
Definition: TypeRecord.h:734
llvm::min
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
Definition: FileCheck.cpp:357
llvm::codeview::CodeViewRecordIO::isStreaming
bool isStreaming() const
Definition: CodeViewRecordIO.h:71
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::codeview::CVRecord< TypeLeafKind >
llvm::codeview::OneMethodRecord::getAccess
MemberAccess getAccess() const
Definition: TypeRecord.h:736
llvm::codeview::VFTableSlotKind
VFTableSlotKind
Definition: CodeView.h:388
llvm::codeview::UdtSourceLineRecord
Definition: TypeRecord.h:628
uint32_t
llvm::codeview::VFTableRecord
Definition: TypeRecord.h:691
llvm::codeview::CodeViewRecordIO::mapInteger
Error mapInteger(TypeIndex &TypeInd, const Twine &Comment="")
Definition: CodeViewRecordIO.cpp:129
llvm::codeview::CodeViewRecordIO::maxFieldLength
uint32_t maxFieldLength() const
Definition: CodeViewRecordIO.cpp:59
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::codeview::ProcedureRecord
Definition: TypeRecord.h:146
llvm::MD5::MD5Result
Definition: MD5.h:43
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::dwarf::TypeKind
TypeKind
Definition: Dwarf.h:151
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::codeview::CodeViewRecordIO::mapEncodedInteger
Error mapEncodedInteger(int64_t &Value, const Twine &Comment="")
Definition: CodeViewRecordIO.cpp:150
uint16_t
LeafTypeNames
static const EnumEntry< TypeLeafKind > LeafTypeNames[]
Definition: TypeDumpVisitor.cpp:24
llvm::codeview::CodeViewRecordIO::endRecord
Error endRecord()
Definition: CodeViewRecordIO.cpp:28
llvm::codeview::UnionRecord
Definition: TypeRecord.h:498
computeHashString
static void computeHashString(StringRef Name, SmallString< 32 > &StringifiedHash)
Definition: TypeRecordMapping.cpp:169
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
CVTypeVisitor.h
llvm::codeview::OneMethodRecord::VFTableOffset
int32_t VFTableOffset
Definition: TypeRecord.h:747
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1562
visitKnownMember
static Error visitKnownMember(CVMemberRecord &Record, TypeVisitorCallbacks &Callbacks)
Definition: CVTypeVisitor.cpp:34
TypeIndex.h
mapNameAndUniqueName
static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName)
Definition: TypeRecordMapping.cpp:178
llvm::codeview::MemberAttributes::Attrs
uint16_t Attrs
Definition: TypeRecord.h:41
llvm::codeview::VFPtrRecord
Definition: TypeRecord.h:851
llvm::codeview::BuildInfoRecord
Definition: TypeRecord.h:667
llvm::codeview::MemberFuncIdRecord
Definition: TypeRecord.h:217
llvm::codeview::TypeLeafKind
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:33
llvm::codeview
Definition: AppendingTypeTableBuilder.h:22
llvm::pdb::PDB_ColorItem::Padding
@ Padding
llvm::makeArrayRef
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
Definition: ArrayRef.h:475
llvm::codeview::CodeViewRecordIO::isReading
bool isReading() const
Definition: CodeViewRecordIO.h:74
SmallVector.h
llvm::codeview::StringListRecord
Definition: TypeRecord.h:250
llvm::codeview::ArrayRecord
Definition: TypeRecord.h:396
N
#define N
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:164
llvm::codeview::LabelRecord
Definition: TypeRecord.h:206
llvm::codeview::ClassOptions::HasUniqueName
@ HasUniqueName
llvm::codeview::OneMethodRecord::getOptions
MethodOptions getOptions() const
Definition: TypeRecord.h:735
llvm::codeview::getCallingConventions
ArrayRef< EnumEntry< uint8_t > > getCallingConventions()
Definition: EnumTables.cpp:549
llvm::codeview::TypeIndex
A 32-bit type reference.
Definition: TypeIndex.h:96
llvm::codeview::CodeViewRecordIO::mapGuid
Error mapGuid(GUID &Guid, const Twine &Comment="")
Definition: CodeViewRecordIO.cpp:227
llvm::codeview::ClassRecord
Definition: TypeRecord.h:465
llvm::codeview::getClassOptionNames
ArrayRef< EnumEntry< uint16_t > > getClassOptionNames()
Definition: EnumTables.cpp:517
llvm::codeview::MemberPointerInfo
Definition: TypeRecord.h:100
llvm::codeview::EndPrecompRecord
Definition: TypeRecord.h:946
llvm::codeview::CodeViewRecordIO::mapVectorTail
Error mapVectorTail(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
Definition: CodeViewRecordIO.h:182
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::codeview::OneMethodRecord::Name
StringRef Name
Definition: TypeRecord.h:748
error
#define error(X)
Definition: TypeRecordMapping.cpp:38
llvm::codeview::PrecompRecord::StartTypeIndex
uint32_t StartTypeIndex
Definition: TypeRecord.h:939
llvm::codeview::MethodOptions
MethodOptions
Equivalent to CV_fldattr_t bitfield.
Definition: CodeView.h:284
ScopedPrinter.h
llvm::codeview::CVRecord::length
uint32_t length() const
Definition: CVRecord.h:40