LLVM  4.0.0
TpiStreamBuilder.cpp
Go to the documentation of this file.
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"
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 TpiStreamBuilder::TpiStreamBuilder(MSFBuilder &Msf, uint32_t StreamIdx)
37  : Msf(Msf), Allocator(Msf.getAllocator()), Header(nullptr), Idx(StreamIdx) {
38 }
39 
41 
43  VerHeader = Version;
44 }
45 
47  TypeRecords.push_back(Record);
48  TypeRecordStream.setItems(TypeRecords);
49 }
50 
51 Error TpiStreamBuilder::finalize() {
52  if (Header)
53  return Error::success();
54 
56 
57  uint32_t Count = TypeRecords.size();
58  uint32_t HashBufferSize = calculateHashBufferSize();
59 
60  H->Version = *VerHeader;
61  H->HeaderSize = sizeof(TpiStreamHeader);
63  H->TypeIndexEnd = H->TypeIndexBegin + Count;
64  H->TypeRecordBytes = TypeRecordStream.getLength();
65 
66  H->HashStreamIndex = HashStreamIndex;
68  H->HashKeySize = sizeof(ulittle32_t);
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  H->HashValueBuffer.Off = 0;
75  H->HashValueBuffer.Length = HashBufferSize;
77  H->HashAdjBuffer.Length = 0;
80 
81  Header = H;
82  return Error::success();
83 }
84 
86  return sizeof(TpiStreamHeader) + TypeRecordStream.getLength();
87 }
88 
89 uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
90  if (TypeRecords.empty() || !TypeRecords[0].Hash.hasValue())
91  return 0;
92  return TypeRecords.size() * sizeof(ulittle32_t);
93 }
94 
97  if (auto EC = Msf.setStreamSize(Idx, Length))
98  return EC;
99 
100  uint32_t HashBufferSize = calculateHashBufferSize();
101 
102  if (HashBufferSize == 0)
103  return Error::success();
104 
105  auto ExpectedIndex = Msf.addStream(HashBufferSize);
106  if (!ExpectedIndex)
107  return ExpectedIndex.takeError();
108  HashStreamIndex = *ExpectedIndex;
109  ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeRecords.size());
110  MutableArrayRef<ulittle32_t> HashBuffer(H, TypeRecords.size());
111  for (uint32_t I = 0; I < TypeRecords.size(); ++I) {
112  HashBuffer[I] = *TypeRecords[I].Hash % MinTpiHashBuckets;
113  }
114  ArrayRef<uint8_t> Bytes(reinterpret_cast<const uint8_t *>(HashBuffer.data()),
115  HashBufferSize);
116  HashValueStream = llvm::make_unique<ByteStream>(Bytes);
117  return Error::success();
118 }
119 
121  const msf::WritableStream &Buffer) {
122  if (auto EC = finalize())
123  return EC;
124 
125  auto InfoS =
126  WritableMappedBlockStream::createIndexedStream(Layout, Buffer, Idx);
127 
128  StreamWriter Writer(*InfoS);
129  if (auto EC = Writer.writeObject(*Header))
130  return EC;
131 
132  auto RecordArray = VarStreamArray<codeview::CVType>(TypeRecordStream);
133  if (auto EC = Writer.writeArray(RecordArray))
134  return EC;
135 
136  if (HashStreamIndex != kInvalidStreamIndex) {
137  auto HVS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
138  HashStreamIndex);
139  StreamWriter HW(*HVS);
140  if (auto EC = HW.writeStreamRef(*HashValueStream))
141  return EC;
142  }
143 
144  return Error::success();
145 }
support::ulittle16_t HashStreamIndex
Definition: RawTypes.h:284
EmbeddedBuf IndexOffsetBuffer
Definition: RawTypes.h:290
support::ulittle32_t NumHashBuckets
Definition: RawTypes.h:287
uint32_t getLength() const override
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
support::ulittle32_t TypeRecordBytes
Definition: RawTypes.h:281
uint32_t calculateSerializedLength() const
Error writeStreamRef(ReadableStreamRef Ref)
Error writeObject(const T &Obj)
Definition: StreamWriter.h:49
void addTypeRecord(const codeview::CVType &Record)
static const uint32_t FirstNonSimpleIndex
Definition: TypeIndex.h:91
const uint16_t kInvalidStreamIndex
Definition: RawConstants.h:20
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:283
support::ulittle32_t TypeIndexEnd
Definition: RawTypes.h:280
#define H(x, y, z)
Definition: MD5.cpp:53
Greedy Register Allocator
support::ulittle32_t TypeIndexBegin
Definition: RawTypes.h:279
Error setStreamSize(uint32_t Idx, uint32_t Size)
Update the size of an existing stream.
Definition: MSFBuilder.cpp:164
Error writeArray(ArrayRef< T > Array)
Definition: StreamWriter.h:58
const uint32_t MinTpiHashBuckets
Definition: RawTypes.h:294
static ErrorSuccess success()
Create a success value.
Expected< uint32_t > addStream(uint32_t Size, ArrayRef< uint32_t > Blocks)
Add a stream to the MSF file with the given size, occupying the given list of blocks.
Definition: MSFBuilder.cpp:127
EmbeddedBuf HashValueBuffer
Definition: RawTypes.h:289
void setVersionHeader(PdbRaw_TpiVer Version)
support::ulittle16_t HashAuxStreamIndex
Definition: RawTypes.h:285
void setItems(ArrayRef< T > ItemArray)
#define I(x, y, z)
Definition: MD5.cpp:54
support::ulittle32_t HashKeySize
Definition: RawTypes.h:286
support::ulittle32_t HeaderSize
Definition: RawTypes.h:278
Error commit(const msf::MSFLayout &Layout, const msf::WritableStream &Buffer)
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:235
support::ulittle32_t Version
Definition: RawTypes.h:277
Lightweight error class with error context and mandatory checking.
EmbeddedBuf HashAdjBuffer
Definition: RawTypes.h:291
const uint64_t Version
Definition: InstrProf.h:799