[pdb] Get rid of Data and RawData in CVType.

The `CVType` had two redundant fields which were confusing and
error-prone to fill out.  By treating member records as a distinct
type from leaf records, we are able to simplify this quite a bit.

Reviewed By: rnk
Differential Revision: https://reviews.llvm.org/D24432

llvm-svn: 281556
diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
index cdcc837..deefa8d 100644
--- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
+++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp
@@ -42,8 +42,8 @@
 }
 
 template <typename T>
-static Expected<CVType> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
-                                                TypeLeafKind Kind) {
+static Expected<CVMemberRecord> deserializeMemberRecord(ArrayRef<uint8_t> &Data,
+                                                        TypeLeafKind Kind) {
   ArrayRef<uint8_t> OldData = Data;
   TypeRecordKind RK = static_cast<TypeRecordKind>(Kind);
   auto ExpectedRecord = T::deserialize(RK, Data);
@@ -53,20 +53,17 @@
   if (auto EC = skipPadding(Data))
     return std::move(EC);
 
-  CVType CVR;
-  CVR.Type = Kind;
-  CVR.Length = OldData.size() - Data.size();
-  CVR.Data = OldData.slice(0, CVR.Length);
-  CVR.RawData = CVR.Data;
-  return CVR;
+  CVMemberRecord CVMR;
+  CVMR.Kind = Kind;
+  CVMR.Data = OldData.drop_back(Data.size());
+  return CVMR;
 }
 
 CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks)
     : Callbacks(Callbacks) {}
 
 template <typename T>
-static Error visitKnownRecord(CVRecord<TypeLeafKind> &Record,
-                              TypeVisitorCallbacks &Callbacks) {
+static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) {
   TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Type);
   T KnownRecord(RK);
   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
@@ -74,7 +71,17 @@
   return Error::success();
 }
 
-Error CVTypeVisitor::visitTypeRecord(CVRecord<TypeLeafKind> &Record) {
+template <typename T>
+static Error visitKnownMember(CVMemberRecord &Record,
+                              TypeVisitorCallbacks &Callbacks) {
+  TypeRecordKind RK = static_cast<TypeRecordKind>(Record.Kind);
+  T KnownRecord(RK);
+  if (auto EC = Callbacks.visitKnownMember(Record, KnownRecord))
+    return EC;
+  return Error::success();
+}
+
+Error CVTypeVisitor::visitTypeRecord(CVType &Record) {
   if (auto EC = Callbacks.visitTypeBegin(Record))
     return EC;
 
@@ -91,10 +98,8 @@
   }
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                  \
   TYPE_RECORD(EnumVal, EnumVal, AliasName)
-#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  TYPE_RECORD(EnumName, EnumVal, Name)
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
-  MEMBER_RECORD(EnumName, EnumVal, AliasName)
+#define MEMBER_RECORD(EnumName, EnumVal, Name)
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
   }
 
@@ -104,6 +109,34 @@
   return Error::success();
 }
 
+Error CVTypeVisitor::visitMemberRecord(CVMemberRecord &Record) {
+  if (auto EC = Callbacks.visitMemberBegin(Record))
+    return EC;
+
+  switch (Record.Kind) {
+  default:
+    if (auto EC = Callbacks.visitUnknownMember(Record))
+      return EC;
+    break;
+#define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
+  case EnumName: {                                                             \
+    if (auto EC = visitKnownMember<Name##Record>(Record, Callbacks))           \
+      return EC;                                                               \
+    break;                                                                     \
+  }
+#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
+  MEMBER_RECORD(EnumVal, EnumVal, AliasName)
+#define TYPE_RECORD(EnumName, EnumVal, Name)
+#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+  }
+
+  if (auto EC = Callbacks.visitMemberEnd(Record))
+    return EC;
+
+  return Error::success();
+}
+
 /// Visits the type records in Data. Sets the error flag on parse failures.
 Error CVTypeVisitor::visitTypeStream(const CVTypeArray &Types) {
   for (auto I : Types) {
@@ -119,12 +152,12 @@
   auto ExpectedRecord = deserializeMemberRecord<MR>(Data, Leaf);
   if (!ExpectedRecord)
     return ExpectedRecord.takeError();
-  CVType &Record = *ExpectedRecord;
-  if (auto EC = Callbacks.visitTypeBegin(Record))
+  CVMemberRecord &Record = *ExpectedRecord;
+  if (auto EC = Callbacks.visitMemberBegin(Record))
     return EC;
-  if (auto EC = visitKnownRecord<MR>(Record, Callbacks))
+  if (auto EC = visitKnownMember<MR>(Record, Callbacks))
     return EC;
-  if (auto EC = Callbacks.visitTypeEnd(Record))
+  if (auto EC = Callbacks.visitMemberEnd(Record))
     return EC;
   return Error::success();
 }
diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
index db805c5..1e7af16 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp
@@ -204,15 +204,12 @@
 }
 
 Error CVTypeDumper::visitTypeBegin(CVRecord<TypeLeafKind> &Record) {
+  assert(!IsInFieldList);
   // Reset Name to the empty string. If the visitor sets it, we know it.
   Name = "";
 
   W->startLine() << getLeafTypeName(Record.Type);
-  if (!IsInFieldList) {
-    // If this is a field list member, don't record its type index because it
-    // doesn't have one.  Only the outer field list has a type index.
-    W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")";
-  }
+  W->getOStream() << " (" << HexNumber(getNextTypeIndex()) << ")";
   W->getOStream() << " {\n";
   W->indent();
   W->printEnum("TypeLeafKind", unsigned(Record.Type),
@@ -220,7 +217,6 @@
   if (Record.Type == LF_FIELDLIST) {
     // Record that we're in a field list so that members do not get assigned
     // type indices.
-    assert(!IsInFieldList);
     IsInFieldList = true;
   }
   return Error::success();
@@ -231,16 +227,38 @@
     assert(IsInFieldList);
     IsInFieldList = false;
   }
+  assert(!IsInFieldList);
 
-  if (!IsInFieldList) {
-    // Record every type that is not a field list member, even if Name is empty.
-    // CVUDTNames is indexed by type index, and must have one entry for every
-    // type.  Field list members are not recorded, and are only referenced by
-    // their containing field list record.
-    recordType(Name);
-  }
+  // Record every type that is not a field list member, even if Name is empty.
+  // CVUDTNames is indexed by type index, and must have one entry for every
+  // type.  Field list members are not recorded, and are only referenced by
+  // their containing field list record.
+  recordType(Name);
 
   if (PrintRecordBytes)
+    W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.content()));
+
+  W->unindent();
+  W->startLine() << "}\n";
+  return Error::success();
+}
+
+Error CVTypeDumper::visitMemberBegin(CVMemberRecord &Record) {
+  assert(IsInFieldList);
+  // Reset Name to the empty string. If the visitor sets it, we know it.
+  Name = "";
+
+  W->startLine() << getLeafTypeName(Record.Kind);
+  W->getOStream() << " {\n";
+  W->indent();
+  W->printEnum("TypeLeafKind", unsigned(Record.Kind),
+               makeArrayRef(LeafTypeNames));
+  return Error::success();
+}
+
+Error CVTypeDumper::visitMemberEnd(CVMemberRecord &Record) {
+  assert(IsInFieldList);
+  if (PrintRecordBytes)
     W->printBinaryBlock("LeafData", getBytesAsCharacters(Record.Data));
 
   W->unindent();
@@ -573,18 +591,18 @@
   }
 }
 
-Error CVTypeDumper::visitUnknownMember(CVRecord<TypeLeafKind> &Record) {
-  W->printHex("UnknownMember", unsigned(Record.Type));
+Error CVTypeDumper::visitUnknownMember(CVMemberRecord &Record) {
+  W->printHex("UnknownMember", unsigned(Record.Kind));
   return Error::success();
 }
 
 Error CVTypeDumper::visitUnknownType(CVRecord<TypeLeafKind> &Record) {
-  W->printEnum("Kind", uint16_t(Record.Type), makeArrayRef(LeafTypeNames));
-  W->printNumber("Length", uint32_t(Record.Data.size()));
+  W->printEnum("Kind", uint16_t(Record.kind()), makeArrayRef(LeafTypeNames));
+  W->printNumber("Length", uint32_t(Record.content().size()));
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      NestedTypeRecord &Nested) {
   printTypeIndex("Type", Nested.getNestedType());
   W->printString("Name", Nested.getName());
@@ -592,7 +610,7 @@
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      OneMethodRecord &Method) {
   MethodKind K = Method.getKind();
   printMemberAttributes(Method.getAccess(), K, Method.getOptions());
@@ -605,7 +623,7 @@
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      OverloadedMethodRecord &Method) {
   W->printHex("MethodCount", Method.getNumOverloads());
   printTypeIndex("MethodListIndex", Method.getMethodList());
@@ -614,7 +632,7 @@
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      DataMemberRecord &Field) {
   printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -625,7 +643,7 @@
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      StaticDataMemberRecord &Field) {
   printMemberAttributes(Field.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -635,13 +653,13 @@
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      VFPtrRecord &VFTable) {
   printTypeIndex("Type", VFTable.getType());
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      EnumeratorRecord &Enum) {
   printMemberAttributes(Enum.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -651,7 +669,7 @@
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      BaseClassRecord &Base) {
   printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -660,7 +678,7 @@
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      VirtualBaseClassRecord &Base) {
   printMemberAttributes(Base.getAccess(), MethodKind::Vanilla,
                         MethodOptions::None);
@@ -671,7 +689,7 @@
   return Error::success();
 }
 
-Error CVTypeDumper::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
+Error CVTypeDumper::visitKnownMember(CVMemberRecord &CVR,
                                      ListContinuationRecord &Cont) {
   printTypeIndex("ContinuationIndex", Cont.getContinuationIndex());
   return Error::success();
diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
index 096fd38..acd7f74 100644
--- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
+++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp
@@ -60,18 +60,18 @@
 
 /// TypeVisitorCallbacks overrides.
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error visitKnownRecord(CVRecord<TypeLeafKind> &CVR, Name##Record &Record)    \
-      override;
+  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  TYPE_RECORD(EnumName, EnumVal, Name)
+  Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override;
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
 
-  Error visitUnknownType(CVRecord<TypeLeafKind> &Record) override;
+  Error visitUnknownType(CVType &Record) override;
 
-  Error visitTypeBegin(CVRecord<TypeLeafKind> &Record) override;
-  Error visitTypeEnd(CVRecord<TypeLeafKind> &Record) override;
+  Error visitTypeBegin(CVType &Record) override;
+  Error visitTypeEnd(CVType &Record) override;
+  Error visitMemberEnd(CVMemberRecord &Record) override;
 
   bool mergeStream(const CVTypeArray &Types);
 
@@ -137,27 +137,30 @@
     IndexMap.push_back(DestStream.writeFieldList(FieldBuilder));
     FieldBuilder.reset();
     IsInFieldList = false;
-  } else if (!IsInFieldList) {
-    assert(IndexMap.size() == BeginIndexMapSize + 1);
   }
   return Error::success();
 }
 
+Error TypeStreamMerger::visitMemberEnd(CVMemberRecord &Rec) {
+  assert(IndexMap.size() == BeginIndexMapSize + 1);
+  return Error::success();
+}
+
 #define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error TypeStreamMerger::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,        \
+  Error TypeStreamMerger::visitKnownRecord(CVType &CVR,                        \
                                            Name##Record &Record) {             \
     return visitKnownRecordImpl(Record);                                       \
   }
 #define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #define MEMBER_RECORD(EnumName, EnumVal, Name)                                 \
-  Error TypeStreamMerger::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,        \
+  Error TypeStreamMerger::visitKnownMember(CVMemberRecord &CVR,                \
                                            Name##Record &Record) {             \
     return visitKnownMemberRecordImpl(Record);                                 \
   }
 #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #include "llvm/DebugInfo/CodeView/TypeRecords.def"
 
-Error TypeStreamMerger::visitUnknownType(CVRecord<TypeLeafKind> &Rec) {
+Error TypeStreamMerger::visitUnknownType(CVType &Rec) {
   // We failed to translate a type. Translate this index as "not translated".
   IndexMap.push_back(
       TypeIndex(SimpleTypeKind::NotTranslated, SimpleTypeMode::Direct));
diff --git a/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp b/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp
index d08ec96..6c3ddb3 100644
--- a/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp
+++ b/llvm/lib/DebugInfo/PDB/Raw/TpiHashing.cpp
@@ -58,15 +58,15 @@
 }
 
 void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, ClassRecord &Rec) {
-  CVR.Hash = getTpiHash(Rec, CVR.RawData);
+  CVR.Hash = getTpiHash(Rec, CVR.data());
 }
 
 void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, EnumRecord &Rec) {
-  CVR.Hash = getTpiHash(Rec, CVR.RawData);
+  CVR.Hash = getTpiHash(Rec, CVR.data());
 }
 
 void TpiHashUpdater::visitKnownRecordImpl(CVType &CVR, UnionRecord &Rec) {
-  CVR.Hash = getTpiHash(Rec, CVR.RawData);
+  CVR.Hash = getTpiHash(Rec, CVR.data());
 }
 
 Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UdtSourceLineRecord &Rec) {
@@ -79,17 +79,17 @@
 }
 
 Error TpiHashVerifier::visitKnownRecord(CVType &CVR, ClassRecord &Rec) {
-  if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
+  if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
     return errorInvalidHash();
   return Error::success();
 }
 Error TpiHashVerifier::visitKnownRecord(CVType &CVR, EnumRecord &Rec) {
-  if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
+  if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
     return errorInvalidHash();
   return Error::success();
 }
 Error TpiHashVerifier::visitKnownRecord(CVType &CVR, UnionRecord &Rec) {
-  if (getTpiHash(Rec, CVR.RawData) % NumHashBuckets != HashValues[Index])
+  if (getTpiHash(Rec, CVR.data()) % NumHashBuckets != HashValues[Index])
     return errorInvalidHash();
   return Error::success();
 }