47 FreeBlocks[BlockMapAddr] =
false;
52 uint32_t MinBlockCount,
bool CanGrow) {
55 "The requested block size is unsupported");
63 if (
Addr == BlockMapAddr)
69 "Cannot grow the number of blocks");
74 return make_error<MSFError>(
76 "Requested block map address is already in use");
77 FreeBlocks[BlockMapAddr] =
true;
78 FreeBlocks[
Addr] =
false;
88 for (
auto B : DirectoryBlocks)
90 for (
auto B : DirBlocks) {
93 "Attempt to reuse an allocated block");
95 FreeBlocks[
B] =
false;
98 DirectoryBlocks = DirBlocks;
108 if (NumFreeBlocks < NumBlocks) {
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);
124 while (NextFpmBlock < NewBlockCount) {
126 FreeBlocks.
resize(NewBlockCount,
true);
127 FreeBlocks.
reset(NextFpmBlock, NextFpmBlock + 2);
128 NextFpmBlock += BlockSize;
139 FreeBlocks.
reset(NextBlock);
141 }
while (--NumBlocks > 0);
161 if (ReqBlocks !=
Blocks.size())
162 return make_error<MSFError>(
164 "Incorrect number of blocks for requested stream size");
170 return make_error<MSFError>(
172 "Attempt to re-use an already allocated block");
178 StreamData.push_back(std::make_pair(
Size,
Blocks));
179 return StreamData.size() - 1;
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;
200 if (NewBlocks > OldBlocks) {
201 uint32_t AddedBlocks = NewBlocks - OldBlocks;
203 std::vector<uint32_t> AddedBlockList;
204 AddedBlockList.resize(AddedBlocks);
205 if (
auto EC = allocateBlocks(AddedBlocks, AddedBlockList))
207 auto &CurrentBlocks = StreamData[
Idx].second;
209 }
else if (OldBlocks > NewBlocks) {
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);
227 return StreamData[StreamIdx].first;
231 return StreamData[StreamIdx].second;
234uint32_t MSFBuilder::computeDirectoryByteSize()
const {
241 for (
const auto &
D : StreamData) {
243 assert(ExpectedNumBlocks ==
D.second.size() &&
244 "Unexpected number of blocks");
263 if (NumDirectoryBlocks > DirectoryBlocks.size()) {
266 std::vector<uint32_t> ExtraBlocks;
267 uint32_t NumExtraBlocks = NumDirectoryBlocks - DirectoryBlocks.size();
268 ExtraBlocks.resize(NumExtraBlocks);
269 if (
auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks))
270 return std::move(EC);
272 }
else if (NumDirectoryBlocks < DirectoryBlocks.size()) {
273 uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks;
276 FreeBlocks[
B] =
true;
277 DirectoryBlocks.resize(NumDirectoryBlocks);
286 std::uninitialized_copy_n(DirectoryBlocks.begin(), NumDirectoryBlocks,
292 if (!StreamData.empty()) {
295 L.StreamMap.resize(StreamData.size());
297 Sizes[
I] = StreamData[
I].first;
300 std::uninitialized_copy_n(StreamData[
I].second.begin(),
301 StreamData[
I].second.size(), BlockList);
307 L.FreePageMap = FreeBlocks;
323 while (BI < Layout.SB->NumBlocks) {
324 uint8_t ThisByte = 0;
328 uint8_t Mask = uint8_t(IsFree) <<
I;
341 return L.takeError();
343 Layout = std::move(*L);
361 return make_error<MSFError>(
363 formatv(
"File size {0,1:N} too large for current PDB page size {1}",
371 if (DirectoryBlockMapSize > Layout.
SB->
BlockSize) {
373 formatv(
"The directory block map ({0} bytes) "
374 "doesn't fit in a block ({1} bytes)",
375 DirectoryBlockMapSize,
380 if (
auto EC = OutFileOrError.takeError())
381 return std::move(EC);
388 return std::move(EC);
396 return std::move(EC);
399 Layout, Buffer, Allocator);
402 return std::move(EC);
405 return std::move(EC);
409 return std::move(EC);
412 return std::move(Buffer);
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
DenseMap< Block *, BlockRelaxAux > Blocks
static const uint32_t kFreePageMap1Block
static void commitFpm(WritableBinaryStream &MsfBuffer, const MSFLayout &Layout, BumpPtrAllocator &Allocator)
static const uint32_t kSuperBlockBlock
static const uint32_t kFreePageMap0Block
static const uint32_t kDefaultBlockMapAddr
static const uint32_t kNumReservedPages
static const uint32_t kDefaultFreePageMap
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const int BlockSize
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
Allocate memory in an ever growing pool, as if by bump-pointer.
LLVM_ATTRIBUTE_RETURNS_NONNULL void * Allocate(size_t Size, Align Alignment)
Allocate space at the specified alignment.
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 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.
A BinaryStream which can be read from as well as written to.
uint32_t getNumStreams() const
Get the total number of streams in the MSF layout.
Error setBlockMapAddr(uint32_t Addr)
Request the block map to be at a specific block address.
ArrayRef< uint32_t > getStreamBlocks(uint32_t StreamIdx) const
Get the list of blocks allocated to a particular stream.
Error setDirectoryBlocksHint(ArrayRef< uint32_t > DirBlocks)
uint32_t getTotalBlockCount() const
Get the total number of blocks in the MSF file.
uint32_t getNumFreeBlocks() const
Get the total number of blocks that exist in the MSF file but are not allocated to any valid data.
Error setStreamSize(uint32_t Idx, uint32_t Size)
Update the size of an existing stream.
Expected< FileBufferByteStream > commit(StringRef Path, MSFLayout &Layout)
Write the MSF layout to the underlying file.
Expected< MSFLayout > generateLayout()
Finalize the layout and build the headers and structures that describe the MSF layout and can be writ...
bool isBlockFree(uint32_t Idx) const
Check whether a particular block is allocated or free.
void setFreePageMap(uint32_t Fpm)
uint32_t getStreamSize(uint32_t StreamIdx) const
Get the size of a stream by index.
static Expected< MSFBuilder > create(BumpPtrAllocator &Allocator, uint32_t BlockSize, uint32_t MinBlockCount=0, bool CanGrow=true)
Create a new MSFBuilder.
uint32_t getNumUsedBlocks() const
Get the total number of blocks that will be allocated to actual data in this MSF file.
void setUnknown1(uint32_t Unk1)
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.
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, little, unaligned > ulittle32_t
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
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< 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