[llvm] r269216 - Refactor CodeView type records to use common code.
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Wed May 11 10:47:35 PDT 2016
Author: zturner
Date: Wed May 11 12:47:35 2016
New Revision: 269216
URL: http://llvm.org/viewvc/llvm-project?rev=269216&view=rev
Log:
Refactor CodeView type records to use common code.
Differential Revision: http://reviews.llvm.org/D20138
Reviewed By: rnk
Modified:
llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h
llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp
llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h Wed May 11 12:47:35 2016
@@ -14,6 +14,7 @@
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/ErrorOr.h"
namespace llvm {
namespace codeview {
@@ -42,12 +43,10 @@ public:
/// FIXME: Make the visitor interpret the trailing bytes so that clients don't
/// need to.
#define TYPE_RECORD(ClassName, LeafEnum) \
- void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
- ArrayRef<uint8_t> LeafData) {}
+ void visit##ClassName(TypeLeafKind LeafType, ClassName &Record) {}
#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
#define MEMBER_RECORD(ClassName, LeafEnum) \
- void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
- ArrayRef<uint8_t> &FieldData) {}
+ void visit##ClassName(TypeLeafKind LeafType, ClassName &Record) {}
#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
#include "TypeRecords.def"
@@ -68,10 +67,11 @@ public:
break;
#define TYPE_RECORD(ClassName, LeafEnum) \
case LeafEnum: { \
- const ClassName *Rec; \
- if (!CVTypeVisitor::consumeObject(LeafData, Rec)) \
- return; \
- DerivedThis->visit##ClassName(Record.Type, Rec, LeafData); \
+ TypeRecordKind RK = static_cast<TypeRecordKind>(LeafEnum); \
+ auto Result = ClassName::deserialize(RK, LeafData); \
+ if (Result.getError()) \
+ return parseError(); \
+ DerivedThis->visit##ClassName(Record.Type, *Result); \
break; \
}
#include "TypeRecords.def"
@@ -120,10 +120,11 @@ public:
return parseError();
#define MEMBER_RECORD(ClassName, LeafEnum) \
case LeafEnum: { \
- const ClassName *Rec; \
- if (!CVTypeVisitor::consumeObject(FieldData, Rec)) \
- return; \
- static_cast<Derived *>(this)->visit##ClassName(Leaf, Rec, FieldData); \
+ TypeRecordKind RK = static_cast<TypeRecordKind>(LeafEnum); \
+ auto Result = ClassName::deserialize(RK, FieldData); \
+ if (Result.getError()) \
+ return parseError(); \
+ static_cast<Derived *>(this)->visit##ClassName(Leaf, *Result); \
break; \
}
#include "TypeRecords.def"
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h Wed May 11 12:47:35 2016
@@ -423,9 +423,10 @@ enum class TypeRecordKind : uint16_t {
Alias = 0x150a,
Member = 0x150d,
StaticMember = 0x150e,
- Method = 0x150f,
+ OverloadedMethod = 0x150f,
NestedType = 0x1510,
OneMethod = 0x1511,
+ TypeServer2 = 0x1515,
VirtualFunctionTable = 0x151d,
FunctionId = 0x1601,
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h Wed May 11 12:47:35 2016
@@ -10,11 +10,14 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORD_H
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/ErrorOr.h"
#include <cinttypes>
+#include <tuple>
namespace llvm {
namespace codeview {
@@ -23,6 +26,155 @@ using llvm::support::little32_t;
using llvm::support::ulittle16_t;
using llvm::support::ulittle32_t;
+/// Decodes a numeric "leaf" value. These are integer literals encountered in
+/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
+/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
+/// that indicates the bitwidth and sign of the numeric data.
+bool decodeNumericLeaf(ArrayRef<uint8_t> &Data, APSInt &Num);
+
+inline bool decodeNumericLeaf(StringRef &Data, APSInt &Num) {
+ ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
+ Data.size());
+ bool Success = decodeNumericLeaf(Bytes, Num);
+ Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
+ return Success;
+}
+
+/// Decode a numeric leaf value that is known to be a uint32_t.
+bool decodeUIntLeaf(ArrayRef<uint8_t> &Data, uint64_t &Num);
+
+/// Reinterpret a byte array as an array of characters. Does not interpret as
+/// a C string, as StringRef has several helpers (split) that make that easy.
+inline StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
+ return StringRef(reinterpret_cast<const char *>(LeafData.data()),
+ LeafData.size());
+}
+
+inline StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData) {
+ return getBytesAsCharacters(LeafData).split('\0').first;
+}
+
+/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
+/// there are not enough bytes remaining. Reinterprets the consumed bytes as a
+/// T object and points 'Res' at them.
+template <typename T, typename U>
+inline std::error_code consumeObject(U &Data, const T *&Res) {
+ if (Data.size() < sizeof(*Res))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ Res = reinterpret_cast<const T *>(Data.data());
+ Data = Data.drop_front(sizeof(*Res));
+ return std::error_code();
+}
+
+inline std::error_code consumeCString(ArrayRef<uint8_t> &Data, StringRef &Str) {
+ if (Data.empty())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ StringRef Rest;
+ std::tie(Str, Rest) = getBytesAsCharacters(Data).split('\0');
+ // We expect this to be null terminated. If it was not, it is an error.
+ if (Data.size() == Str.size())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ Data = ArrayRef<uint8_t>(Rest.bytes_begin(), Rest.bytes_end());
+ return std::error_code();
+}
+
+template <typename T>
+inline std::error_code consumeArray(ArrayRef<uint8_t> &Data,
+ ArrayRef<T> &Result, uint32_t N) {
+ uint32_t Size = sizeof(T) * N;
+ if (Data.size() < Size)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ Result = ArrayRef<T>(reinterpret_cast<const T *>(Data.data()), N);
+ Data = Data.drop_front(Size);
+ return std::error_code();
+}
+
+inline std::error_code consumeUInt32(StringRef &Data, uint32_t &Res) {
+ const support::ulittle32_t *IntPtr;
+ if (auto EC = consumeObject(Data, IntPtr))
+ return EC;
+ Res = *IntPtr;
+ return std::error_code();
+}
+
+/// Equvalent to CV_fldattr_t in cvinfo.h.
+struct MemberAttributes {
+ ulittle16_t Attrs;
+
+ /// Get the access specifier. Valid for any kind of member.
+ MemberAccess getAccess() const {
+ return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask));
+ }
+
+ /// Indicates if a method is defined with friend, virtual, static, etc.
+ MethodKind getMethodKind() const {
+ return MethodKind(
+ (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >> 2);
+ }
+
+ /// Get the flags that are not included in access control or method
+ /// properties.
+ MethodOptions getFlags() const {
+ return MethodOptions(
+ unsigned(Attrs) &
+ ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask));
+ }
+
+ /// Is this method virtual.
+ bool isVirtual() const {
+ auto MP = getMethodKind();
+ return MP != MethodKind::Vanilla && MP != MethodKind::Friend &&
+ MP != MethodKind::Static;
+ }
+
+ /// Does this member introduce a new virtual method.
+ bool isIntroducedVirtual() const {
+ auto MP = getMethodKind();
+ return MP == MethodKind::IntroducingVirtual ||
+ MP == MethodKind::PureIntroducingVirtual;
+ }
+};
+
+// Does not correspond to any tag, this is the tail of an LF_POINTER record
+// if it represents a member pointer.
+class MemberPointerInfo {
+public:
+ MemberPointerInfo() {}
+
+ MemberPointerInfo(TypeIndex ContainingType,
+ PointerToMemberRepresentation Representation)
+ : ContainingType(ContainingType), Representation(Representation) {}
+
+ static ErrorOr<MemberPointerInfo> deserialize(ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ TypeIndex T = L->ClassType;
+ uint16_t R = L->Representation;
+ PointerToMemberRepresentation PMR =
+ static_cast<PointerToMemberRepresentation>(R);
+ return MemberPointerInfo(T, PMR);
+ }
+
+ TypeIndex getContainingType() const { return ContainingType; }
+ PointerToMemberRepresentation getRepresentation() const {
+ return Representation;
+ }
+
+private:
+ struct Layout {
+ TypeIndex ClassType;
+ ulittle16_t Representation; // PointerToMemberRepresentation
+ };
+
+ TypeIndex ContainingType;
+ PointerToMemberRepresentation Representation;
+};
+
class TypeRecord {
protected:
explicit TypeRecord(TypeRecordKind Kind) : Kind(Kind) {}
@@ -34,20 +186,39 @@ private:
TypeRecordKind Kind;
};
+// LF_MODIFIER
class ModifierRecord : public TypeRecord {
public:
- ModifierRecord(TypeIndex ModifiedType, ModifierOptions Options)
+ ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
: TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
- Options(Options) {}
+ Modifiers(Modifiers) {}
+
+ static ErrorOr<ModifierRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ TypeIndex M = L->ModifiedType;
+ uint16_t O = L->Modifiers;
+ ModifierOptions MO = static_cast<ModifierOptions>(O);
+ return ModifierRecord(M, MO);
+ }
TypeIndex getModifiedType() const { return ModifiedType; }
- ModifierOptions getOptions() const { return Options; }
+ ModifierOptions getModifiers() const { return Modifiers; }
private:
+ struct Layout {
+ TypeIndex ModifiedType;
+ ulittle16_t Modifiers; // ModifierOptions
+ };
+
TypeIndex ModifiedType;
- ModifierOptions Options;
+ ModifierOptions Modifiers;
};
+// LF_PROCEDURE
class ProcedureRecord : public TypeRecord {
public:
ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
@@ -57,6 +228,18 @@ public:
CallConv(CallConv), Options(Options), ParameterCount(ParameterCount),
ArgumentList(ArgumentList) {}
+ static ErrorOr<ProcedureRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ return ProcedureRecord(L->ReturnType, L->CallConv, L->Options,
+ L->NumParameters, L->ArgListType);
+ }
+
+ static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
+
TypeIndex getReturnType() const { return ReturnType; }
CallingConvention getCallConv() const { return CallConv; }
FunctionOptions getOptions() const { return Options; }
@@ -64,6 +247,14 @@ public:
TypeIndex getArgumentList() const { return ArgumentList; }
private:
+ struct Layout {
+ TypeIndex ReturnType;
+ CallingConvention CallConv;
+ FunctionOptions Options;
+ ulittle16_t NumParameters;
+ TypeIndex ArgListType;
+ };
+
TypeIndex ReturnType;
CallingConvention CallConv;
FunctionOptions Options;
@@ -71,6 +262,7 @@ private:
TypeIndex ArgumentList;
};
+// LF_MFUNCTION
class MemberFunctionRecord : public TypeRecord {
public:
MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
@@ -83,6 +275,17 @@ public:
ArgumentList(ArgumentList),
ThisPointerAdjustment(ThisPointerAdjustment) {}
+ static ErrorOr<MemberFunctionRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ return MemberFunctionRecord(L->ReturnType, L->ClassType, L->ThisType,
+ L->CallConv, L->Options, L->NumParameters,
+ L->ArgListType, L->ThisAdjustment);
+ }
+
TypeIndex getReturnType() const { return ReturnType; }
TypeIndex getClassType() const { return ClassType; }
TypeIndex getThisType() const { return ThisType; }
@@ -93,6 +296,17 @@ public:
int32_t getThisPointerAdjustment() const { return ThisPointerAdjustment; }
private:
+ struct Layout {
+ TypeIndex ReturnType;
+ TypeIndex ClassType;
+ TypeIndex ThisType;
+ CallingConvention CallConv;
+ FunctionOptions Options;
+ ulittle16_t NumParameters;
+ TypeIndex ArgListType;
+ little32_t ThisAdjustment;
+ };
+
TypeIndex ReturnType;
TypeIndex ClassType;
TypeIndex ThisType;
@@ -103,78 +317,253 @@ private:
int32_t ThisPointerAdjustment;
};
-class ArgumentListRecord : public TypeRecord {
+// LF_MFUNC_ID
+class MemberFunctionIdRecord : public TypeRecord {
public:
- explicit ArgumentListRecord(llvm::ArrayRef<TypeIndex> ArgumentTypes)
- : TypeRecord(TypeRecordKind::ArgumentList), ArgumentTypes(ArgumentTypes) {
+ MemberFunctionIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
+ StringRef Name)
+ : TypeRecord(TypeRecordKind::MemberFunctionId), ClassType(ClassType),
+ FunctionType(FunctionType), Name(Name) {}
+
+ static ErrorOr<MemberFunctionIdRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ return MemberFunctionIdRecord(L->ClassType, L->FunctionType, Name);
}
- llvm::ArrayRef<TypeIndex> getArgumentTypes() const { return ArgumentTypes; }
+ TypeIndex getClassType() const { return ClassType; }
+ TypeIndex getFunctionType() const { return FunctionType; }
+ StringRef getName() const { return Name; }
private:
- llvm::ArrayRef<TypeIndex> ArgumentTypes;
+ struct Layout {
+ TypeIndex ClassType;
+ TypeIndex FunctionType;
+ // Name: The null-terminated name follows.
+ };
+ TypeIndex ClassType;
+ TypeIndex FunctionType;
+ StringRef Name;
};
-class PointerRecordBase : public TypeRecord {
+// LF_ARGLIST, LF_SUBSTR_LIST
+class StringListRecord : public TypeRecord {
public:
- PointerRecordBase(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
- PointerOptions Options, uint8_t Size)
+ StringListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
+ : TypeRecord(Kind), StringIndices(Indices) {}
+
+ static ErrorOr<StringListRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ if (Kind != TypeRecordKind::SubstringList &&
+ Kind != TypeRecordKind::ArgumentList)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ ArrayRef<TypeIndex> Indices;
+ if (auto EC = consumeArray(Data, Indices, L->NumArgs))
+ return EC;
+ return StringListRecord(Kind, Indices);
+ }
+
+ ArrayRef<TypeIndex> getIndices() const { return StringIndices; }
+
+ static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }
+
+private:
+ struct Layout {
+ ulittle32_t NumArgs; // Number of arguments
+ // ArgTypes[]: Type indicies of arguments
+ };
+
+ ArrayRef<TypeIndex> StringIndices;
+};
+
+// LF_POINTER
+class PointerRecord : public TypeRecord {
+public:
+ static const uint32_t PointerKindShift = 0;
+ static const uint32_t PointerKindMask = 0x1F;
+
+ static const uint32_t PointerModeShift = 5;
+ static const uint32_t PointerModeMask = 0x07;
+
+ static const uint32_t PointerSizeShift = 13;
+ static const uint32_t PointerSizeMask = 0xFF;
+
+ PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
+ PointerOptions Options, uint8_t Size)
+ : PointerRecord(ReferentType, Kind, Mode, Options, Size,
+ MemberPointerInfo()) {}
+
+ PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
+ PointerOptions Options, uint8_t Size,
+ const MemberPointerInfo &Member)
: TypeRecord(TypeRecordKind::Pointer), ReferentType(ReferentType),
- PtrKind(Kind), Mode(Mode), Options(Options), Size(Size) {}
+ PtrKind(Kind), Mode(Mode), Options(Options), Size(Size),
+ MemberInfo(Member) {}
+
+ static ErrorOr<PointerRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ PointerKind PtrKind = L->getPtrKind();
+ PointerMode Mode = L->getPtrMode();
+ uint32_t Opts = L->Attrs;
+ PointerOptions Options = static_cast<PointerOptions>(Opts);
+ uint8_t Size = L->getPtrSize();
+
+ if (L->isPointerToMember()) {
+ auto E = MemberPointerInfo::deserialize(Data);
+ if (E.getError())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size, *E);
+ }
+
+ return PointerRecord(L->PointeeType, PtrKind, Mode, Options, Size);
+ }
TypeIndex getReferentType() const { return ReferentType; }
PointerKind getPointerKind() const { return PtrKind; }
PointerMode getMode() const { return Mode; }
PointerOptions getOptions() const { return Options; }
uint8_t getSize() const { return Size; }
+ MemberPointerInfo getMemberInfo() const { return MemberInfo; }
+
+ bool isPointerToMember() const {
+ return Mode == PointerMode::PointerToDataMember ||
+ Mode == PointerMode::PointerToMemberFunction;
+ }
+ bool isFlat() const {
+ return !!(uint32_t(Options) & uint32_t(PointerOptions::Flat32));
+ }
+ bool isConst() const {
+ return !!(uint32_t(Options) & uint32_t(PointerOptions::Const));
+ }
+ bool isVolatile() const {
+ return !!(uint32_t(Options) & uint32_t(PointerOptions::Volatile));
+ }
+ bool isUnaligned() const {
+ return !!(uint32_t(Options) & uint32_t(PointerOptions::Unaligned));
+ }
private:
+ struct Layout {
+ TypeIndex PointeeType;
+ ulittle32_t Attrs; // pointer attributes
+ // if pointer to member:
+ // PointerToMemberTail
+ PointerKind getPtrKind() const {
+ return PointerKind(Attrs & PointerKindMask);
+ }
+ PointerMode getPtrMode() const {
+ return PointerMode((Attrs >> PointerModeShift) & PointerModeMask);
+ }
+ uint8_t getPtrSize() const {
+ return (Attrs >> PointerSizeShift) & PointerSizeMask;
+ }
+ bool isFlat() const { return Attrs & (1 << 8); }
+ bool isVolatile() const { return Attrs & (1 << 9); }
+ bool isConst() const { return Attrs & (1 << 10); }
+ bool isUnaligned() const { return Attrs & (1 << 11); }
+
+ bool isPointerToDataMember() const {
+ return getPtrMode() == PointerMode::PointerToDataMember;
+ }
+ bool isPointerToMemberFunction() const {
+ return getPtrMode() == PointerMode::PointerToMemberFunction;
+ }
+ bool isPointerToMember() const {
+ return isPointerToMemberFunction() || isPointerToDataMember();
+ }
+ };
+
TypeIndex ReferentType;
PointerKind PtrKind;
PointerMode Mode;
PointerOptions Options;
uint8_t Size;
+ MemberPointerInfo MemberInfo;
};
-class PointerRecord : public PointerRecordBase {
-public:
- PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
- PointerOptions Options, uint8_t Size)
- : PointerRecordBase(ReferentType, Kind, Mode, Options, Size) {}
-};
-
-class PointerToMemberRecord : public PointerRecordBase {
+// LF_NESTTYPE
+class NestedTypeRecord : public TypeRecord {
public:
- PointerToMemberRecord(TypeIndex ReferentType, PointerKind Kind,
- PointerMode Mode, PointerOptions Options, uint8_t Size,
- TypeIndex ContainingType,
- PointerToMemberRepresentation Representation)
- : PointerRecordBase(ReferentType, Kind, Mode, Options, Size),
- ContainingType(ContainingType), Representation(Representation) {}
+ NestedTypeRecord(TypeIndex Type, StringRef Name)
+ : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
- TypeIndex getContainingType() const { return ContainingType; }
- PointerToMemberRepresentation getRepresentation() const {
- return Representation;
+ static ErrorOr<NestedTypeRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ return NestedTypeRecord(L->Type, Name);
}
+ TypeIndex getNestedType() const { return Type; }
+ StringRef getName() const { return Name; }
+
private:
- TypeIndex ContainingType;
- PointerToMemberRepresentation Representation;
+ struct Layout {
+ ulittle16_t Pad0; // Should be zero
+ TypeIndex Type; // Type index of nested type
+ // Name: Null-terminated string
+ };
+
+ TypeIndex Type;
+ StringRef Name;
};
+// LF_ARRAY
class ArrayRecord : public TypeRecord {
public:
ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
- llvm::StringRef Name)
+ StringRef Name)
: TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
IndexType(IndexType), Size(Size), Name(Name) {}
+ static ErrorOr<ArrayRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ uint64_t Size;
+ if (!decodeUIntLeaf(Data, Size))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ return ArrayRecord(L->ElementType, L->IndexType, Size, Name);
+ }
+
TypeIndex getElementType() const { return ElementType; }
TypeIndex getIndexType() const { return IndexType; }
uint64_t getSize() const { return Size; }
llvm::StringRef getName() const { return Name; }
private:
+ struct Layout {
+ TypeIndex ElementType;
+ TypeIndex IndexType;
+ // SizeOf: LF_NUMERIC encoded size in bytes. Not element count!
+ // Name: The null-terminated name follows.
+ };
+
TypeIndex ElementType;
TypeIndex IndexType;
uint64_t Size;
@@ -189,6 +578,11 @@ protected:
FieldList(FieldList), Name(Name), UniqueName(UniqueName) {}
public:
+ static const int HfaKindShift = 11;
+ static const int HfaKindMask = 0x1800;
+ static const int WinRTKindShift = 14;
+ static const int WinRTKindMask = 0xC000;
+
uint16_t getMemberCount() const { return MemberCount; }
ClassOptions getOptions() const { return Options; }
TypeIndex getFieldList() const { return FieldList; }
@@ -203,17 +597,48 @@ private:
StringRef UniqueName;
};
-class AggregateRecord : public TagRecord {
+// LF_CLASS, LF_STRUCTURE, LF_INTERFACE
+class ClassRecord : public TagRecord {
public:
- AggregateRecord(TypeRecordKind Kind, uint16_t MemberCount,
- ClassOptions Options, HfaKind Hfa,
- WindowsRTClassKind WinRTKind, TypeIndex FieldList,
- TypeIndex DerivationList, TypeIndex VTableShape,
- uint64_t Size, StringRef Name, StringRef UniqueName)
+ ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
+ HfaKind Hfa, WindowsRTClassKind WinRTKind, TypeIndex FieldList,
+ TypeIndex DerivationList, TypeIndex VTableShape, uint64_t Size,
+ StringRef Name, StringRef UniqueName)
: TagRecord(Kind, MemberCount, Options, FieldList, Name, UniqueName),
Hfa(Hfa), WinRTKind(WinRTKind), DerivationList(DerivationList),
VTableShape(VTableShape), Size(Size) {}
+ static ErrorOr<ClassRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ uint64_t Size = 0;
+ StringRef Name;
+ StringRef UniqueName;
+ uint16_t Props;
+
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ Props = L->Properties;
+ uint16_t WrtValue = (Props & WinRTKindMask) >> WinRTKindShift;
+ WindowsRTClassKind WRT = static_cast<WindowsRTClassKind>(WrtValue);
+ uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift;
+ HfaKind Hfa = static_cast<HfaKind>(HfaMask);
+
+ if (!decodeUIntLeaf(Data, Size))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ if (Props & uint16_t(ClassOptions::HasUniqueName)) {
+ if (auto EC = consumeCString(Data, UniqueName))
+ return EC;
+ }
+
+ ClassOptions Options = static_cast<ClassOptions>(Props);
+ return ClassRecord(Kind, L->MemberCount, Options, Hfa, WRT, L->FieldList,
+ L->DerivedFrom, L->VShape, Size, Name, UniqueName);
+ }
+
HfaKind getHfa() const { return Hfa; }
WindowsRTClassKind getWinRTKind() const { return WinRTKind; }
TypeIndex getDerivationList() const { return DerivationList; }
@@ -221,6 +646,17 @@ public:
uint64_t getSize() const { return Size; }
private:
+ struct Layout {
+ ulittle16_t MemberCount; // Number of members in FieldList.
+ ulittle16_t Properties; // ClassOptions bitset
+ TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members
+ TypeIndex DerivedFrom; // LF_DERIVED: List of known derived classes
+ TypeIndex VShape; // LF_VTSHAPE: Shape of the vftable
+ // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC
+ // integer.
+ // Name: The null-terminated name follows.
+ };
+
HfaKind Hfa;
WindowsRTClassKind WinRTKind;
TypeIndex DerivationList;
@@ -228,6 +664,63 @@ private:
uint64_t Size;
};
+// LF_UNION
+struct UnionRecord : public TagRecord {
+ UnionRecord(uint16_t MemberCount, ClassOptions Options, HfaKind Hfa,
+ TypeIndex FieldList, uint64_t Size, StringRef Name,
+ StringRef UniqueName)
+ : TagRecord(TypeRecordKind::Union, MemberCount, Options, FieldList, Name,
+ UniqueName),
+ Hfa(Hfa), Size(Size) {}
+
+ static ErrorOr<UnionRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ uint64_t Size = 0;
+ StringRef Name;
+ StringRef UniqueName;
+ uint16_t Props;
+
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ Props = L->Properties;
+
+ uint16_t HfaMask = (Props & HfaKindMask) >> HfaKindShift;
+ HfaKind Hfa = static_cast<HfaKind>(HfaMask);
+
+ if (!decodeUIntLeaf(Data, Size))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ if (Props & uint16_t(ClassOptions::HasUniqueName)) {
+ if (auto EC = consumeCString(Data, UniqueName))
+ return EC;
+ }
+
+ ClassOptions Options = static_cast<ClassOptions>(Props);
+ return UnionRecord(L->MemberCount, Options, Hfa, L->FieldList, Size, Name,
+ UniqueName);
+ }
+
+ HfaKind getHfa() const { return Hfa; }
+ uint64_t getSize() const { return Size; }
+
+private:
+ struct Layout {
+ ulittle16_t MemberCount; // Number of members in FieldList.
+ ulittle16_t Properties; // ClassOptions bitset
+ TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members
+ // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC
+ // integer.
+ // Name: The null-terminated name follows.
+ };
+
+ HfaKind Hfa;
+ uint64_t Size;
+};
+
+// LF_ENUM
class EnumRecord : public TagRecord {
public:
EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
@@ -236,9 +729,32 @@ public:
UniqueName),
UnderlyingType(UnderlyingType) {}
+ static ErrorOr<EnumRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ uint16_t P = L->Properties;
+ ClassOptions Options = static_cast<ClassOptions>(P);
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ return EnumRecord(L->NumEnumerators, Options, L->FieldListType, Name, Name,
+ L->UnderlyingType);
+ }
+
TypeIndex getUnderlyingType() const { return UnderlyingType; }
private:
+ struct Layout {
+ ulittle16_t NumEnumerators; // Number of enumerators
+ ulittle16_t Properties;
+ TypeIndex UnderlyingType;
+ TypeIndex FieldListType;
+ // Name: The null-terminated name follows.
+ };
+
TypeIndex UnderlyingType;
};
@@ -258,311 +774,668 @@ private:
uint8_t BitOffset;
};
+// LF_VTSHAPE
class VirtualTableShapeRecord : TypeRecord {
public:
explicit VirtualTableShapeRecord(ArrayRef<VirtualTableSlotKind> Slots)
+ : TypeRecord(TypeRecordKind::VirtualTableShape), SlotsRef(Slots) {}
+ explicit VirtualTableShapeRecord(std::vector<VirtualTableSlotKind> Slots)
: TypeRecord(TypeRecordKind::VirtualTableShape), Slots(Slots) {}
- ArrayRef<VirtualTableSlotKind> getSlots() const { return Slots; }
+ static ErrorOr<VirtualTableShapeRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ std::vector<VirtualTableSlotKind> Slots;
+ uint16_t Count = L->VFEntryCount;
+ while (Count > 0) {
+ if (Data.empty())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ // Process up to 2 nibbles at a time (if there are at least 2 remaining)
+ uint8_t Value = Data[0] & 0x0F;
+ Slots.push_back(static_cast<VirtualTableSlotKind>(Value));
+ if (--Count > 0) {
+ Value = (Data[0] & 0xF0) >> 4;
+ Slots.push_back(static_cast<VirtualTableSlotKind>(Value));
+ --Count;
+ }
+ Data = Data.slice(1);
+ }
-private:
- ArrayRef<VirtualTableSlotKind> Slots;
-};
+ return VirtualTableShapeRecord(Slots);
+ }
-//===----------------------------------------------------------------------===//
-// On-disk representation of type information
+ ArrayRef<VirtualTableSlotKind> getSlots() const {
+ if (!SlotsRef.empty())
+ return SlotsRef;
+ return Slots;
+ }
+ uint32_t getEntryCount() const { return getSlots().size(); }
-// A CodeView type stream is a sequence of TypeRecords. Records larger than
-// 65536 must chain on to a second record. Each TypeRecord is followed by one of
-// the leaf types described below.
+private:
+ struct Layout {
+ // Number of vftable entries. Each method may have more than one entry due
+ // to
+ // things like covariant return types.
+ ulittle16_t VFEntryCount;
+ // Descriptors[]: 4-bit virtual method descriptors of type CV_VTS_desc_e.
+ };
-// LF_TYPESERVER2
-struct TypeServer2 {
- char Signature[16]; // GUID
- ulittle32_t Age;
- // Name: Name of the PDB as a null-terminated string
+private:
+ ArrayRef<VirtualTableSlotKind> SlotsRef;
+ std::vector<VirtualTableSlotKind> Slots;
};
-// LF_STRING_ID
-struct StringId {
- TypeIndex id;
-};
+// LF_TYPESERVER2
+class TypeServer2Record : TypeRecord {
+public:
+ TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name)
+ : TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age),
+ Name(Name) {}
+
+ static ErrorOr<TypeServer2Record> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ return TypeServer2Record(StringRef(L->Guid, 16), L->Age, Name);
+ }
-// LF_FUNC_ID
-struct FuncId {
- TypeIndex ParentScope;
- TypeIndex FunctionType;
- // Name: The null-terminated name follows.
-};
+ StringRef getGuid() const { return Guid; }
-// LF_CLASS, LF_STRUCTURE, LF_INTERFACE
-struct ClassType {
- ulittle16_t MemberCount; // Number of members in FieldList.
- ulittle16_t Properties; // ClassOptions bitset
- TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members
- TypeIndex DerivedFrom; // LF_DERIVED: List of known derived classes
- TypeIndex VShape; // LF_VTSHAPE: Shape of the vftable
- // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC integer.
- // Name: The null-terminated name follows.
-};
+ uint32_t getAge() const { return Age; }
-// LF_UNION
-struct UnionType {
- ulittle16_t MemberCount; // Number of members in FieldList.
- ulittle16_t Properties; // ClassOptions bitset
- TypeIndex FieldList; // LF_FIELDLIST: List of all kinds of members
- // SizeOf: The 'sizeof' the UDT in bytes is encoded as an LF_NUMERIC integer.
- // Name: The null-terminated name follows.
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ char Guid[16]; // GUID
+ ulittle32_t Age;
+ // Name: Name of the PDB as a null-terminated string
+ };
+
+ StringRef Guid;
+ uint32_t Age;
+ StringRef Name;
};
-// LF_POINTER
-struct PointerType {
- TypeIndex PointeeType;
- ulittle32_t Attrs; // pointer attributes
- // if pointer to member:
- // PointerToMemberTail
-
- PointerKind getPtrKind() const { return PointerKind(Attrs & 0x1f); }
- PointerMode getPtrMode() const { return PointerMode((Attrs >> 5) & 0x07); }
- bool isFlat() const { return Attrs & (1 << 8); }
- bool isVolatile() const { return Attrs & (1 << 9); }
- bool isConst() const { return Attrs & (1 << 10); }
- bool isUnaligned() const { return Attrs & (1 << 11); }
+// LF_STRING_ID
+class StringIdRecord : public TypeRecord {
+public:
+ StringIdRecord(TypeIndex Id, StringRef String)
+ : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
- bool isPointerToDataMember() const {
- return getPtrMode() == PointerMode::PointerToDataMember;
+ static ErrorOr<StringIdRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ return StringIdRecord(L->id, Name);
}
- bool isPointerToMemberFunction() const {
- return getPtrMode() == PointerMode::PointerToMemberFunction;
- }
- bool isPointerToMember() const {
- return isPointerToMemberFunction() || isPointerToDataMember();
- }
-};
-struct PointerToMemberTail {
- TypeIndex ClassType;
- ulittle16_t Representation; // PointerToMemberRepresentation
-};
+ TypeIndex getId() const { return Id; }
-/// In Clang parlance, these are "qualifiers". LF_MODIFIER
-struct TypeModifier {
- TypeIndex ModifiedType;
- ulittle16_t Modifiers; // ModifierOptions
-};
+ StringRef getString() const { return String; }
-// LF_VTSHAPE
-struct VTableShape {
- // Number of vftable entries. Each method may have more than one entry due to
- // things like covariant return types.
- ulittle16_t VFEntryCount;
- // Descriptors[]: 4-bit virtual method descriptors of type CV_VTS_desc_e.
-};
+private:
+ struct Layout {
+ TypeIndex id;
+ // Name: Name of the PDB as a null-terminated string
+ };
-// LF_UDT_SRC_LINE
-struct UDTSrcLine {
- TypeIndex UDT; // The user-defined type
- TypeIndex SourceFile; // StringID containing the source filename
- ulittle32_t LineNumber;
+ TypeIndex Id;
+ StringRef String;
};
-// LF_ARGLIST, LF_SUBSTR_LIST
-struct ArgList {
- ulittle32_t NumArgs; // Number of arguments
- // ArgTypes[]: Type indicies of arguments
-};
+// LF_FUNC_ID
+class FuncIdRecord : public TypeRecord {
+public:
+ FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
+ : TypeRecord(TypeRecordKind::FunctionId), ParentScope(ParentScope),
+ FunctionType(FunctionType), Name(Name) {}
+
+ static ErrorOr<FuncIdRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
-// LF_BUILDINFO
-struct BuildInfo {
- ulittle16_t NumArgs; // Number of arguments
- // ArgTypes[]: Type indicies of arguments
-};
+ return FuncIdRecord(L->ParentScope, L->FunctionType, Name);
+ }
-// LF_ENUM
-struct EnumType {
- ulittle16_t NumEnumerators; // Number of enumerators
- ulittle16_t Properties;
- TypeIndex UnderlyingType;
- TypeIndex FieldListType;
- // Name: The null-terminated name follows.
-};
+ TypeIndex getParentScope() const { return ParentScope; }
-// LF_ARRAY
-struct ArrayType {
- TypeIndex ElementType;
- TypeIndex IndexType;
- // SizeOf: LF_NUMERIC encoded size in bytes. Not element count!
- // Name: The null-terminated name follows.
-};
+ TypeIndex getFunctionType() const { return FunctionType; }
-// LF_VFTABLE
-struct VFTableType {
- TypeIndex CompleteClass; // Class that owns this vftable.
- TypeIndex OverriddenVFTable; // VFTable that this overrides.
- ulittle32_t VFPtrOffset; // VFPtr offset in CompleteClass
- ulittle32_t NamesLen; // Length of subsequent names array in bytes.
- // Names: A sequence of null-terminated strings. First string is vftable
- // names.
-};
+ StringRef getName() const { return Name; }
-// LF_MFUNC_ID
-struct MemberFuncId {
- TypeIndex ClassType;
+private:
+ struct Layout {
+ TypeIndex ParentScope;
+ TypeIndex FunctionType;
+ // Name: The null-terminated name follows.
+ };
+
+ TypeIndex ParentScope;
TypeIndex FunctionType;
- // Name: The null-terminated name follows.
+ StringRef Name;
};
-// LF_PROCEDURE
-struct ProcedureType {
- TypeIndex ReturnType;
- CallingConvention CallConv;
- FunctionOptions Options;
- ulittle16_t NumParameters;
- TypeIndex ArgListType;
-};
+// LF_UDT_SRC_LINE
+class UdtSourceLineRecord : public TypeRecord {
+public:
+ UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
+ : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
+ SourceFile(SourceFile), LineNumber(LineNumber) {}
+
+ static ErrorOr<UdtSourceLineRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
-// LF_MFUNCTION
-struct MemberFunctionType {
- TypeIndex ReturnType;
- TypeIndex ClassType;
- TypeIndex ThisType;
- CallingConvention CallConv;
- FunctionOptions Options;
- ulittle16_t NumParameters;
- TypeIndex ArgListType;
- little32_t ThisAdjustment;
-};
+ return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber);
+ }
-//===----------------------------------------------------------------------===//
-// Field list records, which do not include leafs or sizes
+ TypeIndex getUDT() const { return UDT; }
+ TypeIndex getSourceFile() const { return SourceFile; }
+ uint32_t getLineNumber() const { return LineNumber; }
-/// Equvalent to CV_fldattr_t in cvinfo.h.
-struct MemberAttributes {
- ulittle16_t Attrs;
+private:
+ struct Layout {
+ TypeIndex UDT; // The user-defined type
+ TypeIndex SourceFile; // StringID containing the source filename
+ ulittle32_t LineNumber;
+ };
+
+ TypeIndex UDT;
+ TypeIndex SourceFile;
+ uint32_t LineNumber;
+};
- /// Get the access specifier. Valid for any kind of member.
- MemberAccess getAccess() const {
- return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask));
- }
+// LF_BUILDINFO
+class BuildInfoRecord : public TypeRecord {
+public:
+ BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
+ : TypeRecord(TypeRecordKind::Modifier), ArgIndices(ArgIndices) {}
- /// Indicates if a method is defined with friend, virtual, static, etc.
- MethodKind getMethodKind() const {
- return MethodKind(
- (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >> 2);
+ static ErrorOr<BuildInfoRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ ArrayRef<TypeIndex> Indices;
+ if (auto EC = consumeArray(Data, Indices, L->NumArgs))
+ return EC;
+ return BuildInfoRecord(Indices);
}
- /// Get the flags that are not included in access control or method
- /// properties.
- MethodOptions getFlags() const {
- return MethodOptions(
- unsigned(Attrs) &
- ~unsigned(MethodOptions::AccessMask | MethodOptions::MethodKindMask));
- }
+ ArrayRef<TypeIndex> getArgs() const { return ArgIndices; }
- /// Is this method virtual.
- bool isVirtual() const {
- auto MP = getMethodKind();
- return MP != MethodKind::Vanilla && MP != MethodKind::Friend &&
- MP != MethodKind::Static;
+private:
+ struct Layout {
+ ulittle16_t NumArgs; // Number of arguments
+ // ArgTypes[]: Type indicies of arguments
+ };
+ ArrayRef<TypeIndex> ArgIndices;
+};
+
+// LF_VFTABLE
+class VirtualTableRecord : public TypeRecord {
+public:
+ VirtualTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
+ uint32_t VFPtrOffset, StringRef Name,
+ ArrayRef<StringRef> Methods)
+ : TypeRecord(TypeRecordKind::VirtualFunctionTable),
+ CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable),
+ VFPtrOffset(VFPtrOffset), Name(Name), MethodNamesRef(Methods) {}
+ VirtualTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
+ uint32_t VFPtrOffset, StringRef Name,
+ const std::vector<StringRef> &Methods)
+ : TypeRecord(TypeRecordKind::VirtualFunctionTable),
+ CompleteClass(CompleteClass), OverriddenVFTable(OverriddenVFTable),
+ VFPtrOffset(VFPtrOffset), Name(Name), MethodNames(Methods) {}
+
+ static ErrorOr<VirtualTableRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+
+ std::vector<StringRef> Names;
+ while (!Data.empty()) {
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+ Names.push_back(Name);
+ }
+ return VirtualTableRecord(L->CompleteClass, L->OverriddenVFTable,
+ L->VFPtrOffset, Name, Names);
}
- /// Does this member introduce a new virtual method.
- bool isIntroducedVirtual() const {
- auto MP = getMethodKind();
- return MP == MethodKind::IntroducingVirtual ||
- MP == MethodKind::PureIntroducingVirtual;
+ TypeIndex getCompleteClass() const { return CompleteClass; }
+ TypeIndex getOverriddenVTable() const { return OverriddenVFTable; }
+ uint32_t getVFPtrOffset() const { return VFPtrOffset; }
+ StringRef getName() const { return Name; }
+ ArrayRef<StringRef> getMethodNames() const {
+ if (!MethodNamesRef.empty())
+ return MethodNamesRef;
+ return MethodNames;
}
-};
-// LF_NESTTYPE
-struct NestedType {
- ulittle16_t Pad0; // Should be zero
- TypeIndex Type; // Type index of nested type
- // Name: Null-terminated string
+private:
+ struct Layout {
+ TypeIndex CompleteClass; // Class that owns this vftable.
+ TypeIndex OverriddenVFTable; // VFTable that this overrides.
+ ulittle32_t VFPtrOffset; // VFPtr offset in CompleteClass
+ ulittle32_t NamesLen; // Length of subsequent names array in bytes.
+ // Names: A sequence of null-terminated strings. First string is vftable
+ // names.
+ };
+
+ TypeIndex CompleteClass;
+ TypeIndex OverriddenVFTable;
+ ulittle32_t VFPtrOffset;
+ StringRef Name;
+ ArrayRef<StringRef> MethodNamesRef;
+ std::vector<StringRef> MethodNames;
};
// LF_ONEMETHOD
-struct OneMethod {
- MemberAttributes Attrs;
- TypeIndex Type;
- // If is introduced virtual method:
- // VFTableOffset: int32_t offset in vftable
- // Name: Null-terminated string
+class OneMethodRecord : public TypeRecord {
+public:
+ OneMethodRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options,
+ MemberAccess Access, int32_t VFTableOffset, StringRef Name)
+ : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Kind(Kind),
+ Options(Options), Access(Access), VFTableOffset(VFTableOffset),
+ Name(Name) {}
+
+ static ErrorOr<OneMethodRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ MethodOptions Options = L->Attrs.getFlags();
+ MethodKind MethKind = L->Attrs.getMethodKind();
+ MemberAccess Access = L->Attrs.getAccess();
+ int32_t VFTableOffset = 0;
+ if (L->Attrs.isIntroducedVirtual()) {
+ const little32_t *L;
+ if (consumeObject(Data, L))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ VFTableOffset = *L;
+ }
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
- MethodKind getMethodKind() const {
- return Attrs.getMethodKind();
+ return OneMethodRecord(L->Type, MethKind, Options, Access, VFTableOffset,
+ Name);
}
- bool isVirtual() const { return Attrs.isVirtual(); }
- bool isIntroducedVirtual() const { return Attrs.isIntroducedVirtual(); }
-};
+ TypeIndex getType() const { return Type; }
+ MethodKind getKind() const { return Kind; }
+ MethodOptions getOptions() const { return Options; }
+ MemberAccess getAccess() const { return Access; }
+ int32_t getVFTableOffset() const { return VFTableOffset; }
+ StringRef getName() const { return Name; }
-// LF_METHODLIST
-struct MethodListEntry {
- MemberAttributes Attrs;
- ulittle16_t Padding;
+ bool isIntroducingVirtual() const {
+ const uint8_t K = static_cast<uint8_t>(Kind);
+ const uint8_t V = static_cast<uint8_t>(MethodKind::IntroducingVirtual);
+ const uint8_t PV = static_cast<uint8_t>(MethodKind::PureIntroducingVirtual);
+ return (K & V) || (K & PV);
+ }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs;
+ TypeIndex Type;
+ // If is introduced virtual method:
+ // VFTableOffset: int32_t offset in vftable
+ // Name: Null-terminated string
+ };
TypeIndex Type;
- // If is introduced virtual method:
- // VFTableOffset: int32_t offset in vftable
+ MethodKind Kind;
+ MethodOptions Options;
+ MemberAccess Access;
+ int32_t VFTableOffset;
+ StringRef Name;
+};
- MethodKind getMethodKind() const {
- return Attrs.getMethodKind();
+// LF_METHODLIST
+class MethodListRecord : public TypeRecord {
+public:
+ MethodListRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options,
+ MemberAccess Access, int32_t VFTableOffset)
+ : TypeRecord(TypeRecordKind::MethodList), Type(Type), Kind(Kind),
+ Options(Options), Access(Access), VFTableOffset(VFTableOffset) {}
+
+ static ErrorOr<MethodListRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ MethodOptions Options = L->Attrs.getFlags();
+ MethodKind MethKind = L->Attrs.getMethodKind();
+ MemberAccess Access = L->Attrs.getAccess();
+ int32_t VFTableOffset = 0;
+ if (L->Attrs.isIntroducedVirtual()) {
+ const little32_t *L;
+ if (consumeObject(Data, L))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ VFTableOffset = *L;
+ }
+
+ return MethodListRecord(L->Type, MethKind, Options, Access, VFTableOffset);
}
- bool isVirtual() const { return Attrs.isVirtual(); }
- bool isIntroducedVirtual() const { return Attrs.isIntroducedVirtual(); }
+ TypeIndex getType() const { return Type; }
+ MethodKind getMethodKind() const { return Kind; }
+ MethodOptions getOptions() const { return Options; }
+ MemberAccess getAccess() const { return Access; }
+ int32_t getVFTableOffset() const { return VFTableOffset; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs;
+ ulittle16_t Padding;
+
+ TypeIndex Type;
+ // If is introduced virtual method:
+ // VFTableOffset: int32_t offset in vftable
+ };
+
+ TypeIndex Type;
+ MethodKind Kind;
+ MethodOptions Options;
+ MemberAccess Access;
+ int32_t VFTableOffset;
};
/// For method overload sets. LF_METHOD
-struct OverloadedMethod {
- ulittle16_t MethodCount; // Size of overload set
- TypeIndex MethList; // Type index of methods in overload set
- // Name: Null-terminated string
-};
+class OverloadedMethodRecord : public TypeRecord {
+public:
+ OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
+ StringRef Name)
+ : TypeRecord(TypeRecordKind::OverloadedMethod),
+ NumOverloads(NumOverloads), MethodList(MethodList), Name(Name) {}
+
+ static ErrorOr<OverloadedMethodRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
-// LF_VFUNCTAB
-struct VirtualFunctionPointer {
- ulittle16_t Pad0;
- TypeIndex Type; // Type of vfptr
+ return OverloadedMethodRecord(L->MethodCount, L->MethList, Name);
+ }
+
+ uint16_t getNumOverloads() const { return NumOverloads; }
+ TypeIndex getMethodList() const { return MethodList; }
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ ulittle16_t MethodCount; // Size of overload set
+ TypeIndex MethList; // Type index of methods in overload set
+ // Name: Null-terminated string
+ };
+
+ uint16_t NumOverloads;
+ TypeIndex MethodList;
+ StringRef Name;
};
// LF_MEMBER
-struct DataMember {
- MemberAttributes Attrs; // Access control attributes, etc
+class DataMemberRecord : public TypeRecord {
+public:
+ DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset,
+ StringRef Name)
+ : TypeRecord(TypeRecordKind::Member), Access(Access), Type(Type),
+ FieldOffset(Offset), Name(Name) {}
+
+ static ErrorOr<DataMemberRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ uint64_t Offset;
+ if (!decodeUIntLeaf(Data, Offset))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+
+ return DataMemberRecord(L->Attrs.getAccess(), L->Type, Offset, Name);
+ }
+
+ MemberAccess getAccess() const { return Access; }
+ TypeIndex getType() const { return Type; }
+ uint64_t getFieldOffset() const { return FieldOffset; }
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc
+ TypeIndex Type;
+ // FieldOffset: LF_NUMERIC encoded byte offset
+ // Name: Null-terminated string
+ };
+
+ MemberAccess Access;
TypeIndex Type;
- // FieldOffset: LF_NUMERIC encoded byte offset
- // Name: Null-terminated string
+ uint64_t FieldOffset;
+ StringRef Name;
};
// LF_STMEMBER
-struct StaticDataMember {
- MemberAttributes Attrs; // Access control attributes, etc
+class StaticDataMemberRecord : public TypeRecord {
+public:
+ StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
+ : TypeRecord(TypeRecordKind::StaticMember), Access(Access), Type(Type),
+ Name(Name) {}
+
+ static ErrorOr<StaticDataMemberRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+
+ return StaticDataMemberRecord(L->Attrs.getAccess(), L->Type, Name);
+ }
+
+ MemberAccess getAccess() const { return Access; }
+ TypeIndex getType() const { return Type; }
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc
+ TypeIndex Type;
+ // Name: Null-terminated string
+ };
+
+ MemberAccess Access;
TypeIndex Type;
- // Name: Null-terminated string
+ StringRef Name;
};
// LF_ENUMERATE
-struct Enumerator {
- MemberAttributes Attrs; // Access control attributes, etc
- // EnumValue: LF_NUMERIC encoded enumerator value
- // Name: Null-terminated string
+class EnumeratorRecord : public TypeRecord {
+public:
+ EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
+ : TypeRecord(TypeRecordKind::Enumerate), Access(Access), Value(Value),
+ Name(Name) {}
+
+ static ErrorOr<EnumeratorRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ if (Data.empty())
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ APSInt Value;
+ if (!decodeNumericLeaf(Data, Value))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ StringRef Name;
+ if (auto EC = consumeCString(Data, Name))
+ return EC;
+
+ return EnumeratorRecord(L->Attrs.getAccess(), Value, Name);
+ }
+
+ MemberAccess getAccess() const { return Access; }
+ APSInt getValue() const { return Value; }
+ StringRef getName() const { return Name; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc
+ // EnumValue: LF_NUMERIC encoded enumerator value
+ // Name: Null-terminated string
+ };
+
+ MemberAccess Access;
+ APSInt Value;
+ StringRef Name;
+};
+
+// LF_VFUNCTAB
+class VirtualFunctionPointerRecord : public TypeRecord {
+public:
+ VirtualFunctionPointerRecord(TypeIndex Type)
+ : TypeRecord(TypeRecordKind::VirtualFunctionTablePointer), Type(Type) {}
+ static ErrorOr<VirtualFunctionPointerRecord>
+ deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ return VirtualFunctionPointerRecord(L->Type);
+ }
+
+ TypeIndex getType() const { return Type; }
+
+private:
+ struct Layout {
+ ulittle16_t Pad0;
+ TypeIndex Type; // Type of vfptr
+ };
+ TypeIndex Type;
};
// LF_BCLASS, LF_BINTERFACE
-struct BaseClass {
- MemberAttributes Attrs; // Access control attributes, etc
- TypeIndex BaseType; // Base class type
- // BaseOffset: LF_NUMERIC encoded byte offset of base from derived.
+class BaseClassRecord : public TypeRecord {
+public:
+ BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
+ : TypeRecord(TypeRecordKind::BaseClass), Access(Access), Type(Type),
+ Offset(Offset) {}
+
+ static ErrorOr<BaseClassRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ uint64_t Offset;
+ if (!decodeUIntLeaf(Data, Offset))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ return BaseClassRecord(L->Attrs.getAccess(), L->BaseType, Offset);
+ }
+
+ MemberAccess getAccess() const { return Access; }
+ TypeIndex getBaseType() const { return Type; }
+ uint64_t getBaseOffset() const { return Offset; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc
+ TypeIndex BaseType; // Base class type
+ // BaseOffset: LF_NUMERIC encoded byte offset of base from derived.
+ };
+ MemberAccess Access;
+ TypeIndex Type;
+ uint64_t Offset;
};
// LF_VBCLASS, LF_IVBCLASS
-struct VirtualBaseClass {
- MemberAttributes Attrs; // Access control attributes, etc.
- TypeIndex BaseType; // Base class type
- TypeIndex VBPtrType; // Virtual base pointer type
- // VBPtrOffset: Offset of vbptr from vfptr encoded as LF_NUMERIC.
- // VBTableIndex: Index of vbase within vbtable encoded as LF_NUMERIC.
+class VirtualBaseClassRecord : public TypeRecord {
+public:
+ VirtualBaseClassRecord(MemberAccess Access, TypeIndex BaseType,
+ TypeIndex VBPtrType, uint64_t Offset, uint64_t Index)
+ : TypeRecord(TypeRecordKind::VirtualBaseClass), Access(Access),
+ BaseType(BaseType), VBPtrType(VBPtrType), VBPtrOffset(Offset),
+ VTableIndex(Index) {}
+
+ static ErrorOr<VirtualBaseClassRecord> deserialize(TypeRecordKind Kind,
+ ArrayRef<uint8_t> &Data) {
+ const Layout *L = nullptr;
+ if (auto EC = consumeObject(Data, L))
+ return EC;
+
+ uint64_t Offset;
+ uint64_t Index;
+ if (!decodeUIntLeaf(Data, Offset))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ if (!decodeUIntLeaf(Data, Index))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ return VirtualBaseClassRecord(L->Attrs.getAccess(), L->BaseType,
+ L->VBPtrType, Offset, Index);
+ }
+
+ MemberAccess getAccess() const { return Access; }
+ TypeIndex getBaseType() const { return BaseType; }
+ TypeIndex getVBPtrType() const { return VBPtrType; }
+ uint64_t getVBPtrOffset() const { return VBPtrOffset; }
+ uint64_t getVTableIndex() const { return VTableIndex; }
+
+private:
+ struct Layout {
+ MemberAttributes Attrs; // Access control attributes, etc.
+ TypeIndex BaseType; // Base class type
+ TypeIndex VBPtrType; // Virtual base pointer type
+ // VBPtrOffset: Offset of vbptr from vfptr encoded as LF_NUMERIC.
+ // VBTableIndex: Index of vbase within vbtable encoded as LF_NUMERIC.
+ };
+ MemberAccess Access;
+ TypeIndex BaseType;
+ TypeIndex VBPtrType;
+ uint64_t VBPtrOffset;
+ uint64_t VTableIndex;
};
}
}
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def Wed May 11 12:47:35 2016
@@ -30,44 +30,44 @@
#endif
-TYPE_RECORD(PointerType, LF_POINTER)
-TYPE_RECORD(TypeModifier, LF_MODIFIER)
-TYPE_RECORD(ProcedureType, LF_PROCEDURE)
-TYPE_RECORD(MemberFunctionType, LF_MFUNCTION)
-TYPE_RECORD(ArgList, LF_ARGLIST)
-
-TYPE_RECORD(ArrayType, LF_ARRAY)
-TYPE_RECORD(ClassType, LF_CLASS)
-TYPE_RECORD_ALIAS(ClassType, LF_STRUCTURE)
-TYPE_RECORD_ALIAS(ClassType, LF_INTERFACE)
-TYPE_RECORD(UnionType, LF_UNION)
-TYPE_RECORD(EnumType, LF_ENUM)
-TYPE_RECORD(TypeServer2, LF_TYPESERVER2)
-TYPE_RECORD(VFTableType, LF_VFTABLE)
-TYPE_RECORD(VTableShape, LF_VTSHAPE)
+TYPE_RECORD(PointerRecord, LF_POINTER)
+TYPE_RECORD(ModifierRecord, LF_MODIFIER)
+TYPE_RECORD(ProcedureRecord, LF_PROCEDURE)
+TYPE_RECORD(MemberFunctionRecord, LF_MFUNCTION)
+TYPE_RECORD(StringListRecord, LF_ARGLIST)
+
+TYPE_RECORD(ArrayRecord, LF_ARRAY)
+TYPE_RECORD(ClassRecord, LF_CLASS)
+TYPE_RECORD_ALIAS(ClassRecord, LF_STRUCTURE)
+TYPE_RECORD_ALIAS(ClassRecord, LF_INTERFACE)
+TYPE_RECORD(UnionRecord, LF_UNION)
+TYPE_RECORD(EnumRecord, LF_ENUM)
+TYPE_RECORD(TypeServer2Record, LF_TYPESERVER2)
+TYPE_RECORD(VirtualTableRecord, LF_VFTABLE)
+TYPE_RECORD(VirtualTableShapeRecord, LF_VTSHAPE)
// Member type records. These are generally not length prefixed, and appear
// inside of a field list record.
-MEMBER_RECORD(BaseClass, LF_BCLASS)
-MEMBER_RECORD_ALIAS(BaseClass, LF_BINTERFACE)
-MEMBER_RECORD(VirtualBaseClass, LF_VBCLASS)
-MEMBER_RECORD_ALIAS(VirtualBaseClass, LF_IVBCLASS)
-MEMBER_RECORD(VirtualFunctionPointer, LF_VFUNCTAB)
-MEMBER_RECORD(StaticDataMember, LF_STMEMBER)
-MEMBER_RECORD(OverloadedMethod, LF_METHOD)
-MEMBER_RECORD(DataMember, LF_MEMBER)
-MEMBER_RECORD(NestedType, LF_NESTTYPE)
-MEMBER_RECORD(OneMethod, LF_ONEMETHOD)
-MEMBER_RECORD(Enumerator, LF_ENUMERATE)
+MEMBER_RECORD(BaseClassRecord, LF_BCLASS)
+MEMBER_RECORD_ALIAS(BaseClassRecord, LF_BINTERFACE)
+MEMBER_RECORD(VirtualBaseClassRecord, LF_VBCLASS)
+MEMBER_RECORD_ALIAS(VirtualBaseClassRecord, LF_IVBCLASS)
+MEMBER_RECORD(VirtualFunctionPointerRecord, LF_VFUNCTAB)
+MEMBER_RECORD(StaticDataMemberRecord, LF_STMEMBER)
+MEMBER_RECORD(OverloadedMethodRecord, LF_METHOD)
+MEMBER_RECORD(DataMemberRecord, LF_MEMBER)
+MEMBER_RECORD(NestedTypeRecord, LF_NESTTYPE)
+MEMBER_RECORD(OneMethodRecord, LF_ONEMETHOD)
+MEMBER_RECORD(EnumeratorRecord, LF_ENUMERATE)
// ID leaf records. Subsequent leaf types may be referenced from .debug$S.
-TYPE_RECORD(FuncId, LF_FUNC_ID)
-TYPE_RECORD(MemberFuncId, LF_MFUNC_ID)
-TYPE_RECORD(BuildInfo, LF_BUILDINFO)
-TYPE_RECORD_ALIAS(ArgList, LF_SUBSTR_LIST)
-TYPE_RECORD(StringId, LF_STRING_ID)
-TYPE_RECORD(UDTSrcLine, LF_UDT_SRC_LINE)
+TYPE_RECORD(FuncIdRecord, LF_FUNC_ID)
+TYPE_RECORD(MemberFunctionIdRecord, LF_MFUNC_ID)
+TYPE_RECORD(BuildInfoRecord, LF_BUILDINFO)
+TYPE_RECORD_ALIAS(StringListRecord, LF_SUBSTR_LIST)
+TYPE_RECORD(StringIdRecord, LF_STRING_ID)
+TYPE_RECORD(UdtSourceLineRecord, LF_UDT_SRC_LINE)
#undef TYPE_RECORD
#undef TYPE_RECORD_ALIAS
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeStream.h Wed May 11 12:47:35 2016
@@ -15,7 +15,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/RecordIterator.h"
-#include "llvm/Object/Error.h"
#include "llvm/Support/Endian.h"
#include <cstdint>
#include <system_error>
@@ -26,43 +25,6 @@ class APSInt;
namespace codeview {
-/// Consumes sizeof(T) bytes from the given byte sequence. Returns an error if
-/// there are not enough bytes remaining. Reinterprets the consumed bytes as a
-/// T object and points 'Res' at them.
-template <typename T>
-inline std::error_code consumeObject(StringRef &Data, const T *&Res) {
- if (Data.size() < sizeof(*Res))
- return object::object_error::parse_failed;
- Res = reinterpret_cast<const T *>(Data.data());
- Data = Data.drop_front(sizeof(*Res));
- return std::error_code();
-}
-
-inline std::error_code consumeUInt32(StringRef &Data, uint32_t &Res) {
- const support::ulittle32_t *IntPtr;
- if (auto EC = consumeObject(Data, IntPtr))
- return EC;
- Res = *IntPtr;
- return std::error_code();
-}
-
-/// Decodes a numeric "leaf" value. These are integer literals encountered in
-/// the type stream. If the value is positive and less than LF_NUMERIC (1 <<
-/// 15), it is emitted directly in Data. Otherwise, it has a tag like LF_CHAR
-/// that indicates the bitwidth and sign of the numeric data.
-bool decodeNumericLeaf(ArrayRef<uint8_t> &Data, APSInt &Num);
-
-inline bool decodeNumericLeaf(StringRef &Data, APSInt &Num) {
- ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(Data.data()),
- Data.size());
- bool Success = decodeNumericLeaf(Bytes, Num);
- Data = StringRef(reinterpret_cast<const char *>(Bytes.data()), Bytes.size());
- return Success;
-}
-
-/// Decode a numeric leaf value that is known to be a uint32_t.
-bool decodeUIntLeaf(ArrayRef<uint8_t> &Data, uint64_t &Num);
-
typedef RecordIterator<TypeLeafKind> TypeIterator;
inline iterator_range<TypeIterator> makeTypeRange(ArrayRef<uint8_t> Data) {
Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h Wed May 11 12:47:35 2016
@@ -40,12 +40,11 @@ public:
TypeIndex writeModifier(const ModifierRecord &Record);
TypeIndex writeProcedure(const ProcedureRecord &Record);
TypeIndex writeMemberFunction(const MemberFunctionRecord &Record);
- TypeIndex writeArgumentList(const ArgumentListRecord &Record);
+ TypeIndex writeArgumentList(const StringListRecord &Record);
TypeIndex writeRecord(TypeRecordBuilder &builder);
TypeIndex writePointer(const PointerRecord &Record);
- TypeIndex writePointerToMember(const PointerToMemberRecord &Record);
TypeIndex writeArray(const ArrayRecord &Record);
- TypeIndex writeAggregate(const AggregateRecord &Record);
+ TypeIndex writeClass(const ClassRecord &Record);
TypeIndex writeEnum(const EnumRecord &Record);
TypeIndex writeBitField(const BitFieldRecord &Record);
TypeIndex writeVirtualTableShape(const VirtualTableShapeRecord &Record);
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Wed May 11 12:47:35 2016
@@ -263,7 +263,7 @@ void CodeViewDebug::emitTypeInformation(
// type here.
unsigned ArgListIndex = getNextTypeIndex();
OS.AddComment("Type record length");
- OS.EmitIntValue(2 + sizeof(ArgList), 2);
+ OS.EmitIntValue(StringListRecord::getLayoutSize(), 2);
OS.AddComment("Leaf type: LF_ARGLIST");
OS.EmitIntValue(LF_ARGLIST, 2);
OS.AddComment("Number of arguments");
@@ -271,7 +271,7 @@ void CodeViewDebug::emitTypeInformation(
unsigned VoidFnTyIdx = getNextTypeIndex();
OS.AddComment("Type record length");
- OS.EmitIntValue(2 + sizeof(ProcedureType), 2);
+ OS.EmitIntValue(ProcedureRecord::getLayoutSize(), 2);
OS.AddComment("Leaf type: LF_PROCEDURE");
OS.EmitIntValue(LF_PROCEDURE, 2);
OS.AddComment("Return type index");
Modified: llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp Wed May 11 12:47:35 2016
@@ -56,7 +56,7 @@ void FieldListRecordBuilder::writeMethod
TypeIndex MethodList, StringRef Name) {
TypeRecordBuilder &Builder = getBuilder();
- Builder.writeTypeRecordKind(TypeRecordKind::Method);
+ Builder.writeTypeRecordKind(TypeRecordKind::OverloadedMethod);
Builder.writeUInt16(OverloadCount);
Builder.writeTypeIndex(MethodList);
Builder.writeNullTerminatedString(Name);
Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp Wed May 11 12:47:35 2016
@@ -201,12 +201,10 @@ public:
/// CVTypeVisitor overrides.
#define TYPE_RECORD(ClassName, LeafEnum) \
- void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
- ArrayRef<uint8_t> LeafData);
+ void visit##ClassName(TypeLeafKind LeafType, ClassName &Record);
#define TYPE_RECORD_ALIAS(ClassName, LeafEnum)
#define MEMBER_RECORD(ClassName, LeafEnum) \
- void visit##ClassName(TypeLeafKind LeafType, const ClassName *Record, \
- ArrayRef<uint8_t> &FieldData);
+ void visit##ClassName(TypeLeafKind LeafType, ClassName &Record);
#define MEMBER_RECORD_ALIAS(ClassName, LeafEnum)
#include "llvm/DebugInfo/CodeView/TypeRecords.def"
@@ -219,6 +217,8 @@ public:
void visitTypeEnd(TypeLeafKind Leaf, ArrayRef<uint8_t> LeafData);
void printMemberAttributes(MemberAttributes Attrs);
+ void printMemberAttributes(MemberAccess Access, MethodKind Kind,
+ MethodOptions Options);
private:
/// Forwards to the dumper, which holds the persistent state from visitation.
@@ -240,17 +240,6 @@ private:
} // end anonymous namespace
-/// Reinterpret a byte array as an array of characters. Does not interpret as
-/// a C string, as StringRef has several helpers (split) that make that easy.
-static StringRef getBytesAsCharacters(ArrayRef<uint8_t> LeafData) {
- return StringRef(reinterpret_cast<const char *>(LeafData.data()),
- LeafData.size());
-}
-
-static StringRef getBytesAsCString(ArrayRef<uint8_t> LeafData) {
- return getBytesAsCharacters(LeafData).split('\0').first;
-}
-
static StringRef getLeafTypeName(TypeLeafKind LT) {
switch (LT) {
#define KNOWN_TYPE(LeafName, Value, ClassName) \
@@ -286,164 +275,128 @@ void CVTypeDumperImpl::visitTypeEnd(Type
W.startLine() << "}\n";
}
-void CVTypeDumperImpl::visitStringId(TypeLeafKind Leaf, const StringId *String,
- ArrayRef<uint8_t> LeafData) {
- W.printHex("Id", String->id.getIndex());
- StringRef StringData = getBytesAsCString(LeafData);
- W.printString("StringData", StringData);
+void CVTypeDumperImpl::visitStringIdRecord(TypeLeafKind Leaf,
+ StringIdRecord &String) {
+ printTypeIndex("Id", String.getId());
+ W.printString("StringData", String.getString());
// Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
- Name = StringData;
+ Name = String.getString();
}
-
-void CVTypeDumperImpl::visitArgList(TypeLeafKind Leaf, const ArgList *Args,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("NumArgs", Args->NumArgs);
+void CVTypeDumperImpl::visitStringListRecord(TypeLeafKind Leaf,
+ StringListRecord &Args) {
+ auto Indices = Args.getIndices();
+ uint32_t Size = Indices.size();
+ W.printNumber("NumArgs", Size);
ListScope Arguments(W, "Arguments");
SmallString<256> TypeName("(");
- for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
- const TypeIndex *Type;
- if (!consumeObject(LeafData, Type))
- return;
- printTypeIndex("ArgType", *Type);
- StringRef ArgTypeName = getTypeName(*Type);
+ for (uint32_t I = 0; I < Size; ++I) {
+ printTypeIndex("ArgType", Indices[I]);
+ StringRef ArgTypeName = getTypeName(Indices[I]);
TypeName.append(ArgTypeName);
- if (ArgI + 1 != Args->NumArgs)
+ if (I + 1 != Size)
TypeName.append(", ");
}
TypeName.push_back(')');
Name = CVTD.saveName(TypeName);
}
-void CVTypeDumperImpl::visitClassType(TypeLeafKind Leaf, const ClassType *Class,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("MemberCount", Class->MemberCount);
- uint16_t Props = Class->Properties;
+void CVTypeDumperImpl::visitClassRecord(TypeLeafKind Leaf, ClassRecord &Class) {
+ uint16_t Props = static_cast<uint16_t>(Class.getOptions());
+ W.printNumber("MemberCount", Class.getMemberCount());
W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
- printTypeIndex("FieldList", Class->FieldList);
- printTypeIndex("DerivedFrom", Class->DerivedFrom);
- printTypeIndex("VShape", Class->VShape);
- uint64_t SizeOf;
- if (!decodeUIntLeaf(LeafData, SizeOf))
- return parseError();
- W.printNumber("SizeOf", SizeOf);
- StringRef LeafChars = getBytesAsCharacters(LeafData);
- StringRef LinkageName;
- std::tie(Name, LinkageName) = LeafChars.split('\0');
- W.printString("Name", Name);
- if (Props & uint16_t(ClassOptions::HasUniqueName)) {
- LinkageName = LinkageName.split('\0').first;
- if (LinkageName.empty())
- return parseError();
- W.printString("LinkageName", LinkageName);
- }
+ printTypeIndex("FieldList", Class.getFieldList());
+ printTypeIndex("DerivedFrom", Class.getDerivationList());
+ printTypeIndex("VShape", Class.getVTableShape());
+ W.printNumber("SizeOf", Class.getSize());
+ W.printString("Name", Class.getName());
+ if (Props & uint16_t(ClassOptions::HasUniqueName))
+ W.printString("LinkageName", Class.getUniqueName());
+ Name = Class.getName();
}
-void CVTypeDumperImpl::visitUnionType(TypeLeafKind Leaf, const UnionType *Union,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("MemberCount", Union->MemberCount);
- uint16_t Props = Union->Properties;
+void CVTypeDumperImpl::visitUnionRecord(TypeLeafKind Leaf, UnionRecord &Union) {
+ uint16_t Props = static_cast<uint16_t>(Union.getOptions());
+ W.printNumber("MemberCount", Union.getMemberCount());
W.printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
- printTypeIndex("FieldList", Union->FieldList);
- uint64_t SizeOf;
- if (!decodeUIntLeaf(LeafData, SizeOf))
- return parseError();
- W.printNumber("SizeOf", SizeOf);
- StringRef LeafChars = getBytesAsCharacters(LeafData);
- StringRef LinkageName;
- std::tie(Name, LinkageName) = LeafChars.split('\0');
- W.printString("Name", Name);
- if (Props & uint16_t(ClassOptions::HasUniqueName)) {
- LinkageName = LinkageName.split('\0').first;
- if (LinkageName.empty())
- return parseError();
- W.printString("LinkageName", LinkageName);
- }
+ printTypeIndex("FieldList", Union.getFieldList());
+ W.printNumber("SizeOf", Union.getSize());
+ W.printString("Name", Union.getName());
+ if (Props & uint16_t(ClassOptions::HasUniqueName))
+ W.printString("LinkageName", Union.getUniqueName());
+ Name = Union.getName();
}
-void CVTypeDumperImpl::visitEnumType(TypeLeafKind Leaf, const EnumType *Enum,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("NumEnumerators", Enum->NumEnumerators);
- W.printFlags("Properties", uint16_t(Enum->Properties),
+void CVTypeDumperImpl::visitEnumRecord(TypeLeafKind Leaf, EnumRecord &Enum) {
+ W.printNumber("NumEnumerators", Enum.getMemberCount());
+ W.printFlags("Properties", uint16_t(Enum.getOptions()),
makeArrayRef(ClassOptionNames));
- printTypeIndex("UnderlyingType", Enum->UnderlyingType);
- printTypeIndex("FieldListType", Enum->FieldListType);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumperImpl::visitArrayType(TypeLeafKind Leaf, const ArrayType *AT,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ElementType", AT->ElementType);
- printTypeIndex("IndexType", AT->IndexType);
- uint64_t SizeOf;
- if (!decodeUIntLeaf(LeafData, SizeOf))
- return parseError();
- W.printNumber("SizeOf", SizeOf);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumperImpl::visitVFTableType(TypeLeafKind Leaf,
- const VFTableType *VFT,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("CompleteClass", VFT->CompleteClass);
- printTypeIndex("OverriddenVFTable", VFT->OverriddenVFTable);
- W.printHex("VFPtrOffset", VFT->VFPtrOffset);
- StringRef NamesData = getBytesAsCharacters(LeafData.slice(0, VFT->NamesLen));
- std::tie(Name, NamesData) = NamesData.split('\0');
- W.printString("VFTableName", Name);
- while (!NamesData.empty()) {
- StringRef MethodName;
- std::tie(MethodName, NamesData) = NamesData.split('\0');
- W.printString("MethodName", MethodName);
- }
-}
-
-void CVTypeDumperImpl::visitMemberFuncId(TypeLeafKind Leaf,
- const MemberFuncId *Id,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ClassType", Id->ClassType);
- printTypeIndex("FunctionType", Id->FunctionType);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumperImpl::visitProcedureType(TypeLeafKind Leaf,
- const ProcedureType *Proc,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ReturnType", Proc->ReturnType);
- W.printEnum("CallingConvention", uint8_t(Proc->CallConv),
+ printTypeIndex("UnderlyingType", Enum.getUnderlyingType());
+ printTypeIndex("FieldListType", Enum.getFieldList());
+ W.printString("Name", Enum.getName());
+ Name = Enum.getName();
+}
+
+void CVTypeDumperImpl::visitArrayRecord(TypeLeafKind Leaf, ArrayRecord &AT) {
+ printTypeIndex("ElementType", AT.getElementType());
+ printTypeIndex("IndexType", AT.getIndexType());
+ W.printNumber("SizeOf", AT.getSize());
+ W.printString("Name", AT.getName());
+ Name = AT.getName();
+}
+
+void CVTypeDumperImpl::visitVirtualTableRecord(TypeLeafKind Leaf,
+ VirtualTableRecord &VFT) {
+ printTypeIndex("CompleteClass", VFT.getCompleteClass());
+ printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
+ W.printHex("VFPtrOffset", VFT.getVFPtrOffset());
+ W.printString("VFTableName", VFT.getName());
+ for (auto N : VFT.getMethodNames())
+ W.printString("MethodName", N);
+ Name = VFT.getName();
+}
+
+void CVTypeDumperImpl::visitMemberFunctionIdRecord(TypeLeafKind Leaf,
+ MemberFunctionIdRecord &Id) {
+ printTypeIndex("ClassType", Id.getClassType());
+ printTypeIndex("FunctionType", Id.getFunctionType());
+ W.printString("Name", Id.getName());
+ Name = Id.getName();
+}
+
+void CVTypeDumperImpl::visitProcedureRecord(TypeLeafKind Leaf,
+ ProcedureRecord &Proc) {
+ printTypeIndex("ReturnType", Proc.getReturnType());
+ W.printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
makeArrayRef(CallingConventions));
- W.printFlags("FunctionOptions", uint8_t(Proc->Options),
+ W.printFlags("FunctionOptions", uint8_t(Proc.getOptions()),
makeArrayRef(FunctionOptionEnum));
- W.printNumber("NumParameters", Proc->NumParameters);
- printTypeIndex("ArgListType", Proc->ArgListType);
+ W.printNumber("NumParameters", Proc.getParameterCount());
+ printTypeIndex("ArgListType", Proc.getArgumentList());
- StringRef ReturnTypeName = getTypeName(Proc->ReturnType);
- StringRef ArgListTypeName = getTypeName(Proc->ArgListType);
+ StringRef ReturnTypeName = getTypeName(Proc.getReturnType());
+ StringRef ArgListTypeName = getTypeName(Proc.getArgumentList());
SmallString<256> TypeName(ReturnTypeName);
TypeName.push_back(' ');
TypeName.append(ArgListTypeName);
Name = CVTD.saveName(TypeName);
}
-void CVTypeDumperImpl::visitMemberFunctionType(
- TypeLeafKind Leaf, const MemberFunctionType *MemberFunc,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ReturnType", MemberFunc->ReturnType);
- printTypeIndex("ClassType", MemberFunc->ClassType);
- printTypeIndex("ThisType", MemberFunc->ThisType);
- W.printEnum("CallingConvention", uint8_t(MemberFunc->CallConv),
+void CVTypeDumperImpl::visitMemberFunctionRecord(TypeLeafKind Leaf,
+ MemberFunctionRecord &MF) {
+ printTypeIndex("ReturnType", MF.getReturnType());
+ printTypeIndex("ClassType", MF.getClassType());
+ printTypeIndex("ThisType", MF.getThisType());
+ W.printEnum("CallingConvention", uint8_t(MF.getCallConv()),
makeArrayRef(CallingConventions));
- W.printFlags("FunctionOptions", uint8_t(MemberFunc->Options),
+ W.printFlags("FunctionOptions", uint8_t(MF.getOptions()),
makeArrayRef(FunctionOptionEnum));
- W.printNumber("NumParameters", MemberFunc->NumParameters);
- printTypeIndex("ArgListType", MemberFunc->ArgListType);
- W.printNumber("ThisAdjustment", MemberFunc->ThisAdjustment);
-
- StringRef ReturnTypeName = getTypeName(MemberFunc->ReturnType);
- StringRef ClassTypeName = getTypeName(MemberFunc->ClassType);
- StringRef ArgListTypeName = getTypeName(MemberFunc->ArgListType);
+ W.printNumber("NumParameters", MF.getParameterCount());
+ printTypeIndex("ArgListType", MF.getArgumentList());
+ W.printNumber("ThisAdjustment", MF.getThisPointerAdjustment());
+
+ StringRef ReturnTypeName = getTypeName(MF.getReturnType());
+ StringRef ClassTypeName = getTypeName(MF.getClassType());
+ StringRef ArgListTypeName = getTypeName(MF.getArgumentList());
SmallString<256> TypeName(ReturnTypeName);
TypeName.push_back(' ');
TypeName.append(ClassTypeName);
@@ -455,148 +408,141 @@ void CVTypeDumperImpl::visitMemberFuncti
void CVTypeDumperImpl::visitMethodList(TypeLeafKind Leaf,
ArrayRef<uint8_t> LeafData) {
while (!LeafData.empty()) {
- const MethodListEntry *Method;
- if (!consumeObject(LeafData, Method))
+ auto Method =
+ MethodListRecord::deserialize(TypeRecordKind::MethodList, LeafData);
+ if (Method)
return;
+ const MethodListRecord &M = *Method;
+
ListScope S(W, "Method");
- printMemberAttributes(Method->Attrs);
- printTypeIndex("Type", Method->Type);
- if (Method->isIntroducedVirtual()) {
- const little32_t *VFTOffsetPtr;
- if (!consumeObject(LeafData, VFTOffsetPtr))
- return;
- W.printHex("VFTableOffset", *VFTOffsetPtr);
- }
+ printMemberAttributes(M.getAccess(), M.getMethodKind(), M.getOptions());
+ printTypeIndex("Type", Method->getType());
+ if (Method->getMethodKind() == MethodKind::IntroducingVirtual ||
+ Method->getMethodKind() == MethodKind::PureIntroducingVirtual)
+ W.printHex("VFTableOffset", Method->getVFTableOffset());
}
}
-void CVTypeDumperImpl::visitFuncId(TypeLeafKind Leaf, const FuncId *Func,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ParentScope", Func->ParentScope);
- printTypeIndex("FunctionType", Func->FunctionType);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumperImpl::visitTypeServer2(TypeLeafKind Leaf,
- const TypeServer2 *TypeServer,
- ArrayRef<uint8_t> LeafData) {
- W.printBinary("Signature", StringRef(TypeServer->Signature, 16));
- W.printNumber("Age", TypeServer->Age);
- Name = getBytesAsCString(LeafData);
- W.printString("Name", Name);
-}
-
-void CVTypeDumperImpl::visitPointerType(TypeLeafKind Leaf,
- const PointerType *Ptr,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("PointeeType", Ptr->PointeeType);
- W.printHex("PointerAttributes", Ptr->Attrs);
- W.printEnum("PtrType", unsigned(Ptr->getPtrKind()),
+void CVTypeDumperImpl::visitFuncIdRecord(TypeLeafKind Leaf,
+ FuncIdRecord &Func) {
+ printTypeIndex("ParentScope", Func.getParentScope());
+ printTypeIndex("FunctionType", Func.getFunctionType());
+ W.printString("Name", Func.getName());
+ Name = Func.getName();
+}
+
+void CVTypeDumperImpl::visitTypeServer2Record(TypeLeafKind Leaf,
+ TypeServer2Record &TS) {
+ W.printBinary("Signature", TS.getGuid());
+ W.printNumber("Age", TS.getAge());
+ W.printString("Name", TS.getName());
+ Name = TS.getName();
+}
+
+void CVTypeDumperImpl::visitPointerRecord(TypeLeafKind Leaf,
+ PointerRecord &Ptr) {
+ printTypeIndex("PointeeType", Ptr.getReferentType());
+ W.printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
+ W.printEnum("PtrType", unsigned(Ptr.getPointerKind()),
makeArrayRef(PtrKindNames));
- W.printEnum("PtrMode", unsigned(Ptr->getPtrMode()),
- makeArrayRef(PtrModeNames));
- W.printNumber("IsFlat", Ptr->isFlat());
- W.printNumber("IsConst", Ptr->isConst());
- W.printNumber("IsVolatile", Ptr->isVolatile());
- W.printNumber("IsUnaligned", Ptr->isUnaligned());
-
- if (Ptr->isPointerToMember()) {
- const PointerToMemberTail *PMT;
- if (!consumeObject(LeafData, PMT))
- return;
- printTypeIndex("ClassType", PMT->ClassType);
- W.printEnum("Representation", PMT->Representation,
+ W.printEnum("PtrMode", unsigned(Ptr.getMode()), makeArrayRef(PtrModeNames));
+
+ W.printNumber("IsFlat", Ptr.isFlat());
+ W.printNumber("IsConst", Ptr.isConst());
+ W.printNumber("IsVolatile", Ptr.isVolatile());
+ W.printNumber("IsUnaligned", Ptr.isUnaligned());
+
+ if (Ptr.isPointerToMember()) {
+ const MemberPointerInfo &MI = Ptr.getMemberInfo();
+
+ printTypeIndex("ClassType", MI.getContainingType());
+ W.printEnum("Representation", uint16_t(MI.getRepresentation()),
makeArrayRef(PtrMemberRepNames));
- StringRef PointeeName = getTypeName(Ptr->PointeeType);
- StringRef ClassName = getTypeName(PMT->ClassType);
+ StringRef PointeeName = getTypeName(Ptr.getReferentType());
+ StringRef ClassName = getTypeName(MI.getContainingType());
SmallString<256> TypeName(PointeeName);
TypeName.push_back(' ');
TypeName.append(ClassName);
TypeName.append("::*");
Name = CVTD.saveName(TypeName);
} else {
- W.printBinaryBlock("TailData", getBytesAsCharacters(LeafData));
-
SmallString<256> TypeName;
- if (Ptr->isConst())
+ if (Ptr.isConst())
TypeName.append("const ");
- if (Ptr->isVolatile())
+ if (Ptr.isVolatile())
TypeName.append("volatile ");
- if (Ptr->isUnaligned())
+ if (Ptr.isUnaligned())
TypeName.append("__unaligned ");
- TypeName.append(getTypeName(Ptr->PointeeType));
+ TypeName.append(getTypeName(Ptr.getReferentType()));
- if (Ptr->getPtrMode() == PointerMode::LValueReference)
+ if (Ptr.getMode() == PointerMode::LValueReference)
TypeName.append("&");
- else if (Ptr->getPtrMode() == PointerMode::RValueReference)
+ else if (Ptr.getMode() == PointerMode::RValueReference)
TypeName.append("&&");
- else if (Ptr->getPtrMode() == PointerMode::Pointer)
+ else if (Ptr.getMode() == PointerMode::Pointer)
TypeName.append("*");
Name = CVTD.saveName(TypeName);
}
}
-void CVTypeDumperImpl::visitTypeModifier(TypeLeafKind Leaf,
- const TypeModifier *Mod,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("ModifiedType", Mod->ModifiedType);
- W.printFlags("Modifiers", Mod->Modifiers, makeArrayRef(TypeModifierNames));
+void CVTypeDumperImpl::visitModifierRecord(TypeLeafKind Leaf,
+ ModifierRecord &Mod) {
+ uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
+ printTypeIndex("ModifiedType", Mod.getModifiedType());
+ W.printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
- StringRef ModifiedName = getTypeName(Mod->ModifiedType);
+ StringRef ModifiedName = getTypeName(Mod.getModifiedType());
SmallString<256> TypeName;
- if (Mod->Modifiers & uint16_t(ModifierOptions::Const))
+ if (Mods & uint16_t(ModifierOptions::Const))
TypeName.append("const ");
- if (Mod->Modifiers & uint16_t(ModifierOptions::Volatile))
+ if (Mods & uint16_t(ModifierOptions::Volatile))
TypeName.append("volatile ");
- if (Mod->Modifiers & uint16_t(ModifierOptions::Unaligned))
+ if (Mods & uint16_t(ModifierOptions::Unaligned))
TypeName.append("__unaligned ");
TypeName.append(ModifiedName);
Name = CVTD.saveName(TypeName);
}
-void CVTypeDumperImpl::visitVTableShape(TypeLeafKind Leaf,
- const VTableShape *Shape,
- ArrayRef<uint8_t> LeafData) {
- unsigned VFEntryCount = Shape->VFEntryCount;
- W.printNumber("VFEntryCount", VFEntryCount);
- // We could print out whether the methods are near or far, but in practice
- // today everything is CV_VTS_near32, so it's just noise.
+void CVTypeDumperImpl::visitVirtualTableShapeRecord(
+ TypeLeafKind Leaf, VirtualTableShapeRecord &Shape) {
+ W.printNumber("VFEntryCount", Shape.getEntryCount());
}
-void CVTypeDumperImpl::visitUDTSrcLine(TypeLeafKind Leaf,
- const UDTSrcLine *Line,
- ArrayRef<uint8_t> LeafData) {
- printTypeIndex("UDT", Line->UDT);
- printTypeIndex("SourceFile", Line->SourceFile);
- W.printNumber("LineNumber", Line->LineNumber);
+void CVTypeDumperImpl::visitUdtSourceLineRecord(TypeLeafKind Leaf,
+ UdtSourceLineRecord &Line) {
+ printTypeIndex("UDT", Line.getUDT());
+ printTypeIndex("SourceFile", Line.getSourceFile());
+ W.printNumber("LineNumber", Line.getLineNumber());
}
-void CVTypeDumperImpl::visitBuildInfo(TypeLeafKind Leaf, const BuildInfo *Args,
- ArrayRef<uint8_t> LeafData) {
- W.printNumber("NumArgs", Args->NumArgs);
+void CVTypeDumperImpl::visitBuildInfoRecord(TypeLeafKind Leaf,
+ BuildInfoRecord &Args) {
+ W.printNumber("NumArgs", Args.getArgs().size());
ListScope Arguments(W, "Arguments");
- for (uint32_t ArgI = 0; ArgI != Args->NumArgs; ++ArgI) {
- const TypeIndex *Type;
- if (!consumeObject(LeafData, Type))
- return;
- printTypeIndex("ArgType", *Type);
+ for (auto Arg : Args.getArgs()) {
+ printTypeIndex("ArgType", Arg);
}
}
void CVTypeDumperImpl::printMemberAttributes(MemberAttributes Attrs) {
- W.printEnum("AccessSpecifier", uint8_t(Attrs.getAccess()),
+ return printMemberAttributes(Attrs.getAccess(), Attrs.getMethodKind(),
+ Attrs.getFlags());
+}
+
+void CVTypeDumperImpl::printMemberAttributes(MemberAccess Access,
+ MethodKind Kind,
+ MethodOptions Options) {
+ W.printEnum("AccessSpecifier", uint8_t(Access),
makeArrayRef(MemberAccessNames));
- auto MK = Attrs.getMethodKind();
// Data members will be vanilla. Don't try to print a method kind for them.
- if (MK != MethodKind::Vanilla)
- W.printEnum("MethodKind", unsigned(MK), makeArrayRef(MemberKindNames));
- if (Attrs.getFlags() != MethodOptions::None) {
- W.printFlags("MethodOptions", unsigned(Attrs.getFlags()),
+ if (Kind != MethodKind::Vanilla)
+ W.printEnum("MethodKind", unsigned(Kind), makeArrayRef(MemberKindNames));
+ if (Options != MethodOptions::None) {
+ W.printFlags("MethodOptions", unsigned(Options),
makeArrayRef(MethodOptionNames));
}
}
@@ -605,117 +551,91 @@ void CVTypeDumperImpl::visitUnknownMembe
W.printHex("UnknownMember", unsigned(Leaf));
}
-void CVTypeDumperImpl::visitNestedType(TypeLeafKind Leaf,
- const NestedType *Nested,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitNestedTypeRecord(TypeLeafKind Leaf,
+ NestedTypeRecord &Nested) {
DictScope S(W, "NestedType");
- printTypeIndex("Type", Nested->Type);
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
+ printTypeIndex("Type", Nested.getNestedType());
+ W.printString("Name", Nested.getName());
+ Name = Nested.getName();
}
-void CVTypeDumperImpl::visitOneMethod(TypeLeafKind Leaf,
- const OneMethod *Method,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitOneMethodRecord(TypeLeafKind Leaf,
+ OneMethodRecord &Method) {
DictScope S(W, "OneMethod");
- printMemberAttributes(Method->Attrs);
- printTypeIndex("Type", Method->Type);
+ MethodKind K = Method.getKind();
+ printMemberAttributes(Method.getAccess(), K, Method.getOptions());
+ printTypeIndex("Type", Method.getType());
// If virtual, then read the vftable offset.
- if (Method->isIntroducedVirtual()) {
- const little32_t *VFTOffsetPtr;
- if (!consumeObject(FieldData, VFTOffsetPtr))
- return;
- W.printHex("VFTableOffset", *VFTOffsetPtr);
- }
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
+ if (Method.isIntroducingVirtual())
+ W.printHex("VFTableOffset", Method.getVFTableOffset());
+ W.printString("Name", Method.getName());
+ Name = Method.getName();
}
-void CVTypeDumperImpl::visitOverloadedMethod(TypeLeafKind Leaf,
- const OverloadedMethod *Method,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitOverloadedMethodRecord(
+ TypeLeafKind Leaf, OverloadedMethodRecord &Method) {
DictScope S(W, "OverloadedMethod");
- W.printHex("MethodCount", Method->MethodCount);
- W.printHex("MethodListIndex", Method->MethList.getIndex());
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
+ W.printHex("MethodCount", Method.getNumOverloads());
+ printTypeIndex("MethodListIndex", Method.getMethodList());
+ W.printString("Name", Method.getName());
+ Name = Method.getName();
}
-void CVTypeDumperImpl::visitDataMember(TypeLeafKind Leaf,
- const DataMember *Field,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitDataMemberRecord(TypeLeafKind Leaf,
+ DataMemberRecord &Field) {
DictScope S(W, "DataMember");
- printMemberAttributes(Field->Attrs);
- printTypeIndex("Type", Field->Type);
- uint64_t FieldOffset;
- if (!decodeUIntLeaf(FieldData, FieldOffset))
- return parseError();
- W.printHex("FieldOffset", FieldOffset);
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
+ printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ printTypeIndex("Type", Field.getType());
+ W.printHex("FieldOffset", Field.getFieldOffset());
+ W.printString("Name", Field.getName());
+ Name = Field.getName();
}
-void CVTypeDumperImpl::visitStaticDataMember(TypeLeafKind Leaf,
- const StaticDataMember *Field,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitStaticDataMemberRecord(
+ TypeLeafKind Leaf, StaticDataMemberRecord &Field) {
DictScope S(W, "StaticDataMember");
- printMemberAttributes(Field->Attrs);
- printTypeIndex("Type", Field->Type);
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
+ printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ printTypeIndex("Type", Field.getType());
+ W.printString("Name", Field.getName());
+ Name = Field.getName();
}
-void CVTypeDumperImpl::visitVirtualFunctionPointer(
- TypeLeafKind Leaf, const VirtualFunctionPointer *VFTable,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitVirtualFunctionPointerRecord(
+ TypeLeafKind Leaf, VirtualFunctionPointerRecord &VFTable) {
DictScope S(W, "VirtualFunctionPointer");
- printTypeIndex("Type", VFTable->Type);
+ printTypeIndex("Type", VFTable.getType());
}
-void CVTypeDumperImpl::visitEnumerator(TypeLeafKind Leaf,
- const Enumerator *Enum,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitEnumeratorRecord(TypeLeafKind Leaf,
+ EnumeratorRecord &Enum) {
DictScope S(W, "Enumerator");
- printMemberAttributes(Enum->Attrs);
- APSInt EnumValue;
- if (!decodeNumericLeaf(FieldData, EnumValue))
- return parseError();
- W.printNumber("EnumValue", EnumValue);
- StringRef Name = getBytesAsCString(FieldData);
- FieldData = FieldData.drop_front(Name.size() + 1);
- W.printString("Name", Name);
+ printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ W.printNumber("EnumValue", Enum.getValue());
+ W.printString("Name", Enum.getName());
+ Name = Enum.getName();
}
-void CVTypeDumperImpl::visitBaseClass(TypeLeafKind Leaf, const BaseClass *Base,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitBaseClassRecord(TypeLeafKind Leaf,
+ BaseClassRecord &Base) {
DictScope S(W, "BaseClass");
- printMemberAttributes(Base->Attrs);
- printTypeIndex("BaseType", Base->BaseType);
- uint64_t BaseOffset;
- if (!decodeUIntLeaf(FieldData, BaseOffset))
- return parseError();
- W.printHex("BaseOffset", BaseOffset);
+ printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ printTypeIndex("BaseType", Base.getBaseType());
+ W.printHex("BaseOffset", Base.getBaseOffset());
}
-void CVTypeDumperImpl::visitVirtualBaseClass(TypeLeafKind Leaf,
- const VirtualBaseClass *Base,
- ArrayRef<uint8_t> &FieldData) {
+void CVTypeDumperImpl::visitVirtualBaseClassRecord(
+ TypeLeafKind Leaf, VirtualBaseClassRecord &Base) {
DictScope S(W, "VirtualBaseClass");
- printMemberAttributes(Base->Attrs);
- printTypeIndex("BaseType", Base->BaseType);
- printTypeIndex("VBPtrType", Base->VBPtrType);
- uint64_t VBPtrOffset, VBTableIndex;
- if (!decodeUIntLeaf(FieldData, VBPtrOffset))
- return parseError();
- if (!decodeUIntLeaf(FieldData, VBTableIndex))
- return parseError();
- W.printHex("VBPtrOffset", VBPtrOffset);
- W.printHex("VBTableIndex", VBTableIndex);
+ printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
+ MethodOptions::None);
+ printTypeIndex("BaseType", Base.getBaseType());
+ printTypeIndex("VBPtrType", Base.getVBPtrType());
+ W.printHex("VBPtrOffset", Base.getVBPtrOffset());
+ W.printHex("VBTableIndex", Base.getVTableIndex());
}
StringRef CVTypeDumper::getTypeName(TypeIndex TI) {
Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeStream.cpp Wed May 11 12:47:35 2016
@@ -13,7 +13,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
-#include "llvm/DebugInfo/CodeView/TypeStream.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
using namespace llvm;
using namespace llvm::codeview;
Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp?rev=269216&r1=269215&r2=269216&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp Wed May 11 12:47:35 2016
@@ -17,27 +17,6 @@
using namespace llvm;
using namespace codeview;
-namespace {
-
-const int PointerKindShift = 0;
-const int PointerModeShift = 5;
-const int PointerSizeShift = 13;
-
-const int ClassHfaKindShift = 11;
-const int ClassWindowsRTClassKindShift = 14;
-
-void writePointerBase(TypeRecordBuilder &Builder,
- const PointerRecordBase &Record) {
- Builder.writeTypeIndex(Record.getReferentType());
- uint32_t flags =
- static_cast<uint32_t>(Record.getOptions()) |
- (Record.getSize() << PointerSizeShift) |
- (static_cast<uint32_t>(Record.getMode()) << PointerModeShift) |
- (static_cast<uint32_t>(Record.getPointerKind()) << PointerKindShift);
- Builder.writeUInt32(flags);
-}
-}
-
TypeTableBuilder::TypeTableBuilder() {}
TypeTableBuilder::~TypeTableBuilder() {}
@@ -46,7 +25,7 @@ TypeIndex TypeTableBuilder::writeModifie
TypeRecordBuilder Builder(TypeRecordKind::Modifier);
Builder.writeTypeIndex(Record.getModifiedType());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
+ Builder.writeUInt16(static_cast<uint16_t>(Record.getModifiers()));
return writeRecord(Builder);
}
@@ -79,12 +58,11 @@ TypeTableBuilder::writeMemberFunction(co
return writeRecord(Builder);
}
-TypeIndex
-TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
+TypeIndex TypeTableBuilder::writeArgumentList(const StringListRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::ArgumentList);
- Builder.writeUInt32(Record.getArgumentTypes().size());
- for (TypeIndex TI : Record.getArgumentTypes()) {
+ Builder.writeUInt32(Record.getIndices().size());
+ for (TypeIndex TI : Record.getIndices()) {
Builder.writeTypeIndex(TI);
}
@@ -94,19 +72,20 @@ TypeTableBuilder::writeArgumentList(cons
TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
TypeRecordBuilder Builder(TypeRecordKind::Pointer);
- writePointerBase(Builder, Record);
-
- return writeRecord(Builder);
-}
-
-TypeIndex
-TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) {
- TypeRecordBuilder Builder(TypeRecordKind::Pointer);
-
- writePointerBase(Builder, Record);
+ Builder.writeTypeIndex(Record.getReferentType());
+ uint32_t flags = static_cast<uint32_t>(Record.getOptions()) |
+ (Record.getSize() << PointerRecord::PointerSizeShift) |
+ (static_cast<uint32_t>(Record.getMode())
+ << PointerRecord::PointerModeShift) |
+ (static_cast<uint32_t>(Record.getPointerKind())
+ << PointerRecord::PointerKindShift);
+ Builder.writeUInt32(flags);
- Builder.writeTypeIndex(Record.getContainingType());
- Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation()));
+ if (Record.isPointerToMember()) {
+ const MemberPointerInfo &M = Record.getMemberInfo();
+ Builder.writeTypeIndex(M.getContainingType());
+ Builder.writeUInt16(static_cast<uint16_t>(M.getRepresentation()));
+ }
return writeRecord(Builder);
}
@@ -122,7 +101,7 @@ TypeIndex TypeTableBuilder::writeArray(c
return writeRecord(Builder);
}
-TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
+TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) {
assert((Record.getKind() == TypeRecordKind::Structure) ||
(Record.getKind() == TypeRecordKind::Class) ||
(Record.getKind() == TypeRecordKind::Union));
@@ -132,18 +111,13 @@ TypeIndex TypeTableBuilder::writeAggrega
Builder.writeUInt16(Record.getMemberCount());
uint16_t Flags =
static_cast<uint16_t>(Record.getOptions()) |
- (static_cast<uint16_t>(Record.getHfa()) << ClassHfaKindShift) |
+ (static_cast<uint16_t>(Record.getHfa()) << ClassRecord::HfaKindShift) |
(static_cast<uint16_t>(Record.getWinRTKind())
- << ClassWindowsRTClassKindShift);
+ << ClassRecord::WinRTKindShift);
Builder.writeUInt16(Flags);
Builder.writeTypeIndex(Record.getFieldList());
- if (Record.getKind() != TypeRecordKind::Union) {
- Builder.writeTypeIndex(Record.getDerivationList());
- Builder.writeTypeIndex(Record.getVTableShape());
- } else {
- assert(Record.getDerivationList() == TypeIndex());
- assert(Record.getVTableShape() == TypeIndex());
- }
+ Builder.writeTypeIndex(Record.getDerivationList());
+ Builder.writeTypeIndex(Record.getVTableShape());
Builder.writeEncodedUnsignedInteger(Record.getSize());
Builder.writeNullTerminatedString(Record.getName());
if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
More information about the llvm-commits
mailing list