45#define TYPE_RECORD(ename, value, name) \
48#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
55template <
typename T,
typename TFlag>
59 return std::string(
"");
62 for (
const auto &Flag : Flags)
67 return LHS->name() <
RHS->name();
70 std::string FlagLabel;
82 if (!FlagLabel.empty()) {
83 std::string LabelWithBraces(
" ( ");
84 LabelWithBraces += FlagLabel +
" )";
85 return LabelWithBraces;
90template <
typename T,
typename TEnum>
101 std::string AccessSpecifier =
103 std::string MemberAttrs(AccessSpecifier);
117struct MapOneMethodRecord {
118 explicit MapOneMethodRecord(
bool IsFromOverloadList)
119 : IsFromOverloadList(IsFromOverloadList) {}
121 Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method)
const {
122 std::string
Attrs = getMemberAttributes(
125 if (IsFromOverloadList) {
130 if (
Method.isIntroducingVirtual()) {
133 Method.VFTableOffset = -1;
135 if (!IsFromOverloadList)
142 bool IsFromOverloadList;
165 size_t BytesNeeded = Name.size() + UniqueName.
size() + 2;
166 if (BytesNeeded > BytesLeft) {
173 std::string UniqueB =
Twine(
"??@" + Hash +
"@").
str();
174 assert(UniqueB.size() == 36);
178 const size_t MaxTakeN = 4096;
179 size_t TakeN = std::min(MaxTakeN, BytesLeft - UniqueB.size() - 2) - 32;
181 std::string NameB = (Name.take_front(TakeN) + Hash).str();
210 assert(!TypeKind &&
"Already in a type mapping!");
211 assert(!MemberKind &&
"Already in a member mapping!");
216 std::optional<uint32_t> MaxLen;
217 if (CVR.
kind() != TypeLeafKind::LF_FIELDLIST &&
218 CVR.
kind() != TypeLeafKind::LF_METHODLIST)
220 error(IO.beginRecord(MaxLen));
221 TypeKind = CVR.
kind();
223 if (IO.isStreaming()) {
224 auto RecordKind = CVR.
kind();
226 std::string RecordKindName =
228 error(IO.mapInteger(RecordLen,
"Record length"));
229 error(IO.mapEnum(RecordKind,
"Record kind: " + RecordKindName));
235 if (IO.isStreaming())
242 assert(TypeKind &&
"Not in a type mapping!");
243 assert(!MemberKind &&
"Still in a member mapping!");
245 error(IO.endRecord());
252 assert(TypeKind &&
"Not in a type mapping!");
253 assert(!MemberKind &&
"Already in a member mapping!");
265 if (IO.isStreaming()) {
270 error(IO.mapEnum(
Record.Kind,
"Member kind: " + MemberKindName));
276 assert(TypeKind &&
"Not in a type mapping!");
277 assert(MemberKind &&
"Not in a member mapping!");
279 if (IO.isReading()) {
280 if (
auto EC = IO.skipPadding())
285 error(IO.endRecord());
290 std::string ModifierNames = getFlagNames(
297Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
299 std::string CallingConvName = std::string(
301 std::string FuncOptionNames = getFlagNames(
312Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
314 std::string CallingConvName = std::string(
316 std::string FuncOptionNames = getFlagNames(
331 error(IO.mapVectorN<uint32_t>(
333 [](CodeViewRecordIO &IO, TypeIndex &
N) {
334 return IO.mapInteger(N,
"Argument");
340Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
342 error(IO.mapVectorN<uint32_t>(
344 [](CodeViewRecordIO &IO, TypeIndex &
N) {
345 return IO.mapInteger(N,
"Strings");
354 SmallString<128> Attr(
"Attrs: ");
356 if (IO.isStreaming()) {
357 std::string PtrType = std::string(
359 Attr +=
"[ Type: " + PtrType;
361 std::string PtrMode = std::string(
363 Attr +=
", Mode: " + PtrMode;
365 auto PtrSizeOf =
Record.getSize();
366 Attr +=
", SizeOf: " +
itostr(PtrSizeOf);
373 Attr +=
", isVolatile";
375 Attr +=
", isUnaligned";
377 Attr +=
", isRestricted";
378 if (
Record.isLValueReferenceThisPtr())
379 Attr +=
", isThisPtr&";
380 if (
Record.isRValueReferenceThisPtr())
381 Attr +=
", isThisPtr&&";
385 error(IO.mapInteger(
Record.ReferentType,
"PointeeType"));
388 if (
Record.isPointerToMember()) {
390 Record.MemberInfo.emplace();
392 MemberPointerInfo &
M = *
Record.MemberInfo;
393 error(IO.mapInteger(
M.ContainingType,
"ClassType"));
394 std::string PtrMemberGetRepresentation = std::string(
396 error(IO.mapEnum(
M.Representation,
397 "Representation: " + PtrMemberGetRepresentation));
404 error(IO.mapInteger(
Record.ElementType,
"ElementType"));
405 error(IO.mapInteger(
Record.IndexType,
"IndexType"));
406 error(IO.mapEncodedInteger(
Record.Size,
"SizeOf"));
413 assert((CVR.
kind() == TypeLeafKind::LF_STRUCTURE) ||
414 (CVR.
kind() == TypeLeafKind::LF_CLASS) ||
415 (CVR.
kind() == TypeLeafKind::LF_INTERFACE));
417 std::string PropertiesNames = getFlagNames(
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"));
432 std::string PropertiesNames = getFlagNames(
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"));
445 std::string PropertiesNames = getFlagNames(
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"));
460 error(IO.mapInteger(
Record.BitOffset,
"BitOffset"));
465Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
468 if (!IO.isReading()) {
469 ArrayRef<VFTableSlotKind> Slots =
Record.getSlots();
471 error(IO.mapInteger(
Size,
"VFEntryCount"));
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]);
482 for (uint16_t
I = 0;
I <
Size;
I += 2) {
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;
503 error(IO.mapInteger(NamesLen));
504 error(IO.mapVectorTail(
506 [](CodeViewRecordIO &IO, StringRef &S) {
507 return IO.mapStringZ(S,
"MethodName");
521Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
524 error(IO.mapInteger(
Record.SourceFile,
"SourceFile"));
525 error(IO.mapInteger(
Record.LineNumber,
"LineNumber"));
530Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
533 error(IO.mapInteger(
Record.SourceFile,
"SourceFile"));
534 error(IO.mapInteger(
Record.LineNumber,
"LineNumber"));
541 error(IO.mapInteger(
Record.ParentScope,
"ParentScope"));
542 error(IO.mapInteger(
Record.FunctionType,
"FunctionType"));
548Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
550 error(IO.mapInteger(
Record.ClassType,
"ClassType"));
551 error(IO.mapInteger(
Record.FunctionType,
"FunctionType"));
557Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
559 error(IO.mapVectorN<uint16_t>(
561 [](CodeViewRecordIO &IO, TypeIndex &
N) {
562 return IO.mapInteger(N,
"Argument");
569Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
573 error(IO.mapVectorTail(
Record.Methods, MapOneMethodRecord(
true),
"Method"));
578Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
580 if (IO.isStreaming()) {
589Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
598 std::string ModeName =
600 error(IO.mapEnum(
Record.Mode,
"Mode: " + ModeName));
606 std::string
Attrs = getMemberAttributes(
608 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
610 error(IO.mapEncodedInteger(
Record.Offset,
"BaseOffset"));
617 std::string
Attrs = getMemberAttributes(
619 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
622 error(IO.mapEncodedInteger(
Record.Value,
"EnumValue"));
630 std::string
Attrs = getMemberAttributes(
632 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
634 error(IO.mapEncodedInteger(
Record.FieldOffset,
"FieldOffset"));
642 error(IO.mapInteger(
Record.NumOverloads,
"MethodCount"));
643 error(IO.mapInteger(
Record.MethodList,
"MethodListIndex"));
651 const bool IsFromOverloadList = (TypeKind == LF_METHODLIST);
652 MapOneMethodRecord Mapper(IsFromOverloadList);
653 return Mapper(IO, Record);
659 error(IO.mapInteger(Padding,
"Padding"));
669 std::string
Attrs = getMemberAttributes(
671 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
681 std::string
Attrs = getMemberAttributes(
683 error(IO.mapInteger(
Record.Attrs.Attrs,
"Attrs: " + Attrs));
685 error(IO.mapInteger(
Record.VBPtrType,
"VBPtrType"));
686 error(IO.mapEncodedInteger(
Record.VBPtrOffset,
"VBPtrOffset"));
687 error(IO.mapEncodedInteger(
Record.VTableIndex,
"VBTableIndex"));
695 error(IO.mapInteger(Padding,
"Padding"));
704 error(IO.mapInteger(Padding,
"Padding"));
705 error(IO.mapInteger(
Record.ContinuationIndex,
"ContinuationIndex"));
710Error TypeRecordMapping::visitKnownRecord(
CVType &CVR,
719Error 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)
std::string itostr(int64_t X)