LLVM  6.0.0svn
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 
11 #include "llvm/ADT/ArrayRef.h"
12 #include "llvm/ADT/STLExtras.h"
21 #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  Optional<uint32_t> Hash) {
48  // If we just crossed an 8KB threshold, add a type index offset.
49  size_t NewSize = TypeRecordBytes + Record.size();
50  constexpr size_t EightKB = 8 * 1024;
51  if (NewSize / EightKB > TypeRecordBytes / EightKB || TypeRecords.empty()) {
52  TypeIndexOffsets.push_back(
54  TypeRecords.size()),
55  ulittle32_t(TypeRecordBytes)});
56  }
57  TypeRecordBytes = NewSize;
58 
59  TypeRecords.push_back(Record);
60  if (Hash)
61  TypeHashes.push_back(*Hash);
62 }
63 
64 Error TpiStreamBuilder::finalize() {
65  if (Header)
66  return Error::success();
67 
68  TpiStreamHeader *H = Allocator.Allocate<TpiStreamHeader>();
69 
70  uint32_t Count = TypeRecords.size();
71 
72  H->Version = VerHeader;
73  H->HeaderSize = sizeof(TpiStreamHeader);
75  H->TypeIndexEnd = H->TypeIndexBegin + Count;
76  H->TypeRecordBytes = TypeRecordBytes;
77 
78  H->HashStreamIndex = HashStreamIndex;
80  H->HashKeySize = sizeof(ulittle32_t);
82 
83  // Recall that hash values go into a completely different stream identified by
84  // the `HashStreamIndex` field of the `TpiStreamHeader`. Therefore, the data
85  // begins at offset 0 of this independent stream.
86  H->HashValueBuffer.Off = 0;
87  H->HashValueBuffer.Length = calculateHashBufferSize();
88 
89  // We never write any adjustments into our PDBs, so this is usually some
90  // offset with zero length.
92  H->HashAdjBuffer.Length = 0;
93 
95  H->IndexOffsetBuffer.Length = calculateIndexOffsetSize();
96 
97  Header = H;
98  return Error::success();
99 }
100 
102  return sizeof(TpiStreamHeader) + TypeRecordBytes;
103 }
104 
105 uint32_t TpiStreamBuilder::calculateHashBufferSize() const {
106  assert((TypeRecords.size() == TypeHashes.size() || TypeHashes.empty()) &&
107  "either all or no type records should have hashes");
108  return TypeHashes.size() * sizeof(ulittle32_t);
109 }
110 
111 uint32_t TpiStreamBuilder::calculateIndexOffsetSize() const {
112  return TypeIndexOffsets.size() * sizeof(codeview::TypeIndexOffset);
113 }
114 
117  if (auto EC = Msf.setStreamSize(Idx, Length))
118  return EC;
119 
120  uint32_t HashStreamSize =
121  calculateHashBufferSize() + calculateIndexOffsetSize();
122 
123  if (HashStreamSize == 0)
124  return Error::success();
125 
126  auto ExpectedIndex = Msf.addStream(HashStreamSize);
127  if (!ExpectedIndex)
128  return ExpectedIndex.takeError();
129  HashStreamIndex = *ExpectedIndex;
130  if (!TypeHashes.empty()) {
131  ulittle32_t *H = Allocator.Allocate<ulittle32_t>(TypeHashes.size());
132  MutableArrayRef<ulittle32_t> HashBuffer(H, TypeHashes.size());
133  for (uint32_t I = 0; I < TypeHashes.size(); ++I) {
134  HashBuffer[I] = TypeHashes[I] % MinTpiHashBuckets;
135  }
136  ArrayRef<uint8_t> Bytes(
137  reinterpret_cast<const uint8_t *>(HashBuffer.data()),
138  calculateHashBufferSize());
139  HashValueStream =
140  llvm::make_unique<BinaryByteStream>(Bytes, llvm::support::little);
141  }
142  return Error::success();
143 }
144 
146  WritableBinaryStreamRef Buffer) {
147  if (auto EC = finalize())
148  return EC;
149 
150  auto InfoS = WritableMappedBlockStream::createIndexedStream(Layout, Buffer,
151  Idx, Allocator);
152 
153  BinaryStreamWriter Writer(*InfoS);
154  if (auto EC = Writer.writeObject(*Header))
155  return EC;
156 
157  for (auto Rec : TypeRecords)
158  if (auto EC = Writer.writeBytes(Rec))
159  return EC;
160 
161  if (HashStreamIndex != kInvalidStreamIndex) {
162  auto HVS = WritableMappedBlockStream::createIndexedStream(
163  Layout, Buffer, HashStreamIndex, Allocator);
164  BinaryStreamWriter HW(*HVS);
165  if (HashValueStream) {
166  if (auto EC = HW.writeStreamRef(*HashValueStream))
167  return EC;
168  }
169 
170  for (auto &IndexOffset : TypeIndexOffsets) {
171  if (auto EC = HW.writeObject(IndexOffset))
172  return EC;
173  }
174  }
175 
176  return Error::success();
177 }
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
Error writeBytes(ArrayRef< uint8_t > Buffer)
Write the bytes specified in Buffer to the underlying stream.
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
support::ulittle16_t HashStreamIndex
Definition: RawTypes.h:301
EmbeddedBuf IndexOffsetBuffer
Definition: RawTypes.h:307
support::ulittle32_t NumHashBuckets
Definition: RawTypes.h:304
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer)
This file defines the MallocAllocator and BumpPtrAllocator interfaces.
support::ulittle32_t TypeRecordBytes
Definition: RawTypes.h:298
static const uint32_t FirstNonSimpleIndex
Definition: TypeIndex.h:98
A 32-bit type reference.
Definition: TypeIndex.h:96
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:291
support::ulittle32_t TypeIndexEnd
Definition: RawTypes.h:297
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
Definition: Endian.h:271
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:149
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment)
Allocate space at the specified alignment.
Definition: Allocator.h:212
#define H(x, y, z)
Definition: MD5.cpp:57
Error writeStreamRef(BinaryStreamRef Ref)
Efficiently reads all data from Ref, and writes it to this stream.
Provides write only access to a subclass of WritableBinaryStream.
support::ulittle32_t TypeIndexBegin
Definition: RawTypes.h:296
Error setStreamSize(uint32_t Idx, uint32_t Size)
Update the size of an existing stream.
Definition: MSFBuilder.cpp:188
const uint32_t MinTpiHashBuckets
Definition: RawTypes.h:311
Basic Register Allocator
static ErrorSuccess success()
Create a success value.
Definition: Error.h:313
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:151
EmbeddedBuf HashValueBuffer
Definition: RawTypes.h:306
void setVersionHeader(PdbRaw_TpiVer Version)
support::ulittle16_t HashAuxStreamIndex
Definition: RawTypes.h:302
#define I(x, y, z)
Definition: MD5.cpp:58
support::ulittle32_t HashKeySize
Definition: RawTypes.h:303
support::ulittle32_t HeaderSize
Definition: RawTypes.h:295
void addTypeRecord(ArrayRef< uint8_t > Type, Optional< uint32_t > Hash)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
support::ulittle32_t Version
Definition: RawTypes.h:294
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
EmbeddedBuf HashAdjBuffer
Definition: RawTypes.h:308
const uint64_t Version
Definition: InstrProf.h:867