LLVM: lib/DebugInfo/MSF/MSFBuilder.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
20#include
21#include
22#include
23#include
24#include
25#include
26
27using namespace llvm;
30
35
38
47 FreeBlocks[BlockMapAddr] = false;
48}
49
52 uint32_t MinBlockCount, bool CanGrow) {
55 "The requested block size is unsupported");
56
57 return MSFBuilder(BlockSize,
59 CanGrow, Allocator);
60}
61
63 if (Addr == BlockMapAddr)
65
66 if (Addr >= FreeBlocks.size()) {
67 if (!IsGrowable)
69 "Cannot grow the number of blocks");
70 FreeBlocks.resize(Addr + 1, true);
71 }
72
76 "Requested block map address is already in use");
77 FreeBlocks[BlockMapAddr] = true;
78 FreeBlocks[Addr] = false;
79 BlockMapAddr = Addr;
81}
82
84
86
88 for (auto B : DirectoryBlocks)
89 FreeBlocks[B] = true;
90 for (auto B : DirBlocks) {
93 "Attempt to reuse an allocated block");
94 }
95 FreeBlocks[B] = false;
96 }
97
98 DirectoryBlocks = DirBlocks;
100}
101
102Error MSFBuilder::allocateBlocks(uint32_t NumBlocks,
104 if (NumBlocks == 0)
106
108 if (NumFreeBlocks < NumBlocks) {
109 if (!IsGrowable)
111 "There are no free Blocks in the file");
112 uint32_t AllocBlocks = NumBlocks - NumFreeBlocks;
114 uint32_t NewBlockCount = AllocBlocks + OldBlockCount;
116 FreeBlocks.resize(NewBlockCount, true);
117
118
119
120
121
122
123
124 while (NextFpmBlock < NewBlockCount) {
125 NewBlockCount += 2;
126 FreeBlocks.resize(NewBlockCount, true);
127 FreeBlocks.reset(NextFpmBlock, NextFpmBlock + 2);
129 }
130 }
131
132 int I = 0;
134 do {
135 assert(Block != -1 && "We ran out of Blocks!");
136
138 Blocks[I++] = NextBlock;
139 FreeBlocks.reset(NextBlock);
141 } while (--NumBlocks > 0);
143}
144
148
150
152
154
157
158
159
161 if (ReqBlocks != Blocks.size())
164 "Incorrect number of blocks for requested stream size");
165 for (auto Block : Blocks) {
166 if (Block >= FreeBlocks.size())
167 FreeBlocks.resize(Block + 1, true);
168
169 if (!FreeBlocks.test(Block))
172 "Attempt to re-use an already allocated block");
173 }
174
175 for (auto Block : Blocks) {
176 FreeBlocks.reset(Block);
177 }
178 StreamData.push_back(std::make_pair(Size, Blocks));
179 return StreamData.size() - 1;
180}
181
184 std::vector<uint32_t> NewBlocks;
185 NewBlocks.resize(ReqBlocks);
186 if (auto EC = allocateBlocks(ReqBlocks, NewBlocks))
187 return std::move(EC);
188 StreamData.push_back(std::make_pair(Size, NewBlocks));
189 return StreamData.size() - 1;
190}
191
194 if (OldSize == Size)
196
199
200 if (NewBlocks > OldBlocks) {
201 uint32_t AddedBlocks = NewBlocks - OldBlocks;
202
203 std::vector<uint32_t> AddedBlockList;
204 AddedBlockList.resize(AddedBlocks);
205 if (auto EC = allocateBlocks(AddedBlocks, AddedBlockList))
206 return EC;
207 auto &CurrentBlocks = StreamData[Idx].second;
209 } else if (OldBlocks > NewBlocks) {
210
211
212 uint32_t RemovedBlocks = OldBlocks - NewBlocks;
214 auto RemovedBlockList = CurrentBlocks.drop_front(NewBlocks);
215 for (auto P : RemovedBlockList)
216 FreeBlocks[P] = true;
217 StreamData[Idx].second = CurrentBlocks.drop_back(RemovedBlocks);
218 }
219
220 StreamData[Idx].first = Size;
222}
223
225
227 return StreamData[StreamIdx].first;
228}
229
231 return StreamData[StreamIdx].second;
232}
233
234uint32_t MSFBuilder::computeDirectoryByteSize() const {
235
236
237
238
240 Size += StreamData.size() * sizeof(ulittle32_t);
241 for (const auto &D : StreamData) {
243 assert(ExpectedNumBlocks == D.second.size() &&
244 "Unexpected number of blocks");
246 }
248}
249
252
255 L.SB = SB;
256
263
265 if (NumDirectoryBlocks > DirectoryBlocks.size()) {
266
267
268 std::vector<uint32_t> ExtraBlocks;
269 uint32_t NumExtraBlocks = NumDirectoryBlocks - DirectoryBlocks.size();
270 ExtraBlocks.resize(NumExtraBlocks);
271 if (auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks))
272 return std::move(EC);
274 } else if (NumDirectoryBlocks < DirectoryBlocks.size()) {
275 uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks;
276 for (auto B :
278 FreeBlocks[B] = true;
279 DirectoryBlocks.resize(NumDirectoryBlocks);
280 }
281
282
283
284
285 SB->NumBlocks = FreeBlocks.size();
286
290
291
292
293 if (!StreamData.empty()) {
296 L.StreamMap.resize(StreamData.size());
297 for (uint32_t I = 0; I < StreamData.size(); ++I) {
298 Sizes[I] = StreamData[I].first;
300 Allocator.Allocate<ulittle32_t>(StreamData[I].second.size());
302 L.StreamMap[I] =
304 }
305 }
306
307 L.FreePageMap = FreeBlocks;
308
309 return L;
310}
311
314 auto FpmStream =
316
317
319 true);
320
323 while (BI < Layout.SB->NumBlocks) {
326 bool IsFree =
329 ThisByte |= Mask;
330 ++BI;
331 }
333 }
335}
336
340
342 if (!L)
343 return L.takeError();
344
345 Layout = std::move(*L);
346
348
351 switch (BlockSize) {
352 case 8192:
354 case 16384:
356 case 32768:
358 default:
360 }
362
364 error_code,
365 formatv("File size {0,1:N} too large for current PDB page size {1}",
367 }
368
369 uint64_t NumDirectoryBlocks =
371 uint64_t DirectoryBlockMapSize =
373 if (DirectoryBlockMapSize > Layout.SB->BlockSize) {
375 formatv("The directory block map ({0} bytes) "
376 "doesn't fit in a block ({1} bytes)",
377 DirectoryBlockMapSize,
379 }
380
382 if (auto EC = OutFileOrError.takeError())
383 return std::move(EC);
384
388
390 return std::move(EC);
391
392 commitFpm(Buffer, Layout, Allocator);
393
396 Writer.setOffset(BlockMapOffset);
398 return std::move(EC);
399
401 Layout, Buffer, Allocator);
404 return std::move(EC);
405
407 return std::move(EC);
408
409 for (const auto &Blocks : Layout.StreamMap) {
411 return std::move(EC);
412 }
413
414 return std::move(Buffer);
415}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static const uint32_t kFreePageMap1Block
Definition MSFBuilder.cpp:33
static void commitFpm(WritableBinaryStream &MsfBuffer, const MSFLayout &Layout, BumpPtrAllocator &Allocator)
Definition MSFBuilder.cpp:312
static const uint32_t kSuperBlockBlock
Definition MSFBuilder.cpp:31
static const uint32_t kFreePageMap0Block
Definition MSFBuilder.cpp:32
static const uint32_t kDefaultBlockMapAddr
Definition MSFBuilder.cpp:37
static const uint32_t kNumReservedPages
Definition MSFBuilder.cpp:34
static const uint32_t kDefaultFreePageMap
Definition MSFBuilder.cpp:36
static const int BlockSize
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
Provides write only access to a subclass of WritableBinaryStream.
Error writeArray(ArrayRef< T > Array)
Writes an array of objects of type T to the underlying stream, as if by using memcpy.
Error writeInteger(T Value)
Write the integer Value to the underlying stream in the specified endianness.
uint64_t bytesRemaining() const
void setOffset(uint64_t Off)
Error writeObject(const T &Obj)
Writes the object Obj to the underlying stream, as if by using memcpy.
bool test(unsigned Idx) const
int find_first() const
find_first - Returns the index of the first set bit, -1 if none of the bits are set.
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
size_type count() const
count - Returns the number of bits which are set.
int find_next(unsigned Prev) const
find_next - Returns the index of the next set bit following the "Prev" bit.
size_type size() const
size - Returns the number of bits in this bitvector.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
static LLVM_ABI Expected< std::unique_ptr< FileOutputBuffer > > create(StringRef FilePath, size_t Size, unsigned Flags=0)
Factory method to create an OutputBuffer object which manages a read/write buffer of the specified si...
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
StringRef - Represent a constant reference to a string, i.e.
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
A BinaryStream which can be read from as well as written to.
LLVM_ABI uint32_t getNumStreams() const
Get the total number of streams in the MSF layout.
Definition MSFBuilder.cpp:224
LLVM_ABI Error setBlockMapAddr(uint32_t Addr)
Request the block map to be at a specific block address.
Definition MSFBuilder.cpp:62
LLVM_ABI ArrayRef< uint32_t > getStreamBlocks(uint32_t StreamIdx) const
Get the list of blocks allocated to a particular stream.
Definition MSFBuilder.cpp:230
LLVM_ABI Error setDirectoryBlocksHint(ArrayRef< uint32_t > DirBlocks)
Definition MSFBuilder.cpp:87
LLVM_ABI uint32_t getTotalBlockCount() const
Get the total number of blocks in the MSF file.
Definition MSFBuilder.cpp:151
LLVM_ABI uint32_t getNumFreeBlocks() const
Get the total number of blocks that exist in the MSF file but are not allocated to any valid data.
Definition MSFBuilder.cpp:149
LLVM_ABI Error setStreamSize(uint32_t Idx, uint32_t Size)
Update the size of an existing stream.
Definition MSFBuilder.cpp:192
LLVM_ABI Expected< FileBufferByteStream > commit(StringRef Path, MSFLayout &Layout)
Write the MSF layout to the underlying file.
Definition MSFBuilder.cpp:337
LLVM_ABI Expected< MSFLayout > generateLayout()
Finalize the layout and build the headers and structures that describe the MSF layout and can be writ...
Definition MSFBuilder.cpp:250
LLVM_ABI bool isBlockFree(uint32_t Idx) const
Check whether a particular block is allocated or free.
Definition MSFBuilder.cpp:153
LLVM_ABI void setFreePageMap(uint32_t Fpm)
Definition MSFBuilder.cpp:83
LLVM_ABI uint32_t getStreamSize(uint32_t StreamIdx) const
Get the size of a stream by index.
Definition MSFBuilder.cpp:226
static LLVM_ABI Expected< MSFBuilder > create(BumpPtrAllocator &Allocator, uint32_t BlockSize, uint32_t MinBlockCount=0, bool CanGrow=true)
Create a new MSFBuilder.
Definition MSFBuilder.cpp:50
LLVM_ABI uint32_t getNumUsedBlocks() const
Get the total number of blocks that will be allocated to actual data in this MSF file.
Definition MSFBuilder.cpp:145
LLVM_ABI void setUnknown1(uint32_t Unk1)
Definition MSFBuilder.cpp:85
LLVM_ABI 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:155
static std::unique_ptr< WritableMappedBlockStream > createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator, bool AltFpm=false)
static std::unique_ptr< WritableMappedBlockStream > createDirectoryStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, BumpPtrAllocator &Allocator)
uint32_t getMinimumBlockCount()
uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize)
uint64_t getMaxFileSizeFromBlockSize(uint32_t Size)
Given the specified block size, returns the maximum possible file size.
bool isValidBlockSize(uint32_t Size)
@ stream_directory_overflow
uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize)
static const char Magic[]
detail::packed_endian_specific_integral< uint32_t, llvm::endianness::little, unaligned > ulittle32_t
This is an optimization pass for GlobalISel generic memory operations.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
auto uninitialized_copy(R &&Src, IterTy Dst)
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ArrayRef(const T &OneElt) -> ArrayRef< T >
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
ArrayRef< support::ulittle32_t > StreamSizes
ArrayRef< support::ulittle32_t > DirectoryBlocks
std::vector< ArrayRef< support::ulittle32_t > > StreamMap
support::ulittle32_t NumBlocks
support::ulittle32_t BlockSize
support::ulittle32_t Unknown1
char MagicBytes[sizeof(Magic)]
support::ulittle32_t NumDirectoryBytes
support::ulittle32_t BlockMapAddr
support::ulittle32_t FreeBlockMapBlock