[CodeView] Decouple record deserialization from visitor dispatch.
authorZachary Turner <zturner@google.com>
Fri, 5 Aug 2016 21:45:34 +0000 (21:45 +0000)
committerZachary Turner <zturner@google.com>
Fri, 5 Aug 2016 21:45:34 +0000 (21:45 +0000)
Until now, our use case for the visitor has been to take a stream of bytes
representing a type stream, deserialize the records in sequence, and do
something with them, where "something" is determined by how the user
implements a particular set of callbacks on an abstract class.

For actually writing PDBs, however, we want to do the reverse. We have
some kind of description of the list of records in their in-memory format,
and we want to process each one. Perhaps by serializing them to a byte
stream, or perhaps by converting them from one description format (Yaml)
to another (in-memory representation).

This was difficult in the current model because deserialization and
invoking the callbacks were tightly coupled.

With this patch we change this so that TypeDeserializer is itself an
implementation of the particular set of callbacks. This decouples
deserialization from the iteration over a list of records and invocation
of the callbacks.  TypeDeserializer is initialized with another
implementation of the callback interface, so that upon deserialization it
can pass the deserialized record through to the next set of callbacks. In
a sense this is like an implementation of the Decorator design pattern,
where the Deserializer is a decorator.

This will be useful for writing Pdbs from yaml, where we have a
description of the type records in Yaml format. In this case, the visitor
implementation would have each visitation callback method implemented in
such a way as to extract the proper set of fields from the Yaml, and it
could maintain state that builds up a list of these records. Finally at
the end we can pass this information through to another set of callbacks
which serializes them into a byte stream.

Reviewed By: majnemer, ruiu, rnk
Differential Revision: https://reviews.llvm.org/D23177

llvm-svn: 277871

28 files changed:
llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
llvm/include/llvm/DebugInfo/CodeView/CodeView.h
llvm/include/llvm/DebugInfo/CodeView/CodeViewError.h
llvm/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
llvm/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
llvm/include/llvm/DebugInfo/CodeView/RecordSerialization.h
llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h [new file with mode: 0644]
llvm/include/llvm/DebugInfo/CodeView/TypeDumper.h
llvm/include/llvm/DebugInfo/CodeView/TypeRecord.h
llvm/include/llvm/DebugInfo/CodeView/TypeRecords.def
llvm/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
llvm/lib/DebugInfo/CodeView/CMakeLists.txt
llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
llvm/lib/DebugInfo/CodeView/CodeViewError.cpp
llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp [new file with mode: 0644]
llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
llvm/lib/DebugInfo/CodeView/TypeRecord.cpp
llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
llvm/lib/DebugInfo/PDB/Raw/TpiStream.cpp
llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
llvm/tools/llvm-readobj/llvm-readobj.cpp
llvm/tools/llvm-readobj/llvm-readobj.h

index 930ac69..562a893 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
 #define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H
 
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@@ -27,12 +28,6 @@ public:
   /// Visits the type records in Data. Sets the error flag on parse failures.
   Error visitTypeStream(const CVTypeArray &Types);
 
-  Error skipPadding(ArrayRef<uint8_t> &Data);
-
-  /// Visits individual member records of a field list record. Member records do
-  /// not describe their own length, and need special handling.
-  Error visitFieldList(const CVRecord<TypeLeafKind> &Record);
-
 private:
   /// The interface to the class that gets notified of each visitation.
   TypeVisitorCallbacks &Callbacks;
index 1ee203b..9db217e 100644 (file)
@@ -21,8 +21,6 @@ namespace codeview {
 enum class TypeRecordKind : uint16_t {
 #define TYPE_RECORD(lf_ename, value, name) name = value,
 #include "TypeRecords.def"
-  // FIXME: Add serialization support
-  FieldList = 0x1203,
 };
 
 /// Duplicate copy of the above enum, but using the official CV names. Useful
index 69ff29a..0556fd0 100644 (file)
@@ -21,6 +21,7 @@ enum class cv_error_code {
   insufficient_buffer,
   operation_unsupported,
   corrupt_record,
+  unknown_member_record,
 };
 
 /// Base class for errors originating when parsing raw PDB files
index 75a0751..f320153 100644 (file)
@@ -49,15 +49,17 @@ public:
 
   void reset() { ListRecordBuilder::reset(); }
 
-  void writeBaseClass(const BaseClassRecord &Record);
-  void writeEnumerator(const EnumeratorRecord &Record);
-  void writeDataMember(const DataMemberRecord &Record);
-  void writeOneMethod(const OneMethodRecord &Record);
-  void writeOverloadedMethod(const OverloadedMethodRecord &Record);
-  void writeNestedType(const NestedTypeRecord &Record);
-  void writeStaticDataMember(const StaticDataMemberRecord &Record);
-  void writeVirtualBaseClass(const VirtualBaseClassRecord &Record);
-  void writeVFPtr(const VFPtrRecord &Type);
+  void writeMemberType(const BaseClassRecord &Record);
+  void writeMemberType(const EnumeratorRecord &Record);
+  void writeMemberType(const DataMemberRecord &Record);
+  void writeMemberType(const OneMethodRecord &Record);
+  void writeMemberType(const OverloadedMethodRecord &Record);
+  void writeMemberType(const NestedTypeRecord &Record);
+  void writeMemberType(const StaticDataMemberRecord &Record);
+  void writeMemberType(const VirtualBaseClassRecord &Record);
+  void writeMemberType(const VFPtrRecord &Type);
+
+  using ListRecordBuilder::writeMemberType;
 };
 }
 }
index 00bf03d..d75158f 100644 (file)
@@ -35,7 +35,7 @@ public:
     SubrecordStart = 0;
   }
 
-  void writeListContinuation(const ListContinuationRecord &R);
+  void writeMemberType(const ListContinuationRecord &R);
 
   /// Writes this list record as a possible sequence of records.
   TypeIndex writeListRecord(TypeTableBuilder &Table);
index 606536b..6e3db34 100644 (file)
@@ -44,7 +44,7 @@ inline Error consumeObject(U &Data, const T *&Res) {
   if (Data.size() < sizeof(*Res))
     return make_error<CodeViewError>(
         cv_error_code::insufficient_buffer,
-        "Error consuming object.  Not enough data for requested object size.");
+        "Insufficient bytes for expected object type");
   Res = reinterpret_cast<const T *>(Data.data());
   Data = Data.drop_front(sizeof(*Res));
   return Error::success();
@@ -146,9 +146,8 @@ struct serialize_null_term_string_array_impl {
 
   Error deserialize(ArrayRef<uint8_t> &Data) const {
     if (Data.empty())
-      return make_error<CodeViewError>(
-          cv_error_code::insufficient_buffer,
-          "Null terminated string buffer is empty!");
+      return make_error<CodeViewError>(cv_error_code::insufficient_buffer,
+                                       "Null terminated string is empty!");
 
     StringRef Field;
     // Stop when we run out of bytes or we hit record padding bytes.
@@ -159,7 +158,7 @@ struct serialize_null_term_string_array_impl {
       if (Data.empty())
         return make_error<CodeViewError>(
             cv_error_code::insufficient_buffer,
-            "Null terminated string buffer is empty!");
+            "Null terminated string has no null terminator!");
     }
     Data = Data.drop_front(1);
     return Error::success();
diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/llvm/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
new file mode 100644 (file)
index 0000000..6ee82a5
--- /dev/null
@@ -0,0 +1,101 @@
+//===- TypeDeserializer.h ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEDESERIALIZER_H
+
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class TypeDeserializerBase : public TypeVisitorCallbacks {
+public:
+  explicit TypeDeserializerBase(TypeVisitorCallbacks &Recipient)
+      : Recipient(Recipient) {}
+
+  Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override {
+    return Recipient.visitTypeBegin(Record);
+  }
+
+  Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override {
+    return Recipient.visitTypeEnd(Record);
+  }
+
+#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,                    \
+                         Name##Record &Record) override {                      \
+    return defaultVisitKnownRecord(CVR, Record);                               \
+  }
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "TypeRecords.def"
+
+protected:
+  TypeVisitorCallbacks &Recipient;
+
+  template <typename T>
+  Error deserializeRecord(ArrayRef<uint8_t> &Data, TypeLeafKind Kind,
+                          T &Record) const {
+    TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
+    auto ExpectedRecord = T::deserialize(RK, Data);
+    if (!ExpectedRecord)
+      return ExpectedRecord.takeError();
+    Record = std::move(*ExpectedRecord);
+    return Error::success();
+  }
+
+private:
+  template <typename T>
+  Error defaultVisitKnownRecord(const CVRecord<TypeLeafKind> &CVR, T &Record) {
+    ArrayRef<uint8_t> RD = CVR.Data;
+    if (auto EC = deserializeRecord(RD, CVR.Type, Record))
+      return EC;
+    return Recipient.visitKnownRecord(CVR, Record);
+  }
+};
+
+class TypeDeserializer : public TypeDeserializerBase {
+public:
+  explicit TypeDeserializer(TypeVisitorCallbacks &Recipient)
+      : TypeDeserializerBase(Recipient) {}
+
+  /// FieldList records need special handling.  For starters, they do not
+  /// describe their own length, so a different extraction algorithm is
+  /// necessary.  Secondly, a single FieldList record will result in the
+  /// deserialization of many records.  So even though the top level visitor
+  /// calls visitFieldBegin() on a single record, multiple records get visited
+  /// through the callback interface.
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                         FieldListRecord &Record) override;
+
+private:
+  template <typename T>
+  Error visitKnownMember(ArrayRef<uint8_t> &Data, TypeLeafKind Kind,
+                         T &Record) {
+    ArrayRef<uint8_t> OldData = Data;
+    if (auto EC = deserializeRecord(Data, Kind, Record))
+      return EC;
+    assert(Data.size() < OldData.size());
+
+    CVRecord<TypeLeafKind> CVR;
+    CVR.Length = OldData.size() - Data.size();
+    CVR.Data = OldData.slice(0, CVR.Length);
+    CVR.RawData = CVR.Data;
+    return Recipient.visitKnownRecord(CVR, Record);
+  }
+
+  Error skipPadding(ArrayRef<uint8_t> &Data);
+};
+}
+}
+
+#endif
index ca79ab0..00beeb0 100644 (file)
@@ -72,7 +72,8 @@ public:
   Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
 
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error visit##Name(Name##Record &Record) override;
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,                    \
+                         Name##Record &Record) override;
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
   TYPE_RECORD(EnumName, EnumVal, Name)
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
index 8bc61f9..97ca1fa 100644 (file)
@@ -114,6 +114,7 @@ private:
 // LF_MODIFIER
 class ModifierRecord : public TypeRecord {
 public:
+  explicit ModifierRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   ModifierRecord(TypeIndex ModifiedType, ModifierOptions Modifiers)
       : TypeRecord(TypeRecordKind::Modifier), ModifiedType(ModifiedType),
         Modifiers(Modifiers) {}
@@ -141,6 +142,7 @@ private:
 // LF_PROCEDURE
 class ProcedureRecord : public TypeRecord {
 public:
+  explicit ProcedureRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   ProcedureRecord(TypeIndex ReturnType, CallingConvention CallConv,
                   FunctionOptions Options, uint16_t ParameterCount,
                   TypeIndex ArgumentList)
@@ -182,6 +184,8 @@ private:
 // LF_MFUNCTION
 class MemberFunctionRecord : public TypeRecord {
 public:
+  explicit MemberFunctionRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
   MemberFunctionRecord(TypeIndex ReturnType, TypeIndex ClassType,
                        TypeIndex ThisType, CallingConvention CallConv,
                        FunctionOptions Options, uint16_t ParameterCount,
@@ -233,6 +237,7 @@ private:
 // LF_MFUNC_ID
 class MemberFuncIdRecord : public TypeRecord {
 public:
+  explicit MemberFuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   MemberFuncIdRecord(TypeIndex ClassType, TypeIndex FunctionType,
                          StringRef Name)
       : TypeRecord(TypeRecordKind::MemberFuncId), ClassType(ClassType),
@@ -262,6 +267,8 @@ private:
 // LF_ARGLIST, LF_SUBSTR_LIST
 class ArgListRecord : public TypeRecord {
 public:
+  explicit ArgListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
   ArgListRecord(TypeRecordKind Kind, ArrayRef<TypeIndex> Indices)
       : TypeRecord(Kind), StringIndices(Indices) {}
 
@@ -297,6 +304,8 @@ public:
   static const uint32_t PointerSizeShift = 13;
   static const uint32_t PointerSizeMask = 0xFF;
 
+  explicit PointerRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+
   PointerRecord(TypeIndex ReferentType, PointerKind Kind, PointerMode Mode,
                 PointerOptions Options, uint8_t Size)
       : PointerRecord(ReferentType, Kind, Mode, Options, Size,
@@ -382,6 +391,7 @@ private:
 // LF_NESTTYPE
 class NestedTypeRecord : public TypeRecord {
 public:
+  explicit NestedTypeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   NestedTypeRecord(TypeIndex Type, StringRef Name)
       : TypeRecord(TypeRecordKind::NestedType), Type(Type), Name(Name) {}
 
@@ -406,9 +416,30 @@ private:
   StringRef Name;
 };
 
+// LF_FIELDLIST
+class FieldListRecord : public TypeRecord {
+public:
+  explicit FieldListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
+  FieldListRecord(ArrayRef<uint8_t> ListData)
+      : TypeRecord(TypeRecordKind::FieldList), ListData(ListData) {}
+
+  /// Rewrite member type indices with IndexMap. Returns false if a type index
+  /// is not in the map.
+  bool remapTypeIndices(ArrayRef<TypeIndex> IndexMap) { return false; }
+
+  static Expected<FieldListRecord> deserialize(TypeRecordKind Kind,
+                                               ArrayRef<uint8_t> &Data);
+
+  ArrayRef<uint8_t> getFieldListData() const { return ListData; }
+
+private:
+  ArrayRef<uint8_t> ListData;
+};
+
 // LF_ARRAY
 class ArrayRecord : public TypeRecord {
 public:
+  explicit ArrayRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   ArrayRecord(TypeIndex ElementType, TypeIndex IndexType, uint64_t Size,
               StringRef Name)
       : TypeRecord(TypeRecordKind::Array), ElementType(ElementType),
@@ -442,6 +473,7 @@ private:
 
 class TagRecord : public TypeRecord {
 protected:
+  explicit TagRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   TagRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
             TypeIndex FieldList, StringRef Name, StringRef UniqueName)
       : TypeRecord(Kind), MemberCount(MemberCount), Options(Options),
@@ -474,6 +506,7 @@ private:
 // LF_CLASS, LF_STRUCTURE, LF_INTERFACE
 class ClassRecord : public TagRecord {
 public:
+  explicit ClassRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
   ClassRecord(TypeRecordKind Kind, uint16_t MemberCount, ClassOptions Options,
               HfaKind Hfa, WindowsRTClassKind WinRTKind, TypeIndex FieldList,
               TypeIndex DerivationList, TypeIndex VTableShape, uint64_t Size,
@@ -520,6 +553,7 @@ private:
 
 // LF_UNION
 struct UnionRecord : public TagRecord {
+  explicit UnionRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
   UnionRecord(uint16_t MemberCount, ClassOptions Options, HfaKind Hfa,
               TypeIndex FieldList, uint64_t Size, StringRef Name,
               StringRef UniqueName)
@@ -554,6 +588,7 @@ private:
 // LF_ENUM
 class EnumRecord : public TagRecord {
 public:
+  explicit EnumRecord(TypeRecordKind Kind) : TagRecord(Kind) {}
   EnumRecord(uint16_t MemberCount, ClassOptions Options, TypeIndex FieldList,
              StringRef Name, StringRef UniqueName, TypeIndex UnderlyingType)
       : TagRecord(TypeRecordKind::Enum, MemberCount, Options, FieldList, Name,
@@ -587,6 +622,7 @@ private:
 // LF_BITFIELD
 class BitFieldRecord : public TypeRecord {
 public:
+  explicit BitFieldRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   BitFieldRecord(TypeIndex Type, uint8_t BitSize, uint8_t BitOffset)
       : TypeRecord(TypeRecordKind::BitField), Type(Type), BitSize(BitSize),
         BitOffset(BitOffset) {}
@@ -617,6 +653,7 @@ private:
 // LF_VTSHAPE
 class VFTableShapeRecord : public TypeRecord {
 public:
+  explicit VFTableShapeRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   explicit VFTableShapeRecord(ArrayRef<VFTableSlotKind> Slots)
       : TypeRecord(TypeRecordKind::VFTableShape), SlotsRef(Slots) {}
   explicit VFTableShapeRecord(std::vector<VFTableSlotKind> Slots)
@@ -653,6 +690,7 @@ private:
 // LF_TYPESERVER2
 class TypeServer2Record : public TypeRecord {
 public:
+  explicit TypeServer2Record(TypeRecordKind Kind) : TypeRecord(Kind) {}
   TypeServer2Record(StringRef Guid, uint32_t Age, StringRef Name)
       : TypeRecord(TypeRecordKind::TypeServer2), Guid(Guid), Age(Age),
         Name(Name) {}
@@ -685,6 +723,7 @@ private:
 // LF_STRING_ID
 class StringIdRecord : public TypeRecord {
 public:
+  explicit StringIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   StringIdRecord(TypeIndex Id, StringRef String)
       : TypeRecord(TypeRecordKind::StringId), Id(Id), String(String) {}
 
@@ -712,6 +751,7 @@ private:
 // LF_FUNC_ID
 class FuncIdRecord : public TypeRecord {
 public:
+  explicit FuncIdRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   FuncIdRecord(TypeIndex ParentScope, TypeIndex FunctionType, StringRef Name)
       : TypeRecord(TypeRecordKind::FuncId), ParentScope(ParentScope),
         FunctionType(FunctionType), Name(Name) {}
@@ -744,6 +784,7 @@ private:
 // LF_UDT_SRC_LINE
 class UdtSourceLineRecord : public TypeRecord {
 public:
+  explicit UdtSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   UdtSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile, uint32_t LineNumber)
       : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
         SourceFile(SourceFile), LineNumber(LineNumber) {}
@@ -774,6 +815,7 @@ private:
 // LF_UDT_MOD_SRC_LINE
 class UdtModSourceLineRecord : public TypeRecord {
 public:
+  explicit UdtModSourceLineRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   UdtModSourceLineRecord(TypeIndex UDT, TypeIndex SourceFile,
                          uint32_t LineNumber, uint16_t Module)
       : TypeRecord(TypeRecordKind::UdtSourceLine), UDT(UDT),
@@ -812,6 +854,7 @@ private:
 // LF_BUILDINFO
 class BuildInfoRecord : public TypeRecord {
 public:
+  explicit BuildInfoRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   BuildInfoRecord(ArrayRef<TypeIndex> ArgIndices)
       : TypeRecord(TypeRecordKind::BuildInfo),
         ArgIndices(ArgIndices.begin(), ArgIndices.end()) {}
@@ -836,6 +879,7 @@ private:
 // LF_VFTABLE
 class VFTableRecord : public TypeRecord {
 public:
+  explicit VFTableRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   VFTableRecord(TypeIndex CompleteClass, TypeIndex OverriddenVFTable,
                 uint32_t VFPtrOffset, StringRef Name,
                 ArrayRef<StringRef> Methods)
@@ -887,6 +931,7 @@ private:
 // LF_ONEMETHOD
 class OneMethodRecord : public TypeRecord {
 public:
+  explicit OneMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   OneMethodRecord(TypeIndex Type, MethodKind Kind, MethodOptions Options,
                   MemberAccess Access, int32_t VFTableOffset, StringRef Name)
       : TypeRecord(TypeRecordKind::OneMethod), Type(Type), Kind(Kind),
@@ -932,6 +977,7 @@ private:
 // LF_METHODLIST
 class MethodOverloadListRecord : public TypeRecord {
 public:
+  explicit MethodOverloadListRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   MethodOverloadListRecord(ArrayRef<OneMethodRecord> Methods)
       : TypeRecord(TypeRecordKind::MethodOverloadList), Methods(Methods) {}
 
@@ -960,6 +1006,7 @@ private:
 /// For method overload sets.  LF_METHOD
 class OverloadedMethodRecord : public TypeRecord {
 public:
+  explicit OverloadedMethodRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   OverloadedMethodRecord(uint16_t NumOverloads, TypeIndex MethodList,
                          StringRef Name)
       : TypeRecord(TypeRecordKind::OverloadedMethod),
@@ -991,6 +1038,7 @@ private:
 // LF_MEMBER
 class DataMemberRecord : public TypeRecord {
 public:
+  explicit DataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   DataMemberRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset,
                    StringRef Name)
       : TypeRecord(TypeRecordKind::DataMember), Access(Access), Type(Type),
@@ -1025,6 +1073,7 @@ private:
 // LF_STMEMBER
 class StaticDataMemberRecord : public TypeRecord {
 public:
+  explicit StaticDataMemberRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   StaticDataMemberRecord(MemberAccess Access, TypeIndex Type, StringRef Name)
       : TypeRecord(TypeRecordKind::StaticDataMember), Access(Access),
         Type(Type), Name(Name) {}
@@ -1055,6 +1104,7 @@ private:
 // LF_ENUMERATE
 class EnumeratorRecord : public TypeRecord {
 public:
+  explicit EnumeratorRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   EnumeratorRecord(MemberAccess Access, APSInt Value, StringRef Name)
       : TypeRecord(TypeRecordKind::Enumerator), Access(Access),
         Value(std::move(Value)), Name(Name) {}
@@ -1085,6 +1135,7 @@ private:
 // LF_VFUNCTAB
 class VFPtrRecord : public TypeRecord {
 public:
+  explicit VFPtrRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   VFPtrRecord(TypeIndex Type)
       : TypeRecord(TypeRecordKind::VFPtr), Type(Type) {}
 
@@ -1108,6 +1159,7 @@ private:
 // LF_BCLASS, LF_BINTERFACE
 class BaseClassRecord : public TypeRecord {
 public:
+  explicit BaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   BaseClassRecord(MemberAccess Access, TypeIndex Type, uint64_t Offset)
       : TypeRecord(TypeRecordKind::BaseClass), Access(Access), Type(Type),
         Offset(Offset) {}
@@ -1137,6 +1189,7 @@ private:
 // LF_VBCLASS, LF_IVBCLASS
 class VirtualBaseClassRecord : public TypeRecord {
 public:
+  explicit VirtualBaseClassRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   VirtualBaseClassRecord(MemberAccess Access, TypeIndex BaseType,
                          TypeIndex VBPtrType, uint64_t Offset, uint64_t Index)
       : TypeRecord(TypeRecordKind::VirtualBaseClass), Access(Access),
@@ -1175,6 +1228,7 @@ private:
 /// together. The first will end in an LF_INDEX record that points to the next.
 class ListContinuationRecord : public TypeRecord {
 public:
+  explicit ListContinuationRecord(TypeRecordKind Kind) : TypeRecord(Kind) {}
   ListContinuationRecord(TypeIndex ContinuationIndex)
       : TypeRecord(TypeRecordKind::ListContinuation),
         ContinuationIndex(ContinuationIndex) {}
index 0959f4b..c98dbac 100644 (file)
@@ -43,6 +43,8 @@ TYPE_RECORD(LF_PROCEDURE, 0x1008, Procedure)
 TYPE_RECORD(LF_MFUNCTION, 0x1009, MemberFunction)
 TYPE_RECORD(LF_ARGLIST, 0x1201, ArgList)
 
+TYPE_RECORD(LF_FIELDLIST, 0x1203, FieldList)
+
 TYPE_RECORD(LF_ARRAY, 0x1503, Array)
 TYPE_RECORD(LF_CLASS, 0x1504, Class)
 TYPE_RECORD_ALIAS(LF_STRUCTURE, 0x1505, Struct, Class)
@@ -159,7 +161,6 @@ CV_TYPE(LF_OEM2, 0x1011)
 
 CV_TYPE(LF_SKIP, 0x1200)
 CV_TYPE(LF_DEFARG_ST, 0x1202)
-CV_TYPE(LF_FIELDLIST, 0x1203)
 CV_TYPE(LF_DERIVED, 0x1204)
 CV_TYPE(LF_DIMCONU, 0x1207)
 CV_TYPE(LF_DIMCONLU, 0x1208)
index 5b2aa61..d422251 100644 (file)
@@ -37,26 +37,26 @@ public:
   virtual ~TypeTableBuilder();
 
 public:
-  TypeIndex writeModifier(const ModifierRecord &Record);
-  TypeIndex writeProcedure(const ProcedureRecord &Record);
-  TypeIndex writeMemberFunction(const MemberFunctionRecord &Record);
-  TypeIndex writeArgList(const ArgListRecord &Record);
-  TypeIndex writePointer(const PointerRecord &Record);
-  TypeIndex writeArray(const ArrayRecord &Record);
-  TypeIndex writeClass(const ClassRecord &Record);
-  TypeIndex writeUnion(const UnionRecord &Record);
-  TypeIndex writeEnum(const EnumRecord &Record);
-  TypeIndex writeBitField(const BitFieldRecord &Record);
-  TypeIndex writeVFTableShape(const VFTableShapeRecord &Record);
-  TypeIndex writeStringId(const StringIdRecord &Record);
-  TypeIndex writeVFTable(const VFTableRecord &Record);
-  TypeIndex writeUdtSourceLine(const UdtSourceLineRecord &Record);
-  TypeIndex writeUdtModSourceLine(const UdtModSourceLineRecord &Record);
-  TypeIndex writeFuncId(const FuncIdRecord &Record);
-  TypeIndex writeMemberFuncId(const MemberFuncIdRecord &Record);
-  TypeIndex writeBuildInfo(const BuildInfoRecord &Record);
-  TypeIndex writeMethodOverloadList(const MethodOverloadListRecord &Record);
-  TypeIndex writeTypeServer2(const TypeServer2Record &Record);
+  TypeIndex writeKnownType(const ModifierRecord &Record);
+  TypeIndex writeKnownType(const ProcedureRecord &Record);
+  TypeIndex writeKnownType(const MemberFunctionRecord &Record);
+  TypeIndex writeKnownType(const ArgListRecord &Record);
+  TypeIndex writeKnownType(const PointerRecord &Record);
+  TypeIndex writeKnownType(const ArrayRecord &Record);
+  TypeIndex writeKnownType(const ClassRecord &Record);
+  TypeIndex writeKnownType(const UnionRecord &Record);
+  TypeIndex writeKnownType(const EnumRecord &Record);
+  TypeIndex writeKnownType(const BitFieldRecord &Record);
+  TypeIndex writeKnownType(const VFTableShapeRecord &Record);
+  TypeIndex writeKnownType(const StringIdRecord &Record);
+  TypeIndex writeKnownType(const VFTableRecord &Record);
+  TypeIndex writeKnownType(const UdtSourceLineRecord &Record);
+  TypeIndex writeKnownType(const UdtModSourceLineRecord &Record);
+  TypeIndex writeKnownType(const FuncIdRecord &Record);
+  TypeIndex writeKnownType(const MemberFuncIdRecord &Record);
+  TypeIndex writeKnownType(const BuildInfoRecord &Record);
+  TypeIndex writeKnownType(const MethodOverloadListRecord &Record);
+  TypeIndex writeKnownType(const TypeServer2Record &Record);
 
   TypeIndex writeFieldList(FieldListRecordBuilder &FieldList);
 
index 310847e..a734d48 100644 (file)
@@ -41,16 +41,11 @@ public:
     return Error::success();
   }
 
-  virtual Error visitFieldListBegin(const CVRecord<TypeLeafKind> &Record) {
-    return Error::success();
-  }
-
-  virtual Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) {
-    return Error::success();
-  }
-
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  virtual Error visit##Name(Name##Record &Record) { return Error::success(); }
+  virtual Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,            \
+                                 Name##Record &Record) {                       \
+    return Error::success();                                                   \
+  }
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
   TYPE_RECORD(EnumName, EnumVal, Name)
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
index 9d5d212..52d7b45 100644 (file)
@@ -212,7 +212,7 @@ TypeIndex CodeViewDebug::getScopeIndex(const DIScope *Scope) {
   // Build the fully qualified name of the scope.
   std::string ScopeName = getFullyQualifiedName(Scope);
   TypeIndex TI =
-      TypeTable.writeStringId(StringIdRecord(TypeIndex(), ScopeName));
+      TypeTable.writeKnownType(StringIdRecord(TypeIndex(), ScopeName));
   return recordTypeIndexForDINode(Scope, TI);
 }
 
@@ -237,12 +237,12 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
     TypeIndex ClassType = getTypeIndex(Class);
     MemberFuncIdRecord MFuncId(ClassType, getMemberFunctionType(SP, Class),
                                DisplayName);
-    TI = TypeTable.writeMemberFuncId(MFuncId);
+    TI = TypeTable.writeKnownType(MFuncId);
   } else {
     // Otherwise, this must be a free function.
     TypeIndex ParentScope = getScopeIndex(Scope);
     FuncIdRecord FuncId(ParentScope, getTypeIndex(SP->getType()), DisplayName);
-    TI = TypeTable.writeFuncId(FuncId);
+    TI = TypeTable.writeKnownType(FuncId);
   }
 
   return recordTypeIndexForDINode(SP, TI);
@@ -1030,7 +1030,7 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
     StringRef Name = (i == 0) ? Ty->getName() : "";
     // Update the element size and element type index for subsequent subranges.
     ElementSize *= Count;
-    ElementTypeIndex = TypeTable.writeArray(
+    ElementTypeIndex = TypeTable.writeKnownType(
         ArrayRecord(ElementTypeIndex, IndexType, ElementSize, Name));
   }
 
@@ -1174,7 +1174,7 @@ TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) {
   // do.
   PointerOptions PO = PointerOptions::None;
   PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);
-  return TypeTable.writePointer(PR);
+  return TypeTable.writeKnownType(PR);
 }
 
 static PointerToMemberRepresentation
@@ -1225,7 +1225,7 @@ TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) {
   MemberPointerInfo MPI(
       ClassTI, translatePtrToMemberRep(SizeInBytes, IsPMF, Ty->getFlags()));
   PointerRecord PR(PointeeTI, PK, PM, PO, SizeInBytes, MPI);
-  return TypeTable.writePointer(PR);
+  return TypeTable.writeKnownType(PR);
 }
 
 /// Given a DWARF calling convention, get the CodeView equivalent. If we don't
@@ -1272,7 +1272,7 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
     return I->second;
 
   ModifierRecord MR(ModifiedTI, Mods);
-  return TypeTable.writeModifier(MR);
+  return TypeTable.writeKnownType(MR);
 }
 
 TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
@@ -1289,13 +1289,13 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
   }
 
   ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
-  TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
+  TypeIndex ArgListIndex = TypeTable.writeKnownType(ArgListRec);
 
   CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
 
   ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None,
                             ArgTypeIndices.size(), ArgListIndex);
-  return TypeTable.writeProcedure(Procedure);
+  return TypeTable.writeKnownType(Procedure);
 }
 
 TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
@@ -1322,14 +1322,14 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
   }
 
   ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
-  TypeIndex ArgListIndex = TypeTable.writeArgList(ArgListRec);
+  TypeIndex ArgListIndex = TypeTable.writeKnownType(ArgListRec);
 
   CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
 
   // TODO: Need to use the correct values for:
   //       FunctionOptions
   //       ThisPointerAdjustment.
-  TypeIndex TI = TypeTable.writeMemberFunction(MemberFunctionRecord(
+  TypeIndex TI = TypeTable.writeKnownType(MemberFunctionRecord(
       ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FunctionOptions::None,
       ArgTypeIndices.size(), ArgListIndex, ThisAdjustment));
 
@@ -1428,7 +1428,7 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
       // We assume that the frontend provides all members in source declaration
       // order, which is what MSVC does.
       if (auto *Enumerator = dyn_cast_or_null<DIEnumerator>(Element)) {
-        Fields.writeEnumerator(EnumeratorRecord(
+        Fields.writeMemberType(EnumeratorRecord(
             MemberAccess::Public, APSInt::getUnsigned(Enumerator->getValue()),
             Enumerator->getName()));
         EnumeratorCount++;
@@ -1439,9 +1439,9 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
 
   std::string FullName = getFullyQualifiedName(Ty);
 
-  return TypeTable.writeEnum(EnumRecord(EnumeratorCount, CO, FTI, FullName,
-                                        Ty->getIdentifier(),
-                                        getTypeIndex(Ty->getBaseType())));
+  return TypeTable.writeKnownType(EnumRecord(EnumeratorCount, CO, FTI, FullName,
+                                             Ty->getIdentifier(),
+                                             getTypeIndex(Ty->getBaseType())));
 }
 
 //===----------------------------------------------------------------------===//
@@ -1536,7 +1536,7 @@ TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
   ClassOptions CO =
       ClassOptions::ForwardReference | getCommonClassOptions(Ty);
   std::string FullName = getFullyQualifiedName(Ty);
-  TypeIndex FwdDeclTI = TypeTable.writeClass(ClassRecord(
+  TypeIndex FwdDeclTI = TypeTable.writeKnownType(ClassRecord(
       Kind, 0, CO, HfaKind::None, WindowsRTClassKind::None, TypeIndex(),
       TypeIndex(), TypeIndex(), 0, FullName, Ty->getIdentifier()));
   if (!Ty->isForwardDecl())
@@ -1562,12 +1562,12 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
 
   uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
 
-  TypeIndex ClassTI = TypeTable.writeClass(ClassRecord(
+  TypeIndex ClassTI = TypeTable.writeKnownType(ClassRecord(
       Kind, FieldCount, CO, HfaKind::None, WindowsRTClassKind::None, FieldTI,
       TypeIndex(), VShapeTI, SizeInBytes, FullName, Ty->getIdentifier()));
 
-  TypeTable.writeUdtSourceLine(UdtSourceLineRecord(
-      ClassTI, TypeTable.writeStringId(StringIdRecord(
+  TypeTable.writeKnownType(UdtSourceLineRecord(
+      ClassTI, TypeTable.writeKnownType(StringIdRecord(
                    TypeIndex(0x0), getFullFilepath(Ty->getFile()))),
       Ty->getLine()));
 
@@ -1580,9 +1580,8 @@ TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
   ClassOptions CO =
       ClassOptions::ForwardReference | getCommonClassOptions(Ty);
   std::string FullName = getFullyQualifiedName(Ty);
-  TypeIndex FwdDeclTI =
-      TypeTable.writeUnion(UnionRecord(0, CO, HfaKind::None, TypeIndex(), 0,
-                                       FullName, Ty->getIdentifier()));
+  TypeIndex FwdDeclTI = TypeTable.writeKnownType(UnionRecord(
+      0, CO, HfaKind::None, TypeIndex(), 0, FullName, Ty->getIdentifier()));
   if (!Ty->isForwardDecl())
     DeferredCompleteTypes.push_back(Ty);
   return FwdDeclTI;
@@ -1602,12 +1601,12 @@ TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
   uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
   std::string FullName = getFullyQualifiedName(Ty);
 
-  TypeIndex UnionTI = TypeTable.writeUnion(
+  TypeIndex UnionTI = TypeTable.writeKnownType(
       UnionRecord(FieldCount, CO, HfaKind::None, FieldTI, SizeInBytes, FullName,
                   Ty->getIdentifier()));
 
-  TypeTable.writeUdtSourceLine(UdtSourceLineRecord(
-      UnionTI, TypeTable.writeStringId(StringIdRecord(
+  TypeTable.writeKnownType(UdtSourceLineRecord(
+      UnionTI, TypeTable.writeKnownType(StringIdRecord(
                    TypeIndex(0x0), getFullFilepath(Ty->getFile()))),
       Ty->getLine()));
 
@@ -1634,14 +1633,14 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
       unsigned VBPtrOffset = 0;
       // FIXME: Despite the accessor name, the offset is really in bytes.
       unsigned VBTableIndex = I->getOffsetInBits() / 4;
-      Fields.writeVirtualBaseClass(VirtualBaseClassRecord(
+      Fields.writeMemberType(VirtualBaseClassRecord(
           translateAccessFlags(Ty->getTag(), I->getFlags()),
           getTypeIndex(I->getBaseType()), getVBPTypeIndex(), VBPtrOffset,
           VBTableIndex));
     } else {
       assert(I->getOffsetInBits() % 8 == 0 &&
              "bases must be on byte boundaries");
-      Fields.writeBaseClass(BaseClassRecord(
+      Fields.writeMemberType(BaseClassRecord(
           translateAccessFlags(Ty->getTag(), I->getFlags()),
           getTypeIndex(I->getBaseType()), I->getOffsetInBits() / 8));
     }
@@ -1656,7 +1655,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
         translateAccessFlags(Ty->getTag(), Member->getFlags());
 
     if (Member->isStaticMember()) {
-      Fields.writeStaticDataMember(
+      Fields.writeMemberType(
           StaticDataMemberRecord(Access, MemberBaseType, MemberName));
       MemberCount++;
       continue;
@@ -1672,11 +1671,11 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
         MemberOffsetInBits = CI->getZExtValue() + MemberInfo.BaseOffset;
       }
       StartBitOffset -= MemberOffsetInBits;
-      MemberBaseType = TypeTable.writeBitField(BitFieldRecord(
+      MemberBaseType = TypeTable.writeKnownType(BitFieldRecord(
           MemberBaseType, Member->getSizeInBits(), StartBitOffset));
     }
     uint64_t MemberOffsetInBytes = MemberOffsetInBits / 8;
-    Fields.writeDataMember(DataMemberRecord(Access, MemberBaseType,
+    Fields.writeMemberType(DataMemberRecord(Access, MemberBaseType,
                                             MemberOffsetInBytes, MemberName));
     MemberCount++;
   }
@@ -1703,11 +1702,11 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
     }
     assert(Methods.size() > 0 && "Empty methods map entry");
     if (Methods.size() == 1)
-      Fields.writeOneMethod(Methods[0]);
+      Fields.writeMemberType(Methods[0]);
     else {
       TypeIndex MethodList =
-          TypeTable.writeMethodOverloadList(MethodOverloadListRecord(Methods));
-      Fields.writeOverloadedMethod(
+          TypeTable.writeKnownType(MethodOverloadListRecord(Methods));
+      Fields.writeMemberType(
           OverloadedMethodRecord(Methods.size(), MethodList, Name));
     }
   }
@@ -1715,7 +1714,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
   // Create nested classes.
   for (const DICompositeType *Nested : Info.NestedClasses) {
     NestedTypeRecord R(getTypeIndex(DITypeRef(Nested)), Nested->getName());
-    Fields.writeNestedType(R);
+    Fields.writeMemberType(R);
     MemberCount++;
   }
 
@@ -1728,7 +1727,7 @@ TypeIndex CodeViewDebug::getVBPTypeIndex() {
   if (!VBPType.getIndex()) {
     // Make a 'const int *' type.
     ModifierRecord MR(TypeIndex::Int32(), ModifierOptions::Const);
-    TypeIndex ModifiedTI = TypeTable.writeModifier(MR);
+    TypeIndex ModifiedTI = TypeTable.writeKnownType(MR);
 
     PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
                                                   : PointerKind::Near32;
@@ -1736,7 +1735,7 @@ TypeIndex CodeViewDebug::getVBPTypeIndex() {
     PointerOptions PO = PointerOptions::None;
     PointerRecord PR(ModifiedTI, PK, PM, PO, getPointerSizeInBytes());
 
-    VBPType = TypeTable.writePointer(PR);
+    VBPType = TypeTable.writeKnownType(PR);
   }
 
   return VBPType;
index d8c2195..92ffd3d 100644 (file)
@@ -11,6 +11,7 @@ add_llvm_library(LLVMDebugInfoCodeView
   ModuleSubstreamVisitor.cpp
   RecordSerialization.cpp
   SymbolDumper.cpp
+  TypeDeserializer.cpp
   TypeDumper.cpp
   TypeRecord.cpp
   TypeRecordBuilder.cpp
index a7b7f3a..01dd5d4 100644 (file)
@@ -8,47 +8,39 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+
 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/Msf/ByteStream.h"
 
 using namespace llvm;
 using namespace llvm::codeview;
 
+CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
+    : Callbacks(Callbacks) {}
+
 template <typename T>
-static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
-  if (Data.size() < sizeof(*Res))
-    return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
-  Res = reinterpret_cast<const T *>(Data.data());
-  Data = Data.drop_front(sizeof(*Res));
+static Error visitKnownRecord(const CVRecord<TypeLeafKind> &Record,
+                              TypeVisitorCallbacks &Callbacks) {
+  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
+  T KnownRecord(RK);
+  if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
+    return EC;
   return Error::success();
 }
 
-CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
-    : Callbacks(Callbacks) {}
-
 Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
   ArrayRef<uint8_t> LeafData = Record.Data;
   if (auto EC = Callbacks.visitTypeBegin(Record))
     return EC;
+
   switch (Record.Type) {
   default:
     if (auto EC = Callbacks.visitUnknownType(Record))
       return EC;
     break;
-  case LF_FIELDLIST:
-    if (auto EC = Callbacks.visitFieldListBegin(Record))
-      return EC;
-    if (auto EC = visitFieldList(Record))
-      return EC;
-    if (auto EC = Callbacks.visitFieldListEnd(Record))
-      return EC;
-    break;
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
   case EnumName: {                                                             \
-    TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName);                 \
-    auto ExpectedRecord = Name##Record::deserialize(RK, LeafData);             \
-    if (!ExpectedRecord)                                                       \
-      return ExpectedRecord.takeError();                                       \
-    if (auto EC = Callbacks.visit##Name(*ExpectedRecord))                      \
+    if (auto EC = visitKnownRecord<Name##Record>(Record, Callbacks))           \
       return EC;                                                               \
     break;                                                                     \
   }
@@ -57,8 +49,10 @@ Error CVTypeVisitor::visitTypeRecord(const CVRecord<TypeLeafKind> &Record) {
 #define MEMBER_RECORD(EnumName, EnumVal, Name)
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
   }
+
   if (auto EC = Callbacks.visitTypeEnd(Record))
     return EC;
+
   return Error::success();
 }
 
@@ -70,55 +64,3 @@ Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
   }
   return Error::success();
 }
-
-Error CVTypeVisitor::skipPadding(ArrayRef<uint8_t> &Data) {
-  if (Data.empty())
-    return Error::success();
-  uint8_t Leaf = Data.front();
-  if (Leaf < LF_PAD0)
-    return Error::success();
-  // Leaf is greater than 0xf0. We should advance by the number of bytes in
-  // the low 4 bits.
-  unsigned BytesToAdvance = Leaf & 0x0F;
-  if (Data.size() < BytesToAdvance) {
-    return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
-                                           "Invalid padding bytes!");
-  }
-  Data = Data.drop_front(BytesToAdvance);
-  return Error::success();
-}
-
-/// Visits individual member records of a field list record. Member records do
-/// not describe their own length, and need special handling.
-Error CVTypeVisitor::visitFieldList(const CVRecord<TypeLeafKind> &Record) {
-  ArrayRef<uint8_t> RecordData = Record.Data;
-  while (!RecordData.empty()) {
-    const ulittle16_t *LeafPtr;
-    if (auto EC = takeObject(RecordData, LeafPtr))
-      return EC;
-    TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
-    switch (Leaf) {
-    default:
-      // Field list records do not describe their own length, so we cannot
-      // continue parsing past an unknown member type.
-      if (auto EC = Callbacks.visitUnknownMember(Record))
-        return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record);
-#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  case EnumName: {                                                             \
-    TypeRecordKind RK = static_cast<TypeRecordKind>(EnumName);                 \
-    auto ExpectedRecord = Name##Record::deserialize(RK, RecordData);           \
-    if (!ExpectedRecord)                                                       \
-      return ExpectedRecord.takeError();                                       \
-    if (auto EC = Callbacks.visit##Name(*ExpectedRecord))                      \
-      return EC;                                                               \
-    break;                                                                     \
-  }
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
-  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
-#include "llvm/DebugInfo/CodeView/TypeRecords.def"
-    }
-    if (auto EC = skipPadding(RecordData))
-      return EC;
-  }
-  return Error::success();
-}
index aad1d8b..e9678db 100644 (file)
@@ -33,6 +33,8 @@ public:
       return "The CodeView record is corrupted.";
     case cv_error_code::operation_unsupported:
       return "The requested operation is not supported.";
+    case cv_error_code::unknown_member_record:
+      return "The member record is of an unknown type.";
     }
     llvm_unreachable("Unrecognized cv_error_code");
   }
index 5f229e3..ac2ef39 100644 (file)
@@ -15,7 +15,7 @@ using namespace codeview;
 FieldListRecordBuilder::FieldListRecordBuilder()
     : ListRecordBuilder(TypeRecordKind::FieldList) {}
 
-void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const BaseClassRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
   Builder.writeTypeRecordKind(TypeRecordKind::BaseClass);
@@ -26,7 +26,7 @@ void FieldListRecordBuilder::writeBaseClass(const BaseClassRecord &Record) {
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const EnumeratorRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
   Builder.writeTypeRecordKind(TypeRecordKind::Enumerator);
@@ -38,7 +38,7 @@ void FieldListRecordBuilder::writeEnumerator(const EnumeratorRecord &Record) {
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const DataMemberRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
   Builder.writeTypeRecordKind(Record.getKind());
@@ -50,7 +50,7 @@ void FieldListRecordBuilder::writeDataMember(const DataMemberRecord &Record) {
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeOverloadedMethod(
+void FieldListRecordBuilder::writeMemberType(
     const OverloadedMethodRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
@@ -62,7 +62,7 @@ void FieldListRecordBuilder::writeOverloadedMethod(
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeOneMethod(const OneMethodRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const OneMethodRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
   uint16_t Flags = static_cast<uint16_t>(Record.getAccess());
@@ -84,7 +84,7 @@ void FieldListRecordBuilder::writeOneMethod(const OneMethodRecord &Record) {
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const NestedTypeRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
   Builder.writeTypeRecordKind(Record.getKind());
@@ -95,7 +95,7 @@ void FieldListRecordBuilder::writeNestedType(const NestedTypeRecord &Record) {
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeStaticDataMember(
+void FieldListRecordBuilder::writeMemberType(
     const StaticDataMemberRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
@@ -107,7 +107,7 @@ void FieldListRecordBuilder::writeStaticDataMember(
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeVirtualBaseClass(
+void FieldListRecordBuilder::writeMemberType(
     const VirtualBaseClassRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
@@ -121,7 +121,7 @@ void FieldListRecordBuilder::writeVirtualBaseClass(
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeVFPtr(const VFPtrRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const VFPtrRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
   Builder.writeTypeRecordKind(TypeRecordKind::VFPtr);
index eb79e8a..ab019c4 100644 (file)
@@ -17,7 +17,7 @@ using namespace codeview;
 ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind)
     : Kind(Kind), Builder(Kind) {}
 
-void ListRecordBuilder::writeListContinuation(const ListContinuationRecord &R) {
+void ListRecordBuilder::writeMemberType(const ListContinuationRecord &R) {
   TypeRecordBuilder &Builder = getBuilder();
 
   assert(getLastContinuationSize() < 65535 - 8 && "continuation won't fit");
diff --git a/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp b/llvm/lib/DebugInfo/CodeView/TypeDeserializer.cpp
new file mode 100644 (file)
index 0000000..3593458
--- /dev/null
@@ -0,0 +1,81 @@
+//===- TypeDeserializer.cpp -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename T>
+static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+  if (Data.size() < sizeof(*Res))
+    return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+  Res = reinterpret_cast<const T *>(Data.data());
+  Data = Data.drop_front(sizeof(*Res));
+  return Error::success();
+}
+
+Error TypeDeserializer::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                         FieldListRecord &Record) {
+  ArrayRef<uint8_t> FieldListRecordData = CVR.Data;
+  auto ExpectedRecord = FieldListRecord::deserialize(TypeRecordKind::FieldList,
+                                                     FieldListRecordData);
+  if (!ExpectedRecord)
+    return ExpectedRecord.takeError();
+
+  Record = *ExpectedRecord;
+  ArrayRef<uint8_t> MemberData = Record.getFieldListData();
+
+  while (!MemberData.empty()) {
+    const ulittle16_t *LeafPtr;
+    if (auto EC = takeObject(MemberData, LeafPtr))
+      return EC;
+    TypeLeafKind Leaf = TypeLeafKind(unsigned(*LeafPtr));
+    switch (Leaf) {
+    default:
+      // Field list records do not describe their own length, so we cannot
+      // continue parsing past a type that we don't know how to deserialize.
+      if (auto EC = Recipient.visitUnknownMember(CVR))
+        return EC;
+      return llvm::make_error<CodeViewError>(
+          cv_error_code::unknown_member_record);
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  case EnumName: {                                                             \
+    TypeRecordKind RK = static_cast<TypeRecordKind>(Leaf);                     \
+    Name##Record Member(RK);                                                   \
+    if (auto EC = visitKnownMember(MemberData, Leaf, Member))                  \
+      return EC;                                                               \
+    break;                                                                     \
+  }
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
+  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+    }
+    if (auto EC = skipPadding(MemberData))
+      return EC;
+  }
+  return Error::success();
+}
+
+Error TypeDeserializer::skipPadding(ArrayRef<uint8_t> &Data) {
+  if (Data.empty())
+    return Error::success();
+  uint8_t Leaf = Data.front();
+  if (Leaf < LF_PAD0)
+    return Error::success();
+  // Leaf is greater than 0xf0. We should advance by the number of bytes in
+  // the low 4 bits.
+  unsigned BytesToAdvance = Leaf & 0x0F;
+  if (Data.size() < BytesToAdvance) {
+    return llvm::make_error<CodeViewError>(cv_error_code::corrupt_record,
+                                           "Invalid padding bytes!");
+  }
+  Data = Data.drop_front(BytesToAdvance);
+  return Error::success();
+}
index 5ceaa59..e1ec5ce 100644 (file)
@@ -10,6 +10,7 @@
 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/MSF/ByteStream.h"
@@ -195,8 +196,6 @@ static StringRef getLeafTypeName(TypeLeafKind LT) {
   case ename:                                                                  \
     return #name;
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
-  case LF_FIELDLIST:
-    return "FieldList";
   default:
     break;
   }
@@ -231,7 +230,13 @@ Error CVTypeDumper::visitTypeEnd(const CVRecord<TypeLeafKind> &Record) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitStringId(StringIdRecord &String) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     FieldListRecord &FieldList) {
+  return Error::success();
+}
+
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     StringIdRecord &String) {
   printTypeIndex("Id", String.getId());
   W->printString("StringData", String.getString());
   // Put this in CVUDTNames so it gets printed with LF_UDT_SRC_LINE.
@@ -239,7 +244,8 @@ Error CVTypeDumper::visitStringId(StringIdRecord &String) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitArgList(ArgListRecord &Args) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     ArgListRecord &Args) {
   auto Indices = Args.getIndices();
   uint32_t Size = Indices.size();
   W->printNumber("NumArgs", Size);
@@ -257,7 +263,8 @@ Error CVTypeDumper::visitArgList(ArgListRecord &Args) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitClass(ClassRecord &Class) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     ClassRecord &Class) {
   uint16_t Props = static_cast<uint16_t>(Class.getOptions());
   W->printNumber("MemberCount", Class.getMemberCount());
   W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
@@ -272,7 +279,8 @@ Error CVTypeDumper::visitClass(ClassRecord &Class) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitUnion(UnionRecord &Union) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     UnionRecord &Union) {
   uint16_t Props = static_cast<uint16_t>(Union.getOptions());
   W->printNumber("MemberCount", Union.getMemberCount());
   W->printFlags("Properties", Props, makeArrayRef(ClassOptionNames));
@@ -285,7 +293,8 @@ Error CVTypeDumper::visitUnion(UnionRecord &Union) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     EnumRecord &Enum) {
   uint16_t Props = static_cast<uint16_t>(Enum.getOptions());
   W->printNumber("NumEnumerators", Enum.getMemberCount());
   W->printFlags("Properties", uint16_t(Enum.getOptions()),
@@ -299,7 +308,8 @@ Error CVTypeDumper::visitEnum(EnumRecord &Enum) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitArray(ArrayRecord &AT) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     ArrayRecord &AT) {
   printTypeIndex("ElementType", AT.getElementType());
   printTypeIndex("IndexType", AT.getIndexType());
   W->printNumber("SizeOf", AT.getSize());
@@ -308,7 +318,8 @@ Error CVTypeDumper::visitArray(ArrayRecord &AT) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     VFTableRecord &VFT) {
   printTypeIndex("CompleteClass", VFT.getCompleteClass());
   printTypeIndex("OverriddenVFTable", VFT.getOverriddenVTable());
   W->printHex("VFPtrOffset", VFT.getVFPtrOffset());
@@ -319,7 +330,8 @@ Error CVTypeDumper::visitVFTable(VFTableRecord &VFT) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     MemberFuncIdRecord &Id) {
   printTypeIndex("ClassType", Id.getClassType());
   printTypeIndex("FunctionType", Id.getFunctionType());
   W->printString("Name", Id.getName());
@@ -327,7 +339,8 @@ Error CVTypeDumper::visitMemberFuncId(MemberFuncIdRecord &Id) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     ProcedureRecord &Proc) {
   printTypeIndex("ReturnType", Proc.getReturnType());
   W->printEnum("CallingConvention", uint8_t(Proc.getCallConv()),
                makeArrayRef(CallingConventions));
@@ -345,7 +358,8 @@ Error CVTypeDumper::visitProcedure(ProcedureRecord &Proc) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     MemberFunctionRecord &MF) {
   printTypeIndex("ReturnType", MF.getReturnType());
   printTypeIndex("ClassType", MF.getClassType());
   printTypeIndex("ThisType", MF.getThisType());
@@ -369,8 +383,8 @@ Error CVTypeDumper::visitMemberFunction(MemberFunctionRecord &MF) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitMethodOverloadList(
-    MethodOverloadListRecord &MethodList) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     MethodOverloadListRecord &MethodList) {
   for (auto &M : MethodList.getMethods()) {
     ListScope S(*W, "Method");
     printMemberAttributes(M.getAccess(), M.getKind(), M.getOptions());
@@ -381,7 +395,8 @@ Error CVTypeDumper::visitMethodOverloadList(
   return Error::success();
 }
 
-Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     FuncIdRecord &Func) {
   printTypeIndex("ParentScope", Func.getParentScope());
   printTypeIndex("FunctionType", Func.getFunctionType());
   W->printString("Name", Func.getName());
@@ -389,7 +404,8 @@ Error CVTypeDumper::visitFuncId(FuncIdRecord &Func) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     TypeServer2Record &TS) {
   W->printBinary("Signature", TS.getGuid());
   W->printNumber("Age", TS.getAge());
   W->printString("Name", TS.getName());
@@ -397,7 +413,8 @@ Error CVTypeDumper::visitTypeServer2(TypeServer2Record &TS) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     PointerRecord &Ptr) {
   printTypeIndex("PointeeType", Ptr.getReferentType());
   W->printHex("PointerAttributes", uint32_t(Ptr.getOptions()));
   W->printEnum("PtrType", unsigned(Ptr.getPointerKind()),
@@ -448,7 +465,8 @@ Error CVTypeDumper::visitPointer(PointerRecord &Ptr) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitModifier(ModifierRecord &Mod) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     ModifierRecord &Mod) {
   uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
   printTypeIndex("ModifiedType", Mod.getModifiedType());
   W->printFlags("Modifiers", Mods, makeArrayRef(TypeModifierNames));
@@ -466,26 +484,30 @@ Error CVTypeDumper::visitModifier(ModifierRecord &Mod) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitBitField(BitFieldRecord &BitField) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     BitFieldRecord &BitField) {
   printTypeIndex("Type", BitField.getType());
   W->printNumber("BitSize", BitField.getBitSize());
   W->printNumber("BitOffset", BitField.getBitOffset());
   return Error::success();
 }
 
-Error CVTypeDumper::visitVFTableShape(VFTableShapeRecord &Shape) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     VFTableShapeRecord &Shape) {
   W->printNumber("VFEntryCount", Shape.getEntryCount());
   return Error::success();
 }
 
-Error CVTypeDumper::visitUdtSourceLine(UdtSourceLineRecord &Line) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     UdtSourceLineRecord &Line) {
   printTypeIndex("UDT", Line.getUDT());
   printTypeIndex("SourceFile", Line.getSourceFile());
   W->printNumber("LineNumber", Line.getLineNumber());
   return Error::success();
 }
 
-Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     UdtModSourceLineRecord &Line) {
   printTypeIndex("UDT", Line.getUDT());
   printTypeIndex("SourceFile", Line.getSourceFile());
   W->printNumber("LineNumber", Line.getLineNumber());
@@ -493,7 +515,8 @@ Error CVTypeDumper::visitUdtModSourceLine(UdtModSourceLineRecord &Line) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitBuildInfo(BuildInfoRecord &Args) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     BuildInfoRecord &Args) {
   W->printNumber("NumArgs", static_cast<uint32_t>(Args.getArgs().size()));
 
   ListScope Arguments(*W, "Arguments");
@@ -533,7 +556,8 @@ Error CVTypeDumper::visitUnknownType(const CVRecord<TypeLeafKind> &Record) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     NestedTypeRecord &Nested) {
   DictScope S(*W, "NestedType");
   printTypeIndex("Type", Nested.getNestedType());
   W->printString("Name", Nested.getName());
@@ -541,7 +565,8 @@ Error CVTypeDumper::visitNestedType(NestedTypeRecord &Nested) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     OneMethodRecord &Method) {
   DictScope S(*W, "OneMethod");
   MethodKind K = Method.getKind();
   printMemberAttributes(Method.getAccess(), K, Method.getOptions());
@@ -554,7 +579,8 @@ Error CVTypeDumper::visitOneMethod(OneMethodRecord &Method) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     OverloadedMethodRecord &Method) {
   DictScope S(*W, "OverloadedMethod");
   W->printHex("MethodCount", Method.getNumOverloads());
   printTypeIndex("MethodListIndex", Method.getMethodList());
@@ -563,7 +589,8 @@ Error CVTypeDumper::visitOverloadedMethod(OverloadedMethodRecord &Method) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     DataMemberRecord &Field) {
   DictScope S(*W, "DataMember");
   printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -574,7 +601,8 @@ Error CVTypeDumper::visitDataMember(DataMemberRecord &Field) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     StaticDataMemberRecord &Field) {
   DictScope S(*W, "StaticDataMember");
   printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -584,13 +612,15 @@ Error CVTypeDumper::visitStaticDataMember(StaticDataMemberRecord &Field) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitVFPtr(VFPtrRecord &VFTable) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     VFPtrRecord &VFTable) {
   DictScope S(*W, "VFPtr");
   printTypeIndex("Type", VFTable.getType());
   return Error::success();
 }
 
-Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     EnumeratorRecord &Enum) {
   DictScope S(*W, "Enumerator");
   printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -600,7 +630,8 @@ Error CVTypeDumper::visitEnumerator(EnumeratorRecord &Enum) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     BaseClassRecord &Base) {
   DictScope S(*W, "BaseClass");
   printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -609,7 +640,8 @@ Error CVTypeDumper::visitBaseClass(BaseClassRecord &Base) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     VirtualBaseClassRecord &Base) {
   DictScope S(*W, "VirtualBaseClass");
   printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -620,7 +652,8 @@ Error CVTypeDumper::visitVirtualBaseClass(VirtualBaseClassRecord &Base) {
   return Error::success();
 }
 
-Error CVTypeDumper::visitListContinuation(ListContinuationRecord &Cont) {
+Error CVTypeDumper::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                                     ListContinuationRecord &Cont) {
   DictScope S(*W, "ListContinuation");
   printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
   return Error::success();
@@ -665,7 +698,8 @@ void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) {
 
 Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
   assert(W && "printer should not be null");
-  CVTypeVisitor Visitor(*this);
+  TypeDeserializer Deserializer(*this);
+  CVTypeVisitor Visitor(Deserializer);
 
   if (auto EC = Visitor.visitTypeRecord(Record))
     return EC;
@@ -674,7 +708,9 @@ Error CVTypeDumper::dump(const CVRecord<TypeLeafKind> &Record) {
 
 Error CVTypeDumper::dump(const CVTypeArray &Types) {
   assert(W && "printer should not be null");
-  CVTypeVisitor Visitor(*this);
+  TypeDeserializer Deserializer(*this);
+  CVTypeVisitor Visitor(Deserializer);
+
   if (auto EC = Visitor.visitTypeStream(Types))
     return EC;
   return Error::success();
index 4bbd261..e630be8 100644 (file)
@@ -114,6 +114,11 @@ NestedTypeRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
   return NestedTypeRecord(L->Type, Name);
 }
 
+Expected<FieldListRecord>
+FieldListRecord::deserialize(TypeRecordKind Kind, ArrayRef<uint8_t> &Data) {
+  return FieldListRecord(Data);
+}
+
 Expected<ArrayRecord> ArrayRecord::deserialize(TypeRecordKind Kind,
                                                ArrayRef<uint8_t> &Data) {
   const Layout *L = nullptr;
index 8c2bc07..58c8c3f 100644 (file)
@@ -12,6 +12,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@@ -58,7 +59,8 @@ public:
 
 /// TypeVisitorCallbacks overrides.
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error visit##Name(Name##Record &Record) override;
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,                    \
+                         Name##Record &Record) override;
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
   TYPE_RECORD(EnumName, EnumVal, Name)
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
@@ -70,11 +72,28 @@ public:
   Error visitTypeBegin(const CVRecord<TypeLeafKind> &Record) override;
   Error visitTypeEnd(const CVRecord<TypeLeafKind> &Record) override;
 
-  Error visitFieldListEnd(const CVRecord<TypeLeafKind> &Record) override;
-
   bool mergeStream(const CVTypeArray &Types);
 
 private:
+  template <typename RecordType>
+  Error visitKnownRecordImpl(RecordType &Record) {
+    FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);
+    IndexMap.push_back(DestStream.writeKnownType(Record));
+    return Error::success();
+  }
+
+  Error visitKnownRecordImpl(FieldListRecord &Record) {
+    // Don't do anything, this will get written in the call to visitTypeEnd().
+    return Error::success();
+  }
+
+  template <typename RecordType>
+  Error visitKnownMemberRecordImpl(RecordType &Record) {
+    FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);
+    FieldBuilder.writeMemberType(Record);
+    return Error::success();
+  }
+
   bool hadError() { return FoundBadTypeIndex; }
 
   bool FoundBadTypeIndex = false;
@@ -93,33 +112,31 @@ private:
 } // end anonymous namespace
 
 Error TypeStreamMerger::visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) {
-  BeginIndexMapSize = IndexMap.size();
+  if (Rec.Type != TypeLeafKind::LF_FIELDLIST)
+    BeginIndexMapSize = IndexMap.size();
   return Error::success();
 }
 
 Error TypeStreamMerger::visitTypeEnd(const CVRecord<TypeLeafKind> &Rec) {
-  assert(IndexMap.size() == BeginIndexMapSize + 1);
-  return Error::success();
-}
-
-Error TypeStreamMerger::visitFieldListEnd(const CVRecord<TypeLeafKind> &Rec) {
-  IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
-  FieldBuilder.reset();
+  if (Rec.Type == TypeLeafKind::LF_FIELDLIST) {
+    IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
+    FieldBuilder.reset();
+  } else {
+    assert(IndexMap.size() == BeginIndexMapSize + 1);
+  }
   return Error::success();
 }
 
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error TypeStreamMerger::visit##Name(Name##Record &Record) {                  \
-    FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);                   \
-    IndexMap.push_back(DestStream.write##Name(Record));                        \
-    return Error::success();                                                   \
+  Error TypeStreamMerger::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,  \
+                                           Name##Record &Record) {             \
+    return visitKnownRecordImpl(Record);                                       \
   }
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  Error TypeStreamMerger::visit##Name(Name##Record &Record) {                  \
-    FoundBadTypeIndex |= !Record.remapTypeIndices(IndexMap);                   \
-    FieldBuilder.write##Name(Record);                                          \
-    return Error::success();                                                   \
+  Error TypeStreamMerger::visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,  \
+                                           Name##Record &Record) {             \
+    return visitKnownMemberRecordImpl(Record);                                 \
   }
 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
@@ -133,7 +150,9 @@ Error TypeStreamMerger::visitUnknownType(const CVRecord<TypeLeafKind> &Rec) {
 
 bool TypeStreamMerger::mergeStream(const CVTypeArray &Types) {
   assert(IndexMap.empty());
-  CVTypeVisitor Visitor(*this);
+  TypeDeserializer Deserializer(*this);
+  CVTypeVisitor Visitor(Deserializer);
+
   if (auto EC = Visitor.visitTypeStream(Types)) {
     consumeError(std::move(EC));
     return false;
index 647538e..0fcf4f9 100644 (file)
@@ -21,7 +21,7 @@ TypeTableBuilder::TypeTableBuilder() {}
 
 TypeTableBuilder::~TypeTableBuilder() {}
 
-TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ModifierRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   Builder.writeTypeIndex(Record.getModifiedType());
@@ -30,7 +30,7 @@ TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ProcedureRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   Builder.writeTypeIndex(Record.getReturnType());
@@ -42,8 +42,7 @@ TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex
-TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const MemberFunctionRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   Builder.writeTypeIndex(Record.getReturnType());
@@ -58,7 +57,7 @@ TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ArgListRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   Builder.writeUInt32(Record.getIndices().size());
@@ -69,7 +68,7 @@ TypeIndex TypeTableBuilder::writeArgList(const ArgListRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const PointerRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   Builder.writeTypeIndex(Record.getReferentType());
@@ -90,7 +89,7 @@ TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ArrayRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   Builder.writeTypeIndex(Record.getElementType());
@@ -101,7 +100,7 @@ TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const ClassRecord &Record) {
   assert((Record.getKind() == TypeRecordKind::Struct) ||
          (Record.getKind() == TypeRecordKind::Class) ||
          (Record.getKind() == TypeRecordKind::Interface));
@@ -128,7 +127,7 @@ TypeIndex TypeTableBuilder::writeClass(const ClassRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeUnion(const UnionRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const UnionRecord &Record) {
   TypeRecordBuilder Builder(TypeRecordKind::Union);
   Builder.writeUInt16(Record.getMemberCount());
   uint16_t Flags =
@@ -145,7 +144,7 @@ TypeIndex TypeTableBuilder::writeUnion(const UnionRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const EnumRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   Builder.writeUInt16(Record.getMemberCount());
@@ -161,7 +160,7 @@ TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const BitFieldRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   Builder.writeTypeIndex(Record.getType());
@@ -171,8 +170,7 @@ TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex
-TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const VFTableShapeRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
 
   ArrayRef<VFTableSlotKind> Slots = Record.getSlots();
@@ -189,8 +187,7 @@ TypeTableBuilder::writeVFTableShape(const VFTableShapeRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex
-TypeTableBuilder::writeVFTable(const VFTableRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const VFTableRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
   Builder.writeTypeIndex(Record.getCompleteClass());
   Builder.writeTypeIndex(Record.getOverriddenVTable());
@@ -209,15 +206,14 @@ TypeTableBuilder::writeVFTable(const VFTableRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeStringId(const StringIdRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const StringIdRecord &Record) {
   TypeRecordBuilder Builder(TypeRecordKind::StringId);
   Builder.writeTypeIndex(Record.getId());
   Builder.writeNullTerminatedString(Record.getString());
   return writeRecord(Builder);
 }
 
-TypeIndex
-TypeTableBuilder::writeUdtSourceLine(const UdtSourceLineRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const UdtSourceLineRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
   Builder.writeTypeIndex(Record.getUDT());
   Builder.writeTypeIndex(Record.getSourceFile());
@@ -226,7 +222,7 @@ TypeTableBuilder::writeUdtSourceLine(const UdtSourceLineRecord &Record) {
 }
 
 TypeIndex
-TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) {
+TypeTableBuilder::writeKnownType(const UdtModSourceLineRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
   Builder.writeTypeIndex(Record.getUDT());
   Builder.writeTypeIndex(Record.getSourceFile());
@@ -235,7 +231,7 @@ TypeTableBuilder::writeUdtModSourceLine(const UdtModSourceLineRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeFuncId(const FuncIdRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const FuncIdRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
   Builder.writeTypeIndex(Record.getParentScope());
   Builder.writeTypeIndex(Record.getFunctionType());
@@ -243,8 +239,7 @@ TypeIndex TypeTableBuilder::writeFuncId(const FuncIdRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex
-TypeTableBuilder::writeMemberFuncId(const MemberFuncIdRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const MemberFuncIdRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
   Builder.writeTypeIndex(Record.getClassType());
   Builder.writeTypeIndex(Record.getFunctionType());
@@ -252,8 +247,7 @@ TypeTableBuilder::writeMemberFuncId(const MemberFuncIdRecord &Record) {
   return writeRecord(Builder);
 }
 
-TypeIndex
-TypeTableBuilder::writeBuildInfo(const BuildInfoRecord &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const BuildInfoRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
   assert(Record.getArgs().size() <= UINT16_MAX);
   Builder.writeUInt16(Record.getArgs().size());
@@ -270,8 +264,8 @@ TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
   return FieldList.writeListRecord(*this);
 }
 
-TypeIndex TypeTableBuilder::writeMethodOverloadList(
-    const MethodOverloadListRecord &Record) {
+TypeIndex
+TypeTableBuilder::writeKnownType(const MethodOverloadListRecord &Record) {
   TypeRecordBuilder Builder(Record.getKind());
   for (const OneMethodRecord &Method : Record.getMethods()) {
     uint16_t Flags = static_cast<uint16_t>(Method.getAccess());
@@ -294,7 +288,7 @@ TypeIndex TypeTableBuilder::writeMethodOverloadList(
   return writeRecord(Builder);
 }
 
-TypeIndex TypeTableBuilder::writeTypeServer2(const TypeServer2Record &Record) {
+TypeIndex TypeTableBuilder::writeKnownType(const TypeServer2Record &Record) {
   TypeRecordBuilder Builder(Record.getKind());
   Builder.writeGuid(Record.getGuid());
   Builder.writeUInt32(Record.getAge());
index 1398628..424ef0e 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
@@ -96,17 +97,28 @@ public:
                   uint32_t NumHashBuckets)
       : HashValues(HashValues), NumHashBuckets(NumHashBuckets) {}
 
-  Error visitUdtSourceLine(UdtSourceLineRecord &Rec) override {
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                         UdtSourceLineRecord &Rec) override {
     return verifySourceLine(Rec);
   }
 
-  Error visitUdtModSourceLine(UdtModSourceLineRecord &Rec) override {
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                         UdtModSourceLineRecord &Rec) override {
     return verifySourceLine(Rec);
   }
 
-  Error visitClass(ClassRecord &Rec) override { return verify(Rec); }
-  Error visitEnum(EnumRecord &Rec) override { return verify(Rec); }
-  Error visitUnion(UnionRecord &Rec) override { return verify(Rec); }
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                         ClassRecord &Rec) override {
+    return verify(Rec);
+  }
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                         EnumRecord &Rec) override {
+    return verify(Rec);
+  }
+  Error visitKnownRecord(const CVRecord<TypeLeafKind> &CVR,
+                         UnionRecord &Rec) override {
+    return verify(Rec);
+  }
 
   Error visitTypeBegin(const CVRecord<TypeLeafKind> &Rec) override {
     ++Index;
@@ -148,7 +160,8 @@ private:
 // Currently we only verify SRC_LINE records.
 Error TpiStream::verifyHashValues() {
   TpiHashVerifier Verifier(HashValues, Header->NumHashBuckets);
-  CVTypeVisitor Visitor(Verifier);
+  TypeDeserializer Deserializer(Verifier);
+  CVTypeVisitor Visitor(Deserializer);
   return Visitor.visitTypeStream(TypeRecords);
 }
 
index b4e5ea7..1eff236 100644 (file)
@@ -83,7 +83,7 @@ static void printSectionOffset(llvm::raw_ostream &OS,
 }
 
 LLVMOutputStyle::LLVMOutputStyle(PDBFile &File)
-    : File(File), P(outs()), TD(&P, false) {}
+    : File(File), P(outs()), Dumper(&P, false) {}
 
 Error LLVMOutputStyle::dump() {
   if (auto EC = dumpFileHeaders())
@@ -482,7 +482,7 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
       DictScope DD(P, "");
 
       if (DumpRecords) {
-        if (auto EC = TD.dump(Type))
+        if (auto EC = Dumper.dump(Type))
           return EC;
       }
 
@@ -498,16 +498,16 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
     // iterate them in order to build the list of types so that we can print
     // them when dumping module symbols. So when they want to dump symbols
     // but not types, use a null output stream.
-    ScopedPrinter *OldP = TD.getPrinter();
-    TD.setPrinter(nullptr);
+    ScopedPrinter *OldP = Dumper.getPrinter();
+    Dumper.setPrinter(nullptr);
 
     bool HadError = false;
     for (auto &Type : Tpi->types(&HadError)) {
-      if (auto EC = TD.dump(Type))
+      if (auto EC = Dumper.dump(Type))
         return EC;
     }
 
-    TD.setPrinter(OldP);
+    Dumper.setPrinter(OldP);
     dumpTpiHash(P, *Tpi);
     if (HadError)
       return make_error<RawError>(raw_error_code::corrupt_file,
@@ -586,7 +586,7 @@ Error LLVMOutputStyle::dumpDbiStream() {
 
         if (ShouldDumpSymbols) {
           ListScope SS(P, "Symbols");
-          codeview::CVSymbolDumper SD(P, TD, nullptr, false);
+          codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
           bool HadError = false;
           for (const auto &S : ModS.symbols(&HadError)) {
             DictScope DD(P, "");
@@ -796,7 +796,7 @@ Error LLVMOutputStyle::dumpPublicsStream() {
   P.printList("Section Offsets", Publics->getSectionOffsets(),
               printSectionOffset);
   ListScope L(P, "Symbols");
-  codeview::CVSymbolDumper SD(P, TD, nullptr, false);
+  codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
   bool HadError = false;
   for (auto S : Publics->getSymbols(&HadError)) {
     DictScope DD(P, "");
index ff0e492..be6b12f 100644 (file)
@@ -46,7 +46,7 @@ private:
 
   PDBFile &File;
   ScopedPrinter P;
-  codeview::CVTypeDumper TD;
+  codeview::CVTypeDumper Dumper;
 };
 }
 }
index 7ccc2c7..14178b9 100644 (file)
@@ -272,18 +272,16 @@ LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg) {
   exit(1);
 }
 
-void error(llvm::Error EC) {
+void error(Error EC) {
   if (!EC)
     return;
-
   handleAllErrors(std::move(EC),
-                  [&](ErrorInfoBase &EI) { reportError(EI.message()); });
+                  [&](const ErrorInfoBase &EI) { reportError(EI.message()); });
 }
 
 void error(std::error_code EC) {
   if (!EC)
     return;
-
   reportError(EC.message());
 }
 
index 862fd13..0156920 100644 (file)
@@ -23,7 +23,7 @@ namespace llvm {
 
   // Various helper functions.
   LLVM_ATTRIBUTE_NORETURN void reportError(Twine Msg);
-  void error(std::error_code ec);
+  void error(std::error_code EC);
   void error(llvm::Error EC);
   template <class T> T unwrapOrError(ErrorOr<T> EO) {
     if (EO)