diff options
| author | Zachary Turner <zturner@google.com> | 2016-05-11 17:47:35 +0000 | 
|---|---|---|
| committer | Zachary Turner <zturner@google.com> | 2016-05-11 17:47:35 +0000 | 
| commit | ae3882a19a9b8341c707fd3c56f245d77068d269 (patch) | |
| tree | fd82f31802b9888c3762075d7246b2f1e07f6b64 /llvm | |
| parent | c200ad7e3b809d55254a1c2ed4ab833d59a562ef (diff) | |
| download | bcm5719-llvm-ae3882a19a9b8341c707fd3c56f245d77068d269.tar.gz bcm5719-llvm-ae3882a19a9b8341c707fd3c56f245d77068d269.zip  | |
Refactor CodeView type records to use common code.
Differential Revision: http://reviews.llvm.org/D20138
Reviewed By: rnk
llvm-svn: 269216
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h | 25 | ||||
| -rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/CodeView.h | 3 | ||||
| -rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h | 1409 | ||||
| -rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def | 62 | ||||
| -rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/TypeStream.h | 38 | ||||
| -rw-r--r-- | llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h | 5 | ||||
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp | 4 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeDumper.cpp | 566 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeStream.cpp | 2 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp | 70 | 
11 files changed, 1458 insertions, 728 deletions
diff --git a/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index fc8efb8fe39..d25995566c2 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -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" diff --git a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h index 620bfbc288b..f198396ab62 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CodeView.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CodeView.h @@ -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, diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h index c0b9d9293b3..fa675c7af12 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h @@ -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: +  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); +  } + +  TypeIndex getClassType() const { return ClassType; } +  TypeIndex getFunctionType() const { return FunctionType; } +  StringRef getName() const { return Name; } + +private: +  struct Layout { +    TypeIndex ClassType; +    TypeIndex FunctionType; +    // Name: The null-terminated name follows. +  }; +  TypeIndex ClassType; +  TypeIndex FunctionType; +  StringRef Name; +}; + +// LF_ARGLIST, LF_SUBSTR_LIST +class StringListRecord : public TypeRecord {  public: -  explicit ArgumentListRecord(llvm::ArrayRef<TypeIndex> ArgumentTypes) -      : TypeRecord(TypeRecordKind::ArgumentList), ArgumentTypes(ArgumentTypes) { +  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);    } -  llvm::ArrayRef<TypeIndex> getArgumentTypes() const { return ArgumentTypes; } +  ArrayRef<TypeIndex> getIndices() const { return StringIndices; } + +  static uint32_t getLayoutSize() { return 2 + sizeof(Layout); }  private: -  llvm::ArrayRef<TypeIndex> ArgumentTypes; +  struct Layout { +    ulittle32_t NumArgs; // Number of arguments +                         // ArgTypes[]: Type indicies of arguments +  }; + +  ArrayRef<TypeIndex> StringIndices;  }; -class PointerRecordBase : public TypeRecord { +// LF_POINTER +class PointerRecord : public TypeRecord {  public: -  PointerRecordBase(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode, -                    PointerOptions Options, uint8_t Size) +  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) {} - -  TypeIndex getContainingType() const { return ContainingType; } -  PointerToMemberRepresentation getRepresentation() const { -    return Representation; +  NestedTypeRecord(TypeIndex Type, StringRef Name) +      : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {} + +  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); +    } + +    return VirtualTableShapeRecord(Slots); +  } -private: -  ArrayRef<VirtualTableSlotKind> Slots; -}; +  ArrayRef<VirtualTableSlotKind> getSlots() const { +    if (!SlotsRef.empty()) +      return SlotsRef; +    return Slots; +  } +  uint32_t getEntryCount() const { return getSlots().size(); } -//===----------------------------------------------------------------------===// -// On-disk representation of type information +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. +  }; -// 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: +  ArrayRef<VirtualTableSlotKind> SlotsRef; +  std::vector<VirtualTableSlotKind> Slots; +};  // LF_TYPESERVER2 -struct TypeServer2 { -  char Signature[16];  // GUID -  ulittle32_t Age; -  // Name: Name of the PDB as a null-terminated string -}; +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_STRING_ID -struct StringId { -  TypeIndex id; -}; +  StringRef getGuid() const { return Guid; } -// LF_FUNC_ID -struct FuncId { -  TypeIndex ParentScope; -  TypeIndex FunctionType; -  // Name: The null-terminated name follows. -}; +  uint32_t getAge() const { return Age; } -// 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. -}; +  StringRef getName() const { return Name; } -// 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. +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 +// LF_STRING_ID +class StringIdRecord : public TypeRecord { +public: +  StringIdRecord(TypeIndex Id, StringRef String) +      : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {} + +  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); +  } -  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); } +  TypeIndex getId() const { return Id; } -  bool isPointerToDataMember() const { -    return getPtrMode() == PointerMode::PointerToDataMember; -  } -  bool isPointerToMemberFunction() const { -    return getPtrMode() == PointerMode::PointerToMemberFunction; -  } -  bool isPointerToMember() const { -    return isPointerToMemberFunction() || isPointerToDataMember(); -  } -}; +  StringRef getString() const { return String; } -struct PointerToMemberTail { -  TypeIndex ClassType; -  ulittle16_t Representation; // PointerToMemberRepresentation -}; +private: +  struct Layout { +    TypeIndex id; +    // Name: Name of the PDB as a null-terminated string +  }; -/// In Clang parlance, these are "qualifiers".  LF_MODIFIER -struct TypeModifier { -  TypeIndex ModifiedType; -  ulittle16_t Modifiers; // ModifierOptions +  TypeIndex Id; +  StringRef 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. -}; +// LF_FUNC_ID +class FuncIdRecord : public TypeRecord { +public: +  FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name) +      : TypeRecord(TypeRecordKind::FunctionId), ParentScope(ParentScope), +        FunctionType(FunctionType), Name(Name) {} -// LF_UDT_SRC_LINE -struct UDTSrcLine { -  TypeIndex UDT;        // The user-defined type -  TypeIndex SourceFile; // StringID containing the source filename -  ulittle32_t LineNumber; -}; +  static ErrorOr<FuncIdRecord> deserialize(TypeRecordKind Kind, +                                           ArrayRef<uint8_t> &Data) { +    const Layout *L = nullptr; +    if (auto EC = consumeObject(Data, L)) +      return EC; -// LF_ARGLIST, LF_SUBSTR_LIST -struct ArgList { -  ulittle32_t NumArgs; // Number of arguments -  // ArgTypes[]: Type indicies of arguments -}; +    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) {} -// LF_MFUNCTION -struct MemberFunctionType { -  TypeIndex ReturnType; -  TypeIndex ClassType; -  TypeIndex ThisType; -  CallingConvention CallConv; -  FunctionOptions Options; -  ulittle16_t NumParameters; -  TypeIndex ArgListType; -  little32_t ThisAdjustment; -}; +  static ErrorOr<UdtSourceLineRecord> deserialize(TypeRecordKind Kind, +                                                  ArrayRef<uint8_t> &Data) { +    const Layout *L = nullptr; +    if (auto EC = consumeObject(Data, L)) +      return EC; -//===----------------------------------------------------------------------===// -// Field list records, which do not include leafs or sizes +    return UdtSourceLineRecord(L->UDT, L->SourceFile, L->LineNumber); +  } -/// Equvalent to CV_fldattr_t in cvinfo.h. -struct MemberAttributes { -  ulittle16_t Attrs; +  TypeIndex getUDT() const { return UDT; } +  TypeIndex getSourceFile() const { return SourceFile; } +  uint32_t getLineNumber() const { return LineNumber; } -  /// Get the access specifier. Valid for any kind of member. -  MemberAccess getAccess() const { -    return MemberAccess(unsigned(Attrs) & unsigned(MethodOptions::AccessMask)); -  } +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; +}; -  /// Indicates if a method is defined with friend, virtual, static, etc. -  MethodKind getMethodKind() const { -    return MethodKind( -        (unsigned(Attrs) & unsigned(MethodOptions::MethodKindMask)) >> 2); +// LF_BUILDINFO +class BuildInfoRecord : public TypeRecord { +public: +  BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices) +      : TypeRecord(TypeRecordKind::Modifier), ArgIndices(ArgIndices) {} + +  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; + +    return OneMethodRecord(L->Type, MethKind, Options, Access, VFTableOffset, +                           Name); +  } -  MethodKind getMethodKind() const { -    return Attrs.getMethodKind(); +  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; } + +  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);    } -  bool isVirtual() const { return Attrs.isVirtual(); } -  bool isIntroducedVirtual() const { return Attrs.isIntroducedVirtual(); } +private: +  struct Layout { +    MemberAttributes Attrs; +    TypeIndex Type; +    // If is introduced virtual method: +    //   VFTableOffset: int32_t offset in vftable +    // Name: Null-terminated string +  }; + +  TypeIndex Type; +  MethodKind Kind; +  MethodOptions Options; +  MemberAccess Access; +  int32_t VFTableOffset; +  StringRef Name;  };  // LF_METHODLIST -struct MethodListEntry { -  MemberAttributes Attrs; -  ulittle16_t Padding; +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); +  } -  TypeIndex Type; -  // If is introduced virtual method: -  //   VFTableOffset: int32_t offset in vftable +  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; } -  MethodKind getMethodKind() const { -    return Attrs.getMethodKind(); -  } +private: +  struct Layout { +    MemberAttributes Attrs; +    ulittle16_t Padding; -  bool isVirtual() const { return Attrs.isVirtual(); } -  bool isIntroducedVirtual() const { return Attrs.isIntroducedVirtual(); } +    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; + +    return OverloadedMethodRecord(L->MethodCount, L->MethList, Name); +  } -// LF_VFUNCTAB -struct VirtualFunctionPointer { -  ulittle16_t Pad0; -  TypeIndex Type;   // Type of vfptr +  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;  };  }  } diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def b/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def index 48d1ac3cdec..f1b3dd2fddd 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def @@ -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(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(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(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 diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeStream.h b/llvm/include/llvm/DebugInfo/CodeView/TypeStream.h index d770a132fd2..1998d10090d 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeStream.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeStream.h @@ -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) { diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h index 82c7e5983f4..6f9817e903d 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h @@ -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); diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index 4c4809f50e3..3590d937643 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -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"); diff --git a/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp b/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp index 91b71cc4b11..9b016bdf1ce 100644 --- a/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp @@ -56,7 +56,7 @@ void FieldListRecordBuilder::writeMethod(uint16_t OverloadCount,                                           TypeIndex MethodList, StringRef Name) {    TypeRecordBuilder &Builder = getBuilder(); -  Builder.writeTypeRecordKind(TypeRecordKind::Method); +  Builder.writeTypeRecordKind(TypeRecordKind::OverloadedMethod);    Builder.writeUInt16(OverloadCount);    Builder.writeTypeIndex(MethodList);    Builder.writeNullTerminatedString(Name); diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp index 9c21d3fef1e..df9f8f244ba 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp @@ -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(TypeLeafKind Leaf,    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); -  } -} - -void CVTypeDumperImpl::visitUnionType(TypeLeafKind Leaf, const UnionType *Union, -                                      ArrayRef<uint8_t> LeafData) { -  W.printNumber("MemberCount", Union->MemberCount); -  uint16_t Props = Union->Properties; +  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::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); +  W.printNumber("NumParameters", MF.getParameterCount()); +  printTypeIndex("ArgListType", MF.getArgumentList()); +  W.printNumber("ThisAdjustment", MF.getThisPointerAdjustment()); -  StringRef ReturnTypeName = getTypeName(MemberFunc->ReturnType); -  StringRef ClassTypeName = getTypeName(MemberFunc->ClassType); -  StringRef ArgListTypeName = getTypeName(MemberFunc->ArgListType); +  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::visitMemberFunctionType(  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::visitFuncIdRecord(TypeLeafKind Leaf, +                                         FuncIdRecord &Func) { +  printTypeIndex("ParentScope", Func.getParentScope()); +  printTypeIndex("FunctionType", Func.getFunctionType()); +  W.printString("Name", Func.getName()); +  Name = Func.getName();  } -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::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::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::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::visitUnknownMember(TypeLeafKind Leaf) {    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); -} - -void CVTypeDumperImpl::visitStaticDataMember(TypeLeafKind Leaf, -                                             const StaticDataMember *Field, -                                             ArrayRef<uint8_t> &FieldData) { +  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::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); -} - -void CVTypeDumperImpl::visitBaseClass(TypeLeafKind Leaf, const BaseClass *Base, -                                      ArrayRef<uint8_t> &FieldData) { +  printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla, +                        MethodOptions::None); +  W.printNumber("EnumValue", Enum.getValue()); +  W.printString("Name", Enum.getName()); +  Name = Enum.getName(); +} + +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) { diff --git a/llvm/lib/DebugInfo/CodeView/TypeStream.cpp b/llvm/lib/DebugInfo/CodeView/TypeStream.cpp index 73dfc50c8ab..82d3f4d7e86 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStream.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStream.cpp @@ -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; diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp index 5327c351392..faf177b658f 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp @@ -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::writeModifier(const ModifierRecord &Record) {    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(const MemberFunctionRecord &Record) {    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(const ArgumentListRecord &Record) {  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(const ArrayRecord &Record) {    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::writeAggregate(const AggregateRecord &Record) {    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) !=  | 

