LCOV - code coverage report
Current view: top level - lib/DebugInfo/PDB/Raw - TpiStreamBuilder.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 51 73 69.9 %
Date: 2017-01-24 23:09:07 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- TpiStreamBuilder.cpp -   -------------------------------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/ADT/ArrayRef.h"
      11             : #include "llvm/ADT/STLExtras.h"
      12             : #include "llvm/DebugInfo/CodeView/TypeIndex.h"
      13             : #include "llvm/DebugInfo/CodeView/TypeRecord.h"
      14             : #include "llvm/DebugInfo/MSF/ByteStream.h"
      15             : #include "llvm/DebugInfo/MSF/MSFBuilder.h"
      16             : #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
      17             : #include "llvm/DebugInfo/MSF/StreamArray.h"
      18             : #include "llvm/DebugInfo/MSF/StreamReader.h"
      19             : #include "llvm/DebugInfo/MSF/StreamWriter.h"
      20             : #include "llvm/DebugInfo/PDB/Raw/PDBFile.h"
      21             : #include "llvm/DebugInfo/PDB/Raw/RawError.h"
      22             : #include "llvm/DebugInfo/PDB/Raw/RawTypes.h"
      23             : #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
      24             : #include "llvm/DebugInfo/PDB/Raw/TpiStreamBuilder.h"
      25             : #include "llvm/Support/Allocator.h"
      26             : #include "llvm/Support/Endian.h"
      27             : #include "llvm/Support/Error.h"
      28             : #include <algorithm>
      29             : #include <cstdint>
      30             : 
      31             : using namespace llvm;
      32             : using namespace llvm::msf;
      33             : using namespace llvm::pdb;
      34             : using namespace llvm::support;
      35             : 
      36           6 : TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
      37          30 :     : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
      38           6 : }
      39             : 
      40             : TpiStreamBuilder::~TpiStreamBuilder() = default;
      41             : 
      42           6 : void TpiStreamBuilder::setVersionHeader(PdbRaw_TpiVer Version) {
      43          12 :   VerHeader = Version;
      44           6 : }
      45             : 
      46         167 : void TpiStreamBuilder::addTypeRecord(const codeview::CVType &Record) {
      47         167 :   TypeRecords.push_back(Record);
      48         334 :   TypeRecordStream.setItems(TypeRecords);
      49         167 : }
      50             : 
      51           6 : Error TpiStreamBuilder::finalize() {
      52           6 :   if (Header)
      53           0 :     return Error::success();
      54             : 
      55          12 :   TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>();
      56             : 
      57          12 :   uint32_t Count = TypeRecords.size();
      58           6 :   uint32_t HashBufferSize = calculateHashBufferSize();
      59             : 
      60          18 :   H->Version = *VerHeader;
      61          12 :   H->HeaderSize = sizeof(TpiStreamHeader);
      62          12 :   H->TypeIndexBegin = codeview::TypeIndex::FirstNonSimpleIndex;
      63          18 :   H->TypeIndexEnd = H->TypeIndexBegin + Count;
      64          18 :   H->TypeRecordBytes = TypeRecordStream.getLength();
      65             : 
      66          12 :   H->HashStreamIndex = HashStreamIndex;
      67          12 :   H->HashAuxStreamIndex = kInvalidStreamIndex;
      68          12 :   H->HashKeySize = sizeof(ulittle32_t);
      69          12 :   H->NumHashBuckets = MinTpiHashBuckets;
      70             : 
      71             :   // Recall that hash values go into a completely different stream identified by
      72             :   // the `HashStreamIndex` field of the `TpiStreamHeader`.  Therefore, the data
      73             :   // begins at offset 0 of this independent stream.
      74          12 :   H->HashValueBuffer.Off = 0;
      75          12 :   H->HashValueBuffer.Length = HashBufferSize;
      76          24 :   H->HashAdjBuffer.Off = H->HashValueBuffer.Off + H->HashValueBuffer.Length;
      77          12 :   H->HashAdjBuffer.Length = 0;
      78          24 :   H->IndexOffsetBuffer.Off = H->HashAdjBuffer.Off + H->HashAdjBuffer.Length;
      79          12 :   H->IndexOffsetBuffer.Length = 0;
      80             : 
      81           6 :   Header = H;
      82          18 :   return Error::success();
      83             : }
      84             : 
      85           6 : uint32_t TpiStreamBuilder::calculateSerializedLength() const {
      86          12 :   return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
      87             : }
      88             : 
      89          12 : uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
      90          24 :   if (TypeRecords.empty() || !TypeRecords[0].Hash.hasValue())
      91             :     return 0;
      92           0 :   return TypeRecords.size() * sizeof(ulittle32_t);
      93             : }
      94             : 
      95           6 : Error TpiStreamBuilder::finalizeMsfLayout() {
      96           6 :   uint32_t Length = calculateSerializedLength();
      97          18 :   if (auto EC = Msf.setStreamSize(Idx, Length))
      98           0 :     return EC;
      99             : 
     100           6 :   uint32_t HashBufferSize = calculateHashBufferSize();
     101             : 
     102           6 :   if (HashBufferSize == 0)
     103          18 :     return Error::success();
     104             : 
     105           0 :   auto ExpectedIndex = Msf.addStream(HashBufferSize);
     106           0 :   if (!ExpectedIndex)
     107           0 :     return ExpectedIndex.takeError();
     108           0 :   HashStreamIndex = *ExpectedIndex;
     109           0 :   ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeRecords.size());
     110           0 :   MutableArrayRef<ulittle32_t> HashBuffer(H, TypeRecords.size());
     111           0 :   for (uint32_t I = 0; I < TypeRecords.size(); ++I) {
     112           0 :     HashBuffer[I] = *TypeRecords[I].Hash % MinTpiHashBuckets;
     113             :   }
     114           0 :   ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(HashBuffer.data()),
     115           0 :                           HashBufferSize);
     116           0 :   HashValueStream = llvm::make_unique<ByteStream>(Bytes);
     117           0 :   return Error::success();
     118             : }
     119             : 
     120           6 : Error TpiStreamBuilder::commit(const msf::MSFLayout &Layout,
     121             :                                const msf::WritableStream &Buffer) {
     122          18 :   if (auto EC = finalize())
     123           0 :     return EC;
     124             : 
     125             :   auto InfoS =
     126           6 :       WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx);
     127             : 
     128          12 :   StreamWriter Writer(*InfoS);
     129          24 :   if (auto EC = Writer.writeObject(*Header))
     130           0 :     return EC;
     131             : 
     132          18 :   auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream);
     133          24 :   if (auto EC = Writer.writeArray(RecordArray))
     134           0 :     return EC;
     135             : 
     136           6 :   if (HashStreamIndex != kInvalidStreamIndex) {
     137             :     auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
     138           0 :                                                               HashStreamIndex);
     139           0 :     StreamWriter HW(*HVS);
     140           0 :     if (auto EC = HW.writeStreamRef(*HashValueStream))
     141           0 :       return EC;
     142             :   }
     143             : 
     144          18 :   return Error::success();
     145             : }

Generated by: LCOV version 1.13