diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp | 62 |
1 files changed, 46 insertions, 16 deletions
diff --git a/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp b/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp index 51a1f0a544e3..5f4f497690b6 100644 --- a/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp +++ b/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/TpiStreamBuilder.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Error.h" #include <algorithm> #include <cstdint> +#include <numeric> using namespace llvm; using namespace llvm::msf; @@ -41,39 +42,68 @@ void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) { VerHeader = Version; } +void TpiStreamBuilder::updateTypeIndexOffsets(ArrayRef<uint16_t> Sizes) { + // If we just crossed an 8KB threshold, add a type index offset. + for (uint16_t Size : Sizes) { + size_t NewSize = TypeRecordBytes + Size; + constexpr size_t EightKB = 8 * 1024; + if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecordCount == 0) { + TypeIndexOffsets.push_back( + {codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + + TypeRecordCount), + ulittle32_t(TypeRecordBytes)}); + } + ++TypeRecordCount; + TypeRecordBytes = NewSize; + } +} + void TpiStreamBuilder::addTypeRecord(ArrayRef<uint8_t> Record, Optional<uint32_t> Hash) { - // If we just crossed an 8KB threshold, add a type index offset. assert(((Record.size() & 3) == 0) && "The type record's size is not a multiple of 4 bytes which will " "cause misalignment in the output TPI stream!"); - size_t NewSize = TypeRecordBytes + Record.size(); - constexpr size_t EightKB = 8 * 1024; - if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecords.empty()) { - TypeIndexOffsets.push_back( - {codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + - TypeRecords.size()), - ulittle32_t(TypeRecordBytes)}); - } - TypeRecordBytes = NewSize; + assert(Record.size() <= codeview::MaxRecordLength); + uint16_t OneSize = (uint16_t)Record.size(); + updateTypeIndexOffsets(makeArrayRef(&OneSize, 1)); - TypeRecords.push_back(Record); + TypeRecBuffers.push_back(Record); + // FIXME: Require it. if (Hash) TypeHashes.push_back(*Hash); } +void TpiStreamBuilder::addTypeRecords(ArrayRef<uint8_t> Types, + ArrayRef<uint16_t> Sizes, + ArrayRef<uint32_t> Hashes) { + // Ignore empty type buffers. There should be no hashes or sizes in this case. + if (Types.empty()) { + assert(Sizes.empty() && Hashes.empty()); + return; + } + + assert(((Types.size() & 3) == 0) && + "The type record's size is not a multiple of 4 bytes which will " + "cause misalignment in the output TPI stream!"); + assert(Sizes.size() == Hashes.size() && "sizes and hashes should be in sync"); + assert(std::accumulate(Sizes.begin(), Sizes.end(), 0U) == Types.size() && + "sizes of type records should sum to the size of the types"); + updateTypeIndexOffsets(Sizes); + + TypeRecBuffers.push_back(Types); + llvm::append_range(TypeHashes, Hashes); +} + Error TpiStreamBuilder::finalize() { if (Header) return Error::success(); TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>(); - uint32_t Count = TypeRecords.size(); - H->Version = VerHeader; H->HeaderSize = sizeof(TpiStreamHeader); H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex; - H->TypeIndexEnd = H->TypeIndexBegin + Count; + H->TypeIndexEnd = H->TypeIndexBegin + TypeRecordCount; H->TypeRecordBytes = TypeRecordBytes; H->HashStreamIndex = HashStreamIndex; @@ -104,7 +134,7 @@ uint32_t TpiStreamBuilder::calculateSerializedLength() { } uint32_t TpiStreamBuilder::calculateHashBufferSize() const { - assert((TypeRecords.size() == TypeHashes.size() || TypeHashes.empty()) && + assert((TypeRecordCount == TypeHashes.size() || TypeHashes.empty()) && "either all or no type records should have hashes"); return TypeHashes.size() * sizeof(ulittle32_t); } @@ -155,7 +185,7 @@ Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout, if (auto EC = Writer.writeObject(*Header)) return EC; - for (auto Rec : TypeRecords) { + for (auto Rec : TypeRecBuffers) { assert(!Rec.empty() && "Attempting to write an empty type record shifts " "all offsets in the TPI stream!"); assert(((Rec.size() & 3) == 0) && |