[llvm] r305653 - Delete TypeDatabase.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 18 13:52:46 PDT 2017


Author: zturner
Date: Sun Jun 18 15:52:45 2017
New Revision: 305653

URL: http://llvm.org/viewvc/llvm-project?rev=305653&view=rev
Log:
Delete TypeDatabase.

Merge the functionality into the random access type collection.
This class was only being used in 2 places, so getting rid of it
simplifies the code.

Removed:
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h
    llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp
Modified:
    llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
    llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
    llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
    llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp
    llvm/trunk/lib/DebugInfo/CodeView/TypeTableCollection.cpp
    llvm/trunk/tools/llvm-readobj/COFFDumper.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h?rev=305653&r1=305652&r2=305653&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/CVRecord.h Sun Jun 18 15:52:45 2017
@@ -27,9 +27,12 @@ namespace codeview {
 
 template <typename Kind> class CVRecord {
 public:
-  CVRecord() = default;
+  CVRecord() : Type(static_cast<Kind>(0)) {}
+
   CVRecord(Kind K, ArrayRef<uint8_t> Data) : Type(K), RecordData(Data) {}
 
+  bool valid() const { return Type != static_cast<Kind>(0); }
+
   uint32_t length() const { return RecordData.size(); }
   Kind kind() const { return Type; }
   ArrayRef<uint8_t> data() const { return RecordData; }

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h?rev=305653&r1=305652&r2=305653&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h Sun Jun 18 15:52:45 2017
@@ -11,18 +11,15 @@
 #define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H
 
 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/Support/Allocator.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/StringSaver.h"
 
 namespace llvm {
 namespace codeview {
 
-class TypeDatabase;
-class TypeVisitorCallbacks;
-
 /// \brief Provides amortized O(1) random access to a CodeView type stream.
 /// Normally to access a type from a type stream, you must know its byte
 /// offset into the type stream, because type records are variable-lengthed.
@@ -47,6 +44,11 @@ class TypeVisitorCallbacks;
 /// of O(N/M) and an amortized time of O(1).
 class LazyRandomTypeCollection : public TypeCollection {
   typedef FixedStreamArray<TypeIndexOffset> PartialOffsetArray;
+  struct CacheEntry {
+    CVType Type;
+    uint32_t Offset;
+    StringRef Name;
+  };
 
 public:
   explicit LazyRandomTypeCollection(uint32_t RecordCountHint);
@@ -56,8 +58,8 @@ public:
                            PartialOffsetArray PartialOffsets);
   LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint);
 
-  void reset(ArrayRef<uint8_t> Data);
-  void reset(StringRef Data);
+  void reset(ArrayRef<uint8_t> Data, uint32_t RecordCountHint);
+  void reset(StringRef Data, uint32_t RecordCountHint);
 
   CVType getType(TypeIndex Index) override;
   StringRef getTypeName(TypeIndex Index) override;
@@ -68,32 +70,26 @@ public:
   Optional<TypeIndex> getNext(TypeIndex Prev) override;
 
 private:
-  const TypeDatabase &database() const { return Database; }
   Error ensureTypeExists(TypeIndex Index);
+  void ensureCapacityFor(TypeIndex Index);
 
   Error visitRangeForType(TypeIndex TI);
   Error fullScanForType(TypeIndex TI);
-  Error visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
-  Error visitOneRecord(TypeIndex TI, uint32_t Offset, CVType &Record);
+  void visitRange(TypeIndex Begin, uint32_t BeginOffset, TypeIndex End);
 
-  BumpPtrAllocator Allocator;
-  StringSaver NameStorage;
+  /// Number of actual records.
+  uint32_t Count = 0;
 
-  SmallVector<StringRef, 10> TypeNames;
+  /// The largest type index which we've visited.
+  TypeIndex LargestTypeIndex = TypeIndex::None();
 
-  /// Visited records get automatically added to the type database.
-  TypeDatabase Database;
+  BumpPtrAllocator Allocator;
+  StringSaver NameStorage;
 
   /// The type array to allow random access visitation of.
   CVTypeArray Types;
 
-  /// The database visitor which adds new records to the database.
-  TypeDatabaseVisitor DatabaseVisitor;
-
-  /// A vector mapping type indices to type offset.  For every record that has
-  /// been visited, contains the absolute offset of that record in the record
-  /// array.
-  std::vector<uint32_t> KnownOffsets;
+  std::vector<CacheEntry> Records;
 
   /// An array of index offsets for the given type stream, allowing log(N)
   /// lookups of a type record by index.  Similar to KnownOffsets but only

Removed: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h?rev=305652&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabase.h (removed)
@@ -1,84 +0,0 @@
-//===- TypeDatabase.h - A collection of CodeView type records ---*- 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_TYPEDATABASE_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASE_H
-
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/CodeView/TypeCollection.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/StringSaver.h"
-
-namespace llvm {
-namespace codeview {
-class TypeDatabase : public TypeCollection {
-  friend class RandomAccessTypeVisitor;
-
-public:
-  explicit TypeDatabase(uint32_t Capacity);
-
-  /// Records the name of a type, and reserves its type index.
-  TypeIndex appendType(StringRef Name, const CVType &Data);
-
-  /// Records the name of a type, and reserves its type index.
-  void recordType(StringRef Name, TypeIndex Index, const CVType &Data);
-
-  /// Saves the name in a StringSet and creates a stable StringRef.
-  StringRef saveTypeName(StringRef TypeName);
-
-  StringRef getTypeName(TypeIndex Index) const;
-
-  const CVType &getTypeRecord(TypeIndex Index) const;
-  CVType &getTypeRecord(TypeIndex Index);
-
-  bool contains(TypeIndex Index) const;
-  uint32_t size() const;
-  uint32_t capacity() const;
-  bool empty() const;
-
-  CVType getType(TypeIndex Index) override;
-  StringRef getTypeName(TypeIndex Index) override;
-  bool contains(TypeIndex Index) override;
-  uint32_t size() override;
-  uint32_t capacity() override;
-
-  Optional<TypeIndex> getFirst() override;
-  Optional<TypeIndex> getNext(TypeIndex Prev) override;
-
-  Optional<TypeIndex> largestTypeIndexLessThan(TypeIndex TI) const;
-
-private:
-  TypeIndex getAppendIndex() const;
-
-  void grow();
-  void grow(TypeIndex Index);
-
-  BumpPtrAllocator Allocator;
-
-  uint32_t Count = 0;
-  TypeIndex LargestTypeIndex;
-
-  /// All user defined type records in .debug$T live in here. Type indices
-  /// greater than 0x1000 are user defined. Subtract 0x1000 from the index to
-  /// index into this vector.
-  SmallVector<StringRef, 10> CVUDTNames;
-  SmallVector<CVType, 10> TypeRecords;
-
-  StringSaver TypeNameStorage;
-
-  BitVector ValidRecords;
-};
-}
-}
-
-#endif
\ No newline at end of file

Removed: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h?rev=305652&view=auto
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h (removed)
@@ -1,62 +0,0 @@
-//===-- TypeDatabaseVisitor.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_TYPEDATABASEVISITOR_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPEDATABASEVISITOR_H
-
-#include "llvm/ADT/PointerUnion.h"
-
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-
-namespace llvm {
-namespace codeview {
-
-/// Dumper for CodeView type streams found in COFF object files and PDB files.
-class TypeDatabaseVisitor : public TypeVisitorCallbacks {
-public:
-  explicit TypeDatabaseVisitor(TypeDatabase &TypeDB) : TypeDB(&TypeDB) {}
-
-  /// Paired begin/end actions for all types. Receives all record data,
-  /// including the fixed-length record prefix.
-  Error visitTypeBegin(CVType &Record) override;
-  Error visitTypeBegin(CVType &Record, TypeIndex Index) override;
-  Error visitTypeEnd(CVType &Record) override;
-  Error visitMemberBegin(CVMemberRecord &Record) override;
-  Error visitMemberEnd(CVMemberRecord &Record) override;
-
-#define TYPE_RECORD(EnumName, EnumVal, Name)                                   \
-  Error visitKnownRecord(CVType &CVR, Name##Record &Record) override;
-#define MEMBER_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/CodeViewTypes.def"
-
-private:
-  StringRef getTypeName(TypeIndex Index) const;
-  StringRef saveTypeName(StringRef Name);
-
-  bool IsInFieldList = false;
-
-  /// Name of the current type. Only valid before visitTypeEnd.
-  StringRef Name;
-  /// Current type index.  Only valid before visitTypeEnd, and if we are
-  /// visiting a random access type database.
-  Optional<TypeIndex> CurrentTypeIndex;
-
-  TypeDatabase *TypeDB;
-};
-
-} // end namespace codeview
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H

Modified: llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableCollection.h?rev=305653&r1=305652&r2=305653&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableCollection.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/CodeView/TypeTableCollection.h Sun Jun 18 15:52:45 2017
@@ -11,7 +11,9 @@
 #define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H
 
 #include "llvm/DebugInfo/CodeView/TypeCollection.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/Support/StringSaver.h"
+
+#include <vector>
 
 namespace llvm {
 namespace codeview {
@@ -30,11 +32,10 @@ public:
   uint32_t capacity() override;
 
 private:
-  bool hasCapacityFor(TypeIndex Index) const;
-  void ensureTypeExists(TypeIndex Index);
-
+  BumpPtrAllocator Allocator;
+  StringSaver NameStorage;
+  std::vector<StringRef> Names;
   ArrayRef<ArrayRef<uint8_t>> Records;
-  TypeDatabase Database;
 };
 }
 }

Modified: llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt?rev=305653&r1=305652&r2=305653&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/CMakeLists.txt Sun Jun 18 15:52:45 2017
@@ -24,8 +24,6 @@ add_llvm_library(LLVMDebugInfoCodeView
   SymbolRecordMapping.cpp
   SymbolDumper.cpp
   SymbolSerializer.cpp
-  TypeDatabase.cpp
-  TypeDatabaseVisitor.cpp
   TypeDumpVisitor.cpp
   TypeIndex.cpp
   TypeIndexDiscovery.cpp

Modified: llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp?rev=305653&r1=305652&r2=305653&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp Sun Jun 18 15:52:45 2017
@@ -11,7 +11,6 @@
 
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
 #include "llvm/DebugInfo/CodeView/TypeName.h"
 #include "llvm/DebugInfo/CodeView/TypeServerHandler.h"
 #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
@@ -32,15 +31,13 @@ LazyRandomTypeCollection::LazyRandomType
 LazyRandomTypeCollection::LazyRandomTypeCollection(
     const CVTypeArray &Types, uint32_t RecordCountHint,
     PartialOffsetArray PartialOffsets)
-    : NameStorage(Allocator), Database(RecordCountHint), Types(Types),
-      DatabaseVisitor(Database), PartialOffsets(PartialOffsets) {
-  KnownOffsets.resize(Database.capacity());
+    : NameStorage(Allocator), Types(Types), PartialOffsets(PartialOffsets) {
+  Records.resize(RecordCountHint);
 }
 
 LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef<uint8_t> Data,
                                                    uint32_t RecordCountHint)
     : LazyRandomTypeCollection(RecordCountHint) {
-  reset(Data);
 }
 
 LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data,
@@ -53,22 +50,28 @@ LazyRandomTypeCollection::LazyRandomType
                                                    uint32_t NumRecords)
     : LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {}
 
-void LazyRandomTypeCollection::reset(StringRef Data) {
-  reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end()));
-}
-
-void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data) {
+void LazyRandomTypeCollection::reset(StringRef Data, uint32_t RecordCountHint) {
+  Count = 0;
   PartialOffsets = PartialOffsetArray();
 
   BinaryStreamReader Reader(Data, support::little);
   error(Reader.readArray(Types, Reader.getLength()));
 
-  KnownOffsets.resize(Database.capacity());
+  // Clear and then resize, to make sure existing data gets destroyed.
+  Records.clear();
+  Records.resize(RecordCountHint);
+}
+
+void LazyRandomTypeCollection::reset(ArrayRef<uint8_t> Data,
+                                     uint32_t RecordCountHint) {
+  reset(toStringRef(Data), RecordCountHint);
 }
 
 CVType LazyRandomTypeCollection::getType(TypeIndex Index) {
   error(ensureTypeExists(Index));
-  return Database.getTypeRecord(Index);
+  assert(contains(Index));
+
+  return Records[Index.toArrayIndex()].Type;
 }
 
 StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) {
@@ -85,30 +88,43 @@ StringRef LazyRandomTypeCollection::getT
   }
 
   uint32_t I = Index.toArrayIndex();
-  if (I >= TypeNames.size())
-    TypeNames.resize(I + 1);
-
-  if (TypeNames[I].data() == nullptr) {
+  ensureCapacityFor(Index);
+  if (Records[I].Name.data() == nullptr) {
     StringRef Result = NameStorage.save(computeTypeName(*this, Index));
-    TypeNames[I] = Result;
+    Records[I].Name = Result;
   }
-  return TypeNames[I];
+  return Records[I].Name;
 }
 
 bool LazyRandomTypeCollection::contains(TypeIndex Index) {
-  return Database.contains(Index);
+  if (Records.size() <= Index.toArrayIndex())
+    return false;
+  if (!Records[Index.toArrayIndex()].Type.valid())
+    return false;
+  return true;
 }
 
-uint32_t LazyRandomTypeCollection::size() { return Database.size(); }
+uint32_t LazyRandomTypeCollection::size() { return Count; }
 
-uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); }
+uint32_t LazyRandomTypeCollection::capacity() { return Records.size(); }
 
 Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) {
-  if (!Database.contains(TI)) {
-    if (auto EC = visitRangeForType(TI))
-      return EC;
-  }
-  return Error::success();
+  if (contains(TI))
+    return Error::success();
+
+  return visitRangeForType(TI);
+}
+
+void LazyRandomTypeCollection::ensureCapacityFor(TypeIndex Index) {
+  uint32_t MinSize = Index.toArrayIndex() + 1;
+
+  if (MinSize <= capacity())
+    return;
+
+  uint32_t NewCapacity = MinSize * 3 / 2;
+
+  assert(NewCapacity > capacity());
+  Records.resize(NewCapacity);
 }
 
 Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) {
@@ -124,7 +140,7 @@ Error LazyRandomTypeCollection::visitRan
   auto Prev = std::prev(Next);
 
   TypeIndex TIB = Prev->Type;
-  if (Database.contains(TIB)) {
+  if (contains(TIB)) {
     // They've asked us to fetch a type index, but the entry we found in the
     // partial offsets array has already been visited.  Since we visit an entire
     // block every time, that means this record should have been previously
@@ -135,13 +151,12 @@ Error LazyRandomTypeCollection::visitRan
 
   TypeIndex TIE;
   if (Next == PartialOffsets.end()) {
-    TIE = TypeIndex::fromArrayIndex(Database.capacity());
+    TIE = TypeIndex::fromArrayIndex(capacity());
   } else {
     TIE = Next->Type;
   }
 
-  if (auto EC = visitRange(TIB, Prev->Offset, TIE))
-    return EC;
+  visitRange(TIB, Prev->Offset, TIE);
   return Error::success();
 }
 
@@ -170,34 +185,31 @@ Error LazyRandomTypeCollection::fullScan
   assert(PartialOffsets.empty());
 
   TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0);
-  uint32_t Offset = 0;
   auto Begin = Types.begin();
 
-  if (!Database.empty()) {
+  if (Count > 0) {
     // In the case of type streams which we don't know the number of records of,
     // it's possible to search for a type index triggering a full scan, but then
     // later additional records are added since we didn't know how many there
     // would be until we did a full visitation, then you try to access the new
     // type triggering another full scan.  To avoid this, we assume that if the
-    // database has some records, this must be what's going on.  So we ask the
-    // database for the largest type index less than the one we're searching for
-    // and only do the forward scan from there.
-    auto Prev = Database.largestTypeIndexLessThan(TI);
-    assert(Prev.hasValue() && "Empty database with valid types?");
-    Offset = KnownOffsets[Prev->toArrayIndex()];
-    CurrentTI = *Prev;
-    ++CurrentTI;
+    // database has some records, this must be what's going on.  We can also
+    // assume that this index must be larger than the largest type index we've
+    // visited, so we start from there and scan forward.
+    uint32_t Offset = Records[LargestTypeIndex.toArrayIndex()].Offset;
+    CurrentTI = LargestTypeIndex + 1;
     Begin = Types.at(Offset);
     ++Begin;
-    Offset = Begin.offset();
   }
 
   auto End = Types.end();
   while (Begin != End) {
-    if (auto EC = visitOneRecord(CurrentTI, Offset, *Begin))
-      return EC;
-
-    Offset += Begin.getRecordLength();
+    ensureCapacityFor(CurrentTI);
+    LargestTypeIndex = std::max(LargestTypeIndex, CurrentTI);
+    auto Idx = CurrentTI.toArrayIndex();
+    Records[Idx].Type = *Begin;
+    Records[Idx].Offset = Begin.offset();
+    ++Count;
     ++Begin;
     ++CurrentTI;
   }
@@ -207,36 +219,19 @@ Error LazyRandomTypeCollection::fullScan
   return Error::success();
 }
 
-Error LazyRandomTypeCollection::visitRange(TypeIndex Begin,
-                                           uint32_t BeginOffset,
-                                           TypeIndex End) {
-
+void LazyRandomTypeCollection::visitRange(TypeIndex Begin, uint32_t BeginOffset,
+                                          TypeIndex End) {
   auto RI = Types.at(BeginOffset);
   assert(RI != Types.end());
 
+  ensureCapacityFor(End);
   while (Begin != End) {
-    if (auto EC = visitOneRecord(Begin, BeginOffset, *RI))
-      return EC;
-
-    BeginOffset += RI.getRecordLength();
+    LargestTypeIndex = std::max(LargestTypeIndex, Begin);
+    auto Idx = Begin.toArrayIndex();
+    Records[Idx].Type = *RI;
+    Records[Idx].Offset = RI.offset();
+    ++Count;
     ++Begin;
     ++RI;
   }
-
-  return Error::success();
-}
-
-Error LazyRandomTypeCollection::visitOneRecord(TypeIndex TI, uint32_t Offset,
-                                               CVType &Record) {
-  assert(!Database.contains(TI));
-  if (auto EC = codeview::visitTypeRecord(Record, TI, DatabaseVisitor))
-    return EC;
-  // Keep the KnownOffsets array the same size as the Database's capacity. Since
-  // we don't always know how many records are in the type stream, we need to be
-  // prepared for the database growing and receicing a type index that can't fit
-  // in our current buffer.
-  if (KnownOffsets.size() < Database.capacity())
-    KnownOffsets.resize(Database.capacity());
-  KnownOffsets[TI.toArrayIndex()] = Offset;
-  return Error::success();
 }

Removed: llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp?rev=305652&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDatabase.cpp (removed)
@@ -1,146 +0,0 @@
-//===- TypeDatabase.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/TypeDatabase.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-
-TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) {
-  CVUDTNames.resize(Capacity);
-  TypeRecords.resize(Capacity);
-  ValidRecords.resize(Capacity);
-}
-
-TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) {
-  LargestTypeIndex = getAppendIndex();
-  if (LargestTypeIndex.toArrayIndex() >= capacity())
-    grow();
-  recordType(Name, LargestTypeIndex, Data);
-  return LargestTypeIndex;
-}
-
-void TypeDatabase::recordType(StringRef Name, TypeIndex Index,
-                              const CVType &Data) {
-  LargestTypeIndex = empty() ? Index : std::max(Index, LargestTypeIndex);
-
-  if (LargestTypeIndex.toArrayIndex() >= capacity())
-    grow(Index);
-
-  uint32_t AI = Index.toArrayIndex();
-
-  assert(!contains(Index));
-  assert(AI < capacity());
-
-  CVUDTNames[AI] = Name;
-  TypeRecords[AI] = Data;
-  ValidRecords.set(AI);
-  ++Count;
-}
-
-/// Saves the name in a StringSet and creates a stable StringRef.
-StringRef TypeDatabase::saveTypeName(StringRef TypeName) {
-  return TypeNameStorage.save(TypeName);
-}
-
-StringRef TypeDatabase::getTypeName(TypeIndex Index) const {
-  if (Index.isNoneType() || Index.isSimple())
-    return TypeIndex::simpleTypeName(Index);
-
-  if (contains(Index))
-    return CVUDTNames[Index.toArrayIndex()];
-
-  return "<unknown UDT>";
-}
-
-const CVType &TypeDatabase::getTypeRecord(TypeIndex Index) const {
-  assert(contains(Index));
-  return TypeRecords[Index.toArrayIndex()];
-}
-
-CVType &TypeDatabase::getTypeRecord(TypeIndex Index) {
-  assert(contains(Index));
-  return TypeRecords[Index.toArrayIndex()];
-}
-
-bool TypeDatabase::contains(TypeIndex Index) const {
-  uint32_t AI = Index.toArrayIndex();
-  if (AI >= capacity())
-    return false;
-
-  return ValidRecords.test(AI);
-}
-
-uint32_t TypeDatabase::size() const { return Count; }
-
-uint32_t TypeDatabase::capacity() const { return TypeRecords.size(); }
-
-CVType TypeDatabase::getType(TypeIndex Index) { return getTypeRecord(Index); }
-
-StringRef TypeDatabase::getTypeName(TypeIndex Index) {
-  return static_cast<const TypeDatabase *>(this)->getTypeName(Index);
-}
-
-bool TypeDatabase::contains(TypeIndex Index) {
-  return static_cast<const TypeDatabase *>(this)->contains(Index);
-}
-
-uint32_t TypeDatabase::size() {
-  return static_cast<const TypeDatabase *>(this)->size();
-}
-
-uint32_t TypeDatabase::capacity() {
-  return static_cast<const TypeDatabase *>(this)->capacity();
-}
-
-void TypeDatabase::grow() { grow(LargestTypeIndex + 1); }
-
-void TypeDatabase::grow(TypeIndex NewIndex) {
-  uint32_t NewSize = NewIndex.toArrayIndex() + 1;
-
-  if (NewSize <= capacity())
-    return;
-
-  uint32_t NewCapacity = NewSize * 3 / 2;
-
-  TypeRecords.resize(NewCapacity);
-  CVUDTNames.resize(NewCapacity);
-  ValidRecords.resize(NewCapacity);
-}
-
-bool TypeDatabase::empty() const { return size() == 0; }
-
-Optional<TypeIndex> TypeDatabase::largestTypeIndexLessThan(TypeIndex TI) const {
-  uint32_t AI = TI.toArrayIndex();
-  int N = ValidRecords.find_prev(AI);
-  if (N == -1)
-    return None;
-  return TypeIndex::fromArrayIndex(N);
-}
-
-TypeIndex TypeDatabase::getAppendIndex() const {
-  if (empty())
-    return TypeIndex::fromArrayIndex(0);
-
-  return LargestTypeIndex + 1;
-}
-
-Optional<TypeIndex> TypeDatabase::getFirst() {
-  int N = ValidRecords.find_first();
-  if (N == -1)
-    return None;
-  return TypeIndex::fromArrayIndex(N);
-}
-
-Optional<TypeIndex> TypeDatabase::getNext(TypeIndex Prev) {
-  int N = ValidRecords.find_next(Prev.toArrayIndex());
-  if (N == -1)
-    return None;
-  return TypeIndex::fromArrayIndex(N);
-}

Removed: llvm/trunk/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp?rev=305652&view=auto
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeDatabaseVisitor.cpp (removed)
@@ -1,330 +0,0 @@
-//===- TypeDatabaseVisitor.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/TypeDatabaseVisitor.h"
-
-#include "llvm/ADT/SmallString.h"
-
-using namespace llvm;
-
-using namespace llvm::codeview;
-
-Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record) {
-  assert(!IsInFieldList);
-  // Reset Name to the empty string. If the visitor sets it, we know it.
-  Name = "";
-
-  if (Record.Type == LF_FIELDLIST) {
-    // Record that we're in a field list so that members do not get assigned
-    // type indices.
-    IsInFieldList = true;
-  }
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) {
-  if (auto EC = visitTypeBegin(Record))
-    return EC;
-
-  CurrentTypeIndex = Index;
-  return Error::success();
-}
-
-StringRef TypeDatabaseVisitor::getTypeName(TypeIndex Index) const {
-  return TypeDB->getTypeName(Index);
-}
-
-StringRef TypeDatabaseVisitor::saveTypeName(StringRef Name) {
-  return TypeDB->saveTypeName(Name);
-}
-
-Error TypeDatabaseVisitor::visitTypeEnd(CVType &CVR) {
-  if (CVR.Type == LF_FIELDLIST) {
-    assert(IsInFieldList);
-    IsInFieldList = false;
-  }
-  assert(!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.
-  if (CurrentTypeIndex)
-    TypeDB->recordType(Name, *CurrentTypeIndex, CVR);
-  else
-    TypeDB->appendType(Name, CVR);
-
-  CurrentTypeIndex.reset();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitMemberBegin(CVMemberRecord &Record) {
-  assert(IsInFieldList);
-  // Reset Name to the empty string. If the visitor sets it, we know it.
-  Name = "";
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitMemberEnd(CVMemberRecord &Record) {
-  assert(IsInFieldList);
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
-                                            FieldListRecord &FieldList) {
-  Name = "<field list>";
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVRecord<TypeLeafKind> &CVR,
-                                            StringIdRecord &String) {
-  // Put this in the database so it gets printed with LF_UDT_SRC_LINE.
-  Name = String.getString();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArgListRecord &Args) {
-  auto Indices = Args.getIndices();
-  uint32_t Size = Indices.size();
-  SmallString<256> TypeName("(");
-  for (uint32_t I = 0; I < Size; ++I) {
-    StringRef ArgTypeName = getTypeName(Indices[I]);
-    TypeName.append(ArgTypeName);
-    if (I + 1 != Size)
-      TypeName.append(", ");
-  }
-  TypeName.push_back(')');
-  Name = saveTypeName(TypeName);
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
-                                            StringListRecord &Strings) {
-  auto Indices = Strings.getIndices();
-  uint32_t Size = Indices.size();
-  SmallString<256> TypeName("\"");
-  for (uint32_t I = 0; I < Size; ++I) {
-    StringRef ArgTypeName = getTypeName(Indices[I]);
-    TypeName.append(ArgTypeName);
-    if (I + 1 != Size)
-      TypeName.append("\" \"");
-  }
-  TypeName.push_back('\"');
-  Name = saveTypeName(TypeName);
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ClassRecord &Class) {
-  Name = Class.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, UnionRecord &Union) {
-  Name = Union.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, EnumRecord &Enum) {
-  Name = Enum.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ArrayRecord &AT) {
-  Name = AT.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, VFTableRecord &VFT) {
-  Name = VFT.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
-                                            MemberFuncIdRecord &Id) {
-  Name = Id.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
-                                            ProcedureRecord &Proc) {
-  StringRef ReturnTypeName = getTypeName(Proc.getReturnType());
-  StringRef ArgListTypeName = getTypeName(Proc.getArgumentList());
-  SmallString<256> TypeName(ReturnTypeName);
-  TypeName.push_back(' ');
-  TypeName.append(ArgListTypeName);
-  Name = saveTypeName(TypeName);
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
-                                            MemberFunctionRecord &MF) {
-  StringRef ReturnTypeName = getTypeName(MF.getReturnType());
-  StringRef ClassTypeName = getTypeName(MF.getClassType());
-  StringRef ArgListTypeName = getTypeName(MF.getArgumentList());
-  SmallString<256> TypeName(ReturnTypeName);
-  TypeName.push_back(' ');
-  TypeName.append(ClassTypeName);
-  TypeName.append("::");
-  TypeName.append(ArgListTypeName);
-  Name = saveTypeName(TypeName);
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, FuncIdRecord &Func) {
-  Name = Func.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
-                                            TypeServer2Record &TS) {
-  Name = TS.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, PointerRecord &Ptr) {
-
-  if (Ptr.isPointerToMember()) {
-    const MemberPointerInfo &MI = Ptr.getMemberInfo();
-
-    StringRef PointeeName = getTypeName(Ptr.getReferentType());
-    StringRef ClassName = getTypeName(MI.getContainingType());
-    SmallString<256> TypeName(PointeeName);
-    TypeName.push_back(' ');
-    TypeName.append(ClassName);
-    TypeName.append("::*");
-    Name = saveTypeName(TypeName);
-  } else {
-    SmallString<256> TypeName;
-    if (Ptr.isConst())
-      TypeName.append("const ");
-    if (Ptr.isVolatile())
-      TypeName.append("volatile ");
-    if (Ptr.isUnaligned())
-      TypeName.append("__unaligned ");
-
-    TypeName.append(getTypeName(Ptr.getReferentType()));
-
-    if (Ptr.getMode() == PointerMode::LValueReference)
-      TypeName.append("&");
-    else if (Ptr.getMode() == PointerMode::RValueReference)
-      TypeName.append("&&");
-    else if (Ptr.getMode() == PointerMode::Pointer)
-      TypeName.append("*");
-
-    if (!TypeName.empty())
-      Name = saveTypeName(TypeName);
-  }
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, ModifierRecord &Mod) {
-  uint16_t Mods = static_cast<uint16_t>(Mod.getModifiers());
-
-  StringRef ModifiedName = getTypeName(Mod.getModifiedType());
-  SmallString<256> TypeName;
-  if (Mods & uint16_t(ModifierOptions::Const))
-    TypeName.append("const ");
-  if (Mods & uint16_t(ModifierOptions::Volatile))
-    TypeName.append("volatile ");
-  if (Mods & uint16_t(ModifierOptions::Unaligned))
-    TypeName.append("__unaligned ");
-  TypeName.append(ModifiedName);
-  Name = saveTypeName(TypeName);
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
-                                            VFTableShapeRecord &Shape) {
-  Name =
-      saveTypeName("<vftable " + utostr(Shape.getEntryCount()) + " methods>");
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            NestedTypeRecord &Nested) {
-  Name = Nested.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            OneMethodRecord &Method) {
-  Name = Method.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            OverloadedMethodRecord &Method) {
-  Name = Method.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            DataMemberRecord &Field) {
-  Name = Field.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            StaticDataMemberRecord &Field) {
-  Name = Field.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            EnumeratorRecord &Enum) {
-  Name = Enum.getName();
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            BaseClassRecord &Base) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            VirtualBaseClassRecord &VBase) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            ListContinuationRecord &Cont) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(
-    CVType &CVR, UdtModSourceLineRecord &ModSourceLine) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR,
-                                            UdtSourceLineRecord &SourceLine) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BitFieldRecord &BF) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(
-    CVType &CVR, MethodOverloadListRecord &Overloads) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, BuildInfoRecord &BI) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownRecord(CVType &CVR, LabelRecord &R) {
-  return Error::success();
-}
-
-Error TypeDatabaseVisitor::visitKnownMember(CVMemberRecord &CVR,
-                                            VFPtrRecord &VFP) {
-  return Error::success();
-}

Modified: llvm/trunk/lib/DebugInfo/CodeView/TypeTableCollection.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/CodeView/TypeTableCollection.cpp?rev=305653&r1=305652&r2=305653&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/CodeView/TypeTableCollection.cpp (original)
+++ llvm/trunk/lib/DebugInfo/CodeView/TypeTableCollection.cpp Sun Jun 18 15:52:45 2017
@@ -10,7 +10,7 @@
 #include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
 
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
-#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeName.h"
 #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
 #include "llvm/Support/BinaryByteStream.h"
 #include "llvm/Support/BinaryStreamReader.h"
@@ -18,14 +18,10 @@
 using namespace llvm;
 using namespace llvm::codeview;
 
-static void error(Error &&EC) {
-  assert(!static_cast<bool>(EC));
-  if (EC)
-    consumeError(std::move(EC));
-}
-
 TypeTableCollection::TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records)
-    : Records(Records), Database(Records.size()) {}
+    : NameStorage(Allocator), Records(Records) {
+  Names.resize(Records.size());
+}
 
 Optional<TypeIndex> TypeTableCollection::getFirst() {
   if (empty())
@@ -34,50 +30,38 @@ Optional<TypeIndex> TypeTableCollection:
 }
 
 Optional<TypeIndex> TypeTableCollection::getNext(TypeIndex Prev) {
+  assert(contains(Prev));
   ++Prev;
-  assert(Prev.toArrayIndex() <= size());
   if (Prev.toArrayIndex() == size())
     return None;
   return Prev;
 }
 
-void TypeTableCollection::ensureTypeExists(TypeIndex Index) {
-  assert(hasCapacityFor(Index));
-
-  if (Database.contains(Index))
-    return;
-
-  BinaryByteStream Bytes(Records[Index.toArrayIndex()], support::little);
-
-  CVType Type;
-  uint32_t Len;
-  VarStreamArrayExtractor<CVType> Extract;
-  error(Extract(Bytes, Len, Type));
-
-  TypeDatabaseVisitor DBV(Database);
-  error(codeview::visitTypeRecord(Type, Index, DBV));
-  assert(Database.contains(Index));
-}
-
 CVType TypeTableCollection::getType(TypeIndex Index) {
-  ensureTypeExists(Index);
-  return Database.getTypeRecord(Index);
+  assert(Index.toArrayIndex() < Records.size());
+  ArrayRef<uint8_t> Bytes = Records[Index.toArrayIndex()];
+  const RecordPrefix *Prefix =
+      reinterpret_cast<const RecordPrefix *>(Bytes.data());
+  TypeLeafKind Kind = static_cast<TypeLeafKind>(uint16_t(Prefix->RecordKind));
+  return CVType(Kind, Bytes);
 }
 
 StringRef TypeTableCollection::getTypeName(TypeIndex Index) {
-  if (!Index.isSimple())
-    ensureTypeExists(Index);
-  return Database.getTypeName(Index);
+  if (Index.isNoneType() || Index.isSimple())
+    return TypeIndex::simpleTypeName(Index);
+
+  uint32_t I = Index.toArrayIndex();
+  if (Names[I].data() == nullptr) {
+    StringRef Result = NameStorage.save(computeTypeName(*this, Index));
+    Names[I] = Result;
+  }
+  return Names[I];
 }
 
 bool TypeTableCollection::contains(TypeIndex Index) {
-  return Database.contains(Index);
+  return Index.toArrayIndex() <= size();
 }
 
 uint32_t TypeTableCollection::size() { return Records.size(); }
 
 uint32_t TypeTableCollection::capacity() { return Records.size(); }
-
-bool TypeTableCollection::hasCapacityFor(TypeIndex Index) const {
-  return Index.toArrayIndex() < Records.size();
-}

Modified: llvm/trunk/tools/llvm-readobj/COFFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/COFFDumper.cpp?rev=305653&r1=305652&r2=305653&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/COFFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/COFFDumper.cpp Sun Jun 18 15:52:45 2017
@@ -1099,7 +1099,7 @@ void COFFDumper::printCodeViewTypeSectio
   if (Magic != COFF::DEBUG_SECTION_MAGIC)
     return error(object_error::parse_failed);
 
-  Types.reset(Data);
+  Types.reset(Data, 100);
 
   TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes);
   error(codeview::visitTypeStream(Types, TDV));




More information about the llvm-commits mailing list