LLVM 20.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"
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
33using namespace llvm;
34using namespace llvm::codeview;
35
36namespace {
37
38#define error(X) \
39 do { \
40 if (auto EC = X) \
41 return EC; \
42 } while (false)
43
45#define CV_TYPE(enum, val) {#enum, enum},
46#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
47};
48
50 switch (LT) {
51#define TYPE_RECORD(ename, value, name) \
52 case ename: \
53 return #name;
54#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
55 default:
56 break;
57 }
58 return "UnknownLeaf";
59}
60
61template <typename T>
62static bool compEnumNames(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
63 return lhs.Name < rhs.Name;
64}
65
66template <typename T, typename TFlag>
67static std::string getFlagNames(CodeViewRecordIO &IO, T Value,
69 if (!IO.isStreaming())
70 return std::string("");
72 typedef SmallVector<FlagEntry, 10> FlagVector;
73 FlagVector SetFlags;
74 for (const auto &Flag : Flags) {
75 if (Flag.Value == 0)
76 continue;
77 if ((Value & Flag.Value) == Flag.Value) {
78 SetFlags.push_back(Flag);
79 }
80 }
81
82 llvm::sort(SetFlags, &compEnumNames<TFlag>);
83
84 std::string FlagLabel;
85 bool FirstOcc = true;
86 for (const auto &Flag : SetFlags) {
87 if (FirstOcc)
88 FirstOcc = false;
89 else
90 FlagLabel += (" | ");
91
92 FlagLabel += (Flag.Name.str() + " (0x" + utohexstr(Flag.Value) + ")");
93 }
94
95 if (!FlagLabel.empty()) {
96 std::string LabelWithBraces(" ( ");
97 LabelWithBraces += FlagLabel + " )";
98 return LabelWithBraces;
99 } else
100 return FlagLabel;
101}
102
103template <typename T, typename TEnum>
104static StringRef getEnumName(CodeViewRecordIO &IO, T Value,
105 ArrayRef<EnumEntry<TEnum>> EnumValues) {
106 if (!IO.isStreaming())
107 return "";
109 for (const auto &EnumItem : EnumValues) {
110 if (EnumItem.Value == Value) {
111 Name = EnumItem.Name;
112 break;
113 }
114 }
115
116 return Name;
117}
118
119static std::string getMemberAttributes(CodeViewRecordIO &IO,
120 MemberAccess Access, MethodKind Kind,
122 if (!IO.isStreaming())
123 return "";
124 std::string AccessSpecifier = std::string(
125 getEnumName(IO, uint8_t(Access), ArrayRef(getMemberAccessNames())));
126 std::string MemberAttrs(AccessSpecifier);
127 if (Kind != MethodKind::Vanilla) {
128 std::string MethodKind = std::string(
129 getEnumName(IO, unsigned(Kind), ArrayRef(getMemberKindNames())));
130 MemberAttrs += ", " + MethodKind;
131 }
132 if (Options != MethodOptions::None) {
133 std::string MethodOptions =
134 getFlagNames(IO, unsigned(Options), ArrayRef(getMethodOptionNames()));
135 MemberAttrs += ", " + MethodOptions;
136 }
137 return MemberAttrs;
138}
139
140struct MapOneMethodRecord {
141 explicit MapOneMethodRecord(bool IsFromOverloadList)
142 : IsFromOverloadList(IsFromOverloadList) {}
143
144 Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
145 std::string Attrs = getMemberAttributes(
146 IO, Method.getAccess(), Method.getMethodKind(), Method.getOptions());
147 error(IO.mapInteger(Method.Attrs.Attrs, "Attrs: " + Attrs));
148 if (IsFromOverloadList) {
149 uint16_t Padding = 0;
150 error(IO.mapInteger(Padding));
151 }
152 error(IO.mapInteger(Method.Type, "Type"));
153 if (Method.isIntroducingVirtual()) {
154 error(IO.mapInteger(Method.VFTableOffset, "VFTableOffset"));
155 } else if (IO.isReading())
156 Method.VFTableOffset = -1;
157
158 if (!IsFromOverloadList)
159 error(IO.mapStringZ(Method.Name, "Name"));
160
161 return Error::success();
162 }
163
164private:
165 bool IsFromOverloadList;
166};
167} // namespace
168
169// Computes a string representation of a hash of the specified name, suitable
170// for use when emitting CodeView type names.
172 SmallString<32> &StringifiedHash) {
173 llvm::MD5 Hash;
175 Hash.update(Name);
176 Hash.final(Result);
177 Hash.stringifyResult(Result, StringifiedHash);
178}
179
181 StringRef &UniqueName, bool HasUniqueName) {
182 if (IO.isWriting()) {
183 // Try to be smart about what we write here. We can't write anything too
184 // large, so if we're going to go over the limit, replace lengthy names with
185 // a stringified hash value.
186 size_t BytesLeft = IO.maxFieldLength();
187 if (HasUniqueName) {
188 size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
189 if (BytesNeeded > BytesLeft) {
190 // The minimum space required for emitting hashes of both names.
191 assert(BytesLeft >= 70);
192
193 // Replace the entire unique name with a hash of the unique name.
194 SmallString<32> Hash;
195 computeHashString(UniqueName, Hash);
196 std::string UniqueB = Twine("??@" + Hash + "@").str();
197 assert(UniqueB.size() == 36);
198
199 // Truncate the name if necessary and append a hash of the name.
200 // The name length, hash included, is limited to 4096 bytes.
201 const size_t MaxTakeN = 4096;
202 size_t TakeN = std::min(MaxTakeN, BytesLeft - UniqueB.size() - 2) - 32;
203 computeHashString(Name, Hash);
204 std::string NameB = (Name.take_front(TakeN) + Hash).str();
205
206 StringRef N = NameB;
207 StringRef U = UniqueB;
208 error(IO.mapStringZ(N));
209 error(IO.mapStringZ(U));
210 } else {
211 error(IO.mapStringZ(Name));
212 error(IO.mapStringZ(UniqueName));
213 }
214 } else {
215 // Cap the length of the string at however many bytes we have available,
216 // plus one for the required null terminator.
217 auto N = StringRef(Name).take_front(BytesLeft - 1);
218 error(IO.mapStringZ(N));
219 }
220 } else {
221 // Reading & Streaming mode come after writing mode is executed for each
222 // record. Truncating large names are done during writing, so its not
223 // necessary to do it while reading or streaming.
224 error(IO.mapStringZ(Name, "Name"));
225 if (HasUniqueName)
226 error(IO.mapStringZ(UniqueName, "LinkageName"));
227 }
228
229 return Error::success();
230}
231
233 assert(!TypeKind && "Already in a type mapping!");
234 assert(!MemberKind && "Already in a member mapping!");
235
236 // FieldList and MethodList records can be any length because they can be
237 // split with continuation records. All other record types cannot be
238 // longer than the maximum record length.
239 std::optional<uint32_t> MaxLen;
240 if (CVR.kind() != TypeLeafKind::LF_FIELDLIST &&
241 CVR.kind() != TypeLeafKind::LF_METHODLIST)
242 MaxLen = MaxRecordLength - sizeof(RecordPrefix);
243 error(IO.beginRecord(MaxLen));
244 TypeKind = CVR.kind();
245
246 if (IO.isStreaming()) {
247 auto RecordKind = CVR.kind();
248 uint16_t RecordLen = CVR.length() - 2;
249 std::string RecordKindName = std::string(
250 getEnumName(IO, unsigned(RecordKind), ArrayRef(LeafTypeNames)));
251 error(IO.mapInteger(RecordLen, "Record length"));
252 error(IO.mapEnum(RecordKind, "Record kind: " + RecordKindName));
253 }
254 return Error::success();
255}
256
258 if (IO.isStreaming())
259 IO.emitRawComment(" " + getLeafTypeName(CVR.kind()) + " (0x" +
260 utohexstr(Index.getIndex()) + ")");
261 return visitTypeBegin(CVR);
262}
263
265 assert(TypeKind && "Not in a type mapping!");
266 assert(!MemberKind && "Still in a member mapping!");
267
268 error(IO.endRecord());
269
270 TypeKind.reset();
271 return Error::success();
272}
273
275 assert(TypeKind && "Not in a type mapping!");
276 assert(!MemberKind && "Already in a member mapping!");
277
278 // The largest possible subrecord is one in which there is a record prefix,
279 // followed by the subrecord, followed by a continuation, and that entire
280 // sequence spawns `MaxRecordLength` bytes. So the record's length is
281 // calculated as follows.
282
283 constexpr uint32_t ContinuationLength = 8;
286
287 MemberKind = Record.Kind;
288 if (IO.isStreaming()) {
289 std::string MemberKindName = std::string(getLeafTypeName(Record.Kind));
290 MemberKindName +=
291 " ( " +
292 (getEnumName(IO, unsigned(Record.Kind), ArrayRef(LeafTypeNames)))
293 .str() +
294 " )";
295 error(IO.mapEnum(Record.Kind, "Member kind: " + MemberKindName));
296 }
297 return Error::success();
298}
299
301 assert(TypeKind && "Not in a type mapping!");
302 assert(MemberKind && "Not in a member mapping!");
303
304 if (IO.isReading()) {
305 if (auto EC = IO.skipPadding())
306 return EC;
307 }
308
309 MemberKind.reset();
310 error(IO.endRecord());
311 return Error::success();
312}
313
314Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
315 std::string ModifierNames =
316 getFlagNames(IO, static_cast<uint16_t>(Record.Modifiers),
318 error(IO.mapInteger(Record.ModifiedType, "ModifiedType"));
319 error(IO.mapEnum(Record.Modifiers, "Modifiers" + ModifierNames));
320 return Error::success();
321}
322
323Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
325 std::string CallingConvName = std::string(getEnumName(
326 IO, uint8_t(Record.CallConv), ArrayRef(getCallingConventions())));
327 std::string FuncOptionNames =
328 getFlagNames(IO, static_cast<uint16_t>(Record.Options),
330 error(IO.mapInteger(Record.ReturnType, "ReturnType"));
331 error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));
332 error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));
333 error(IO.mapInteger(Record.ParameterCount, "NumParameters"));
334 error(IO.mapInteger(Record.ArgumentList, "ArgListType"));
335
336 return Error::success();
337}
338
339Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
341 std::string CallingConvName = std::string(getEnumName(
342 IO, uint8_t(Record.CallConv), ArrayRef(getCallingConventions())));
343 std::string FuncOptionNames =
344 getFlagNames(IO, static_cast<uint16_t>(Record.Options),
346 error(IO.mapInteger(Record.ReturnType, "ReturnType"));
347 error(IO.mapInteger(Record.ClassType, "ClassType"));
348 error(IO.mapInteger(Record.ThisType, "ThisType"));
349 error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));
350 error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));
351 error(IO.mapInteger(Record.ParameterCount, "NumParameters"));
352 error(IO.mapInteger(Record.ArgumentList, "ArgListType"));
353 error(IO.mapInteger(Record.ThisPointerAdjustment, "ThisAdjustment"));
354
355 return Error::success();
356}
357
358Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
360 Record.ArgIndices,
361 [](CodeViewRecordIO &IO, TypeIndex &N) {
362 return IO.mapInteger(N, "Argument");
363 },
364 "NumArgs"));
365 return Error::success();
366}
367
368Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
371 Record.StringIndices,
372 [](CodeViewRecordIO &IO, TypeIndex &N) {
373 return IO.mapInteger(N, "Strings");
374 },
375 "NumStrings"));
376
377 return Error::success();
378}
379
380Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
381
382 SmallString<128> Attr("Attrs: ");
383
384 if (IO.isStreaming()) {
385 std::string PtrType = std::string(getEnumName(
386 IO, unsigned(Record.getPointerKind()), ArrayRef(getPtrKindNames())));
387 Attr += "[ Type: " + PtrType;
388
389 std::string PtrMode = std::string(getEnumName(
390 IO, unsigned(Record.getMode()), ArrayRef(getPtrModeNames())));
391 Attr += ", Mode: " + PtrMode;
392
393 auto PtrSizeOf = Record.getSize();
394 Attr += ", SizeOf: " + itostr(PtrSizeOf);
395
396 if (Record.isFlat())
397 Attr += ", isFlat";
398 if (Record.isConst())
399 Attr += ", isConst";
400 if (Record.isVolatile())
401 Attr += ", isVolatile";
402 if (Record.isUnaligned())
403 Attr += ", isUnaligned";
404 if (Record.isRestrict())
405 Attr += ", isRestricted";
406 if (Record.isLValueReferenceThisPtr())
407 Attr += ", isThisPtr&";
408 if (Record.isRValueReferenceThisPtr())
409 Attr += ", isThisPtr&&";
410 Attr += " ]";
411 }
412
413 error(IO.mapInteger(Record.ReferentType, "PointeeType"));
414 error(IO.mapInteger(Record.Attrs, Attr));
415
416 if (Record.isPointerToMember()) {
417 if (IO.isReading())
418 Record.MemberInfo.emplace();
419
420 MemberPointerInfo &M = *Record.MemberInfo;
421 error(IO.mapInteger(M.ContainingType, "ClassType"));
422 std::string PtrMemberGetRepresentation = std::string(getEnumName(
423 IO, uint16_t(M.Representation), ArrayRef(getPtrMemberRepNames())));
424 error(IO.mapEnum(M.Representation,
425 "Representation: " + PtrMemberGetRepresentation));
426 }
427
428 return Error::success();
429}
430
431Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
432 error(IO.mapInteger(Record.ElementType, "ElementType"));
433 error(IO.mapInteger(Record.IndexType, "IndexType"));
434 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
435 error(IO.mapStringZ(Record.Name, "Name"));
436
437 return Error::success();
438}
439
440Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
441 assert((CVR.kind() == TypeLeafKind::LF_STRUCTURE) ||
442 (CVR.kind() == TypeLeafKind::LF_CLASS) ||
443 (CVR.kind() == TypeLeafKind::LF_INTERFACE));
444
445 std::string PropertiesNames =
446 getFlagNames(IO, static_cast<uint16_t>(Record.Options),
448 error(IO.mapInteger(Record.MemberCount, "MemberCount"));
449 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
450 error(IO.mapInteger(Record.FieldList, "FieldList"));
451 error(IO.mapInteger(Record.DerivationList, "DerivedFrom"));
452 error(IO.mapInteger(Record.VTableShape, "VShape"));
453 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
454 error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
455 Record.hasUniqueName()));
456
457 return Error::success();
458}
459
460Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
461 std::string PropertiesNames =
462 getFlagNames(IO, static_cast<uint16_t>(Record.Options),
464 error(IO.mapInteger(Record.MemberCount, "MemberCount"));
465 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
466 error(IO.mapInteger(Record.FieldList, "FieldList"));
467 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
468 error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
469 Record.hasUniqueName()));
470
471 return Error::success();
472}
473
474Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
475 std::string PropertiesNames =
476 getFlagNames(IO, static_cast<uint16_t>(Record.Options),
478 error(IO.mapInteger(Record.MemberCount, "NumEnumerators"));
479 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
480 error(IO.mapInteger(Record.UnderlyingType, "UnderlyingType"));
481 error(IO.mapInteger(Record.FieldList, "FieldListType"));
482 error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
483 Record.hasUniqueName()));
484
485 return Error::success();
486}
487
488Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
489 error(IO.mapInteger(Record.Type, "Type"));
490 error(IO.mapInteger(Record.BitSize, "BitSize"));
491 error(IO.mapInteger(Record.BitOffset, "BitOffset"));
492
493 return Error::success();
494}
495
496Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
499 if (!IO.isReading()) {
500 ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
501 Size = Slots.size();
502 error(IO.mapInteger(Size, "VFEntryCount"));
503
504 for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
505 uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
506 if ((SlotIndex + 1) < Slots.size()) {
507 Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
508 }
509 error(IO.mapInteger(Byte));
510 }
511 } else {
512 error(IO.mapInteger(Size));
513 for (uint16_t I = 0; I < Size; I += 2) {
514 uint8_t Byte;
515 error(IO.mapInteger(Byte));
516 Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
517 if ((I + 1) < Size)
518 Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
519 }
520 }
521
522 return Error::success();
523}
524
525Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
526 error(IO.mapInteger(Record.CompleteClass, "CompleteClass"));
527 error(IO.mapInteger(Record.OverriddenVFTable, "OverriddenVFTable"));
528 error(IO.mapInteger(Record.VFPtrOffset, "VFPtrOffset"));
529 uint32_t NamesLen = 0;
530 if (!IO.isReading()) {
531 for (auto Name : Record.MethodNames)
532 NamesLen += Name.size() + 1;
533 }
534 error(IO.mapInteger(NamesLen));
536 Record.MethodNames,
537 [](CodeViewRecordIO &IO, StringRef &S) {
538 return IO.mapStringZ(S, "MethodName");
539 },
540 "VFTableName"));
541
542 return Error::success();
543}
544
545Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
546 error(IO.mapInteger(Record.Id, "Id"));
547 error(IO.mapStringZ(Record.String, "StringData"));
548
549 return Error::success();
550}
551
552Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
554 error(IO.mapInteger(Record.UDT, "UDT"));
555 error(IO.mapInteger(Record.SourceFile, "SourceFile"));
556 error(IO.mapInteger(Record.LineNumber, "LineNumber"));
557
558 return Error::success();
559}
560
561Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
563 error(IO.mapInteger(Record.UDT, "UDT"));
564 error(IO.mapInteger(Record.SourceFile, "SourceFile"));
565 error(IO.mapInteger(Record.LineNumber, "LineNumber"));
566 error(IO.mapInteger(Record.Module, "Module"));
567
568 return Error::success();
569}
570
571Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
572 error(IO.mapInteger(Record.ParentScope, "ParentScope"));
573 error(IO.mapInteger(Record.FunctionType, "FunctionType"));
574 error(IO.mapStringZ(Record.Name, "Name"));
575
576 return Error::success();
577}
578
579Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
581 error(IO.mapInteger(Record.ClassType, "ClassType"));
582 error(IO.mapInteger(Record.FunctionType, "FunctionType"));
583 error(IO.mapStringZ(Record.Name, "Name"));
584
585 return Error::success();
586}
587
588Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
591 Record.ArgIndices,
592 [](CodeViewRecordIO &IO, TypeIndex &N) {
593 return IO.mapInteger(N, "Argument");
594 },
595 "NumArgs"));
596
597 return Error::success();
598}
599
600Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
602 // TODO: Split the list into multiple records if it's longer than 64KB, using
603 // a subrecord of TypeRecordKind::Index to chain the records together.
604 error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true), "Method"));
605
606 return Error::success();
607}
608
609Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
611 if (IO.isStreaming()) {
612 if (auto EC = codeview::visitMemberRecordStream(Record.Data, *this))
613 return EC;
614 } else
616
617 return Error::success();
618}
619
620Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
622 error(IO.mapGuid(Record.Guid, "Guid"));
623 error(IO.mapInteger(Record.Age, "Age"));
624 error(IO.mapStringZ(Record.Name, "Name"));
625 return Error::success();
626}
627
628Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
629 std::string ModeName = std::string(
630 getEnumName(IO, uint16_t(Record.Mode), ArrayRef(getLabelTypeEnum())));
631 error(IO.mapEnum(Record.Mode, "Mode: " + ModeName));
632 return Error::success();
633}
634
635Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
637 std::string Attrs = getMemberAttributes(
639 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
640 error(IO.mapInteger(Record.Type, "BaseType"));
641 error(IO.mapEncodedInteger(Record.Offset, "BaseOffset"));
642
643 return Error::success();
644}
645
646Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
648 std::string Attrs = getMemberAttributes(
650 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
651
652 // FIXME: Handle full APInt such as __int128.
653 error(IO.mapEncodedInteger(Record.Value, "EnumValue"));
654 error(IO.mapStringZ(Record.Name, "Name"));
655
656 return Error::success();
657}
658
659Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
661 std::string Attrs = getMemberAttributes(
663 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
664 error(IO.mapInteger(Record.Type, "Type"));
665 error(IO.mapEncodedInteger(Record.FieldOffset, "FieldOffset"));
666 error(IO.mapStringZ(Record.Name, "Name"));
667
668 return Error::success();
669}
670
671Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
673 error(IO.mapInteger(Record.NumOverloads, "MethodCount"));
674 error(IO.mapInteger(Record.MethodList, "MethodListIndex"));
675 error(IO.mapStringZ(Record.Name, "Name"));
676
677 return Error::success();
678}
679
680Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
682 const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
683 MapOneMethodRecord Mapper(IsFromOverloadList);
684 return Mapper(IO, Record);
685}
686
687Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
689 uint16_t Padding = 0;
690 error(IO.mapInteger(Padding, "Padding"));
691 error(IO.mapInteger(Record.Type, "Type"));
692 error(IO.mapStringZ(Record.Name, "Name"));
693
694 return Error::success();
695}
696
697Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
699
700 std::string Attrs = getMemberAttributes(
702 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
703 error(IO.mapInteger(Record.Type, "Type"));
704 error(IO.mapStringZ(Record.Name, "Name"));
705
706 return Error::success();
707}
708
709Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
711
712 std::string Attrs = getMemberAttributes(
714 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
715 error(IO.mapInteger(Record.BaseType, "BaseType"));
716 error(IO.mapInteger(Record.VBPtrType, "VBPtrType"));
717 error(IO.mapEncodedInteger(Record.VBPtrOffset, "VBPtrOffset"));
718 error(IO.mapEncodedInteger(Record.VTableIndex, "VBTableIndex"));
719
720 return Error::success();
721}
722
723Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
725 uint16_t Padding = 0;
726 error(IO.mapInteger(Padding, "Padding"));
727 error(IO.mapInteger(Record.Type, "Type"));
728
729 return Error::success();
730}
731
732Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
734 uint16_t Padding = 0;
735 error(IO.mapInteger(Padding, "Padding"));
736 error(IO.mapInteger(Record.ContinuationIndex, "ContinuationIndex"));
737
738 return Error::success();
739}
740
741Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
742 PrecompRecord &Precomp) {
743 error(IO.mapInteger(Precomp.StartTypeIndex, "StartIndex"));
744 error(IO.mapInteger(Precomp.TypesCount, "Count"));
745 error(IO.mapInteger(Precomp.Signature, "Signature"));
746 error(IO.mapStringZ(Precomp.PrecompFilePath, "PrecompFile"));
747 return Error::success();
748}
749
750Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
751 EndPrecompRecord &EndPrecomp) {
752 error(IO.mapInteger(EndPrecomp.Signature, "Signature"));
753 return Error::success();
754}
static constexpr uint32_t ContinuationLength
std::string Name
uint64_t Size
static LVOptions Options
Definition: LVOptions.cpp:25
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallString class.
This file defines the SmallVector class.
#define error(X)
static StringRef getLeafTypeName(TypeLeafKind LT)
static const EnumEntry< TypeLeafKind > LeafTypeNames[]
static void computeHashString(StringRef Name, SmallString< 32 > &StringifiedHash)
#define error(X)
static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:337
Definition: MD5.h:41
void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
Definition: MD5.cpp:189
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
void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
Definition: MD5.cpp:234
SlotIndex - An opaque wrapper around machine indexes.
Definition: SlotIndexes.h:65
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
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:565
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
LLVM Value Representation.
Definition: Value.h:74
Kind kind() const
Definition: CVRecord.h:42
uint32_t length() const
Definition: CVRecord.h:40
Error mapVectorTail(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
Error mapVectorN(T &Items, const ElementMapper &Mapper, const Twine &Comment="")
Error mapInteger(TypeIndex &TypeInd, const Twine &Comment="")
Error mapGuid(GUID &Guid, const Twine &Comment="")
Error mapStringZ(StringRef &Value, const Twine &Comment="")
Error mapEnum(T &Value, const Twine &Comment="")
Error mapEncodedInteger(int64_t &Value, const Twine &Comment="")
Error beginRecord(std::optional< uint32_t > MaxLength)
Error mapByteVectorTail(ArrayRef< uint8_t > &Bytes, const Twine &Comment="")
void emitRawComment(const Twine &T)
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition: TypeRecord.h:914
MemberAccess getAccess() const
Definition: TypeRecord.h:735
MethodOptions getOptions() const
Definition: TypeRecord.h:734
MethodKind getMethodKind() const
Definition: TypeRecord.h:733
For method overload sets. LF_METHOD.
Definition: TypeRecord.h:764
A 32-bit type reference.
Definition: TypeIndex.h:96
Error visitTypeBegin(CVType &Record) override
Paired begin/end actions for all types.
Error visitMemberBegin(CVMemberRecord &Record) override
Error visitTypeEnd(CVType &Record) override
Error visitMemberEnd(CVMemberRecord &Record) override
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:148
ArrayRef< EnumEntry< uint16_t > > getMethodOptionNames()
Definition: EnumTables.cpp:544
MethodKind
Part of member attribute flags. (CV_methodprop_e)
Definition: CodeView.h:280
ArrayRef< EnumEntry< uint8_t > > getCallingConventions()
Definition: EnumTables.cpp:568
ArrayRef< EnumEntry< uint8_t > > getMemberAccessNames()
Definition: EnumTables.cpp:540
ArrayRef< EnumEntry< uint8_t > > getPtrKindNames()
Definition: EnumTables.cpp:552
ArrayRef< EnumEntry< uint16_t > > getPtrMemberRepNames()
Definition: EnumTables.cpp:560
ArrayRef< EnumEntry< uint16_t > > getLabelTypeEnum()
Definition: EnumTables.cpp:576
Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)
ArrayRef< EnumEntry< uint16_t > > getTypeModifierNames()
Definition: EnumTables.cpp:564
MethodOptions
Equivalent to CV_fldattr_t bitfield.
Definition: CodeView.h:291
ArrayRef< EnumEntry< uint16_t > > getMemberKindNames()
Definition: EnumTables.cpp:548
MemberAccess
Source-level access specifier. (CV_access_e)
Definition: CodeView.h:272
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:34
ArrayRef< EnumEntry< uint8_t > > getPtrModeNames()
Definition: EnumTables.cpp:556
ArrayRef< EnumEntry< uint8_t > > getFunctionOptionEnum()
Definition: EnumTables.cpp:572
ArrayRef< EnumEntry< uint16_t > > getClassOptionNames()
Definition: EnumTables.cpp:536
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1647
#define N
StringRef Name
Definition: ScopedPrinter.h:25