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