[llvm] r277871 - [CodeView] Decouple record deserialization from visitor dispatch.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 5 14:45:34 PDT 2016


Author: zturner
Date: Fri Aug  5 16:45:34 2016
New Revision: 277871

URL: http://llvm.org/viewvc/llvm-project?rev=277871&view=rev
Log:
[CodeView] Decouple record deserialization from visitor dispatch.

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

Added:
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
    llvm/trunk/lib/DebugInfo/CodeView/TypeDeserializer.cpp
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewError.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
    llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
    llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
    llvm/trunk/lib/DebugInfo/CodeView/CodeViewError.cpp
    llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
    llvm/trunk/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeRecord.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
    llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
    llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
    llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h
    llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
    llvm/trunk/tools/llvm-readobj/llvm-readobj.h

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h Fri Aug  5 16:45:34 2016
@@ -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;

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CodeView.h Fri Aug  5 16:45:34 2016
@@ -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

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewError.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewError.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewError.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewError.h Fri Aug  5 16:45:34 2016
@@ -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

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/FieldListRecordBuilder.h Fri Aug  5 16:45:34 2016
@@ -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;
 };
 }
 }

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/ListRecordBuilder.h Fri Aug  5 16:45:34 2016
@@ -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);

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/RecordSerialization.h Fri Aug  5 16:45:34 2016
@@ -44,7 +44,7 @@ inline Error consumeObject(U &Data, cons
   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_
 
   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_
       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();

Added: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDeserializer.h?rev=277871&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDeserializer.h (added)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDeserializer.h Fri Aug  5 16:45:34 2016
@@ -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

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDumper.h Fri Aug  5 16:45:34 2016
@@ -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)

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecord.h Fri Aug  5 16:45:34 2016
@@ -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) {}

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeRecords.def Fri Aug  5 16:45:34 2016
@@ -43,6 +43,8 @@ TYPE_RECORD(LF_PROCEDURE, 0x1008, Proced
 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)

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h Fri Aug  5 16:45:34 2016
@@ -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);
 

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h Fri Aug  5 16:45:34 2016
@@ -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)

Modified: llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp Fri Aug  5 16:45:34 2016
@@ -212,7 +212,7 @@ TypeIndex CodeViewDebug::getScopeIndex(c
   // 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::getFuncIdForSub
     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(
     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::lowerTypePointe
   // 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::lowerTypeMember
   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::lowerTypeModifi
     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::lowerTypeFuncti
   }
 
   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::lowerTypeMember
   }
 
   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(c
       // 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(c
 
   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(
   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::lowerCompleteTy
 
   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(
   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::lowerCompleteTy
   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(cons
       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(cons
         translateAccessFlags(Ty->getTag(), Member->getFlags());
 
     if (Member->isStaticMember()) {
-      Fields.writeStaticDataMember(
+      Fields.writeMemberType(
           StaticDataMemberRecord(Access, MemberBaseType, MemberName));
       MemberCount++;
       continue;
@@ -1672,11 +1671,11 @@ CodeViewDebug::lowerRecordFieldList(cons
         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(cons
     }
     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(cons
   // 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;

Modified: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt Fri Aug  5 16:45:34 2016
@@ -11,6 +11,7 @@ add_llvm_library(LLVMDebugInfoCodeView
   ModuleSubstreamVisitor.cpp
   RecordSerialization.cpp
   SymbolDumper.cpp
+  TypeDeserializer.cpp
   TypeDumper.cpp
   TypeRecord.cpp
   TypeRecordBuilder.cpp

Modified: llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CVTypeVisitor.cpp Fri Aug  5 16:45:34 2016
@@ -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(con
 #define MEMBER_RECORD(EnumName, EnumVal, Name)
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
   }
+
   if (auto EC = Callbacks.visitTypeEnd(Record))
     return EC;
+
   return Error::success();
 }
 
@@ -69,56 +63,4 @@ Error CVTypeVisitor::visitTypeStream(con
       return EC;
   }
   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();
 }

Modified: llvm/trunk/lib/DebugInfo/CodeView/CodeViewError.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CodeViewError.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CodeViewError.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CodeViewError.cpp Fri Aug  5 16:45:34 2016
@@ -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");
   }

Modified: llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp Fri Aug  5 16:45:34 2016
@@ -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::writeBaseCl
   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::writeEnumer
   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::writeDataMe
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeOverloadedMethod(
+void FieldListRecordBuilder::writeMemberType(
     const OverloadedMethodRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
@@ -62,7 +62,7 @@ void FieldListRecordBuilder::writeOverlo
   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::writeOneMet
   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::writeNested
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeStaticDataMember(
+void FieldListRecordBuilder::writeMemberType(
     const StaticDataMemberRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
@@ -107,7 +107,7 @@ void FieldListRecordBuilder::writeStatic
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeVirtualBaseClass(
+void FieldListRecordBuilder::writeMemberType(
     const VirtualBaseClassRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
@@ -121,7 +121,7 @@ void FieldListRecordBuilder::writeVirtua
   finishSubRecord();
 }
 
-void FieldListRecordBuilder::writeVFPtr(const VFPtrRecord &Record) {
+void FieldListRecordBuilder::writeMemberType(const VFPtrRecord &Record) {
   TypeRecordBuilder &Builder = getBuilder();
 
   Builder.writeTypeRecordKind(TypeRecordKind::VFPtr);

Modified: llvm/trunk/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/ListRecordBuilder.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/ListRecordBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/ListRecordBuilder.cpp Fri Aug  5 16:45:34 2016
@@ -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");

Added: llvm/trunk/lib/DebugInfo/CodeView/TypeDeserializer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDeserializer.cpp?rev=277871&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDeserializer.cpp (added)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDeserializer.cpp Fri Aug  5 16:45:34 2016
@@ -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();
+}

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDumper.cpp Fri Aug  5 16:45:34 2016
@@ -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(TypeLea
   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 C
   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(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(ArgList
   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(ClassReco
   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(UnionReco
   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
   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(ArrayReco
   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(VFTable
   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(Me
   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(Proce
   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(
   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::visitMethodOverloadL
   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(FuncIdRe
   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(Typ
   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(Pointer
   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(Modifi
   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::visitUdtModSourceLin
   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(con
   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(Nest
   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(OneMe
   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::visitOverloadedMetho
   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(Data
   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::visitStaticDataMembe
   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(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(BaseC
   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::visitVirtualBaseClas
   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(String
 
 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<
 
 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();

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeRecord.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeRecord.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeRecord.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeRecord.cpp Fri Aug  5 16:45:34 2016
@@ -114,6 +114,11 @@ NestedTypeRecord::deserialize(TypeRecord
   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;

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp Fri Aug  5 16:45:34 2016
@@ -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
 
 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;

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeTableBuilder.cpp Fri Aug  5 16:45:34 2016
@@ -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::writeModifie
   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::writeProcedu
   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(co
   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
   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
   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(c
   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(c
   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(c
   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(co
   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::writeBitFiel
   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(cons
   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 VFT
   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(con
 }
 
 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(
   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(
   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(cons
   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::writeFieldLi
   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::writeMethodO
   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());

Modified: llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp (original)
+++ llvm/trunk/lib/DebugInfo/PDB/Raw/TpiStream.cpp Fri Aug  5 16:45:34 2016
@@ -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);
 }
 

Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.cpp Fri Aug  5 16:45:34 2016
@@ -83,7 +83,7 @@ static void printSectionOffset(llvm::raw
 }
 
 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(uin
       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(uin
     // 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, "");

Modified: llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h (original)
+++ llvm/trunk/tools/llvm-pdbdump/LLVMOutputStyle.h Fri Aug  5 16:45:34 2016
@@ -46,7 +46,7 @@ private:
 
   PDBFile &File;
   ScopedPrinter P;
-  codeview::CVTypeDumper TD;
+  codeview::CVTypeDumper Dumper;
 };
 }
 }

Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp Fri Aug  5 16:45:34 2016
@@ -272,18 +272,16 @@ LLVM_ATTRIBUTE_NORETURN void reportError
   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());
 }
 

Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.h?rev=277871&r1=277870&r2=277871&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.h (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.h Fri Aug  5 16:45:34 2016
@@ -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)




More information about the llvm-commits mailing list