diff --git a/lld/COFF/PDB.cpp b/lld/COFF/PDB.cpp index 0266148cc6c9..631fee12b88d 100644 --- a/lld/COFF/PDB.cpp +++ b/lld/COFF/PDB.cpp @@ -14,8 +14,7 @@ #include "SymbolTable.h" #include "Symbols.h" #include "llvm/DebugInfo/CodeView/CVDebugRecord.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" @@ -135,11 +134,12 @@ static void dumpDebugT(ScopedPrinter &W, ObjectFile *File) { if (Data.empty()) return; - LazyRandomTypeCollection Types(Data, 100); - TypeDumpVisitor TDV(Types, &W, false); + TypeDatabase TDB(0); + TypeDumpVisitor TDV(TDB, &W, false); // Use a default implementation that does not follow type servers and instead // just dumps the contents of the TypeServer2 record. - if (auto EC = codeview::visitTypeStream(Types, TDV)) + CVTypeDumper TypeDumper(TDB); + if (auto EC = TypeDumper.dump(Data, TDV)) fatal(EC, "CVTypeDumper::dump failed"); } diff --git a/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h b/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h index 71ea82b6a9ab..ac8aaafeadc1 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CVRecord.h @@ -32,10 +32,6 @@ public: uint32_t length() const { return RecordData.size(); } Kind kind() const { return Type; } ArrayRef data() const { return RecordData; } - StringRef str_data() const { - return StringRef(reinterpret_cast(RecordData.data()), - RecordData.size()); - } ArrayRef content() const { return RecordData.drop_front(sizeof(RecordPrefix)); diff --git a/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h b/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h new file mode 100644 index 000000000000..02f14ea2107b --- /dev/null +++ b/llvm/include/llvm/DebugInfo/CodeView/CVTypeDumper.h @@ -0,0 +1,61 @@ +//===-- CVTypeDumper.h - CodeView type info dumper --------------*- 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_CVTYPEDUMPER_H +#define LLVM_DEBUGINFO_CODEVIEW_CVTYPEDUMPER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringSet.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" +#include "llvm/Support/ScopedPrinter.h" + +namespace llvm { + +namespace codeview { + +class TypeServerHandler; + +/// Dumper for CodeView type streams found in COFF object files and PDB files. +class CVTypeDumper { +public: + explicit CVTypeDumper(TypeDatabase &TypeDB, + TypeServerHandler *Handler = nullptr) + : TypeDB(TypeDB), Handler(Handler) {} + + /// Dumps one type record. Returns false if there was a type parsing error, + /// and true otherwise. This should be called in order, since the dumper + /// maintains state about previous records which are necessary for cross + /// type references. + Error dump(const CVType &Record, TypeVisitorCallbacks &Dumper); + + /// Dumps the type records in Types. Returns false if there was a type stream + /// parse error, and true otherwise. + Error dump(const CVTypeArray &Types, TypeVisitorCallbacks &Dumper); + + /// Dumps the type records in Data. Returns false if there was a type stream + /// parse error, and true otherwise. Use this method instead of the + /// CVTypeArray overload when type records are laid out contiguously in + /// memory. + Error dump(ArrayRef Data, TypeVisitorCallbacks &Dumper); + + static void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, + TypeIndex TI, TypeDatabase &DB); + +private: + TypeDatabase &TypeDB; + TypeServerHandler *Handler; +}; + +} // end namespace codeview +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_CODEVIEW_TYPEDUMPER_H diff --git a/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index 4bc8fbefd5d8..6d9f345755ab 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -10,15 +10,42 @@ #ifndef LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H #define LLVM_DEBUGINFO_CODEVIEW_CVTYPEVISITOR_H +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/DebugInfo/CodeView/CVRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeServerHandler.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/Support/Error.h" namespace llvm { namespace codeview { -class TypeCollection; -class TypeServerHandler; -class TypeVisitorCallbacks; + +class CVTypeVisitor { +public: + explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks); + + void addTypeServerHandler(TypeServerHandler &Handler); + + Error visitTypeRecord(CVType &Record, TypeIndex Index); + Error visitTypeRecord(CVType &Record); + Error visitMemberRecord(CVMemberRecord Record); + + /// Visits the type records in Data. Sets the error flag on parse failures. + Error visitTypeStream(const CVTypeArray &Types); + Error visitTypeStream(CVTypeRange Types); + + Error visitFieldListMemberStream(ArrayRef FieldList); + Error visitFieldListMemberStream(BinaryStreamReader Reader); + +private: + Expected handleTypeServer(CVType &Record); + Error finishVisitation(CVType &Record); + + /// The interface to the class that gets notified of each visitation. + TypeVisitorCallbacks &Callbacks; + + TinyPtrVector Handlers; +}; enum VisitorDataSource { VDS_BytesPresent, // The record bytes are passed into the the visitation @@ -49,8 +76,6 @@ Error visitTypeStream(const CVTypeArray &Types, TypeVisitorCallbacks &Callbacks, TypeServerHandler *TS = nullptr); Error visitTypeStream(CVTypeRange Types, TypeVisitorCallbacks &Callbacks, TypeServerHandler *TS = nullptr); -Error visitTypeStream(TypeCollection &Types, TypeVisitorCallbacks &Callbacks, - TypeServerHandler *TS = nullptr); } // end namespace codeview } // end namespace llvm diff --git a/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/llvm/include/llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h similarity index 66% rename from llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h rename to llvm/include/llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h index 92aa263bd004..21288df89be2 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h +++ b/llvm/include/llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h @@ -1,4 +1,4 @@ -//===- LazyRandomTypeCollection.h ---------------------------- *- C++ --*-===// +//===- RandomAccessTypeVisitor.h ------------------------------ *- C++ --*-===// // // The LLVM Compiler Infrastructure // @@ -7,10 +7,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H -#define LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H +#ifndef LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H +#define LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H -#include "llvm/DebugInfo/CodeView/TypeCollection.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" @@ -21,6 +21,7 @@ namespace llvm { namespace codeview { class TypeDatabase; +class TypeServerHandler; class TypeVisitorCallbacks; /// \brief Provides amortized O(1) random access to a CodeView type stream. @@ -39,48 +40,32 @@ class TypeVisitorCallbacks; /// consumer much better access time, because the consumer can find the nearest /// index in this array, and do a linear scan forward only from there. /// -/// LazyRandomTypeCollection implements this algorithm, but additionally goes -/// one step further by caching offsets of every record that has been visited at +/// RandomAccessTypeVisitor implements this algorithm, but additionally goes one +/// step further by caching offsets of every record that has been visited at /// least once. This way, even repeated visits of the same record will never /// require more than one linear scan. For a type stream of N elements divided /// into M chunks of roughly equal size, this yields a worst case lookup time /// of O(N/M) and an amortized time of O(1). -class LazyRandomTypeCollection : public TypeCollection { +class RandomAccessTypeVisitor { typedef FixedStreamArray PartialOffsetArray; public: - explicit LazyRandomTypeCollection(uint32_t RecordCountHint); - LazyRandomTypeCollection(StringRef Data, uint32_t RecordCountHint); - LazyRandomTypeCollection(ArrayRef Data, uint32_t RecordCountHint); - LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint, - PartialOffsetArray PartialOffsets); - LazyRandomTypeCollection(const CVTypeArray &Types, uint32_t RecordCountHint); + RandomAccessTypeVisitor(const CVTypeArray &Types, uint32_t NumRecords, + PartialOffsetArray PartialOffsets); - void reset(ArrayRef Data); - void reset(StringRef Data); + Error visitTypeIndex(TypeIndex Index, TypeVisitorCallbacks &Callbacks); - CVType getType(TypeIndex Index) override; - StringRef getTypeName(TypeIndex Index) override; - bool contains(TypeIndex Index) override; - uint32_t size() override; - uint32_t capacity() override; - TypeIndex getFirst() override; - Optional getNext(TypeIndex Prev) override; + const TypeDatabase &database() const { return Database; } private: - const TypeDatabase &database() const { return Database; } - Error ensureTypeExists(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); /// Visited records get automatically added to the type database. TypeDatabase Database; /// The type array to allow random access visitation of. - CVTypeArray Types; + const CVTypeArray &Types; /// The database visitor which adds new records to the database. TypeDatabaseVisitor DatabaseVisitor; @@ -100,4 +85,4 @@ private: } // end namespace codeview } // end namespace llvm -#endif // LLVM_DEBUGINFO_CODEVIEW_LAZYRANDOMTYPECOLLECTION_H +#endif // LLVM_DEBUGINFO_CODEVIEW_RANDOMACCESSTYPEVISITOR_H diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h index e91065dcf87e..a5419b37e776 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -20,15 +20,15 @@ namespace llvm { class ScopedPrinter; namespace codeview { -class TypeCollection; +class TypeDatabase; /// Dumper for CodeView symbol streams found in COFF object files and PDB files. class CVSymbolDumper { public: - CVSymbolDumper(ScopedPrinter &W, TypeCollection &Types, + CVSymbolDumper(ScopedPrinter &W, TypeDatabase &TypeDB, std::unique_ptr ObjDelegate, bool PrintRecordBytes) - : W(W), Types(Types), ObjDelegate(std::move(ObjDelegate)), + : W(W), TypeDB(TypeDB), ObjDelegate(std::move(ObjDelegate)), PrintRecordBytes(PrintRecordBytes) {} /// Dumps one type record. Returns false if there was a type parsing error, @@ -43,7 +43,7 @@ public: private: ScopedPrinter &W; - TypeCollection &Types; + TypeDatabase &TypeDB; std::unique_ptr ObjDelegate; bool PrintRecordBytes; diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h b/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h deleted file mode 100644 index 6f6cfc983e0a..000000000000 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeCollection.h +++ /dev/null @@ -1,38 +0,0 @@ -//===- TypeCollection.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_TYPECOLLECTION_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H - -#include "llvm/ADT/StringRef.h" - -#include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/CodeView/TypeRecord.h" - -namespace llvm { -namespace codeview { -class TypeCollection { -public: - virtual ~TypeCollection() = default; - - bool empty() { return size() == 0; } - - virtual TypeIndex getFirst() = 0; - virtual Optional getNext(TypeIndex Prev) = 0; - - virtual CVType getType(TypeIndex Index) = 0; - virtual StringRef getTypeName(TypeIndex Index) = 0; - virtual bool contains(TypeIndex Index) = 0; - virtual uint32_t size() = 0; - virtual uint32_t capacity() = 0; -}; -} -} - -#endif diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h b/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h index dc8adcda8e2f..92c15ebd8b2b 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeDatabase.h @@ -13,7 +13,6 @@ #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" @@ -21,7 +20,7 @@ namespace llvm { namespace codeview { -class TypeDatabase : public TypeCollection { +class TypeDatabase { friend class RandomAccessTypeVisitor; public: @@ -42,31 +41,19 @@ public: 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; - - TypeIndex getFirst() override; - Optional getNext(TypeIndex Prev) override; - - Optional largestTypeIndexLessThan(TypeIndex TI) const; - -private: TypeIndex getAppendIndex() const; +private: 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 diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h index 65b3a33e6548..6f10afb30d60 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeDumpVisitor.h @@ -12,6 +12,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSet.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" @@ -21,20 +22,17 @@ class ScopedPrinter; namespace codeview { -class TypeCollection; - /// Dumper for CodeView type streams found in COFF object files and PDB files. class TypeDumpVisitor : public TypeVisitorCallbacks { public: - TypeDumpVisitor(TypeCollection &TpiTypes, ScopedPrinter *W, - bool PrintRecordBytes) - : W(W), PrintRecordBytes(PrintRecordBytes), TpiTypes(TpiTypes) {} + TypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W, bool PrintRecordBytes) + : W(W), PrintRecordBytes(PrintRecordBytes), TypeDB(TypeDB) {} /// When dumping types from an IPI stream in a PDB, a type index may refer to /// a type or an item ID. The dumper will lookup the "name" of the index in /// the item database if appropriate. If ItemDB is null, it will use TypeDB, /// which is correct when dumping types from an object file (/Z7). - void setIpiTypes(TypeCollection &Types) { IpiTypes = &Types; } + void setItemDB(TypeDatabase &DB) { ItemDB = &DB; } void printTypeIndex(StringRef FieldName, TypeIndex TI) const; @@ -68,16 +66,14 @@ private: /// Get the database of indices for the stream that we are dumping. If ItemDB /// is set, then we must be dumping an item (IPI) stream. This will also /// always get the appropriate DB for printing item names. - TypeCollection &getSourceTypes() const { - return IpiTypes ? *IpiTypes : TpiTypes; - } + TypeDatabase &getSourceDB() const { return ItemDB ? *ItemDB : TypeDB; } ScopedPrinter *W; bool PrintRecordBytes = false; - TypeCollection &TpiTypes; - TypeCollection *IpiTypes = nullptr; + TypeDatabase &TypeDB; + TypeDatabase *ItemDB = nullptr; }; } // end namespace codeview diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h b/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h index 31eed7d3e877..b5d695fc49d5 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeIndex.h @@ -15,13 +15,8 @@ #include namespace llvm { - -class ScopedPrinter; - namespace codeview { -class TypeCollection; - enum class SimpleTypeKind : uint32_t { None = 0x0000, // uncharacterized type (no type) Void = 0x0003, // void @@ -243,11 +238,6 @@ public: return Result; } - friend inline uint32_t operator-(const TypeIndex &A, const TypeIndex &B) { - assert(A >= B); - return A.toArrayIndex() - B.toArrayIndex(); - } - private: support::ulittle32_t Index; }; @@ -259,9 +249,6 @@ struct TypeIndexOffset { TypeIndex Type; support::ulittle32_t Offset; }; - -void printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, TypeIndex TI, - TypeCollection &Types); } } diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeTableCollection.h b/llvm/include/llvm/DebugInfo/CodeView/TypeTableCollection.h deleted file mode 100644 index 4ad09d6aa182..000000000000 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeTableCollection.h +++ /dev/null @@ -1,42 +0,0 @@ -//===- TypeTableCollection.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_TYPETABLECOLLECTION_H -#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLECOLLECTION_H - -#include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" - -namespace llvm { -namespace codeview { - -class TypeTableCollection : public TypeCollection { -public: - explicit TypeTableCollection(ArrayRef> Records); - - TypeIndex getFirst() override; - Optional getNext(TypeIndex Prev) override; - - CVType getType(TypeIndex Index) override; - StringRef getTypeName(TypeIndex Index) override; - bool contains(TypeIndex Index) override; - uint32_t size() override; - uint32_t capacity() override; - -private: - bool hasCapacityFor(TypeIndex Index) const; - void ensureTypeExists(TypeIndex Index); - - ArrayRef> Records; - TypeDatabase Database; -}; -} -} - -#endif diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h b/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h index 0ea754deb425..2950c7d27cb6 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h @@ -17,6 +17,8 @@ namespace llvm { namespace codeview { class TypeVisitorCallbacks { + friend class CVTypeVisitor; + public: virtual ~TypeVisitorCallbacks() = default; diff --git a/llvm/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h b/llvm/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h index bfd38b6c80ec..d965e1008e95 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h +++ b/llvm/include/llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeServerHandler.h" #include "llvm/DebugInfo/PDB/Native/NativeSession.h" diff --git a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp index ae14e000c381..7d945690e9c3 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp @@ -13,6 +13,7 @@ #include "CodeViewDebug.h" #include "llvm/ADT/TinyPtrVector.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/Line.h" @@ -22,7 +23,6 @@ #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" -#include "llvm/DebugInfo/CodeView/TypeTableCollection.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/IR/Constants.h" #include "llvm/MC/MCAsmInfo.h" @@ -469,21 +469,17 @@ void CodeViewDebug::emitTypeInformation() { CommentPrefix += ' '; } - TypeTableCollection Table(TypeTable.records()); - Optional B = Table.getFirst(); - do { - // This will fail if the record data is invalid. - CVType Record = Table.getType(*B); - + TypeDatabase TypeDB(TypeTable.records().size()); + CVTypeDumper CVTD(TypeDB); + TypeTable.ForEachRecord([&](TypeIndex Index, ArrayRef Record) { if (OS.isVerboseAsm()) { // Emit a block comment describing the type record for readability. SmallString<512> CommentBlock; raw_svector_ostream CommentOS(CommentBlock); ScopedPrinter SP(CommentOS); SP.setPrefix(CommentPrefix); - TypeDumpVisitor TDV(Table, &SP, false); - - Error E = codeview::visitTypeRecord(Record, *B, TDV); + TypeDumpVisitor TDV(TypeDB, &SP, false); + Error E = CVTD.dump(Record, TDV); if (E) { logAllUnhandledErrors(std::move(E), errs(), "error: "); llvm_unreachable("produced malformed type record"); @@ -493,9 +489,29 @@ void CodeViewDebug::emitTypeInformation() { // newline. OS.emitRawComment( CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim()); + } else { +#ifndef NDEBUG + // Assert that the type data is valid even if we aren't dumping + // comments. The MSVC linker doesn't do much type record validation, + // so the first link of an invalid type record can succeed while + // subsequent links will fail with LNK1285. + BinaryByteStream Stream(Record, llvm::support::little); + CVTypeArray Types; + BinaryStreamReader Reader(Stream); + Error E = Reader.readArray(Types, Reader.getLength()); + if (!E) { + TypeVisitorCallbacks C; + E = codeview::visitTypeStream(Types, C); + } + if (E) { + logAllUnhandledErrors(std::move(E), errs(), "error: "); + llvm_unreachable("produced malformed type record"); + } +#endif } - OS.EmitBinaryData(Record.str_data()); - } while ((B = Table.getNext(*B))); + StringRef S(reinterpret_cast(Record.data()), Record.size()); + OS.EmitBinaryData(S); + }); } namespace { diff --git a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt index 556ebf78622f..8d9353ae5f5e 100644 --- a/llvm/lib/DebugInfo/CodeView/CMakeLists.txt +++ b/llvm/lib/DebugInfo/CodeView/CMakeLists.txt @@ -2,10 +2,10 @@ add_llvm_library(LLVMDebugInfoCodeView CodeViewError.cpp CodeViewRecordIO.cpp CVSymbolVisitor.cpp + CVTypeDumper.cpp CVTypeVisitor.cpp EnumTables.cpp Formatters.cpp - LazyRandomTypeCollection.cpp Line.cpp ModuleDebugFileChecksumFragment.cpp ModuleDebugFragment.cpp @@ -13,6 +13,7 @@ add_llvm_library(LLVMDebugInfoCodeView ModuleDebugFragmentVisitor.cpp ModuleDebugInlineeLinesFragment.cpp ModuleDebugLineFragment.cpp + RandomAccessTypeVisitor.cpp RecordSerialization.cpp StringTable.cpp SymbolRecordMapping.cpp @@ -21,12 +22,10 @@ add_llvm_library(LLVMDebugInfoCodeView TypeDatabase.cpp TypeDatabaseVisitor.cpp TypeDumpVisitor.cpp - TypeIndex.cpp TypeRecordMapping.cpp TypeSerializer.cpp TypeStreamMerger.cpp - TypeTableCollection.cpp - + ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/CodeView ) diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp new file mode 100644 index 000000000000..02e1682f76e7 --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/CVTypeDumper.cpp @@ -0,0 +1,61 @@ +//===-- CVTypeDumper.cpp - CodeView type info dumper ------------*- 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/CVTypeDumper.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" +#include "llvm/Support/BinaryByteStream.h" + +using namespace llvm; +using namespace llvm::codeview; + +Error CVTypeDumper::dump(const CVType &Record, TypeVisitorCallbacks &Dumper) { + TypeDatabaseVisitor DBV(TypeDB); + TypeVisitorCallbackPipeline Pipeline; + Pipeline.addCallbackToPipeline(DBV); + Pipeline.addCallbackToPipeline(Dumper); + + CVType RecordCopy = Record; + return codeview::visitTypeRecord(RecordCopy, Pipeline, VDS_BytesPresent, + Handler); +} + +Error CVTypeDumper::dump(const CVTypeArray &Types, + TypeVisitorCallbacks &Dumper) { + TypeDatabaseVisitor DBV(TypeDB); + TypeVisitorCallbackPipeline Pipeline; + Pipeline.addCallbackToPipeline(DBV); + Pipeline.addCallbackToPipeline(Dumper); + + return codeview::visitTypeStream(Types, Pipeline, Handler); +} + +Error CVTypeDumper::dump(ArrayRef Data, TypeVisitorCallbacks &Dumper) { + BinaryByteStream Stream(Data, llvm::support::little); + CVTypeArray Types; + BinaryStreamReader Reader(Stream); + if (auto EC = Reader.readArray(Types, Reader.getLength())) + return EC; + + return dump(Types, Dumper); +} + +void CVTypeDumper::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, + TypeIndex TI, TypeDatabase &DB) { + StringRef TypeName; + if (!TI.isNoneType()) + TypeName = DB.getTypeName(TI); + if (!TypeName.empty()) + Printer.printHex(FieldName, TypeName, TI.getIndex()); + else + Printer.printHex(FieldName, TI.getIndex()); +} diff --git a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp index e8d967b6389f..0f7f5f667790 100644 --- a/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/CVTypeVisitor.cpp @@ -9,9 +9,7 @@ #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/ADT/TinyPtrVector.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/TypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" @@ -24,6 +22,8 @@ using namespace llvm; using namespace llvm::codeview; +CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks) + : Callbacks(Callbacks) {} template static Error visitKnownRecord(CVType &Record, TypeVisitorCallbacks &Callbacks) { @@ -66,67 +66,6 @@ static Expected deserializeTypeServerRecord(CVType &Record) { return R; } -static Error visitMemberRecord(CVMemberRecord &Record, - TypeVisitorCallbacks &Callbacks) { - 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(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(); -} - -namespace { - -class CVTypeVisitor { -public: - explicit CVTypeVisitor(TypeVisitorCallbacks &Callbacks); - - void addTypeServerHandler(TypeServerHandler &Handler); - - Error visitTypeRecord(CVType &Record, TypeIndex Index); - Error visitTypeRecord(CVType &Record); - - /// Visits the type records in Data. Sets the error flag on parse failures. - Error visitTypeStream(const CVTypeArray &Types); - Error visitTypeStream(CVTypeRange Types); - Error visitTypeStream(TypeCollection &Types); - - Error visitMemberRecord(CVMemberRecord Record); - Error visitFieldListMemberStream(BinaryStreamReader &Stream); - -private: - Expected handleTypeServer(CVType &Record); - Error finishVisitation(CVType &Record); - - /// The interface to the class that gets notified of each visitation. - TypeVisitorCallbacks &Callbacks; - - TinyPtrVector Handlers; -}; - -CVTypeVisitor::CVTypeVisitor(TypeVisitorCallbacks &Callbacks) - : Callbacks(Callbacks) {} - void CVTypeVisitor::addTypeServerHandler(TypeServerHandler &Handler) { Handlers.push_back(&Handler); } @@ -205,6 +144,35 @@ Error CVTypeVisitor::visitTypeRecord(CVType &Record) { return finishVisitation(Record); } +static Error visitMemberRecord(CVMemberRecord &Record, + TypeVisitorCallbacks &Callbacks) { + 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(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(); +} + Error CVTypeVisitor::visitMemberRecord(CVMemberRecord Record) { return ::visitMemberRecord(Record, Callbacks); } @@ -226,20 +194,12 @@ Error CVTypeVisitor::visitTypeStream(CVTypeRange Types) { return Error::success(); } -Error CVTypeVisitor::visitTypeStream(TypeCollection &Types) { - if (Types.empty()) - return Error::success(); +Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader Reader) { + FieldListDeserializer Deserializer(Reader); + TypeVisitorCallbackPipeline Pipeline; + Pipeline.addCallbackToPipeline(Deserializer); + Pipeline.addCallbackToPipeline(Callbacks); - Optional I = Types.getFirst(); - do { - CVType Type = Types.getType(*I); - if (auto EC = visitTypeRecord(Type, *I)) - return EC; - } while ((I = Types.getNext(*I))); - return Error::success(); -} - -Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) { TypeLeafKind Leaf; while (!Reader.empty()) { if (auto EC = Reader.readEnum(Leaf)) @@ -247,13 +207,20 @@ Error CVTypeVisitor::visitFieldListMemberStream(BinaryStreamReader &Reader) { CVMemberRecord Record; Record.Kind = Leaf; - if (auto EC = ::visitMemberRecord(Record, Callbacks)) + if (auto EC = ::visitMemberRecord(Record, Pipeline)) return EC; } return Error::success(); } +Error CVTypeVisitor::visitFieldListMemberStream(ArrayRef Data) { + BinaryByteStream S(Data, llvm::support::little); + BinaryStreamReader SR(S); + return visitFieldListMemberStream(SR); +} + +namespace { struct FieldListVisitHelper { FieldListVisitHelper(TypeVisitorCallbacks &Callbacks, ArrayRef Data, VisitorDataSource Source) @@ -274,8 +241,11 @@ struct FieldListVisitHelper { }; struct VisitHelper { - VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source) + VisitHelper(TypeVisitorCallbacks &Callbacks, VisitorDataSource Source, + TypeServerHandler *TS) : Visitor((Source == VDS_BytesPresent) ? Pipeline : Callbacks) { + if (TS) + Visitor.addTypeServerHandler(*TS); if (Source == VDS_BytesPresent) { Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Callbacks); @@ -292,57 +262,29 @@ Error llvm::codeview::visitTypeRecord(CVType &Record, TypeIndex Index, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source, TypeServerHandler *TS) { - VisitHelper V(Callbacks, Source); - if (TS) - V.Visitor.addTypeServerHandler(*TS); - return V.Visitor.visitTypeRecord(Record, Index); + VisitHelper Helper(Callbacks, Source, TS); + return Helper.Visitor.visitTypeRecord(Record, Index); } Error llvm::codeview::visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source, TypeServerHandler *TS) { - VisitHelper V(Callbacks, Source); - if (TS) - V.Visitor.addTypeServerHandler(*TS); - return V.Visitor.visitTypeRecord(Record); + VisitHelper Helper(Callbacks, Source, TS); + return Helper.Visitor.visitTypeRecord(Record); } -Error llvm::codeview::visitTypeStream(const CVTypeArray &Types, - TypeVisitorCallbacks &Callbacks, - TypeServerHandler *TS) { - VisitHelper V(Callbacks, VDS_BytesPresent); - if (TS) - V.Visitor.addTypeServerHandler(*TS); - return V.Visitor.visitTypeStream(Types); -} - -Error llvm::codeview::visitTypeStream(CVTypeRange Types, - TypeVisitorCallbacks &Callbacks, - TypeServerHandler *TS) { - VisitHelper V(Callbacks, VDS_BytesPresent); - if (TS) - V.Visitor.addTypeServerHandler(*TS); - return V.Visitor.visitTypeStream(Types); -} - -Error llvm::codeview::visitTypeStream(TypeCollection &Types, - TypeVisitorCallbacks &Callbacks, - TypeServerHandler *TS) { - // When the internal visitor calls Types.getType(Index) the interface is - // required to return a CVType with the bytes filled out. So we can assume - // that the bytes will be present when individual records are visited. - VisitHelper V(Callbacks, VDS_BytesPresent); - if (TS) - V.Visitor.addTypeServerHandler(*TS); - return V.Visitor.visitTypeStream(Types); +Error llvm::codeview::visitMemberRecordStream(ArrayRef FieldList, + TypeVisitorCallbacks &Callbacks) { + CVTypeVisitor Visitor(Callbacks); + return Visitor.visitFieldListMemberStream(FieldList); } Error llvm::codeview::visitMemberRecord(CVMemberRecord Record, TypeVisitorCallbacks &Callbacks, VisitorDataSource Source) { - FieldListVisitHelper V(Callbacks, Record.Data, Source); - return V.Visitor.visitMemberRecord(Record); + FieldListVisitHelper Helper(Callbacks, Record.Data, Source); + return Helper.Visitor.visitMemberRecord(Record); } Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind, @@ -354,8 +296,16 @@ Error llvm::codeview::visitMemberRecord(TypeLeafKind Kind, return visitMemberRecord(R, Callbacks, VDS_BytesPresent); } -Error llvm::codeview::visitMemberRecordStream(ArrayRef FieldList, - TypeVisitorCallbacks &Callbacks) { - FieldListVisitHelper V(Callbacks, FieldList, VDS_BytesPresent); - return V.Visitor.visitFieldListMemberStream(V.Reader); +Error llvm::codeview::visitTypeStream(const CVTypeArray &Types, + TypeVisitorCallbacks &Callbacks, + TypeServerHandler *TS) { + VisitHelper Helper(Callbacks, VDS_BytesPresent, TS); + return Helper.Visitor.visitTypeStream(Types); +} + +Error llvm::codeview::visitTypeStream(CVTypeRange Types, + TypeVisitorCallbacks &Callbacks, + TypeServerHandler *TS) { + VisitHelper Helper(Callbacks, VDS_BytesPresent, TS); + return Helper.Visitor.visitTypeStream(Types); } diff --git a/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp b/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp deleted file mode 100644 index 4886a1870882..000000000000 --- a/llvm/lib/DebugInfo/CodeView/LazyRandomTypeCollection.cpp +++ /dev/null @@ -1,226 +0,0 @@ -//===- LazyRandomTypeCollection.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/LazyRandomTypeCollection.h" - -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/CodeViewError.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" -#include "llvm/DebugInfo/CodeView/TypeServerHandler.h" -#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" - -using namespace llvm; -using namespace llvm::codeview; - -static void error(Error &&EC) { - assert(!static_cast(EC)); - if (EC) - consumeError(std::move(EC)); -} - -LazyRandomTypeCollection::LazyRandomTypeCollection(uint32_t RecordCountHint) - : LazyRandomTypeCollection(CVTypeArray(), RecordCountHint, - PartialOffsetArray()) {} - -LazyRandomTypeCollection::LazyRandomTypeCollection( - const CVTypeArray &Types, uint32_t RecordCountHint, - PartialOffsetArray PartialOffsets) - : Database(RecordCountHint), Types(Types), DatabaseVisitor(Database), - PartialOffsets(PartialOffsets) { - KnownOffsets.resize(Database.capacity()); -} - -LazyRandomTypeCollection::LazyRandomTypeCollection(ArrayRef Data, - uint32_t RecordCountHint) - : LazyRandomTypeCollection(RecordCountHint) { - reset(Data); -} - -LazyRandomTypeCollection::LazyRandomTypeCollection(StringRef Data, - uint32_t RecordCountHint) - : LazyRandomTypeCollection( - makeArrayRef(Data.bytes_begin(), Data.bytes_end()), RecordCountHint) { -} - -LazyRandomTypeCollection::LazyRandomTypeCollection(const CVTypeArray &Types, - uint32_t NumRecords) - : LazyRandomTypeCollection(Types, NumRecords, PartialOffsetArray()) {} - -void LazyRandomTypeCollection::reset(StringRef Data) { - reset(makeArrayRef(Data.bytes_begin(), Data.bytes_end())); -} - -void LazyRandomTypeCollection::reset(ArrayRef Data) { - PartialOffsets = PartialOffsetArray(); - - BinaryStreamReader Reader(Data, support::little); - error(Reader.readArray(Types, Reader.getLength())); - - KnownOffsets.resize(Database.capacity()); -} - -CVType LazyRandomTypeCollection::getType(TypeIndex Index) { - error(ensureTypeExists(Index)); - return Database.getTypeRecord(Index); -} - -StringRef LazyRandomTypeCollection::getTypeName(TypeIndex Index) { - if (!Index.isSimple()) { - // Try to make sure the type exists. Even if it doesn't though, it may be - // because we're dumping a symbol stream with no corresponding type stream - // present, in which case we still want to be able to print - // for the type names. - consumeError(ensureTypeExists(Index)); - } - - return Database.getTypeName(Index); -} - -bool LazyRandomTypeCollection::contains(TypeIndex Index) { - return Database.contains(Index); -} - -uint32_t LazyRandomTypeCollection::size() { return Database.size(); } - -uint32_t LazyRandomTypeCollection::capacity() { return Database.capacity(); } - -Error LazyRandomTypeCollection::ensureTypeExists(TypeIndex TI) { - if (!Database.contains(TI)) { - if (auto EC = visitRangeForType(TI)) - return EC; - } - return Error::success(); -} - -Error LazyRandomTypeCollection::visitRangeForType(TypeIndex TI) { - if (PartialOffsets.empty()) - return fullScanForType(TI); - - auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI, - [](TypeIndex Value, const TypeIndexOffset &IO) { - return Value < IO.Type; - }); - - assert(Next != PartialOffsets.begin()); - auto Prev = std::prev(Next); - - TypeIndex TIB = Prev->Type; - if (Database.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 - // discovered. Ultimately, this means this is a request for a non-existant - // type index. - return make_error("Invalid type index"); - } - - TypeIndex TIE; - if (Next == PartialOffsets.end()) { - TIE = TypeIndex::fromArrayIndex(Database.capacity()); - } else { - TIE = Next->Type; - } - - if (auto EC = visitRange(TIB, Prev->Offset, TIE)) - return EC; - return Error::success(); -} - -TypeIndex LazyRandomTypeCollection::getFirst() { - TypeIndex TI = TypeIndex::fromArrayIndex(0); - error(ensureTypeExists(TI)); - return TI; -} - -Optional LazyRandomTypeCollection::getNext(TypeIndex Prev) { - // We can't be sure how long this type stream is, given that the initial count - // given to the constructor is just a hint. So just try to make sure the next - // record exists, and if anything goes wrong, we must be at the end. - if (auto EC = ensureTypeExists(Prev + 1)) { - consumeError(std::move(EC)); - return None; - } - - return Prev + 1; -} - -Error LazyRandomTypeCollection::fullScanForType(TypeIndex TI) { - assert(PartialOffsets.empty()); - - TypeIndex CurrentTI = TypeIndex::fromArrayIndex(0); - uint32_t Offset = 0; - auto Begin = Types.begin(); - - if (!Database.empty()) { - // 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; - 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(); - ++Begin; - ++CurrentTI; - } - if (CurrentTI <= TI) { - return make_error("Type Index does not exist!"); - } - return Error::success(); -} - -Error LazyRandomTypeCollection::visitRange(TypeIndex Begin, - uint32_t BeginOffset, - TypeIndex End) { - - auto RI = Types.at(BeginOffset); - assert(RI != Types.end()); - - while (Begin != End) { - if (auto EC = visitOneRecord(Begin, BeginOffset, *RI)) - return EC; - - BeginOffset += RI.getRecordLength(); - ++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(); -} diff --git a/llvm/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp b/llvm/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp new file mode 100644 index 000000000000..704d1131108a --- /dev/null +++ b/llvm/lib/DebugInfo/CodeView/RandomAccessTypeVisitor.cpp @@ -0,0 +1,89 @@ +//===- RandomAccessTypeVisitor.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/RandomAccessTypeVisitor.h" + +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDatabase.h" +#include "llvm/DebugInfo/CodeView/TypeServerHandler.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" + +using namespace llvm; +using namespace llvm::codeview; + +RandomAccessTypeVisitor::RandomAccessTypeVisitor( + const CVTypeArray &Types, uint32_t NumRecords, + PartialOffsetArray PartialOffsets) + : Database(NumRecords), Types(Types), DatabaseVisitor(Database), + PartialOffsets(PartialOffsets) { + + KnownOffsets.resize(Database.capacity()); +} + +Error RandomAccessTypeVisitor::visitTypeIndex(TypeIndex TI, + TypeVisitorCallbacks &Callbacks) { + assert(TI.toArrayIndex() < Database.capacity()); + + if (!Database.contains(TI)) { + if (auto EC = visitRangeForType(TI)) + return EC; + } + + assert(Database.contains(TI)); + auto &Record = Database.getTypeRecord(TI); + return codeview::visitTypeRecord(Record, TI, Callbacks); +} + +Error RandomAccessTypeVisitor::visitRangeForType(TypeIndex TI) { + if (PartialOffsets.empty()) { + TypeIndex TIB(TypeIndex::FirstNonSimpleIndex); + TypeIndex TIE = TIB + Database.capacity(); + return visitRange(TIB, 0, TIE); + } + + auto Next = std::upper_bound(PartialOffsets.begin(), PartialOffsets.end(), TI, + [](TypeIndex Value, const TypeIndexOffset &IO) { + return Value < IO.Type; + }); + + assert(Next != PartialOffsets.begin()); + auto Prev = std::prev(Next); + + TypeIndex TIB = Prev->Type; + TypeIndex TIE; + if (Next == PartialOffsets.end()) { + TIE = TypeIndex::fromArrayIndex(Database.capacity()); + } else { + TIE = Next->Type; + } + + if (auto EC = visitRange(TIB, Prev->Offset, TIE)) + return EC; + return Error::success(); +} + +Error RandomAccessTypeVisitor::visitRange(TypeIndex Begin, uint32_t BeginOffset, + TypeIndex End) { + + auto RI = Types.at(BeginOffset); + assert(RI != Types.end()); + + while (Begin != End) { + assert(!Database.contains(Begin)); + if (auto EC = codeview::visitTypeRecord(*RI, Begin, DatabaseVisitor)) + return EC; + KnownOffsets[Begin.toArrayIndex()] = BeginOffset; + + BeginOffset += RI.getRecordLength(); + ++Begin; + ++RI; + } + + return Error::success(); +} diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index 7d01c8c5f194..5395e4349b28 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" #include "llvm/DebugInfo/CodeView/StringTable.h" #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" @@ -32,9 +33,9 @@ namespace { /// the visitor out of SymbolDumper.h. class CVSymbolDumperImpl : public SymbolVisitorCallbacks { public: - CVSymbolDumperImpl(TypeCollection &Types, SymbolDumpDelegate *ObjDelegate, + CVSymbolDumperImpl(TypeDatabase &TypeDB, SymbolDumpDelegate *ObjDelegate, ScopedPrinter &W, bool PrintRecordBytes) - : Types(Types), ObjDelegate(ObjDelegate), W(W), + : TypeDB(TypeDB), ObjDelegate(ObjDelegate), W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {} /// CVSymbolVisitor overrides. @@ -53,7 +54,7 @@ private: void printLocalVariableAddrGap(ArrayRef Gaps); void printTypeIndex(StringRef FieldName, TypeIndex TI); - TypeCollection &Types; + TypeDatabase &TypeDB; SymbolDumpDelegate *ObjDelegate; ScopedPrinter &W; @@ -82,7 +83,7 @@ void CVSymbolDumperImpl::printLocalVariableAddrGap( } void CVSymbolDumperImpl::printTypeIndex(StringRef FieldName, TypeIndex TI) { - codeview::printTypeIndex(W, FieldName, TI, Types); + CVTypeDumper::printTypeIndex(W, FieldName, TI, TypeDB); } Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) { @@ -669,7 +670,7 @@ Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) { Error CVSymbolDumper::dump(CVRecord &Record) { SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(ObjDelegate.get()); - CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes); + CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); @@ -680,7 +681,7 @@ Error CVSymbolDumper::dump(CVRecord &Record) { Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) { SymbolVisitorCallbackPipeline Pipeline; SymbolDeserializer Deserializer(ObjDelegate.get()); - CVSymbolDumperImpl Dumper(Types, ObjDelegate.get(), W, PrintRecordBytes); + CVSymbolDumperImpl Dumper(TypeDB, ObjDelegate.get(), W, PrintRecordBytes); Pipeline.addCallbackToPipeline(Deserializer); Pipeline.addCallbackToPipeline(Dumper); diff --git a/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp b/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp index 89531e022128..7924440e5e29 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDatabase.cpp @@ -72,20 +72,16 @@ TypeDatabase::TypeDatabase(uint32_t Capacity) : TypeNameStorage(Allocator) { } TypeIndex TypeDatabase::appendType(StringRef Name, const CVType &Data) { - LargestTypeIndex = getAppendIndex(); - if (LargestTypeIndex.toArrayIndex() >= capacity()) + TypeIndex TI; + TI = getAppendIndex(); + if (TI.toArrayIndex() >= capacity()) grow(); - recordType(Name, LargestTypeIndex, Data); - return LargestTypeIndex; + recordType(Name, TI, Data); + return TI; } 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)); @@ -148,65 +144,19 @@ 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(this)->getTypeName(Index); -} - -bool TypeDatabase::contains(TypeIndex Index) { - return static_cast(this)->contains(Index); -} - -uint32_t TypeDatabase::size() { - return static_cast(this)->size(); -} - -uint32_t TypeDatabase::capacity() { - return static_cast(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); +void TypeDatabase::grow() { + TypeRecords.emplace_back(); + CVUDTNames.emplace_back(); + ValidRecords.resize(ValidRecords.size() + 1); } bool TypeDatabase::empty() const { return size() == 0; } -Optional 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; -} - -TypeIndex TypeDatabase::getFirst() { - int N = ValidRecords.find_first(); - assert(N != -1); - return TypeIndex::fromArrayIndex(N); -} - -Optional TypeDatabase::getNext(TypeIndex Prev) { - int N = ValidRecords.find_next(Prev.toArrayIndex()); - if (N == -1) - return None; - return TypeIndex::fromArrayIndex(N); + int Index = ValidRecords.find_last(); + assert(Index != -1); + return TypeIndex::fromArrayIndex(Index) + 1; } diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp index 84f52a055815..9485c9cfedff 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumpVisitor.cpp @@ -10,13 +10,15 @@ #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/Formatters.h" -#include "llvm/DebugInfo/CodeView/TypeCollection.h" #include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/Support/BinaryByteStream.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ScopedPrinter.h" @@ -163,15 +165,16 @@ static StringRef getLeafTypeName(TypeLeafKind LT) { } void TypeDumpVisitor::printTypeIndex(StringRef FieldName, TypeIndex TI) const { - codeview::printTypeIndex(*W, FieldName, TI, TpiTypes); + CVTypeDumper::printTypeIndex(*W, FieldName, TI, TypeDB); } void TypeDumpVisitor::printItemIndex(StringRef FieldName, TypeIndex TI) const { - codeview::printTypeIndex(*W, FieldName, TI, getSourceTypes()); + CVTypeDumper::printTypeIndex(*W, FieldName, TI, getSourceDB()); } Error TypeDumpVisitor::visitTypeBegin(CVType &Record) { - return visitTypeBegin(Record, TypeIndex::fromArrayIndex(TpiTypes.size())); + TypeIndex TI = getSourceDB().getAppendIndex(); + return visitTypeBegin(Record, TI); } Error TypeDumpVisitor::visitTypeBegin(CVType &Record, TypeIndex Index) { @@ -242,7 +245,7 @@ Error TypeDumpVisitor::visitKnownRecord(CVType &CVR, StringListRecord &Strs) { W->printNumber("NumStrings", Size); ListScope Arguments(*W, "Strings"); for (uint32_t I = 0; I < Size; ++I) { - printItemIndex("String", Indices[I]); + printTypeIndex("String", Indices[I]); } return Error::success(); } diff --git a/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp b/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp deleted file mode 100644 index 20ba6470cd5b..000000000000 --- a/llvm/lib/DebugInfo/CodeView/TypeIndex.cpp +++ /dev/null @@ -1,27 +0,0 @@ -//===-- TypeIndex.cpp - CodeView type index ---------------------*- 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/TypeIndex.h" - -#include "llvm/DebugInfo/CodeView/TypeCollection.h" -#include "llvm/Support/ScopedPrinter.h" - -using namespace llvm; -using namespace llvm::codeview; - -void llvm::codeview::printTypeIndex(ScopedPrinter &Printer, StringRef FieldName, - TypeIndex TI, TypeCollection &Types) { - StringRef TypeName; - if (!TI.isNoneType()) - TypeName = Types.getTypeName(TI); - if (!TypeName.empty()) - Printer.printHex(FieldName, TypeName, TI.getIndex()); - else - Printer.printHex(FieldName, TI.getIndex()); -} diff --git a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp index 46747f8eab99..9b70b7f6700f 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -11,9 +11,11 @@ #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.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/CodeView/TypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/Support/Error.h" #include "llvm/Support/ScopedPrinter.h" diff --git a/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp b/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp deleted file mode 100644 index 4e53437f24ab..000000000000 --- a/llvm/lib/DebugInfo/CodeView/TypeTableCollection.cpp +++ /dev/null @@ -1,82 +0,0 @@ -//===- TypeTableCollection.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/TypeTableCollection.h" - -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" -#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" -#include "llvm/Support/BinaryByteStream.h" -#include "llvm/Support/BinaryStreamReader.h" - -using namespace llvm; -using namespace llvm::codeview; - -static void error(Error &&EC) { - assert(!static_cast(EC)); - if (EC) - consumeError(std::move(EC)); -} - -TypeTableCollection::TypeTableCollection( - ArrayRef> Records) - : Records(Records), Database(Records.size()) {} - -TypeIndex TypeTableCollection::getFirst() { - assert(!empty()); - return TypeIndex::fromArrayIndex(0); -} - -Optional TypeTableCollection::getNext(TypeIndex 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; - error(VarStreamArrayExtractor::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); -} - -StringRef TypeTableCollection::getTypeName(TypeIndex Index) { - if (!Index.isSimple()) - ensureTypeExists(Index); - return Database.getTypeName(Index); -} - -bool TypeTableCollection::contains(TypeIndex Index) { - return Database.contains(Index); -} - -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(); -} diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp index f00567db743e..cb783cf4fea7 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PDBTypeServerHandler.cpp @@ -21,7 +21,6 @@ #include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/CodeViewError.h" #include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" diff --git a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp index 8e0065873892..c53ba815c0b5 100644 --- a/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -9,7 +9,10 @@ #include "llvm/DebugInfo/PDB/Native/TpiStream.h" #include "llvm/ADT/iterator_range.h" +#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" #include "llvm/DebugInfo/PDB/Native/PDBTypeServerHandler.h" diff --git a/llvm/test/DebugInfo/PDB/pdbdump-headers.test b/llvm/test/DebugInfo/PDB/pdbdump-headers.test index 4e6bb75f8b8d..d67743efd707 100644 --- a/llvm/test/DebugInfo/PDB/pdbdump-headers.test +++ b/llvm/test/DebugInfo/PDB/pdbdump-headers.test @@ -326,7 +326,7 @@ ; EMPTY-NEXT: TypeLeafKind: LF_SUBSTR_LIST (0x1604) ; EMPTY-NEXT: NumStrings: 1 ; EMPTY-NEXT: Strings [ -; EMPTY-NEXT: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows +; EMPTY-NEXT: String: __vc_attributes::threadingAttribute (0x100B) ; EMPTY-NEXT: ] ; EMPTY-NEXT: } ; EMPTY-NEXT: Bytes ( @@ -1253,7 +1253,7 @@ ; ALL: TypeLeafKind: LF_SUBSTR_LIST (0x1604) ; ALL: NumStrings: 1 ; ALL: Strings [ -; ALL: String: -Zi -MT -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE" -I"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\ATLMFC\INCLUDE" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared" -I"C:\Program Files (x86)\Windows (0x100B) +; ALL: String: __vc_attributes::threadingAttribute (0x100B) ; ALL: ] ; ALL: } ; ALL: } diff --git a/llvm/tools/llvm-pdbdump/Analyze.cpp b/llvm/tools/llvm-pdbdump/Analyze.cpp index 3a026e5d2451..ab4477ed7bad 100644 --- a/llvm/tools/llvm-pdbdump/Analyze.cpp +++ b/llvm/tools/llvm-pdbdump/Analyze.cpp @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" diff --git a/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp b/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp index 3b609ae50c1c..5ad0bfad26c1 100644 --- a/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp +++ b/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp @@ -29,15 +29,15 @@ static StringRef getLeafName(TypeLeafKind K) { return StringRef(); } -CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types, +CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB, ScopedPrinter *W) - : CompactTypeDumpVisitor(Types, TypeIndex(TypeIndex::FirstNonSimpleIndex), + : CompactTypeDumpVisitor(TypeDB, TypeIndex(TypeIndex::FirstNonSimpleIndex), W) {} -CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeCollection &Types, +CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB, TypeIndex FirstTI, ScopedPrinter *W) - : W(W), TI(FirstTI), Offset(0), Types(Types) {} + : W(W), TI(FirstTI), Offset(0), TypeDB(TypeDB) {} Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) { return Error::success(); @@ -46,7 +46,7 @@ Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) { Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) { uint32_t I = TI.getIndex(); StringRef Leaf = getLeafName(Record.Type); - StringRef Name = Types.getTypeName(TI); + StringRef Name = TypeDB.getTypeName(TI); W->printString( llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I, Record.length(), Offset, Leaf, Name) diff --git a/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.h b/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.h index 41ccea0c2e90..76fafc93e030 100644 --- a/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.h +++ b/llvm/tools/llvm-pdbdump/CompactTypeDumpVisitor.h @@ -17,7 +17,7 @@ namespace llvm { class ScopedPrinter; namespace codeview { -class TypeCollection; +class TypeDatabase; } namespace pdb { @@ -26,8 +26,8 @@ namespace pdb { /// Dumps records on a single line, and ignores member records. class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks { public: - CompactTypeDumpVisitor(codeview::TypeCollection &Types, ScopedPrinter *W); - CompactTypeDumpVisitor(codeview::TypeCollection &Types, + CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W); + CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, codeview::TypeIndex FirstTI, ScopedPrinter *W); /// Paired begin/end actions for all types. Receives all record data, @@ -40,7 +40,7 @@ private: codeview::TypeIndex TI; uint32_t Offset; - codeview::TypeCollection &Types; + codeview::TypeDatabase &TypeDB; }; } // end namespace pdb diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp index f75a2411ac23..c4fecb80ea5a 100644 --- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp +++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp @@ -14,9 +14,9 @@ #include "StreamUtil.h" #include "llvm-pdbdump.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" -#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFragmentVisitor.h" @@ -25,6 +25,7 @@ #include "llvm/DebugInfo/CodeView/ModuleDebugUnknownFragment.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/TypeDatabaseVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" @@ -83,7 +84,7 @@ struct PageStats { class C13RawVisitor : public C13DebugFragmentVisitor { public: - C13RawVisitor(ScopedPrinter &P, PDBFile &F, LazyRandomTypeCollection &IPI) + C13RawVisitor(ScopedPrinter &P, PDBFile &F, TypeDatabase &IPI) : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {} Error handleLines() override { @@ -159,7 +160,7 @@ public: if (auto EC = printFileName("FileName", L.Header->FileID)) return EC; - if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee)) + if (auto EC = dumpTypeRecord("Function", IPI, L.Header->Inlinee)) return EC; P.printNumber("SourceLine", L.Header->SourceLineNum); if (IL.hasExtraFiles()) { @@ -175,11 +176,11 @@ public: } private: - Error dumpTypeRecord(StringRef Label, TypeIndex Index) { - CompactTypeDumpVisitor CTDV(IPI, Index, &P); + Error dumpTypeRecord(StringRef Label, TypeDatabase &DB, TypeIndex Index) { + CompactTypeDumpVisitor CTDV(DB, Index, &P); DictScope D(P, Label); - if (IPI.contains(Index)) { - CVType Type = IPI.getType(Index); + if (DB.contains(Index)) { + CVType &Type = DB.getTypeRecord(Index); if (auto EC = codeview::visitTypeRecord(Type, CTDV)) return EC; } else { @@ -198,7 +199,7 @@ private: } ScopedPrinter &P; - LazyRandomTypeCollection &IPI; + TypeDatabase &IPI; }; } @@ -608,19 +609,14 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { VerLabel = "IPI Version"; } + if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash) + return Error::success(); + auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream(); if (!Tpi) return Tpi.takeError(); - auto ExpectedTypes = initializeTypeDatabase(StreamIdx); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &Types = *ExpectedTypes; - - if (!DumpRecordBytes && !DumpRecords && !DumpTpiHash) - return Error::success(); - std::unique_ptr StreamScope; std::unique_ptr RecordScope; @@ -628,19 +624,25 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { P.printNumber(VerLabel, Tpi->getTpiVersion()); P.printNumber("Record count", Tpi->getNumTypeRecords()); + Optional &StreamDB = (StreamIdx == StreamTPI) ? TypeDB : ItemDB; + std::vector> Visitors; + if (!StreamDB.hasValue()) { + StreamDB.emplace(Tpi->getNumTypeRecords()); + Visitors.push_back(make_unique(*StreamDB)); + } // If we're in dump mode, add a dumper with the appropriate detail level. if (DumpRecords) { std::unique_ptr Dumper; if (opts::raw::CompactRecords) - Dumper = make_unique(Types, &P); + Dumper = make_unique(*StreamDB, &P); else { - assert(TpiTypes); + assert(TypeDB.hasValue()); - auto X = make_unique(*TpiTypes, &P, false); + auto X = make_unique(*TypeDB, &P, false); if (StreamIdx == StreamIPI) - X->setIpiTypes(*IpiTypes); + X->setItemDB(*ItemDB); Dumper = std::move(X); } Visitors.push_back(std::move(Dumper)); @@ -658,17 +660,23 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { if (DumpRecords || DumpRecordBytes) RecordScope = llvm::make_unique(P, "Records"); - Optional I = Types.getFirst(); - do { + bool HadError = false; + + TypeIndex T(TypeIndex::FirstNonSimpleIndex); + for (auto Type : Tpi->types(&HadError)) { std::unique_ptr OneRecordScope; if ((DumpRecords || DumpRecordBytes) && !opts::raw::CompactRecords) OneRecordScope = llvm::make_unique(P, ""); - auto T = Types.getType(*I); - if (auto EC = codeview::visitTypeRecord(T, *I, Pipeline)) + if (auto EC = codeview::visitTypeRecord(Type, Pipeline)) return EC; - } while ((I = Types.getNext(*I))); + + ++T; + } + if (HadError) + return make_error(raw_error_code::corrupt_file, + "TPI stream contained corrupt record"); if (DumpTpiHash) { DictScope DD(P, "Hash"); @@ -703,26 +711,35 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) { return Error::success(); } -Expected -LLVMOutputStyle::initializeTypeDatabase(uint32_t SN) { - auto &TypeCollection = (SN == StreamTPI) ? TpiTypes : IpiTypes; +Error LLVMOutputStyle::buildTypeDatabase(uint32_t SN) { + assert(SN == StreamIPI || SN == StreamTPI); + + auto &DB = (SN == StreamIPI) ? ItemDB : TypeDB; + + if (DB.hasValue()) + return Error::success(); + auto Tpi = (SN == StreamTPI) ? File.getPDBTpiStream() : File.getPDBIpiStream(); + if (!Tpi) return Tpi.takeError(); - if (!TypeCollection) { - // Initialize the type collection, even if we're not going to dump it. This - // way if some other part of the dumper decides it wants to use some or all - // of the records for whatever purposes, it can still access them lazily. - auto &Types = Tpi->typeArray(); - uint32_t Count = Tpi->getNumTypeRecords(); - auto Offsets = Tpi->getTypeIndexOffsets(); - TypeCollection = - llvm::make_unique(Types, Count, Offsets); - } + DB.emplace(Tpi->getNumTypeRecords()); - return *TypeCollection; + TypeDatabaseVisitor DBV(*DB); + + auto HashValues = Tpi->getHashValues(); + if (HashValues.empty()) + return codeview::visitTypeStream(Tpi->typeArray(), DBV); + + TypeVisitorCallbackPipeline Pipeline; + Pipeline.addCallbackToPipeline(DBV); + + TpiHashVerifier HashVerifier(HashValues, Tpi->getNumHashBuckets()); + Pipeline.addCallbackToPipeline(HashVerifier); + + return codeview::visitTypeStream(Tpi->typeArray(), Pipeline); } Error LLVMOutputStyle::dumpDbiStream() { @@ -797,13 +814,11 @@ Error LLVMOutputStyle::dumpDbiStream() { return EC; if (ShouldDumpSymbols) { - auto ExpectedTypes = initializeTypeDatabase(StreamTPI); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &Types = *ExpectedTypes; + if (auto EC = buildTypeDatabase(StreamTPI)) + return EC; ListScope SS(P, "Symbols"); - codeview::CVSymbolDumper SD(P, Types, nullptr, false); + codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false); bool HadError = false; for (auto S : ModS.symbols(&HadError)) { DictScope LL(P, ""); @@ -824,11 +839,10 @@ Error LLVMOutputStyle::dumpDbiStream() { } if (opts::raw::DumpLineInfo) { ListScope SS(P, "LineInfo"); - auto ExpectedTypes = initializeTypeDatabase(StreamIPI); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &IpiItems = *ExpectedTypes; - C13RawVisitor V(P, File, IpiItems); + if (auto EC = buildTypeDatabase(StreamIPI)) + return EC; + + C13RawVisitor V(P, File, *ItemDB); if (auto EC = codeview::visitModuleDebugFragments( ModS.linesAndChecksums(), V)) return EC; @@ -946,12 +960,10 @@ Error LLVMOutputStyle::dumpPublicsStream() { P.printList("Section Offsets", Publics->getSectionOffsets(), printSectionOffset); ListScope L(P, "Symbols"); - auto ExpectedTypes = initializeTypeDatabase(StreamTPI); - if (!ExpectedTypes) - return ExpectedTypes.takeError(); - auto &Tpi = *ExpectedTypes; + if (auto EC = buildTypeDatabase(StreamTPI)) + return EC; - codeview::CVSymbolDumper SD(P, Tpi, nullptr, false); + codeview::CVSymbolDumper SD(P, *TypeDB, nullptr, false); bool HadError = false; for (auto S : Publics->getSymbols(&HadError)) { DictScope DD(P, ""); diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h index 184dc4e1f44d..b0e7e3406b36 100644 --- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h +++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h @@ -21,11 +21,6 @@ namespace llvm { class BitVector; - -namespace codeview { -class LazyRandomTypeCollection; -} - namespace pdb { class LLVMOutputStyle : public OutputStyle { public: @@ -34,8 +29,7 @@ public: Error dump() override; private: - Expected - initializeTypeDatabase(uint32_t SN); + Error buildTypeDatabase(uint32_t SN); Error dumpFileHeaders(); Error dumpStreamSummary(); @@ -60,8 +54,8 @@ private: PDBFile &File; ScopedPrinter P; - std::unique_ptr TpiTypes; - std::unique_ptr IpiTypes; + Optional TypeDB; + Optional ItemDB; SmallVector StreamPurposes; }; } diff --git a/llvm/tools/llvm-pdbdump/PdbYaml.cpp b/llvm/tools/llvm-pdbdump/PdbYaml.cpp index dd32eca14c1d..6527bec31a77 100644 --- a/llvm/tools/llvm-pdbdump/PdbYaml.cpp +++ b/llvm/tools/llvm-pdbdump/PdbYaml.cpp @@ -19,6 +19,7 @@ #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeSerializer.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/PDB/Native/PDBFile.h" @@ -370,6 +371,7 @@ void MappingContextTraits::mapping( void MappingContextTraits:: mapping(IO &IO, pdb::yaml::PdbTpiRecord &Obj, pdb::yaml::SerializationContext &Context) { + if (IO.outputting()) { // For PDB to Yaml, deserialize into a high level record type, then dump it. consumeError(codeview::visitTypeRecord(Obj.Record, Context.Dumper)); diff --git a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h index 068312aec450..517c7d86d7ab 100644 --- a/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h +++ b/llvm/tools/llvm-pdbdump/YAMLOutputStyle.h @@ -13,6 +13,7 @@ #include "OutputStyle.h" #include "PdbYaml.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/YAMLTraits.h" diff --git a/llvm/tools/llvm-pdbdump/YamlTypeDumper.cpp b/llvm/tools/llvm-pdbdump/YamlTypeDumper.cpp index beb700720954..3e447ca60b61 100644 --- a/llvm/tools/llvm-pdbdump/YamlTypeDumper.cpp +++ b/llvm/tools/llvm-pdbdump/YamlTypeDumper.cpp @@ -13,6 +13,7 @@ #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" #include "llvm/DebugInfo/CodeView/EnumTables.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeSerializer.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp index 1767c3cfda85..49a0dae5c27d 100644 --- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp +++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp @@ -31,7 +31,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Config/config.h" -#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugLineFragment.h" @@ -886,7 +885,7 @@ static void mergePdbs() { DestIpi.addTypeRecord(Data, None); }); - SmallString<64> OutFile(opts::merge::PdbOutputFile); + SmallString<64> OutFile = opts::merge::PdbOutputFile; if (OutFile.empty()) { OutFile = opts::merge::InputFilenames[0]; llvm::sys::path::replace_extension(OutFile, "merged.pdb"); diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp index 78bfa558e4a3..8e71c85fa8fa 100644 --- a/llvm/tools/llvm-readobj/COFFDumper.cpp +++ b/llvm/tools/llvm-readobj/COFFDumper.cpp @@ -22,9 +22,8 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/CVTypeDumper.h" #include "llvm/DebugInfo/CodeView/CodeView.h" -#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" #include "llvm/DebugInfo/CodeView/Line.h" #include "llvm/DebugInfo/CodeView/ModuleDebugFileChecksumFragment.h" #include "llvm/DebugInfo/CodeView/ModuleDebugInlineeLinesFragment.h" @@ -35,13 +34,11 @@ #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h" #include "llvm/DebugInfo/CodeView/SymbolDumper.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" -#include "llvm/DebugInfo/CodeView/TypeDatabase.h" #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" -#include "llvm/DebugInfo/CodeView/TypeTableCollection.h" #include "llvm/Object/COFF.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/BinaryStreamReader.h" @@ -73,7 +70,7 @@ class COFFDumper : public ObjDumper { public: friend class COFFObjectDumpDelegate; COFFDumper(const llvm::object::COFFObjectFile *Obj, ScopedPrinter &Writer) - : ObjDumper(Writer), Obj(Obj), Writer(Writer), Types(100) {} + : ObjDumper(Writer), Obj(Obj), Writer(Writer), TypeDB(100) {} void printFileHeaders() override; void printSections() override; @@ -109,7 +106,7 @@ private: void printFileNameForOffset(StringRef Label, uint32_t FileOffset); void printTypeIndex(StringRef FieldName, TypeIndex TI) { // Forward to CVTypeDumper for simplicity. - codeview::printTypeIndex(Writer, FieldName, TI, Types); + CVTypeDumper::printTypeIndex(Writer, FieldName, TI, TypeDB); } void printCodeViewSymbolsSubsection(StringRef Subsection, @@ -162,8 +159,7 @@ private: StringTableRef CVStringTable; ScopedPrinter &Writer; - BinaryByteStream TypeContents; - LazyRandomTypeCollection Types; + TypeDatabase TypeDB; }; class COFFObjectDumpDelegate : public SymbolDumpDelegate { @@ -979,7 +975,9 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection, Subsection.bytes_end()); auto CODD = llvm::make_unique(*this, Section, Obj, SectionContents); - CVSymbolDumper CVSD(W, Types, std::move(CODD), opts::CodeViewSubsectionBytes); + + CVSymbolDumper CVSD(W, TypeDB, std::move(CODD), + opts::CodeViewSubsectionBytes); CVSymbolArray Symbols; BinaryStreamReader Reader(BinaryData, llvm::support::little); if (auto EC = Reader.readArray(Symbols, Reader.getLength())) { @@ -1096,11 +1094,12 @@ void COFFDumper::printCodeViewTypeSection(StringRef SectionName, if (Magic != COFF::DEBUG_SECTION_MAGIC) return error(object_error::parse_failed); - Types.reset(Data); - - TypeDumpVisitor TDV(Types, &W, opts::CodeViewSubsectionBytes); - error(codeview::visitTypeStream(Types, TDV)); - W.flush(); + CVTypeDumper CVTD(TypeDB); + TypeDumpVisitor TDV(TypeDB, &W, opts::CodeViewSubsectionBytes); + if (auto EC = CVTD.dump({Data.bytes_begin(), Data.bytes_end()}, TDV)) { + W.flush(); + error(llvm::errorToErrorCode(std::move(EC))); + } } void COFFDumper::printSections() { @@ -1640,22 +1639,35 @@ void llvm::dumpCodeViewMergedTypes(ScopedPrinter &Writer, TypeBuf.append(Record.begin(), Record.end()); }); - TypeTableCollection TpiTypes(CVTypes.records()); + TypeDatabase TypeDB(CVTypes.records().size()); { ListScope S(Writer, "MergedTypeStream"); - TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes); - error(codeview::visitTypeStream(TpiTypes, TDV)); - Writer.flush(); + CVTypeDumper CVTD(TypeDB); + TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes); + if (auto EC = CVTD.dump( + {TypeBuf.str().bytes_begin(), TypeBuf.str().bytes_end()}, TDV)) { + Writer.flush(); + error(std::move(EC)); + } } // Flatten the id stream and print it next. The ID stream refers to names from // the type stream. - TypeTableCollection IpiTypes(IDTable.records()); + SmallString<0> IDBuf; + IDTable.ForEachRecord([&](TypeIndex TI, ArrayRef Record) { + IDBuf.append(Record.begin(), Record.end()); + }); + { ListScope S(Writer, "MergedIDStream"); - TypeDumpVisitor TDV(TpiTypes, &Writer, opts::CodeViewSubsectionBytes); - TDV.setIpiTypes(IpiTypes); - error(codeview::visitTypeStream(IpiTypes, TDV)); - Writer.flush(); + TypeDatabase IDDB(IDTable.records().size()); + CVTypeDumper CVTD(IDDB); + TypeDumpVisitor TDV(TypeDB, &Writer, opts::CodeViewSubsectionBytes); + TDV.setItemDB(IDDB); + if (auto EC = CVTD.dump( + {IDBuf.str().bytes_begin(), IDBuf.str().bytes_end()}, TDV)) { + Writer.flush(); + error(std::move(EC)); + } } } diff --git a/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp b/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp index 0ca24c716d1d..9ff37e93b151 100644 --- a/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp +++ b/llvm/unittests/DebugInfo/CodeView/RandomAccessVisitorTest.cpp @@ -11,12 +11,14 @@ #include "llvm/ADT/SmallBitVector.h" #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" -#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/RandomAccessTypeVisitor.h" +#include "llvm/DebugInfo/CodeView/TypeDeserializer.h" #include "llvm/DebugInfo/CodeView/TypeRecord.h" #include "llvm/DebugInfo/CodeView/TypeRecordMapping.h" #include "llvm/DebugInfo/CodeView/TypeSerializer.h" #include "llvm/DebugInfo/CodeView/TypeServerHandler.h" #include "llvm/DebugInfo/CodeView/TypeTableBuilder.h" +#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h" #include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" #include "llvm/Support/Allocator.h" @@ -128,16 +130,20 @@ public: void SetUp() override { TestState = llvm::make_unique(); + + TestState->Pipeline.addCallbackToPipeline(TestState->Deserializer); + TestState->Pipeline.addCallbackToPipeline(TestState->Callbacks); } void TearDown() override { TestState.reset(); } protected: - bool ValidateDatabaseRecord(LazyRandomTypeCollection &Types, uint32_t Index) { + bool ValidateDatabaseRecord(const RandomAccessTypeVisitor &Visitor, + uint32_t Index) { TypeIndex TI = TypeIndex::fromArrayIndex(Index); - if (!Types.contains(TI)) + if (!Visitor.database().contains(TI)) return false; - if (GlobalState->TypeVector[Index] != Types.getType(TI)) + if (GlobalState->TypeVector[Index] != Visitor.database().getTypeRecord(TI)) return false; return true; } @@ -178,6 +184,8 @@ protected: struct PerTestState { FixedStreamArray Offsets; + TypeVisitorCallbackPipeline Pipeline; + TypeDeserializer Deserializer; MockCallbacks Callbacks; }; @@ -210,22 +218,21 @@ std::unique_ptr TEST_F(RandomAccessVisitorTest, MultipleVisits) { TestState->Offsets = createPartialOffsets(GlobalState->Stream, {0, 8}); - LazyRandomTypeCollection Types(GlobalState->TypeArray, - GlobalState->TypeVector.size(), - TestState->Offsets); + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); std::vector IndicesToVisit = {5, 5, 5}; for (uint32_t I : IndicesToVisit) { TypeIndex TI = TypeIndex::fromArrayIndex(I); - CVType T = Types.getType(TI); - EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks)); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); } // [0,8) should be present - EXPECT_EQ(8u, Types.size()); + EXPECT_EQ(8u, Visitor.database().size()); for (uint32_t I = 0; I < 8; ++I) - EXPECT_TRUE(ValidateDatabaseRecord(Types, I)); + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); // 5, 5, 5 EXPECT_EQ(3u, TestState->Callbacks.count()); @@ -241,19 +248,19 @@ TEST_F(RandomAccessVisitorTest, DescendingWithinChunk) { std::vector IndicesToVisit = {7, 4, 2}; - LazyRandomTypeCollection Types(GlobalState->TypeArray, - GlobalState->TypeVector.size(), - TestState->Offsets); + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); + for (uint32_t I : IndicesToVisit) { TypeIndex TI = TypeIndex::fromArrayIndex(I); - CVType T = Types.getType(TI); - EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks)); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); } // [0, 7] - EXPECT_EQ(8u, Types.size()); + EXPECT_EQ(8u, Visitor.database().size()); for (uint32_t I = 0; I < 8; ++I) - EXPECT_TRUE(ValidateDatabaseRecord(Types, I)); + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); // 2, 4, 7 EXPECT_EQ(3u, TestState->Callbacks.count()); @@ -269,19 +276,19 @@ TEST_F(RandomAccessVisitorTest, AscendingWithinChunk) { std::vector IndicesToVisit = {2, 4, 7}; - LazyRandomTypeCollection Types(GlobalState->TypeArray, - GlobalState->TypeVector.size(), - TestState->Offsets); + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); + for (uint32_t I : IndicesToVisit) { TypeIndex TI = TypeIndex::fromArrayIndex(I); - CVType T = Types.getType(TI); - EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks)); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); } // [0, 7] - EXPECT_EQ(8u, Types.size()); + EXPECT_EQ(8u, Visitor.database().size()); for (uint32_t I = 0; I < 8; ++I) - EXPECT_TRUE(ValidateDatabaseRecord(Types, I)); + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); // 2, 4, 7 EXPECT_EQ(3u, TestState->Callbacks.count()); @@ -298,20 +305,19 @@ TEST_F(RandomAccessVisitorTest, StopPrematurelyInChunk) { std::vector IndicesToVisit = {0, 1, 2}; - LazyRandomTypeCollection Types(GlobalState->TypeArray, - GlobalState->TypeVector.size(), - TestState->Offsets); + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); for (uint32_t I : IndicesToVisit) { TypeIndex TI = TypeIndex::fromArrayIndex(I); - CVType T = Types.getType(TI); - EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks)); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); } // [0, 8) should be visited. - EXPECT_EQ(8u, Types.size()); + EXPECT_EQ(8u, Visitor.database().size()); for (uint32_t I = 0; I < 8; ++I) - EXPECT_TRUE(ValidateDatabaseRecord(Types, I)); + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); // [0, 2] EXPECT_EQ(3u, TestState->Callbacks.count()); @@ -327,20 +333,19 @@ TEST_F(RandomAccessVisitorTest, InnerChunk) { std::vector IndicesToVisit = {5, 7}; - LazyRandomTypeCollection Types(GlobalState->TypeArray, - GlobalState->TypeVector.size(), - TestState->Offsets); + RandomAccessTypeVisitor Visitor(GlobalState->TypeArray, + GlobalState->TypeVector.size(), + TestState->Offsets); for (uint32_t I : IndicesToVisit) { TypeIndex TI = TypeIndex::fromArrayIndex(I); - CVType T = Types.getType(TI); - EXPECT_NO_ERROR(codeview::visitTypeRecord(T, TI, TestState->Callbacks)); + EXPECT_NO_ERROR(Visitor.visitTypeIndex(TI, TestState->Pipeline)); } // [4, 9) - EXPECT_EQ(5u, Types.size()); + EXPECT_EQ(5u, Visitor.database().size()); for (uint32_t I = 4; I < 9; ++I) - EXPECT_TRUE(ValidateDatabaseRecord(Types, I)); + EXPECT_TRUE(ValidateDatabaseRecord(Visitor, I)); // 5, 7 EXPECT_EQ(2u, TestState->Callbacks.count());