Index: llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h =================================================================== --- llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h +++ llvm/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h @@ -33,6 +33,8 @@ virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0; virtual void EmitBinaryData(StringRef Data) = 0; virtual void AddComment(const Twine &T) = 0; + virtual bool isVerboseAsm() = 0; + virtual StringRef getTypeName(TypeIndex TI) = 0; virtual ~CodeViewRecordStreamer() = default; }; @@ -225,7 +227,7 @@ } void emitComment(const Twine &Comment) { - if (isStreaming()) { + if (isStreaming() && Streamer->isVerboseAsm()) { Twine TComment(Comment); if (!TComment.isTriviallyEmpty()) Streamer->AddComment(TComment); Index: llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -98,7 +98,8 @@ namespace { class CVMCAdapter : public CodeViewRecordStreamer { public: - CVMCAdapter(MCStreamer &OS) : OS(&OS) {} + CVMCAdapter(MCStreamer &OS, TypeCollection &TypeTable) + : OS(&OS), TypeTable(TypeTable) {} void EmitBytes(StringRef Data) { OS->EmitBytes(Data); } @@ -110,8 +111,22 @@ void AddComment(const Twine &T) { OS->AddComment(T); } + bool isVerboseAsm() { return OS->isVerboseAsm(); } + + StringRef getTypeName(TypeIndex TI) { + StringRef TypeName; + if (!TI.isNoneType()) { + if (TI.isSimple()) + TypeName = TypeIndex::simpleTypeName(TI); + else + TypeName = TypeTable.getTypeName(TI); + } + return TypeName; + } + private: MCStreamer *OS = nullptr; + TypeCollection &TypeTable; }; } // namespace @@ -617,13 +632,6 @@ OS.EmitBytes(NullTerminatedString); } -static StringRef getTypeLeafName(TypeLeafKind TypeKind) { - for (const EnumEntry &EE : getTypeLeafNames()) - if (EE.Value == TypeKind) - return EE.Name; - return ""; -} - void CodeViewDebug::emitTypeInformation() { if (TypeTable.empty()) return; @@ -640,11 +648,11 @@ } TypeTableCollection Table(TypeTable.records()); + TypeVisitorCallbackPipeline Pipeline; SmallString<512> CommentBlock; raw_svector_ostream CommentOS(CommentBlock); std::unique_ptr SP; std::unique_ptr TDV; - TypeVisitorCallbackPipeline Pipeline; if (OS.isVerboseAsm()) { // To construct block comment describing the type record for readability. @@ -655,7 +663,7 @@ } // To emit type record using Codeview MCStreamer adapter - CVMCAdapter CVMCOS(OS); + CVMCAdapter CVMCOS(OS, Table); TypeRecordMapping typeMapping(CVMCOS); Pipeline.addCallbackToPipeline(typeMapping); @@ -665,16 +673,6 @@ CVType Record = Table.getType(*B); CommentBlock.clear(); - - auto RecordLen = Record.length(); - auto RecordKind = Record.kind(); - if (OS.isVerboseAsm()) - CVMCOS.AddComment("Record length"); - CVMCOS.EmitIntValue(RecordLen - 2, 2); - if (OS.isVerboseAsm()) - CVMCOS.AddComment("Record kind: " + getTypeLeafName(RecordKind)); - CVMCOS.EmitIntValue(RecordKind, sizeof(RecordKind)); - Error E = codeview::visitTypeRecord(Record, *B, Pipeline); if (E) { Index: llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp +++ llvm/lib/DebugInfo/CodeView/CodeViewRecordIO.cpp @@ -126,7 +126,11 @@ Error CodeViewRecordIO::mapInteger(TypeIndex &TypeInd, const Twine &Comment) { if (isStreaming()) { - emitComment(Comment); + StringRef TypeNameStr = Streamer->getTypeName(TypeInd); + if (!TypeNameStr.empty()) + emitComment(Comment + ": " + TypeNameStr); + else + emitComment(Comment); Streamer->EmitIntValue(TypeInd.getIndex(), sizeof(TypeInd.getIndex())); incrStreamedLen(sizeof(TypeInd.getIndex())); } else if (isWriting()) { Index: llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp =================================================================== --- llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp +++ llvm/lib/DebugInfo/CodeView/TypeRecordMapping.cpp @@ -7,21 +7,234 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/DebugInfo/CodeView/EnumTables.h" using namespace llvm; using namespace llvm::codeview; +namespace { + #define error(X) \ if (auto EC = X) \ return EC; -namespace { +static const EnumEntry LeafTypeNames[] = { +#define CV_TYPE(enum, val) {#enum, enum}, +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" +}; + +#define ENUM_ENTRY(enum_class, enum) \ + { #enum, std::underlying_type < enum_class> ::type(enum_class::enum) } + +static const EnumEntry ClassOptionNames[] = { + ENUM_ENTRY(ClassOptions, Packed), + ENUM_ENTRY(ClassOptions, HasConstructorOrDestructor), + ENUM_ENTRY(ClassOptions, HasOverloadedOperator), + ENUM_ENTRY(ClassOptions, Nested), + ENUM_ENTRY(ClassOptions, ContainsNestedClass), + ENUM_ENTRY(ClassOptions, HasOverloadedAssignmentOperator), + ENUM_ENTRY(ClassOptions, HasConversionOperator), + ENUM_ENTRY(ClassOptions, ForwardReference), + ENUM_ENTRY(ClassOptions, Scoped), + ENUM_ENTRY(ClassOptions, HasUniqueName), + ENUM_ENTRY(ClassOptions, Sealed), + ENUM_ENTRY(ClassOptions, Intrinsic), +}; + +static const EnumEntry MemberAccessNames[] = { + ENUM_ENTRY(MemberAccess, None), + ENUM_ENTRY(MemberAccess, Private), + ENUM_ENTRY(MemberAccess, Protected), + ENUM_ENTRY(MemberAccess, Public), +}; + +static const EnumEntry MethodOptionNames[] = { + ENUM_ENTRY(MethodOptions, Pseudo), + ENUM_ENTRY(MethodOptions, NoInherit), + ENUM_ENTRY(MethodOptions, NoConstruct), + ENUM_ENTRY(MethodOptions, CompilerGenerated), + ENUM_ENTRY(MethodOptions, Sealed), +}; + +static const EnumEntry MemberKindNames[] = { + ENUM_ENTRY(MethodKind, Vanilla), + ENUM_ENTRY(MethodKind, Virtual), + ENUM_ENTRY(MethodKind, Static), + ENUM_ENTRY(MethodKind, Friend), + ENUM_ENTRY(MethodKind, IntroducingVirtual), + ENUM_ENTRY(MethodKind, PureVirtual), + ENUM_ENTRY(MethodKind, PureIntroducingVirtual), +}; + +static const EnumEntry PtrKindNames[] = { + ENUM_ENTRY(PointerKind, Near16), + ENUM_ENTRY(PointerKind, Far16), + ENUM_ENTRY(PointerKind, Huge16), + ENUM_ENTRY(PointerKind, BasedOnSegment), + ENUM_ENTRY(PointerKind, BasedOnValue), + ENUM_ENTRY(PointerKind, BasedOnSegmentValue), + ENUM_ENTRY(PointerKind, BasedOnAddress), + ENUM_ENTRY(PointerKind, BasedOnSegmentAddress), + ENUM_ENTRY(PointerKind, BasedOnType), + ENUM_ENTRY(PointerKind, BasedOnSelf), + ENUM_ENTRY(PointerKind, Near32), + ENUM_ENTRY(PointerKind, Far32), + ENUM_ENTRY(PointerKind, Near64), +}; + +static const EnumEntry PtrModeNames[] = { + ENUM_ENTRY(PointerMode, Pointer), + ENUM_ENTRY(PointerMode, LValueReference), + ENUM_ENTRY(PointerMode, PointerToDataMember), + ENUM_ENTRY(PointerMode, PointerToMemberFunction), + ENUM_ENTRY(PointerMode, RValueReference), +}; + +static const EnumEntry PtrMemberRepNames[] = { + ENUM_ENTRY(PointerToMemberRepresentation, Unknown), + ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceData), + ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceData), + ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceData), + ENUM_ENTRY(PointerToMemberRepresentation, GeneralData), + ENUM_ENTRY(PointerToMemberRepresentation, SingleInheritanceFunction), + ENUM_ENTRY(PointerToMemberRepresentation, MultipleInheritanceFunction), + ENUM_ENTRY(PointerToMemberRepresentation, VirtualInheritanceFunction), + ENUM_ENTRY(PointerToMemberRepresentation, GeneralFunction), +}; + +static const EnumEntry TypeModifierNames[] = { + ENUM_ENTRY(ModifierOptions, Const), + ENUM_ENTRY(ModifierOptions, Volatile), + ENUM_ENTRY(ModifierOptions, Unaligned), +}; + +static const EnumEntry CallingConventions[] = { + ENUM_ENTRY(CallingConvention, NearC), + ENUM_ENTRY(CallingConvention, FarC), + ENUM_ENTRY(CallingConvention, NearPascal), + ENUM_ENTRY(CallingConvention, FarPascal), + ENUM_ENTRY(CallingConvention, NearFast), + ENUM_ENTRY(CallingConvention, FarFast), + ENUM_ENTRY(CallingConvention, NearStdCall), + ENUM_ENTRY(CallingConvention, FarStdCall), + ENUM_ENTRY(CallingConvention, NearSysCall), + ENUM_ENTRY(CallingConvention, FarSysCall), + ENUM_ENTRY(CallingConvention, ThisCall), + ENUM_ENTRY(CallingConvention, MipsCall), + ENUM_ENTRY(CallingConvention, Generic), + ENUM_ENTRY(CallingConvention, AlphaCall), + ENUM_ENTRY(CallingConvention, PpcCall), + ENUM_ENTRY(CallingConvention, SHCall), + ENUM_ENTRY(CallingConvention, ArmCall), + ENUM_ENTRY(CallingConvention, AM33Call), + ENUM_ENTRY(CallingConvention, TriCall), + ENUM_ENTRY(CallingConvention, SH5Call), + ENUM_ENTRY(CallingConvention, M32RCall), + ENUM_ENTRY(CallingConvention, ClrCall), + ENUM_ENTRY(CallingConvention, Inline), + ENUM_ENTRY(CallingConvention, NearVector), +}; + +static const EnumEntry FunctionOptionEnum[] = { + ENUM_ENTRY(FunctionOptions, CxxReturnUdt), + ENUM_ENTRY(FunctionOptions, Constructor), + ENUM_ENTRY(FunctionOptions, ConstructorWithVirtualBases), +}; + +static const EnumEntry LabelTypeEnum[] = { + ENUM_ENTRY(LabelType, Near), + ENUM_ENTRY(LabelType, Far), +}; + +#undef ENUM_ENTRY + +static StringRef getLeafTypeName(TypeLeafKind LT) { + switch (LT) { +#define TYPE_RECORD(ename, value, name) \ + case ename: \ + return #ename; +#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" + default: + break; + } + return "UnknownLeaf"; +} + +template +static bool compEnumNames(const EnumEntry &lhs, const EnumEntry &rhs) { + return lhs.Name < rhs.Name; +} + +template +static StringRef getFlagNames(T Value, ArrayRef> Flags) { + typedef EnumEntry FlagEntry; + typedef SmallVector FlagVector; + FlagVector SetFlags; + for (const auto &Flag : Flags) { + if (Flag.Value == 0) + continue; + if ((Value & Flag.Value) == Flag.Value) { + SetFlags.push_back(Flag); + } + } + + llvm::sort(SetFlags, &compEnumNames); + + SmallString<128> FlagLabel; + for (const auto &Flag : SetFlags) + FlagLabel += + ("\t" + Flag.Name + " (0x" + utohexstr(Flag.Value) + ") " + "\n").str(); + + if (!FlagLabel.empty()) { + SmallString<128> LabelWithBraces("\n[\n"); + LabelWithBraces += (FlagLabel + "]").str(); + return LabelWithBraces.str(); + } else + return FlagLabel.str(); +} + +template +static StringRef getEnumName(T Value, ArrayRef> EnumValues) { + StringRef Name; + for (const auto &EnumItem : EnumValues) { + if (EnumItem.Value == Value) { + Name = EnumItem.Name; + break; + } + } + + return Name; +} + +static StringRef getMemberAttributes(MemberAccess Access, MethodKind Kind, + MethodOptions Options) { + SmallString<256> AccessSpecifier = + getEnumName(uint8_t(Access), makeArrayRef(MemberAccessNames)); + SmallString<256> MemberAttrs( + ("\n[\n\tAccessSpecifier: " + AccessSpecifier + "\n").str()); + if (Kind != MethodKind::Vanilla) { + SmallString<256> MethodKind = + getEnumName(unsigned(Kind), makeArrayRef(MemberKindNames)); + MemberAttrs += ("\tMethodKind: " + MethodKind + "\n").str(); + } + if (Options != MethodOptions::None) { + SmallString<256> MethodOptions = + getFlagNames(unsigned(Options), makeArrayRef(MethodOptionNames)); + MemberAttrs += ("\tMethodOptions" + MethodOptions + "\n").str(); + } + MemberAttrs += "]"; + return MemberAttrs.str(); +} + struct MapOneMethodRecord { explicit MapOneMethodRecord(bool IsFromOverloadList) : IsFromOverloadList(IsFromOverloadList) {} Error operator()(CodeViewRecordIO &IO, OneMethodRecord &Method) const { - error(IO.mapInteger(Method.Attrs.Attrs, "AccessSpecifier")); + StringRef Attrs = getMemberAttributes( + Method.getAccess(), Method.getMethodKind(), Method.getOptions()); + error(IO.mapInteger(Method.Attrs.Attrs, "Attributes" + Attrs)); if (IsFromOverloadList) { uint16_t Padding = 0; error(IO.mapInteger(Padding, "Padding")); @@ -41,7 +254,7 @@ private: bool IsFromOverloadList; }; -} +} // namespace static Error mapNameAndUniqueName(CodeViewRecordIO &IO, StringRef &Name, StringRef &UniqueName, bool HasUniqueName) { @@ -83,18 +296,6 @@ return Error::success(); } -static StringRef getLeafTypeName(TypeLeafKind LT) { - switch (LT) { -#define TYPE_RECORD(ename, value, name) \ - case ename: \ - return #ename; -#include "llvm/DebugInfo/CodeView/CodeViewTypes.def" - default: - break; - } - return "UnknownLeaf"; -} - Error TypeRecordMapping::visitTypeBegin(CVType &CVR) { assert(!TypeKind.hasValue() && "Already in a type mapping!"); assert(!MemberKind.hasValue() && "Already in a member mapping!"); @@ -108,6 +309,14 @@ MaxLen = MaxRecordLength - sizeof(RecordPrefix); error(IO.beginRecord(MaxLen)); TypeKind = CVR.kind(); + + if (IO.isStreaming()) { + auto RecordKind = CVR.kind(); + uint16_t RecordLen = CVR.length() - 2; + error(IO.mapInteger(RecordLen, "Record length")); + error( + IO.mapEnum(RecordKind, "Record kind: " + getLeafTypeName(RecordKind))); + } return Error::success(); } @@ -161,16 +370,22 @@ } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ModifierRecord &Record) { + SmallString<256> ModifierNames = getFlagNames( + static_cast(Record.Modifiers), makeArrayRef(TypeModifierNames)); error(IO.mapInteger(Record.ModifiedType, "ModifiedType")); - error(IO.mapEnum(Record.Modifiers, "Modifiers")); + error(IO.mapEnum(Record.Modifiers, "Modifiers" + ModifierNames)); return Error::success(); } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, ProcedureRecord &Record) { + SmallString<256> CallinConvName = + getEnumName(uint8_t(Record.CallConv), makeArrayRef(CallingConventions)); + SmallString<256> FuncOptionNames = getFlagNames( + static_cast(Record.Options), makeArrayRef(FunctionOptionEnum)); error(IO.mapInteger(Record.ReturnType, "ReturnType")); - error(IO.mapEnum(Record.CallConv, "CallingConvention")); - error(IO.mapEnum(Record.Options, "FunctionOptions")); + error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallinConvName)); + error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames)); error(IO.mapInteger(Record.ParameterCount, "NumParameters")); error(IO.mapInteger(Record.ArgumentList, "ArgListType")); @@ -179,11 +394,15 @@ Error TypeRecordMapping::visitKnownRecord(CVType &CVR, MemberFunctionRecord &Record) { + SmallString<256> CallinConvName = + getEnumName(uint8_t(Record.CallConv), makeArrayRef(CallingConventions)); + SmallString<256> FuncOptionNames = getFlagNames( + static_cast(Record.Options), makeArrayRef(FunctionOptionEnum)); error(IO.mapInteger(Record.ReturnType, "ReturnType")); error(IO.mapInteger(Record.ClassType, "ClassType")); error(IO.mapInteger(Record.ThisType, "ThisType")); - error(IO.mapEnum(Record.CallConv, "CallingConvention")); - error(IO.mapEnum(Record.Options, "FunctionOptions")); + error(IO.mapEnum(Record.CallConv, "CallingConvention: " + CallinConvName)); + error(IO.mapEnum(Record.Options, "FunctionOptions" + FuncOptionNames)); error(IO.mapInteger(Record.ParameterCount, "NumParameters")); error(IO.mapInteger(Record.ArgumentList, "ArgListType")); error(IO.mapInteger(Record.ThisPointerAdjustment, "ThisAdjustment")); @@ -214,8 +433,32 @@ } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, PointerRecord &Record) { + + SmallString<512> Attr("Attributes\n"); + SmallString<256> PtrType = getEnumName(unsigned(Record.getPointerKind()), + makeArrayRef(PtrKindNames)); + SmallString<256> PtrMode = + getEnumName(unsigned(Record.getMode()), makeArrayRef(PtrModeNames)); + auto PtrIsFlat = Record.isFlat(); + auto PtrIsConst = Record.isConst(); + auto PtrIsVolatile = Record.isVolatile(); + auto PtrIsUnaligned = Record.isUnaligned(); + auto PtrIsRestrict = Record.isRestrict(); + auto PtrIsLValueReferenceThisPtr = Record.isLValueReferenceThisPtr(); + auto PtrIsRValueReferenceThisPtr = Record.isRValueReferenceThisPtr(); + auto PtrSizeOf = Record.getSize(); + error(IO.mapInteger(Record.ReferentType, "PointeeType")); - error(IO.mapInteger(Record.Attrs, "Attributes")); + + Attr += ("[\nPtrType: " + PtrType + "\nPtrMode: " + PtrMode + "\nIsFlat: " + + itostr(PtrIsFlat) + "\nIsConst: " + itostr(PtrIsConst) + + "\nIsVolatile: " + itostr(PtrIsVolatile) + "\nIsUnaligned: " + + itostr(PtrIsUnaligned) + "\nIsRestrict: " + itostr(PtrIsRestrict) + + "\nIsThisPtr&: " + itostr(PtrIsLValueReferenceThisPtr) + + "\nIsThisPtr&&: " + itostr(PtrIsRValueReferenceThisPtr) + + "\nSizeOf: " + itostr(PtrSizeOf) + "\n]") + .str(); + error(IO.mapInteger(Record.Attrs, Attr)); if (Record.isPointerToMember()) { if (IO.isReading()) @@ -223,7 +466,10 @@ MemberPointerInfo &M = *Record.MemberInfo; error(IO.mapInteger(M.ContainingType, "ClassType")); - error(IO.mapEnum(M.Representation, "Representation")); + SmallString<256> PtrMemberGetRepresentation = getEnumName( + uint16_t(M.Representation), makeArrayRef(PtrMemberRepNames)); + error(IO.mapEnum(M.Representation, + "Representation: " + PtrMemberGetRepresentation)); } return Error::success(); @@ -243,8 +489,10 @@ (CVR.kind() == TypeLeafKind::LF_CLASS) || (CVR.kind() == TypeLeafKind::LF_INTERFACE)); + SmallString<256> PropertiesNames = getFlagNames( + static_cast(Record.Options), makeArrayRef(ClassOptionNames)); error(IO.mapInteger(Record.MemberCount, "MemberCount")); - error(IO.mapEnum(Record.Options, "Properties")); + error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames)); error(IO.mapInteger(Record.FieldList, "FieldList")); error(IO.mapInteger(Record.DerivationList, "DerivedFrom")); error(IO.mapInteger(Record.VTableShape, "VShape")); @@ -256,8 +504,10 @@ } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, UnionRecord &Record) { + SmallString<256> PropertiesNames = getFlagNames( + static_cast(Record.Options), makeArrayRef(ClassOptionNames)); error(IO.mapInteger(Record.MemberCount, "MemberCount")); - error(IO.mapEnum(Record.Options, "Properties")); + error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames)); error(IO.mapInteger(Record.FieldList, "FieldList")); error(IO.mapEncodedInteger(Record.Size, "SizeOf")); error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName, @@ -267,8 +517,10 @@ } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, EnumRecord &Record) { + SmallString<256> PropertiesNames = getFlagNames( + static_cast(Record.Options), makeArrayRef(ClassOptionNames)); error(IO.mapInteger(Record.MemberCount, "NumEnumerators")); - error(IO.mapEnum(Record.Options, "Properties")); + error(IO.mapEnum(Record.Options, "Properties" + PropertiesNames)); error(IO.mapInteger(Record.UnderlyingType, "UnderlyingType")); error(IO.mapInteger(Record.FieldList, "FieldListType")); error(mapNameAndUniqueName(IO, Record.Name, Record.UniqueName, @@ -418,13 +670,17 @@ } Error TypeRecordMapping::visitKnownRecord(CVType &CVR, LabelRecord &Record) { - error(IO.mapEnum(Record.Mode, "Mode")); + SmallString<256> ModeName = + getEnumName(uint16_t(), makeArrayRef(LabelTypeEnum)); + error(IO.mapEnum(Record.Mode, "Mode: " + ModeName)); return Error::success(); } Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, BaseClassRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs, "AccessSpecifier")); + StringRef Attrs = getMemberAttributes(Record.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attributes" + Attrs)); error(IO.mapInteger(Record.Type, "BaseType")); error(IO.mapEncodedInteger(Record.Offset, "BaseOffset")); @@ -433,7 +689,9 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, EnumeratorRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs)); + StringRef Attrs = getMemberAttributes(Record.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attributes" + Attrs)); // FIXME: Handle full APInt such as __int128. error(IO.mapEncodedInteger(Record.Value, "EnumValue")); @@ -444,7 +702,9 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, DataMemberRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs, "AccessSpecifier")); + StringRef Attrs = getMemberAttributes(Record.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attributes" + Attrs)); error(IO.mapInteger(Record.Type, "Type")); error(IO.mapEncodedInteger(Record.FieldOffset, "FieldOffset")); error(IO.mapStringZ(Record.Name, "Name")); @@ -481,7 +741,9 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, StaticDataMemberRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs, "AccessSpecifier")); + StringRef Attrs = getMemberAttributes(Record.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attributes" + Attrs)); error(IO.mapInteger(Record.Type, "Type")); error(IO.mapStringZ(Record.Name, "Name")); @@ -491,7 +753,9 @@ Error TypeRecordMapping::visitKnownMember(CVMemberRecord &CVR, VirtualBaseClassRecord &Record) { - error(IO.mapInteger(Record.Attrs.Attrs, "AccessSpecifier")); + StringRef Attrs = getMemberAttributes(Record.getAccess(), MethodKind::Vanilla, + MethodOptions::None); + error(IO.mapInteger(Record.Attrs.Attrs, "Attributes" + Attrs)); error(IO.mapInteger(Record.BaseType, "BaseType")); error(IO.mapInteger(Record.VBPtrType, "VBPtrType")); error(IO.mapEncodedInteger(Record.VBPtrOffset, "VBPtrOffset")); Index: llvm/test/DebugInfo/COFF/types-basic.ll =================================================================== --- llvm/test/DebugInfo/COFF/types-basic.ll +++ llvm/test/DebugInfo/COFF/types-basic.ll @@ -353,9 +353,9 @@ ; ASM: .short 0x12 # Record length ; ASM: .short 0x1201 # Record kind: LF_ARGLIST ; ASM: .long 0x3 # NumArgs -; ASM: .long 0x40 # Argument -; ASM: .long 0x41 # Argument -; ASM: .long 0x13 # Argument +; ASM: .long 0x40 # Argument: float +; ASM: .long 0x41 # Argument: double +; ASM: .long 0x13 # Argument: __int64 ; ASM: # ArgList (0x1000) { ; ASM: # TypeLeafKind: LF_ARGLIST (0x1201) ; ASM: # NumArgs: 3 @@ -367,11 +367,11 @@ ; ASM: # } ; ASM: .short 0xe # Record length ; ASM: .short 0x1008 # Record kind: LF_PROCEDURE -; ASM: .long 0x3 # ReturnType -; ASM: .byte 0x0 # CallingConvention +; ASM: .long 0x3 # ReturnType: void +; ASM: .byte 0x0 # CallingConvention: NearC ; ASM: .byte 0x0 # FunctionOptions ; ASM: .short 0x3 # NumParameters -; ASM: .long 0x1000 # ArgListType +; ASM: .long 0x1000 # ArgListType: (float, double, __int64) ; ASM: # Procedure (0x1001) { ; ASM: # TypeLeafKind: LF_PROCEDURE (0x1008) ; ASM: # ReturnType: void (0x3) @@ -384,7 +384,7 @@ ; ASM: .short 0xe # Record length ; ASM: .short 0x1601 # Record kind: LF_FUNC_ID ; ASM: .long 0x0 # ParentScope -; ASM: .long 0x1001 # FunctionType +; ASM: .long 0x1001 # FunctionType: void (float, double, __int64) ; ASM: .asciz "f" # Name ; ASM: .byte 242 ; ASM: .byte 241 @@ -396,8 +396,11 @@ ; ASM: # } ; ASM: .short 0xa # Record length ; ASM: .short 0x1001 # Record kind: LF_MODIFIER -; ASM: .long 0x74 # ModifiedType +; ASM: .long 0x74 # ModifiedType: int ; ASM: .short 0x1 # Modifiers +; ASM: # [ +; ASM: # Const (0x1) +; ASM: # ] ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: # Modifier (0x1003) { @@ -409,8 +412,20 @@ ; ASM: # } ; ASM: .short 0xa # Record length ; ASM: .short 0x1002 # Record kind: LF_POINTER -; ASM: .long 0x1003 # PointeeType +; ASM: .long 0x1003 # PointeeType: const int ; ASM: .long 0x1000c # Attributes +; ASM: # [ +; ASM: # PtrType: Near64 +; ASM: # PtrMode: Pointer +; ASM: # IsFlat: 0 +; ASM: # IsConst: 0 +; ASM: # IsVolatile: 0 +; ASM: # IsUnaligned: 0 +; ASM: # IsRestrict: 0 +; ASM: # IsThisPtr&: 0 +; ASM: # IsThisPtr&&: 0 +; ASM: # SizeOf: 8 +; ASM: # ] ; ASM: # Pointer (0x1004) { ; ASM: # TypeLeafKind: LF_POINTER (0x1002) ; ASM: # PointeeType: const int (0x1003) @@ -429,6 +444,9 @@ ; ASM: .short 0x1505 # Record kind: LF_STRUCTURE ; ASM: .short 0x0 # MemberCount ; ASM: .short 0x80 # Properties +; ASM: # [ +; ASM: # ForwardReference (0x80) +; ASM: # ] ; ASM: .long 0x0 # FieldList ; ASM: .long 0x0 # DerivedFrom ; ASM: .long 0x0 # VShape @@ -450,8 +468,20 @@ ; ASM: .short 0x1002 # Record kind: LF_POINTER ; ASM: .long 0x74 # PointeeType ; ASM: .long 0x804c # Attributes -; ASM: .long 0x1005 # ClassType -; ASM: .short 0x4 # Representation +; ASM: # [ +; ASM: # PtrType: Near64 +; ASM: # PtrMode: PointerToDataMember +; ASM: # IsFlat: 0 +; ASM: # IsConst: 0 +; ASM: # IsVolatile: 0 +; ASM: # IsUnaligned: 0 +; ASM: # IsRestrict: 0 +; ASM: # IsThisPtr&: 0 +; ASM: # IsThisPtr&&: 0 +; ASM: # SizeOf: 4 +; ASM: # ] +; ASM: .long 0x1005 # ClassType: A +; ASM: .short 0x4 # Representation: GeneralData ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: # Pointer (0x1006) { @@ -472,8 +502,20 @@ ; ASM: # } ; ASM: .short 0xa # Record length ; ASM: .short 0x1002 # Record kind: LF_POINTER -; ASM: .long 0x1005 # PointeeType +; ASM: .long 0x1005 # PointeeType: A ; ASM: .long 0x1040c # Attributes +; ASM: # [ +; ASM: # PtrType: Near64 +; ASM: # PtrMode: Pointer +; ASM: # IsFlat: 0 +; ASM: # IsConst: 1 +; ASM: # IsVolatile: 0 +; ASM: # IsUnaligned: 0 +; ASM: # IsRestrict: 0 +; ASM: # IsThisPtr&: 0 +; ASM: # IsThisPtr&&: 0 +; ASM: # SizeOf: 8 +; ASM: # ] ; ASM: # Pointer (0x1007) { ; ASM: # TypeLeafKind: LF_POINTER (0x1002) ; ASM: # PointeeType: A (0x1005) @@ -499,13 +541,13 @@ ; ASM: # } ; ASM: .short 0x1a # Record length ; ASM: .short 0x1009 # Record kind: LF_MFUNCTION -; ASM: .long 0x3 # ReturnType -; ASM: .long 0x1005 # ClassType -; ASM: .long 0x1007 # ThisType -; ASM: .byte 0x0 # CallingConvention +; ASM: .long 0x3 # ReturnType: void +; ASM: .long 0x1005 # ClassType: A +; ASM: .long 0x1007 # ThisType: A* const +; ASM: .byte 0x0 # CallingConvention: NearC ; ASM: .byte 0x0 # FunctionOptions ; ASM: .short 0x0 # NumParameters -; ASM: .long 0x1008 # ArgListType +; ASM: .long 0x1008 # ArgListType: () ; ASM: .long 0x0 # ThisAdjustment ; ASM: # MemberFunction (0x1009) { ; ASM: # TypeLeafKind: LF_MFUNCTION (0x1009) @@ -522,13 +564,19 @@ ; ASM: .short 0x1e # Record length ; ASM: .short 0x1203 # Record kind: LF_FIELDLIST ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x0 # FieldOffset ; ASM: .asciz "a" # Name ; ASM: .short 0x1511 # Member kind: LF_ONEMETHOD -; ASM: .short 0x3 # AccessSpecifier -; ASM: .long 0x1009 # Type +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] +; ASM: .long 0x1009 # Type: void A::() ; ASM: .asciz "A::f" # Name ; ASM: .byte 243 ; ASM: .byte 242 @@ -553,7 +601,7 @@ ; ASM: .short 0x1505 # Record kind: LF_STRUCTURE ; ASM: .short 0x2 # MemberCount ; ASM: .short 0x0 # Properties -; ASM: .long 0x100a # FieldList +; ASM: .long 0x100a # FieldList: ; ASM: .long 0x0 # DerivedFrom ; ASM: .long 0x0 # VShape ; ASM: .short 0x4 # SizeOf @@ -580,8 +628,8 @@ ; ASM: # } ; ASM: .short 0xe # Record length ; ASM: .short 0x1606 # Record kind: LF_UDT_SRC_LINE -; ASM: .long 0x100b # UDT -; ASM: .long 0x100c # SourceFile +; ASM: .long 0x100b # UDT: A +; ASM: .long 0x100c # SourceFile: D:\src\llvm\build\t.cpp ; ASM: .long 0x1 # LineNumber ; ASM: # UdtSourceLine (0x100D) { ; ASM: # TypeLeafKind: LF_UDT_SRC_LINE (0x1606) @@ -591,10 +639,22 @@ ; ASM: # } ; ASM: .short 0x12 # Record length ; ASM: .short 0x1002 # Record kind: LF_POINTER -; ASM: .long 0x1009 # PointeeType +; ASM: .long 0x1009 # PointeeType: void A::() ; ASM: .long 0x1006c # Attributes -; ASM: .long 0x1005 # ClassType -; ASM: .short 0x8 # Representation +; ASM: # [ +; ASM: # PtrType: Near64 +; ASM: # PtrMode: PointerToMemberFunction +; ASM: # IsFlat: 0 +; ASM: # IsConst: 0 +; ASM: # IsVolatile: 0 +; ASM: # IsUnaligned: 0 +; ASM: # IsRestrict: 0 +; ASM: # IsThisPtr&: 0 +; ASM: # IsThisPtr&&: 0 +; ASM: # SizeOf: 8 +; ASM: # ] +; ASM: .long 0x1005 # ClassType: A +; ASM: .short 0x8 # Representation: GeneralFunction ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: # Pointer (0x100E) { @@ -615,8 +675,11 @@ ; ASM: # } ; ASM: .short 0xa # Record length ; ASM: .short 0x1001 # Record kind: LF_MODIFIER -; ASM: .long 0x3 # ModifiedType +; ASM: .long 0x3 # ModifiedType: void ; ASM: .short 0x1 # Modifiers +; ASM: # [ +; ASM: # Const (0x1) +; ASM: # ] ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: # Modifier (0x100F) { @@ -628,8 +691,20 @@ ; ASM: # } ; ASM: .short 0xa # Record length ; ASM: .short 0x1002 # Record kind: LF_POINTER -; ASM: .long 0x100f # PointeeType +; ASM: .long 0x100f # PointeeType: const void ; ASM: .long 0x1000c # Attributes +; ASM: # [ +; ASM: # PtrType: Near64 +; ASM: # PtrMode: Pointer +; ASM: # IsFlat: 0 +; ASM: # IsConst: 0 +; ASM: # IsVolatile: 0 +; ASM: # IsUnaligned: 0 +; ASM: # IsRestrict: 0 +; ASM: # IsThisPtr&: 0 +; ASM: # IsThisPtr&&: 0 +; ASM: # SizeOf: 8 +; ASM: # ] ; ASM: # Pointer (0x1010) { ; ASM: # TypeLeafKind: LF_POINTER (0x1002) ; ASM: # PointeeType: const void (0x100F) @@ -646,11 +721,11 @@ ; ASM: # } ; ASM: .short 0xe # Record length ; ASM: .short 0x1008 # Record kind: LF_PROCEDURE -; ASM: .long 0x3 # ReturnType -; ASM: .byte 0x0 # CallingConvention +; ASM: .long 0x3 # ReturnType: void +; ASM: .byte 0x0 # CallingConvention: NearC ; ASM: .byte 0x0 # FunctionOptions ; ASM: .short 0x0 # NumParameters -; ASM: .long 0x1008 # ArgListType +; ASM: .long 0x1008 # ArgListType: () ; ASM: # Procedure (0x1011) { ; ASM: # TypeLeafKind: LF_PROCEDURE (0x1008) ; ASM: # ReturnType: void (0x3) @@ -663,7 +738,7 @@ ; ASM: .short 0x16 # Record length ; ASM: .short 0x1601 # Record kind: LF_FUNC_ID ; ASM: .long 0x0 # ParentScope -; ASM: .long 0x1011 # FunctionType +; ASM: .long 0x1011 # FunctionType: void () ; ASM: .asciz "CharTypes" # Name ; ASM: .byte 242 ; ASM: .byte 241 @@ -698,9 +773,9 @@ ; ASM: .short 0x1a # Record length ; ASM: .short 0x1603 # Record kind: LF_BUILDINFO ; ASM: .short 0x5 # NumArgs -; ASM: .long 0x1013 # Argument +; ASM: .long 0x1013 # Argument: D:\src\llvm\build ; ASM: .long 0x0 # Argument -; ASM: .long 0x1014 # Argument +; ASM: .long 0x1014 # Argument: t.cpp ; ASM: .long 0x0 # Argument ; ASM: .long 0x0 # Argument ; ASM: .byte 242 Index: llvm/test/DebugInfo/COFF/types-data-members.ll =================================================================== --- llvm/test/DebugInfo/COFF/types-data-members.ll +++ llvm/test/DebugInfo/COFF/types-data-members.ll @@ -474,7 +474,10 @@ ; ASM: .short 0x3e # Record length ; ASM: .short 0x1203 # Record kind: LF_FIELDLIST ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x0 # FieldOffset ; ASM: .asciz "s1" # Name @@ -482,7 +485,10 @@ ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x4 # FieldOffset ; ASM: .asciz "s2" # Name @@ -490,7 +496,10 @@ ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x8 # FieldOffset ; ASM: .asciz "s3" # Name @@ -498,7 +507,10 @@ ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: .short 0x150e # Member kind: LF_STMEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x1004 # Type ; ASM: .asciz "sdm" # Name ; ASM: # FieldList (0x1005) { @@ -599,12 +611,18 @@ ; ASM: .short 0x1a # Record length ; ASM: .short 0x1203 # Record kind: LF_FIELDLIST ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x0 # FieldOffset ; ASM: .asciz "a" # Name ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x40 # Type ; ASM: .short 0x0 # FieldOffset ; ASM: .asciz "b" # Name @@ -683,20 +701,29 @@ ; ASM: .short 0x32 # Record length ; ASM: .short 0x1203 # Record kind: LF_FIELDLIST ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x0 # FieldOffset ; ASM: .asciz "pub" # Name ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x1 # AccessSpecifier +; ASM: .short 0x1 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Private +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x4 # FieldOffset ; ASM: .asciz "priv" # Name ; ASM: .byte 241 ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x2 # AccessSpecifier +; ASM: .short 0x2 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Protected +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x8 # FieldOffset ; ASM: .asciz "prot" # Name @@ -833,13 +860,19 @@ ; ASM: .short 0x32 # Record length ; ASM: .short 0x1203 # Record kind: LF_FIELDLIST ; ASM: .short 0x1400 # Member kind: LF_BCLASS -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x1003 # BaseType ; ASM: .short 0x0 # BaseOffset ; ASM: .byte 242 ; ASM: .byte 241 ; ASM: .short 0x1401 # Member kind: LF_VBCLASS -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x100d # BaseType ; ASM: .long 0x1012 # VBPtrType ; ASM: .short 0x0 # VBPtrOffset @@ -848,7 +881,10 @@ ; ASM: .short 0x0 # Padding ; ASM: .long 0x1014 # Type ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x18 # FieldOffset ; ASM: .asciz "d" # Name @@ -945,7 +981,10 @@ ; ASM: .short 0xe # Record length ; ASM: .short 0x1203 # Record kind: LF_FIELDLIST ; ASM: .short 0x150d # Member kind: LF_MEMBER -; ASM: .short 0x3 # AccessSpecifier +; ASM: .short 0x3 # Attributes +; ASM: # [ +; ASM: # AccessSpecifier: Public +; ASM: # ] ; ASM: .long 0x74 # Type ; ASM: .short 0x0 # FieldOffset ; ASM: .asciz "n" # Name @@ -963,6 +1002,10 @@ ; ASM: .short 0x1505 # Record kind: LF_STRUCTURE ; ASM: .short 0x1 # MemberCount ; ASM: .short 0x208 # Properties +; ASM: # [ +; ASM: # HasUniqueName (0x200) +; ASM: # Nested (0x8) +; ASM: # ] ; ASM: .long 0x1019 # FieldList ; ASM: .long 0x0 # DerivedFrom ; ASM: .long 0x0 # VShape