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