46#define TYPE_RECORD(ename, value, name) \
49#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
56template <
typename T,
typename TFlag>
60 return std::string(
"");
63 for (
const auto &Flag : Flags)
68 return LHS->name() <
RHS->name();
71 std::string FlagLabel;
83 if (!FlagLabel.empty()) {
84 std::string LabelWithBraces(
" ( ");
85 LabelWithBraces += FlagLabel +
" )";
86 return LabelWithBraces;
91template <
typename T,
typename TEnum>
102 std::string AccessSpecifier =
104 std::string MemberAttrs(AccessSpecifier);
118struct MapOneMethodRecord {
119 explicit MapOneMethodRecord(
bool IsFromOverloadList)
120 : IsFromOverloadList(IsFromOverloadList) {}
122 Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method)
const {
123 std::string
Attrs = getMemberAttributes(
126 if (IsFromOverloadList) {
131 if (
Method.isIntroducingVirtual()) {
134 Method.VFTableOffset = -1;
136 if (!IsFromOverloadList)
143 bool IsFromOverloadList;
166 size_t BytesNeeded = Name.size() + UniqueName.
size() + 2;
167 if (BytesNeeded > BytesLeft) {
174 std::string UniqueB =
Twine(
"??@" + Hash +
"@").
str();
175 assert(UniqueB.size() == 36);
179 const size_t MaxTakeN = 4096;
180 size_t TakeN = std::min(MaxTakeN, BytesLeft - UniqueB.size() - 2) - 32;
182 std::string NameB = (Name.take_front(TakeN) + Hash).str();
211 assert(!TypeKind &&
"Already in a type mapping!");
212 assert(!MemberKind &&
"Already in a member mapping!");
217 std::optional<uint32_t> MaxLen;
218 if (CVR.
kind() != TypeLeafKind::LF_FIELDLIST &&
219 CVR.
kind() != TypeLeafKind::LF_METHODLIST)
221 error(IO.beginRecord(MaxLen));
222 TypeKind = CVR.
kind();
224 if (IO.isStreaming()) {
225 auto RecordKind = CVR.
kind();
226 uint16_t RecordLen = CVR.
length() - 2;
227 std::string RecordKindName =
229 error(IO.mapInteger(RecordLen,
"Record length"));
230 error(IO.mapEnum(RecordKind,
"Record kind: " + RecordKindName));
236 if (IO.isStreaming())
243 assert(TypeKind &&
"Not in a type mapping!");
244 assert(!MemberKind &&
"Still in a member mapping!");
246 error(IO.endRecord());
253 assert(TypeKind &&
"Not in a type mapping!");
254 assert(!MemberKind &&
"Already in a member mapping!");
266 if (IO.isStreaming()) {
271 error(IO.mapEnum(
Record.Kind,
"Member kind: " + MemberKindName));
277 assert(TypeKind &&
"Not in a type mapping!");
278 assert(MemberKind &&
"Not in a member mapping!");
280 if (IO.isReading()) {
281 if (
auto EC = IO.skipPadding())
286 error(IO.endRecord());
291 std::string ModifierNames = getFlagNames(
298Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
300 std::string CallingConvName = std::string(
302 std::string FuncOptionNames = getFlagNames(
313Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
315 std::string CallingConvName = std::string(
317 std::string FuncOptionNames = getFlagNames(
332 error(IO.mapVectorN<uint32_t>(
334 [](CodeViewRecordIO &IO, TypeIndex &
N) {
335 return IO.mapInteger(N,
"Argument");
341Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
343 error(IO.mapVectorN<uint32_t>(
345 [](CodeViewRecordIO &IO, TypeIndex &
N) {
346 return IO.mapInteger(N,
"Strings");
355 SmallString<128> Attr(
"Attrs: ");
357 if (IO.isStreaming()) {
358 std::string PtrType = std::string(
360 Attr +=
"[ Type: " + PtrType;
362 std::string PtrMode = std::string(
364 Attr +=
", Mode: " + PtrMode;
366 auto PtrSizeOf =
Record.getSize();
367 Attr +=
", SizeOf: " +
itostr(PtrSizeOf);
374 Attr +=
", isVolatile";
376 Attr +=
", isUnaligned";
378 Attr +=
", isRestricted";
379 if (
Record.isLValueReferenceThisPtr())
380 Attr +=
", isThisPtr&";
381 if (
Record.isRValueReferenceThisPtr())
382 Attr +=
", isThisPtr&&";
386 error(IO.mapInteger(
Record.ReferentType,
"PointeeType"));
389 if (
Record.isPointerToMember()) {
391 Record.MemberInfo.emplace();
393 MemberPointerInfo &
M = *
Record.MemberInfo;
394 error(IO.mapInteger(
M.ContainingType,
"ClassType"));
395 std::string PtrMemberGetRepresentation = std::string(
397 error(IO.mapEnum(
M.Representation,
398 "Representation: " + PtrMemberGetRepresentation));
405 error(IO.mapInteger(
Record.ElementType,
"ElementType"));
406 error(IO.mapInteger(
Record.IndexType,
"IndexType"));
407 error(IO.mapEncodedInteger(
Record.Size,
"SizeOf"));
414 std::string PropertiesNames = getFlagNames(
421 if (Kind == TypeLeafKind::LF_STRUCTURE2 || Kind == TypeLeafKind::LF_CLASS2 ||
422 Kind == TypeLeafKind::LF_INTERFACE2) {
424 error(IO.mapInteger(
Options,
"Properties" + PropertiesNames));
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"));
436 assert(Kind == TypeLeafKind::LF_STRUCTURE ||
437 Kind == TypeLeafKind::LF_CLASS ||
438 Kind == TypeLeafKind::LF_INTERFACE);
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");
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"));
460 std::string PropertiesNames = getFlagNames(
463 if (CVR.
kind() == LF_UNION2) {
465 error(IO.mapInteger(
Options,
"Properties" + PropertiesNames));
469 error(IO.mapInteger(
Record.FieldList,
"FieldList"));
470 error(IO.mapEncodedInteger(
Record.MemberCount,
"MemberCount"));
471 error(IO.mapEncodedInteger(
Record.Size,
"SizeOf"));
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");
481 error(IO.mapTruncInteger<uint16_t>(
Record.MemberCount,
"MemberCount"));
483 error(IO.mapEnum(
Record.Options,
"Properties" + PropertiesNames));
484 error(IO.mapInteger(
Record.FieldList,
"FieldList"));
485 error(IO.mapEncodedInteger(
Record.Size,
"SizeOf"));
494 std::string PropertiesNames = getFlagNames(
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"));
509 error(IO.mapInteger(
Record.BitOffset,
"BitOffset"));
514Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
517 if (!IO.isReading()) {
518 ArrayRef<VFTableSlotKind> Slots =
Record.getSlots();
520 error(IO.mapInteger(
Size,
"VFEntryCount"));
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]);
531 for (uint16_t
I = 0;
I <
Size;
I += 2) {
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;
552 error(IO.mapInteger(NamesLen));
553 error(IO.mapVectorTail(
555 [](CodeViewRecordIO &IO, StringRef &S) {
556 return IO.mapStringZ(S,
"MethodName");
570Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
573 error(IO.mapInteger(
Record.SourceFile,
"SourceFile"));
574 error(IO.mapInteger(
Record.LineNumber,
"LineNumber"));
579Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
582 error(IO.mapInteger(
Record.SourceFile,
"SourceFile"));
583 error(IO.mapInteger(
Record.LineNumber,
"LineNumber"));
590 error(IO.mapInteger(
Record.ParentScope,
"ParentScope"));
591 error(IO.mapInteger(
Record.FunctionType,
"FunctionType"));
597Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
599 error(IO.mapInteger(
Record.ClassType,
"ClassType"));
600 error(IO.mapInteger(
Record.FunctionType,
"FunctionType"));
606Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
608 error(IO.mapVectorN<uint16_t>(
610 [](CodeViewRecordIO &IO, TypeIndex &
N) {
611 return IO.mapInteger(N,
"Argument");
618Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
622 error(IO.mapVectorTail(
Record.Methods, MapOneMethodRecord(
true),
"Method"));
627Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
629 if (IO.isStreaming()) {
638Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
647 std::string ModeName =
649 error(IO.mapEnum(
Record.Mode,
"Mode: " + ModeName));
655 std::string
Attrs = getMemberAttributes(
657 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
659 error(IO.mapEncodedInteger(
Record.Offset,
"BaseOffset"));
666 std::string
Attrs = getMemberAttributes(
668 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
671 error(IO.mapEncodedInteger(
Record.Value,
"EnumValue"));
679 std::string
Attrs = getMemberAttributes(
681 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
683 error(IO.mapEncodedInteger(
Record.FieldOffset,
"FieldOffset"));
691 error(IO.mapInteger(
Record.NumOverloads,
"MethodCount"));
692 error(IO.mapInteger(
Record.MethodList,
"MethodListIndex"));
700 const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
701 MapOneMethodRecord
Mapper(IsFromOverloadList);
702 return Mapper(IO, Record);
708 error(IO.mapInteger(Padding,
"Padding"));
718 std::string
Attrs = getMemberAttributes(
720 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
730 std::string
Attrs = getMemberAttributes(
732 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
734 error(IO.mapInteger(
Record.VBPtrType,
"VBPtrType"));
735 error(IO.mapEncodedInteger(
Record.VBPtrOffset,
"VBPtrOffset"));
736 error(IO.mapEncodedInteger(
Record.VTableIndex,
"VBTableIndex"));
744 error(IO.mapInteger(Padding,
"Padding"));
753 error(IO.mapInteger(Padding,
"Padding"));
754 error(IO.mapInteger(
Record.ContinuationIndex,
"ContinuationIndex"));
759Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
768Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static constexpr uint32_t ContinuationLength
This file defines the SmallString class.
This file defines the SmallVector class.
static StringRef getLeafTypeName(TypeLeafKind LT)
static void computeHashString(StringRef Name, SmallString< 32 > &StringifiedHash)
static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName)
size_t size() const
Get the array size.
StringRef toString(TValue Value, unsigned StrIdx=0) const
::llvm::EnumString< T, NumStrs > EnumString
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Updates the hash for the byte stream provided.
static LLVM_ABI void stringifyResult(MD5Result &Result, SmallVectorImpl< char > &Str)
Translates the bytes in Res to a hex string that is deposited into Str.
LLVM_ABI void final(MD5Result &Result)
Finishes off the hash and puts the result in result.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
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.
constexpr size_t size() const
Get the string size.
StringRef take_front(size_t N=1) const
Return a StringRef equal to 'this' but with only the first N elements remaining.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
LLVM Value Representation.
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.
For method overload sets. LF_METHOD.
StringRef PrecompFilePath
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)
LLVM_ABI EnumStrings< uint8_t, 1 > getCallingConventions()
CVRecord< TypeLeafKind > CVType
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.
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)
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
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)
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
std::string itostr(int64_t X)