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"
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 std::string PropertiesNames = getFlagNames(
414 IO, static_cast<uint16_t>(Record.Options), getClassOptionNames());
415
416 // The original and *2 versions are handled in the same high level record as
417 // they're almost identical except for the widths of members. The *2 versions
418 // store the properties as 32 bits and the member count as an encoded integer.
419 TypeLeafKind Kind = CVR.kind();
420 if (Kind == TypeLeafKind::LF_STRUCTURE2 || Kind == TypeLeafKind::LF_CLASS2 ||
421 Kind == TypeLeafKind::LF_INTERFACE2) {
422 uint32_t Options = llvm::to_underlying(Record.Options);
423 error(IO.mapInteger(Options, "Properties" + PropertiesNames));
424 if (IO.isReading())
425 Record.Options = static_cast<ClassOptions>(Options);
426
427 error(IO.mapInteger(Record.FieldList, "FieldList"));
428 error(IO.mapInteger(Record.DerivationList, "DerivedFrom"));
429 error(IO.mapInteger(Record.VTableShape, "VShape"));
430 error(IO.mapEncodedInteger(Record.MemberCount, "MemberCount"));
431 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
432 error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
433 Record.hasUniqueName()));
434 } else {
435 assert(Kind == TypeLeafKind::LF_STRUCTURE ||
436 Kind == TypeLeafKind::LF_CLASS ||
437 Kind == TypeLeafKind::LF_INTERFACE);
438
439 // This is not an error to avoid failing to write all type records.
440 assert(
441 (IO.isReading() ||
442 Record.MemberCount <= std::numeric_limits<uint16_t>::max()) &&
443 "use the *2 versions of this record if there are 2^16 or more members");
444
445 error(IO.mapTruncInteger<uint16_t>(Record.MemberCount, "MemberCount"));
446 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
447 error(IO.mapInteger(Record.FieldList, "FieldList"));
448 error(IO.mapInteger(Record.DerivationList, "DerivedFrom"));
449 error(IO.mapInteger(Record.VTableShape, "VShape"));
450 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
451 error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
452 Record.hasUniqueName()));
453 }
454
455 return Error::success();
456}
457
458Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) {
459 std::string PropertiesNames = getFlagNames(
460 IO, static_cast<uint16_t>(Record.Options), getClassOptionNames());
461
462 if (CVR.kind() == LF_UNION2) {
463 uint32_t Options = llvm::to_underlying(Record.Options);
464 error(IO.mapInteger(Options, "Properties" + PropertiesNames));
465 if (IO.isReading())
466 Record.Options = static_cast<ClassOptions>(Options);
467
468 error(IO.mapInteger(Record.FieldList, "FieldList"));
469 error(IO.mapEncodedInteger(Record.MemberCount, "MemberCount"));
470 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
471 error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
472 Record.hasUniqueName()));
473 } else {
474 // This is not an error to avoid failing to write all type records.
475 assert(
476 (IO.isReading() ||
477 Record.MemberCount <= std::numeric_limits<uint16_t>::max()) &&
478 "use the *2 versions of this record if there are 2^16 or more members");
479
480 error(IO.mapTruncInteger<uint16_t>(Record.MemberCount, "MemberCount"));
481
482 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
483 error(IO.mapInteger(Record.FieldList, "FieldList"));
484 error(IO.mapEncodedInteger(Record.Size, "SizeOf"));
485 error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
486 Record.hasUniqueName()));
487 }
488
489 return Error::success();
490}
491
492Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) {
493 std::string PropertiesNames = getFlagNames(
494 IO, static_cast<uint16_t>(Record.Options), getClassOptionNames());
495 error(IO.mapTruncInteger<uint16_t>(Record.MemberCount, "NumEnumerators"));
496 error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames));
497 error(IO.mapInteger(Record.UnderlyingType, "UnderlyingType"));
498 error(IO.mapInteger(Record.FieldList, "FieldListType"));
499 error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName,
500 Record.hasUniqueName()));
501
502 return Error::success();
503}
504
505Error TypeRecordMapping::visitKnownRecord(CVType &CVR, BitFieldRecord &Record) {
506 error(IO.mapInteger(Record.Type, "Type"));
507 error(IO.mapInteger(Record.BitSize, "BitSize"));
508 error(IO.mapInteger(Record.BitOffset, "BitOffset"));
509
510 return Error::success();
511}
512
513Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
514 VFTableShapeRecord &Record) {
515 uint16_t Size;
516 if (!IO.isReading()) {
517 ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
518 Size = Slots.size();
519 error(IO.mapInteger(Size, "VFEntryCount"));
520
521 for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
522 uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
523 if ((SlotIndex + 1) < Slots.size()) {
524 Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
525 }
526 error(IO.mapInteger(Byte));
527 }
528 } else {
529 error(IO.mapInteger(Size));
530 for (uint16_t I = 0; I < Size; I += 2) {
531 uint8_t Byte;
532 error(IO.mapInteger(Byte));
533 Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte >> 4));
534 if ((I + 1) < Size)
535 Record.Slots.push_back(static_cast<VFTableSlotKind>(Byte & 0xF));
536 }
537 }
538
539 return Error::success();
540}
541
542Error TypeRecordMapping::visitKnownRecord(CVType &CVR, VFTableRecord &Record) {
543 error(IO.mapInteger(Record.CompleteClass, "CompleteClass"));
544 error(IO.mapInteger(Record.OverriddenVFTable, "OverriddenVFTable"));
545 error(IO.mapInteger(Record.VFPtrOffset, "VFPtrOffset"));
546 uint32_t NamesLen = 0;
547 if (!IO.isReading()) {
548 for (auto Name : Record.MethodNames)
549 NamesLen += Name.size() + 1;
550 }
551 error(IO.mapInteger(NamesLen));
552 error(IO.mapVectorTail(
553 Record.MethodNames,
554 [](CodeViewRecordIO &IO, StringRef &S) {
555 return IO.mapStringZ(S, "MethodName");
556 },
557 "VFTableName"));
558
559 return Error::success();
560}
561
562Error TypeRecordMapping::visitKnownRecord(CVType &CVR, StringIdRecord &Record) {
563 error(IO.mapInteger(Record.Id, "Id"));
564 error(IO.mapStringZ(Record.String, "StringData"));
565
566 return Error::success();
567}
568
569Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
570 UdtSourceLineRecord &Record) {
571 error(IO.mapInteger(Record.UDT, "UDT"));
572 error(IO.mapInteger(Record.SourceFile, "SourceFile"));
573 error(IO.mapInteger(Record.LineNumber, "LineNumber"));
574
575 return Error::success();
576}
577
578Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
579 UdtModSourceLineRecord &Record) {
580 error(IO.mapInteger(Record.UDT, "UDT"));
581 error(IO.mapInteger(Record.SourceFile, "SourceFile"));
582 error(IO.mapInteger(Record.LineNumber, "LineNumber"));
583 error(IO.mapInteger(Record.Module, "Module"));
584
585 return Error::success();
586}
587
588Error TypeRecordMapping::visitKnownRecord(CVType &CVR, FuncIdRecord &Record) {
589 error(IO.mapInteger(Record.ParentScope, "ParentScope"));
590 error(IO.mapInteger(Record.FunctionType, "FunctionType"));
591 error(IO.mapStringZ(Record.Name, "Name"));
592
593 return Error::success();
594}
595
596Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
597 MemberFuncIdRecord &Record) {
598 error(IO.mapInteger(Record.ClassType, "ClassType"));
599 error(IO.mapInteger(Record.FunctionType, "FunctionType"));
600 error(IO.mapStringZ(Record.Name, "Name"));
601
602 return Error::success();
603}
604
605Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
606 BuildInfoRecord &Record) {
607 error(IO.mapVectorN<uint16_t>(
608 Record.ArgIndices,
609 [](CodeViewRecordIO &IO, TypeIndex &N) {
610 return IO.mapInteger(N, "Argument");
611 },
612 "NumArgs"));
613
614 return Error::success();
615}
616
617Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
618 MethodOverloadListRecord &Record) {
619 // TODO: Split the list into multiple records if it's longer than 64KB, using
620 // a subrecord of TypeRecordKind::Index to chain the records together.
621 error(IO.mapVectorTail(Record.Methods, MapOneMethodRecord(true), "Method"));
622
623 return Error::success();
624}
625
626Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
627 FieldListRecord &Record) {
628 if (IO.isStreaming()) {
629 if (auto EC = codeview::visitMemberRecordStream(Record.Data, *this))
630 return EC;
631 } else
632 error(IO.mapByteVectorTail(Record.Data));
633
634 return Error::success();
635}
636
637Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
638 TypeServer2Record &Record) {
639 error(IO.mapGuid(Record.Guid, "Guid"));
640 error(IO.mapInteger(Record.Age, "Age"));
641 error(IO.mapStringZ(Record.Name, "Name"));
642 return Error::success();
643}
644
645Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) {
646 std::string ModeName =
647 std::string(getEnumName(IO, uint16_t(Record.Mode), getLabelTypeEnum()));
648 error(IO.mapEnum(Record.Mode, "Mode: " + ModeName));
649 return Error::success();
650}
651
652Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
653 BaseClassRecord &Record) {
654 std::string Attrs = getMemberAttributes(
656 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
657 error(IO.mapInteger(Record.Type, "BaseType"));
658 error(IO.mapEncodedInteger(Record.Offset, "BaseOffset"));
659
660 return Error::success();
661}
662
663Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
664 EnumeratorRecord &Record) {
665 std::string Attrs = getMemberAttributes(
667 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
668
669 // FIXME: Handle full APInt such as __int128.
670 error(IO.mapEncodedInteger(Record.Value, "EnumValue"));
671 error(IO.mapStringZ(Record.Name, "Name"));
672
673 return Error::success();
674}
675
676Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
677 DataMemberRecord &Record) {
678 std::string Attrs = getMemberAttributes(
680 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
681 error(IO.mapInteger(Record.Type, "Type"));
682 error(IO.mapEncodedInteger(Record.FieldOffset, "FieldOffset"));
683 error(IO.mapStringZ(Record.Name, "Name"));
684
685 return Error::success();
686}
687
688Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
689 OverloadedMethodRecord &Record) {
690 error(IO.mapInteger(Record.NumOverloads, "MethodCount"));
691 error(IO.mapInteger(Record.MethodList, "MethodListIndex"));
692 error(IO.mapStringZ(Record.Name, "Name"));
693
694 return Error::success();
695}
696
697Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
698 OneMethodRecord &Record) {
699 const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
700 MapOneMethodRecord Mapper(IsFromOverloadList);
701 return Mapper(IO, Record);
702}
703
704Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
705 NestedTypeRecord &Record) {
706 uint16_t Padding = 0;
707 error(IO.mapInteger(Padding, "Padding"));
708 error(IO.mapInteger(Record.Type, "Type"));
709 error(IO.mapStringZ(Record.Name, "Name"));
710
711 return Error::success();
712}
713
714Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
715 StaticDataMemberRecord &Record) {
716
717 std::string Attrs = getMemberAttributes(
719 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
720 error(IO.mapInteger(Record.Type, "Type"));
721 error(IO.mapStringZ(Record.Name, "Name"));
722
723 return Error::success();
724}
725
726Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
727 VirtualBaseClassRecord &Record) {
728
729 std::string Attrs = getMemberAttributes(
731 error(IO.mapInteger(Record.Attrs.Attrs, "Attrs: " + Attrs));
732 error(IO.mapInteger(Record.BaseType, "BaseType"));
733 error(IO.mapInteger(Record.VBPtrType, "VBPtrType"));
734 error(IO.mapEncodedInteger(Record.VBPtrOffset, "VBPtrOffset"));
735 error(IO.mapEncodedInteger(Record.VTableIndex, "VBTableIndex"));
736
737 return Error::success();
738}
739
740Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
741 VFPtrRecord &Record) {
742 uint16_t Padding = 0;
743 error(IO.mapInteger(Padding, "Padding"));
744 error(IO.mapInteger(Record.Type, "Type"));
745
746 return Error::success();
747}
748
749Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR,
750 ListContinuationRecord &Record) {
751 uint16_t Padding = 0;
752 error(IO.mapInteger(Padding, "Padding"));
753 error(IO.mapInteger(Record.ContinuationIndex, "ContinuationIndex"));
754
755 return Error::success();
756}
757
758Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
759 PrecompRecord &Precomp) {
760 error(IO.mapInteger(Precomp.StartTypeIndex, "StartIndex"));
761 error(IO.mapInteger(Precomp.TypesCount, "Count"));
762 error(IO.mapInteger(Precomp.Signature, "Signature"));
763 error(IO.mapStringZ(Precomp.PrecompFilePath, "PrecompFile"));
764 return Error::success();
765}
766
767Error TypeRecordMapping::visitKnownRecord(CVType &CVR,
768 EndPrecompRecord &EndPrecomp) {
769 error(IO.mapInteger(EndPrecomp.Signature, "Signature"));
770 return Error::success();
771}
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:926
For method overload sets. LF_METHOD.
Definition TypeRecord.h:776
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