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