From 6c247c8cc8054c0c4cc18f1d7c21c5fdb8b1d0e3 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Fri, 27 May 2016 18:31:02 +0000 Subject: [PATCH] Revert "[pdb] Allow zero-copy read support for symbol streams." This reverts commit r271024 due to error: static_assert failed "You must either provide a specialization of VarStreamArrayExtractor or a custom extractor" llvm-svn: 271026 --- .../llvm/DebugInfo/CodeView/CVSymbolVisitor.h | 2 +- .../llvm/DebugInfo/CodeView/CVTypeVisitor.h | 2 +- .../llvm/DebugInfo/CodeView/RecordIterator.h | 38 ++-------- .../llvm/DebugInfo/CodeView/StreamArray.h | 73 ++++++++----------- .../llvm/DebugInfo/CodeView/StreamReader.h | 9 --- .../llvm/DebugInfo/CodeView/SymbolDumper.h | 2 +- .../llvm/DebugInfo/CodeView/SymbolRecord.h | 4 - .../llvm/DebugInfo/CodeView/TypeDumper.h | 2 +- .../llvm/DebugInfo/PDB/Raw/DbiStream.h | 1 + llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h | 15 +--- .../llvm/DebugInfo/PDB/Raw/ModStream.h | 6 +- llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp | 2 +- llvm/lib/DebugInfo/CodeView/TypeDumper.cpp | 2 +- llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp | 10 ++- llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp | 2 - llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp | 13 +--- 16 files changed, 61 insertions(+), 122 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h index febd9a026158..fe21ff9956b9 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h @@ -46,7 +46,7 @@ public: #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "CVSymbolTypes.def" - void visitSymbolRecord(const CVRecord &Record) { + void visitSymbolRecord(const SymbolIterator::Record &Record) { ArrayRef Data = Record.Data; auto *DerivedThis = static_cast(this); DerivedThis->visitSymbolBegin(Record.Type, Data); diff --git a/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h index f9184895d8d4..5058050de569 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h +++ b/llvm/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h @@ -51,7 +51,7 @@ public: #define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) #include "TypeRecords.def" - void visitTypeRecord(const CVRecord &Record) { + void visitTypeRecord(const TypeIterator::Record &Record) { ArrayRef LeafData = Record.Data; ArrayRef RecordData = LeafData; auto *DerivedThis = static_cast(this); diff --git a/llvm/include/llvm/DebugInfo/CodeView/RecordIterator.h b/llvm/include/llvm/DebugInfo/CodeView/RecordIterator.h index a8073eae9c72..463e63645d37 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/RecordIterator.h +++ b/llvm/include/llvm/DebugInfo/CodeView/RecordIterator.h @@ -13,41 +13,19 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/iterator_range.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" -#include "llvm/DebugInfo/CodeView/StreamReader.h" #include "llvm/Support/Endian.h" namespace llvm { namespace codeview { -template struct CVRecord { - uint32_t Length; - Kind Type; - ArrayRef Data; -}; - -template struct VarStreamArrayExtractor> { - uint32_t operator()(const StreamInterface &Stream, - CVRecord &Item) const { - const RecordPrefix *Prefix = nullptr; - StreamReader Reader(Stream); - if (auto EC = Reader.readObject(Prefix)) { - consumeError(std::move(EC)); - return 0; - } - Item.Length = Prefix->RecordLen; - Item.Type = static_cast(uint16_t(Prefix->RecordKind)); - if (auto EC = Reader.readBytes(Item.Length - 2, Item.Data)) { - consumeError(std::move(EC)); - return 0; - } - return Prefix->RecordLen + 2; - } -}; - // A const input iterator interface to the CodeView record stream. template class RecordIterator { public: + struct Record { + std::size_t Length; + Kind Type; + ArrayRef Data; + }; explicit RecordIterator(const ArrayRef &RecordBytes, bool *HadError) : HadError(HadError), Data(RecordBytes), AtEnd(false) { @@ -68,12 +46,12 @@ public: return !(lhs == rhs); } - const CVRecord &operator*() const { + const Record &operator*() const { assert(!AtEnd); return Current; } - const CVRecord *operator->() const { + const Record *operator->() const { assert(!AtEnd); return &Current; } @@ -128,7 +106,7 @@ private: bool *HadError; ArrayRef Data; - CVRecord Current; + Record Current; bool AtEnd; }; diff --git a/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h b/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h index 7117a3af2c8a..bc21b20d49d1 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h +++ b/llvm/include/llvm/DebugInfo/CodeView/StreamArray.h @@ -18,19 +18,6 @@ namespace llvm { namespace codeview { -/// VarStreamArrayExtractor is intended to be specialized to provide customized -/// extraction logic. It should return the total number of bytes of the next -/// record (so that the array knows how much data to skip to get to the next -/// record, and it should initialize the second parameter with the desired -/// value type. -template struct VarStreamArrayExtractor { - uint32_t operator()(const StreamInterface &Stream, T &t) const { - static_assert(false, "You must either provide a specialization of " - "VarStreamArrayExtractor or a custom extractor"); - return 0; - } -}; - /// VarStreamArray represents an array of variable length records backed by a /// stream. This could be a contiguous sequence of bytes in memory, it could /// be a file on disk, or it could be a PDB stream where bytes are stored as @@ -40,39 +27,33 @@ template struct VarStreamArrayExtractor { /// re-ordering of stream data to be contiguous before iterating over it. By /// abstracting this out, we need not duplicate this memory, and we can /// iterate over arrays in arbitrarily formatted streams. -template class VarStreamArrayIterator; +class VarStreamArrayIterator; -template > class VarStreamArray { - friend class VarStreamArrayIterator; + friend class VarStreamArrayIterator; + typedef std::function LengthFuncType; public: - typedef VarStreamArrayIterator Iterator; + template + VarStreamArray(StreamRef Stream, const LengthFunc &Len) + : Stream(Stream), Len(Len) {} - VarStreamArray() {} - - VarStreamArray(StreamRef Stream) : Stream(Stream) {} - - Iterator begin() const { return Iterator(*this); } - - Iterator end() const { return Iterator(); } + VarStreamArrayIterator begin() const; + VarStreamArrayIterator end() const; private: StreamRef Stream; + LengthFuncType Len; // Function used to calculate legth of a record }; -template class VarStreamArrayIterator { - typedef VarStreamArrayIterator IterType; - typedef VarStreamArray ArrayType; - +class VarStreamArrayIterator { public: - VarStreamArrayIterator(const ArrayType &Array) + VarStreamArrayIterator(const VarStreamArray &Array) : Array(&Array), IterRef(Array.Stream) { - ThisLen = Extract(IterRef, ThisValue); + ThisLen = Array.Len(IterRef); } VarStreamArrayIterator() : Array(nullptr), IterRef() {} - bool operator==(const IterType &R) const { + bool operator==(const VarStreamArrayIterator &R) const { if (Array && R.Array) { // Both have a valid array, make sure they're same. assert(Array == R.Array); @@ -87,37 +68,45 @@ public: return false; } - bool operator!=(const IterType &R) { return !(*this == R); } + bool operator!=(const VarStreamArrayIterator &R) { return !(*this == R); } - const ValueType &operator*() const { return ThisValue; } + StreamRef operator*() const { + ArrayRef Result; + return IterRef.keep_front(ThisLen); + } - IterType &operator++() { - if (!Array || IterRef.getLength() == 0 || ThisLen == 0) + VarStreamArrayIterator &operator++() { + if (!Array || IterRef.getLength() == 0) return *this; IterRef = IterRef.drop_front(ThisLen); if (IterRef.getLength() == 0) { Array = nullptr; ThisLen = 0; } else { - ThisLen = Extract(IterRef, ThisValue); + ThisLen = Array->Len(IterRef); } return *this; } - IterType operator++(int) { - IterType Original = *this; + VarStreamArrayIterator operator++(int) { + VarStreamArrayIterator Original = *this; ++*this; return Original; } private: - const ArrayType *Array; + const VarStreamArray *Array; uint32_t ThisLen; - ValueType ThisValue; StreamRef IterRef; - Extractor Extract; }; +inline VarStreamArrayIterator VarStreamArray::begin() const { + return VarStreamArrayIterator(*this); +} +inline VarStreamArrayIterator VarStreamArray::end() const { + return VarStreamArrayIterator(); +} + template class FixedStreamArrayIterator; template class FixedStreamArray { diff --git a/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h b/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h index 71691dc26436..89e2ef0a1244 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h +++ b/llvm/include/llvm/DebugInfo/CodeView/StreamReader.h @@ -45,15 +45,6 @@ public: return Error::success(); } - template - Error readArray(VarStreamArray &Array, uint32_t Size) { - StreamRef S; - if (auto EC = readStreamRef(S, Size)) - return EC; - Array = VarStreamArray(S); - return Error::success(); - } - template Error readArray(FixedStreamArray &Array, uint32_t NumItems) { if (NumItems == 0) { diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h index 97c795225e2c..62c5ab3931b5 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolDumper.h @@ -35,7 +35,7 @@ public: /// and true otherwise. This should be called in order, since the dumper /// maintains state about previous records which are necessary for cross /// type references. - bool dump(const CVRecord &Record); + bool dump(const SymbolIterator::Record &Record); /// Dumps the type records in Data. Returns false if there was a type stream /// parse error, and true otherwise. diff --git a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h index 9ab559d8e277..57c7628df737 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h +++ b/llvm/include/llvm/DebugInfo/CodeView/SymbolRecord.h @@ -15,8 +15,6 @@ #include "llvm/DebugInfo/CodeView/CodeView.h" #include "llvm/DebugInfo/CodeView/RecordIterator.h" #include "llvm/DebugInfo/CodeView/RecordSerialization.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" -#include "llvm/DebugInfo/CodeView/StreamInterface.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" #include "llvm/Support/Endian.h" #include "llvm/Support/Error.h" @@ -1443,8 +1441,6 @@ public: }; typedef RecordIterator SymbolIterator; -typedef CVRecord CVSymbol; -typedef VarStreamArray CVSymbolArray; inline iterator_range makeSymbolRange(ArrayRef Data, bool *HadError) { diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeDumper.h b/llvm/include/llvm/DebugInfo/CodeView/TypeDumper.h index c74f5cffb91b..3085666fe0f4 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeDumper.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeDumper.h @@ -34,7 +34,7 @@ public: /// and true otherwise. This should be called in order, since the dumper /// maintains state about previous records which are necessary for cross /// type references. - bool dump(const CVRecord &Record); + bool dump(const TypeIterator::Record &Record); /// Dumps the type records in Data. Returns false if there was a type stream /// parse error, and true otherwise. diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h index 8a50e138cd28..17f31f5695f4 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/DbiStream.h @@ -10,6 +10,7 @@ #ifndef LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H #define LLVM_DEBUGINFO_PDB_RAW_PDBDBISTREAM_H +#include "llvm/DebugInfo/CodeView/ByteStream.h" #include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/DebugInfo/CodeView/StreamRef.h" #include "llvm/DebugInfo/PDB/PDBTypes.h" diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h b/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h index c9050abe05f3..3b79d48a8a10 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/ModInfo.h @@ -11,7 +11,6 @@ #define LLVM_DEBUGINFO_PDB_RAW_MODINFO_H #include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/CodeView/StreamArray.h" #include "llvm/DebugInfo/CodeView/StreamRef.h" #include #include @@ -24,7 +23,6 @@ private: struct FileLayout; public: - ModInfo(); ModInfo(codeview::StreamRef Stream); ModInfo(const ModInfo &Info); ~ModInfo(); @@ -52,7 +50,6 @@ private: struct ModuleInfoEx { ModuleInfoEx(codeview::StreamRef Stream) : Info(Stream) {} - ModuleInfoEx(const ModInfo &Info) : Info(Info) {} ModuleInfoEx(const ModuleInfoEx &Ex) : Info(Ex.Info), SourceFiles(Ex.SourceFiles) {} @@ -60,17 +57,11 @@ struct ModuleInfoEx { std::vector SourceFiles; }; -} // end namespace pdb - -namespace codeview { -template <> struct VarStreamArrayExtractor { - uint32_t operator()(const StreamInterface &Stream, pdb::ModInfo &Info) const { - Info = pdb::ModInfo(Stream); - return Info.getRecordLength(); - } -}; +inline uint32_t ModInfoRecordLength(const codeview::StreamInterface &Stream) { + return ModInfo(Stream).getRecordLength(); } +} // end namespace pdb } // end namespace llvm #endif // LLVM_DEBUGINFO_PDB_RAW_MODINFO_H diff --git a/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h b/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h index 72869134b484..e5bd2eba4ba9 100644 --- a/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h +++ b/llvm/include/llvm/DebugInfo/PDB/Raw/ModStream.h @@ -11,7 +11,7 @@ #define LLVM_DEBUGINFO_PDB_RAW_MODSTREAM_H #include "llvm/ADT/iterator_range.h" -#include "llvm/DebugInfo/CodeView/RecordIterator.h" +#include "llvm/DebugInfo/CodeView/ByteStream.h" #include "llvm/DebugInfo/CodeView/StreamRef.h" #include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/PDB/Raw/MappedBlockStream.h" @@ -29,14 +29,14 @@ public: Error reload(); - iterator_range symbols() const; + iterator_range symbols() const; private: const ModInfo &Mod; MappedBlockStream Stream; - codeview::CVSymbolArray SymbolsSubstream; + codeview::ByteStream SymbolsSubstream; codeview::StreamRef LinesSubstream; codeview::StreamRef C13LinesSubstream; codeview::StreamRef GlobalRefsSubstream; diff --git a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp index 7d405ec24533..03b711282b4a 100644 --- a/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/SymbolDumper.cpp @@ -866,7 +866,7 @@ void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind, W.printNumber("Length", uint32_t(Data.size())); } -bool CVSymbolDumper::dump(const CVRecord &Record) { +bool CVSymbolDumper::dump(const SymbolIterator::Record &Record) { CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes); Dumper.visitSymbolRecord(Record); return !Dumper.hadError(); diff --git a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp index 1db1e54f4308..74cb2d9e9c49 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeDumper.cpp @@ -676,7 +676,7 @@ void CVTypeDumper::printTypeIndex(StringRef FieldName, TypeIndex TI) { W->printHex(FieldName, TI.getIndex()); } -bool CVTypeDumper::dump(const CVRecord &Record) { +bool CVTypeDumper::dump(const TypeIterator::Record &Record) { assert(W && "printer should not be null"); CVTypeDumperImpl Dumper(*this, *W, PrintRecordBytes); Dumper.visitTypeRecord(Record); diff --git a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp index 1827ab078df2..35937574645d 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/DbiStream.cpp @@ -136,12 +136,14 @@ Error DbiStream::reload() { return make_error(raw_error_code::corrupt_file, "DBI type server substream not aligned."); + if (auto EC = + Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize)) + return EC; + // Since each ModInfo in the stream is a variable length, we have to iterate // them to know how many there actually are. - codeview::VarStreamArray ModInfoArray; - if (auto EC = Reader.readArray(ModInfoArray, Header->ModiSubstreamSize)) - return EC; - for (auto &Info : ModInfoArray) { + codeview::VarStreamArray ModInfoArray(ModInfoSubstream, ModInfoRecordLength); + for (auto Info : ModInfoArray) { ModuleInfos.emplace_back(Info); } diff --git a/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp b/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp index 67dc81da63ac..9ccb7edd696c 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/ModInfo.cpp @@ -67,8 +67,6 @@ struct ModInfo::FileLayout { // Null terminated Obj File Name }; -ModInfo::ModInfo() : Layout(nullptr) {} - ModInfo::ModInfo(codeview::StreamRef Stream) : Layout(nullptr) { codeview::StreamReader Reader(Stream); if (auto EC = Reader.readObject(Layout)) { diff --git a/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp b/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp index 404208a64877..38d3f2f23e38 100644 --- a/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Raw/ModStream.cpp @@ -9,7 +9,6 @@ #include "llvm/DebugInfo/PDB/Raw/ModStream.h" -#include "llvm/DebugInfo/CodeView/RecordIterator.h" #include "llvm/DebugInfo/CodeView/StreamReader.h" #include "llvm/DebugInfo/PDB/Raw/ModInfo.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" @@ -33,14 +32,8 @@ Error ModStream::reload() { return llvm::make_error(raw_error_code::corrupt_file, "Module has both C11 and C13 line info"); - codeview::StreamRef S; - - uint32_t SymbolSubstreamSig = 0; - if (auto EC = Reader.readInteger(SymbolSubstreamSig)) + if (auto EC = SymbolsSubstream.load(Reader, SymbolSize)) return EC; - if (auto EC = Reader.readArray(SymbolsSubstream, SymbolSize - 4)) - return EC; - if (auto EC = Reader.readStreamRef(LinesSubstream, C11Size)) return EC; if (auto EC = Reader.readStreamRef(C13LinesSubstream, C13Size)) @@ -58,6 +51,6 @@ Error ModStream::reload() { return Error::success(); } -iterator_range ModStream::symbols() const { - return llvm::make_range(SymbolsSubstream.begin(), SymbolsSubstream.end()); +iterator_range ModStream::symbols() const { + return codeview::makeSymbolRange(SymbolsSubstream.data().slice(4), nullptr); }