LLVM 22.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
32using namespace llvm;
33using namespace llvm::codeview;
34
35namespace {
36
37#define error(X) \
38 do { \
39 if (auto EC = X) \
40 return EC; \
41 } while (false)
42
44#define CV_TYPE(enum, val) {#enum, enum},
45#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
46};
47
49 switch (LT) {
50#define TYPE_RECORD(ename, value, name) \
51 case ename: \
52 return #name;
53#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
54 default:
55 break;
56 }
57 return "UnknownLeaf";
58}
59
60template <typename T>
61static bool compEnumNames(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
62 return lhs.Name < rhs.Name;
63}
64
65template <typename T, typename TFlag>
66static std::string getFlagNames(CodeViewRecordIO &IO, T Value,
68 if (!IO.isStreaming())
69 return std::string("");
71 typedef SmallVector<FlagEntry, 10> FlagVector;
72 FlagVector SetFlags;
73 for (const auto &Flag : Flags) {
74 if (Flag.Value == 0)
75 continue;
76 if ((Value & Flag.Value) == Flag.Value) {
77 SetFlags.push_back(Flag);
78 }
79 }
80
81 llvm::sort(SetFlags, &compEnumNames<TFlag>);
82
83 std::string FlagLabel;
84 bool FirstOcc = true;
85 for (const auto &Flag : SetFlags) {
86 if (FirstOcc)
87 FirstOcc = false;
88 else
89 FlagLabel += (" | ");
90
91 FlagLabel += (Flag.Name.str() + " (0x" + utohexstr(Flag.Value) + ")");
92 }
93
94 if (!FlagLabel.empty()) {
95 std::string LabelWithBraces(" ( ");
96 LabelWithBraces += FlagLabel + " )";
97 return LabelWithBraces;
98 } else
99 return FlagLabel;
100}
101
102template <typename T, typename TEnum>
103static StringRef getEnumName(CodeViewRecordIO &IO, T Value,
104 ArrayRef<EnumEntry<TEnum>> EnumValues) {
105 if (!IO.isStreaming())
106 return "";
108 for (const auto &EnumItem : EnumValues) {
109 if (EnumItem.Value == Value) {
110 Name = EnumItem.Name;
111 break;
112 }
113 }
114
115 return Name;
116}
117
118static std::string getMemberAttributes(CodeViewRecordIO &IO,
121 if (!IO.isStreaming())
122 return "";
123 std::string AccessSpecifier = std::string(
124 getEnumName(IO, uint8_t(Access), ArrayRef(getMemberAccessNames())));
125 std::string MemberAttrs(AccessSpecifier);
126 if (Kind != MethodKind::Vanilla) {
127 std::string MethodKind = std::string(
128 getEnumName(IO, unsigned(Kind), ArrayRef(getMemberKindNames())));
129 MemberAttrs += ", " + MethodKind;
130 }
132 std::string MethodOptions =
133 getFlagNames(IO, unsigned(Options), ArrayRef(getMethodOptionNames()));
134 MemberAttrs += ", " + MethodOptions;
135 }
136 return MemberAttrs;
137}
138
139struct MapOneMethodRecord {
140 explicit MapOneMethodRecord(bool IsFromOverloadList)
141 : IsFromOverloadList(IsFromOverloadList) {}
142
143 Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const {
144 std::string Attrs = getMemberAttributes(
145 IO, Method.getAccess(), Method.getMethodKind(), Method.getOptions());
146 error(IO.mapInteger(Method.Attrs.Attrs, "Attrs: " + Attrs));
147 if (IsFromOverloadList) {
148 uint16_t Padding = 0;
149 error(IO.mapInteger(Padding));
150 }
151 error(IO.mapInteger(Method.Type, "Type"));
152 if (Method.isIntroducingVirtual()) {
153 error(IO.mapInteger(Method.VFTableOffset, "VFTableOffset"));
154 } else if (IO.isReading())
155 Method.VFTableOffset = -1;
156
157 if (!IsFromOverloadList)
158 error(IO.mapStringZ(Method.Name, "Name"));
159
160 return Error::success();
161 }
162
163private:
164 bool IsFromOverloadList;
165};
166} // namespace
167
168// Computes a string representation of a hash of the specified name, suitable
169// for use when emitting CodeView type names.
171 SmallString<32> &StringifiedHash) {
172 llvm::MD5 Hash;
174 Hash.update(Name);
175 Hash.final(Result);
176 Hash.stringifyResult(Result, StringifiedHash);
177}
178
180 StringRef &UniqueName, bool HasUniqueName) {
181 if (IO.isWriting()) {
182 // Try to be smart about what we write here. We can't write anything too
183 // large, so if we're going to go over the limit, replace lengthy names with
184 // a stringified hash value.
185 size_t BytesLeft = IO.maxFieldLength();
186 if (HasUniqueName) {
187 size_t BytesNeeded = Name.size() + UniqueName.size() + 2;
188 if (BytesNeeded > BytesLeft) {
189 // The minimum space required for emitting hashes of both names.
190 assert(BytesLeft >= 70);
191
192 // Replace the entire unique name with a hash of the unique name.
193 SmallString<32> Hash;
194 computeHashString(UniqueName, Hash);
195 std::string UniqueB = Twine("??@" + Hash + "@").str();
196 assert(UniqueB.size() == 36);
197
198 // Truncate the name if necessary and append a hash of the name.
199 // The name length, hash included, is limited to 4096 bytes.
200 const size_t MaxTakeN = 4096;
201 size_t TakeN = std::min(MaxTakeN, BytesLeft - UniqueB.size() - 2) - 32;
202 computeHashString(Name, Hash);
203 std::string NameB = (Name.take_front(TakeN) + Hash).str();
204
205 StringRef N = NameB;
206 StringRef U = UniqueB;
207 error(IO.mapStringZ(N));
208 error(IO.mapStringZ(U));
209 } else {
210 error(IO.mapStringZ(Name));
211 error(IO.mapStringZ(UniqueName));
212 }
213 } else {
214 // Cap the length of the string at however many bytes we have available,
215 // plus one for the required null terminator.
216 auto N = StringRef(Name).take_front(BytesLeft - 1);
217 error(IO.mapStringZ(N));
218 }
219 } else {
220 // Reading & Streaming mode come after writing mode is executed for each
221 // record. Truncating large names are done during writing, so its not
222 // necessary to do it while reading or streaming.
223 error(IO.mapStringZ(Name, "Name"));
224 if (HasUniqueName)
225 error(IO.mapStringZ(UniqueName, "LinkageName"));
226 }
227
228 return Error::success();
229}
230
232 assert(!TypeKind && "Already in a type mapping!");
233 assert(!MemberKind && "Already in a member mapping!");
234
235 // FieldList and MethodList records can be any length because they can be
236 // split with continuation records. All other record types cannot be
237 // longer than the maximum record length.
238 std::optional<uint32_t> MaxLen;
239 if (CVR.kind() != TypeLeafKind::LF_FIELDLIST &&
240 CVR.kind() != TypeLeafKind::LF_METHODLIST)
241 MaxLen = MaxRecordLength - sizeof(RecordPrefix);
242 error(IO.beginRecord(MaxLen));
243 TypeKind = CVR.kind();
244
245 if (IO.isStreaming()) {
246 auto RecordKind = CVR.kind();
247 uint16_t RecordLen = CVR.length() - 2;
248 std::string RecordKindName = std::string(
249 getEnumName(IO, unsigned(RecordKind), ArrayRef(LeafTypeNames)));
250 error(IO.mapInteger(RecordLen, "Record length"));
251 error(IO.mapEnum(RecordKind, "Record kind: " + RecordKindName));
252 }
253 return Error::success();
254}
255
257 if (IO.isStreaming())
258 IO.emitRawComment(" " + getLeafTypeName(CVR.kind()) + " (0x" +
259 utohexstr(Index.getIndex()) + ")");
260 return visitTypeBegin(CVR);
261}
262
264 assert(TypeKind && "Not in a type mapping!");
265 assert(!MemberKind && "Still in a member mapping!");
266
267 error(IO.endRecord());
268
269 TypeKind.reset();
270 return Error::success();
271}
272
274 assert(TypeKind && "Not in a type mapping!");
275 assert(!MemberKind && "Already in a member mapping!");
276
277 // The largest possible subrecord is one in which there is a record prefix,
278 // followed by the subrecord, followed by a continuation, and that entire
279 // sequence spawns `MaxRecordLength` bytes. So the record's length is
280 // calculated as follows.
281
282 constexpr uint32_t ContinuationLength = 8;
283 error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix) -
285
286 MemberKind = Record.Kind;
287 if (IO.isStreaming()) {
288 std::string MemberKindName = std::string(getLeafTypeName(Record.Kind));
289 MemberKindName +=
290 " ( " +
291 (getEnumName(IO, unsigned(Record.Kind), ArrayRef(LeafTypeNames)))
292 .str() +
293 " )";
294 error(IO.mapEnum(Record.Kind, "Member kind: " + MemberKindName));
295 }
296 return Error::success();
297}
298
300 assert(TypeKind && "Not in a type mapping!");
301 assert(MemberKind && "Not in a member mapping!");
302
303 if (IO.isReading()) {
304 if (auto EC = IO.skipPadding())
305 return EC;
306 }
307
308 MemberKind.reset();
309 error(IO.endRecord());
310 return Error::success();
311}
312
313Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) {
314 std::string ModifierNames =
315 getFlagNames(IO, static_cast<uint16_t>(Record.Modifiers),
317 error(IO.mapInteger(Record.ModifiedType, "ModifiedType"));
318 error(IO.mapEnum(Record.Modifiers, "Modifiers" + ModifierNames));
319 return Error::success();
320}
321
322Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
324 std::string CallingConvName = std::string(getEnumName(
325 IO, uint8_t(Record.CallConv), ArrayRef(getCallingConventions())));
326 std::string FuncOptionNames =
327 getFlagNames(IO, static_cast<uint16_t>(Record.Options),
329 error(IO.mapInteger(Record.ReturnType, "ReturnType"));
330 error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));
331 error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));
332 error(IO.mapInteger(Record.ParameterCount, "NumParameters"));
333 error(IO.mapInteger(Record.ArgumentList, "ArgListType"));
334
335 return Error::success();
336}
337
338Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
340 std::string CallingConvName = std::string(getEnumName(
341 IO, uint8_t(Record.CallConv), ArrayRef(getCallingConventions())));
342 std::string FuncOptionNames =
343 getFlagNames(IO, static_cast<uint16_t>(Record.Options),
345 error(IO.mapInteger(Record.ReturnType, "ReturnType"));
346 error(IO.mapInteger(Record.ClassType, "ClassType"));
347 error(IO.mapInteger(Record.ThisType, "ThisType"));
348 error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallingConvName));
349 error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames));
350 error(IO.mapInteger(Record.ParameterCount, "NumParameters"));
351 error(IO.mapInteger(Record.ArgumentList, "ArgListType"));
352 error(IO.mapInteger(Record.ThisPointerAdjustment, "ThisAdjustment"));
353
354 return Error::success();
355}
356
357Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArgListRecord &Record) {
358 error(IO.mapVectorN<uint32_t>(
359 Record.ArgIndices,
360 [](CodeViewRecordIO &IO, TypeIndex &N) {
361 return IO.mapInteger(N, "Argument");
362 },
363 "NumArgs"));
364 return Error::success();
365}
366
367Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
368 StringListRecord &Record) {
369 error(IO.mapVectorN<uint32_t>(
370 Record.StringIndices,
371 [](CodeViewRecordIO &IO, TypeIndex &N) {
372 return IO.mapInteger(N, "Strings");
373 },
374 "NumStrings"));
375
376 return Error::success();
377}
378
379Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) {
380
381 SmallString<128> Attr("Attrs: ");
382
383 if (IO.isStreaming()) {
384 std::string PtrType = std::string(getEnumName(
385 IO, unsigned(Record.getPointerKind()), ArrayRef(getPtrKindNames())));
386 Attr += "[ Type: " + PtrType;
387
388 std::string PtrMode = std::string(getEnumName(
389 IO, unsigned(Record.getMode()), ArrayRef(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), ArrayRef(getPtrMemberRepNames())));
423 error(IO.mapEnum(M.Representation,
424 "Representation: " + PtrMemberGetRepresentation));
425 }
426
427 return Error::success();
428}
429
430Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ArrayRecord &Record) {
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
439Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ClassRecord &Record) {
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
459Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
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
473Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
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
487Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
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
495Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
496 VFTableShapeRecord &Record) {
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
524Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
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
544Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
545 error(IO.mapInteger(Record.Id, "Id"));
546 error(IO.mapStringZ(Record.String, "StringData"));
547
548 return Error::success();
549}
550
551Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
552 UdtSourceLineRecord &Record) {
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
560Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
561 UdtModSourceLineRecord &Record) {
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
570Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
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
578Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
579 MemberFuncIdRecord &Record) {
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
587Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
588 BuildInfoRecord &Record) {
589 error(IO.mapVectorN<uint16_t>(
590 Record.ArgIndices,
591 [](CodeViewRecordIO &IO, TypeIndex &N) {
592 return IO.mapInteger(N, "Argument");
593 },
594 "NumArgs"));
595
596 return Error::success();
597}
598
599Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
600 MethodOverloadListRecord &Record) {
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
608Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
609 FieldListRecord &Record) {
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
619Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
620 TypeServer2Record &Record) {
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
627Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
628 std::string ModeName = std::string(
629 getEnumName(IO, uint16_t(Record.Mode), ArrayRef(getLabelTypeEnum())));
630 error(IO.mapEnum(Record.Mode, "Mode: " + ModeName));
631 return Error::success();
632}
633
634Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
635 BaseClassRecord &Record) {
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
645Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
646 EnumeratorRecord &Record) {
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
658Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
659 DataMemberRecord &Record) {
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
670Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
671 OverloadedMethodRecord &Record) {
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
679Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
680 OneMethodRecord &Record) {
681 const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
682 MapOneMethodRecord Mapper(IsFromOverloadList);
683 return Mapper(IO, Record);
684}
685
686Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
687 NestedTypeRecord &Record) {
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
696Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
697 StaticDataMemberRecord &Record) {
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
708Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
709 VirtualBaseClassRecord &Record) {
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
722Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
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
731Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
732 ListContinuationRecord &Record) {
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
740Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
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
749Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
750 EndPrecompRecord &EndPrecomp) {
751 error(IO.mapInteger(EndPrecomp.Signature, "Signature"));
752 return Error::success();
753}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static constexpr uint32_t ContinuationLength
DXIL Resource Access
static LVOptions Options
Definition LVOptions.cpp:25
#define I(x, y, z)
Definition MD5.cpp:57
#define T
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:143
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
Definition MD5.cpp:188
static LLVM_ABI void stringifyResult(MD5Result &Result, SmallVectorImpl< char > &Str)
Translates the bytes in Res to a hex string that is deposited into Str.
Definition MD5.cpp:286
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
Definition MD5.cpp:233
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:146
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:582
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
LLVM Value Representation.
Definition Value.h:75
std::vector< TypeIndex > ArgIndices
Definition TypeRecord.h:246
MemberAccess getAccess() const
Definition TypeRecord.h:874
SmallVector< TypeIndex, MaxArgs > ArgIndices
Definition TypeRecord.h:686
uint32_t length() const
Definition CVRecord.h:40
LLVM_ABI Error mapInteger(TypeIndex &TypeInd, const Twine &Comment="")
LLVM_ABI Error mapStringZ(StringRef &Value, const Twine &Comment="")
Error mapEnum(T &Value, const Twine &Comment="")
LLVM_ABI uint32_t maxFieldLength() const
MemberAccess getAccess() const
Definition TypeRecord.h:796
MemberAccess getAccess() const
Definition TypeRecord.h:840
LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records together.
Definition TypeRecord.h:914
std::vector< OneMethodRecord > Methods
Definition TypeRecord.h:760
For method overload sets. LF_METHOD.
Definition TypeRecord.h:764
bool isRValueReferenceThisPtr() const
Definition TypeRecord.h:344
std::optional< MemberPointerInfo > MemberInfo
Definition TypeRecord.h:350
bool isLValueReferenceThisPtr() const
Definition TypeRecord.h:340
PointerMode getMode() const
Definition TypeRecord.h:305
PointerKind getPointerKind() const
Definition TypeRecord.h:300
std::vector< TypeIndex > StringIndices
Definition TypeRecord.h:260
A 32-bit type reference.
Definition TypeIndex.h:97
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
std::vector< StringRef > MethodNames
Definition TypeRecord.h:715
ArrayRef< VFTableSlotKind > getSlots() const
Definition TypeRecord.h:562
std::vector< VFTableSlotKind > Slots
Definition TypeRecord.h:571
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
Flag
These should be considered private to the implementation of the MCInstrDesc class.
LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getMethodOptionNames()
MethodKind
Part of member attribute flags. (CV_methodprop_e)
Definition CodeView.h:253
LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getCallingConventions()
LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getMemberAccessNames()
CVRecord< TypeLeafKind > CVType
Definition CVRecord.h:64
LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getPtrKindNames()
LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getPtrMemberRepNames()
LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getLabelTypeEnum()
LLVM_ABI Error visitMemberRecordStream(ArrayRef< uint8_t > FieldList, TypeVisitorCallbacks &Callbacks)
LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getTypeModifierNames()
MethodOptions
Equivalent to CV_fldattr_t bitfield.
Definition CodeView.h:264
LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getMemberKindNames()
MemberAccess
Source-level access specifier. (CV_access_e)
Definition CodeView.h:245
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition CodeView.h:35
LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getPtrModeNames()
LLVM_ABI ArrayRef< EnumEntry< uint8_t > > getFunctionOptionEnum()
LLVM_ABI ArrayRef< EnumEntry< uint16_t > > getClassOptionNames()
This is an optimization pass for GlobalISel generic memory operations.
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1622
ArrayRef(const T &OneElt) -> ArrayRef< T >
std::string itostr(int64_t X)
#define N