48 FreeBlocks[BlockMapAddr] =
false;
53 uint32_t MinBlockCount,
bool CanGrow) {
56 "The requested block size is unsupported");
64 if (
Addr == BlockMapAddr)
70 "Cannot grow the number of blocks");
75 return make_error<MSFError>(
77 "Requested block map address is already in use");
78 FreeBlocks[BlockMapAddr] =
true;
79 FreeBlocks[
Addr] =
false;
89 for (
auto B : DirectoryBlocks)
91 for (
auto B : DirBlocks) {
94 "Attempt to reuse an allocated block");
96 FreeBlocks[
B] =
false;
99 DirectoryBlocks = DirBlocks;
109 if (NumFreeBlocks < NumBlocks) {
112 "There are no free Blocks in the file");
113 uint32_t AllocBlocks = NumBlocks - NumFreeBlocks;
115 uint32_t NewBlockCount = AllocBlocks + OldBlockCount;
117 FreeBlocks.
resize(NewBlockCount,
true);
125 while (NextFpmBlock < NewBlockCount) {
127 FreeBlocks.
resize(NewBlockCount,
true);
128 FreeBlocks.
reset(NextFpmBlock, NextFpmBlock + 2);
129 NextFpmBlock += BlockSize;
140 FreeBlocks.
reset(NextBlock);
142 }
while (--NumBlocks > 0);
162 if (ReqBlocks !=
Blocks.size())
163 return make_error<MSFError>(
165 "Incorrect number of blocks for requested stream size");
171 return make_error<MSFError>(
173 "Attempt to re-use an already allocated block");
179 StreamData.push_back(std::make_pair(
Size,
Blocks));
180 return StreamData.size() - 1;
185 std::vector<uint32_t> NewBlocks;
186 NewBlocks.resize(ReqBlocks);
187 if (
auto EC = allocateBlocks(ReqBlocks, NewBlocks))
188 return std::move(EC);
189 StreamData.push_back(std::make_pair(
Size, NewBlocks));
190 return StreamData.size() - 1;
201 if (NewBlocks > OldBlocks) {
202 uint32_t AddedBlocks = NewBlocks - OldBlocks;
204 std::vector<uint32_t> AddedBlockList;
205 AddedBlockList.resize(AddedBlocks);
206 if (
auto EC = allocateBlocks(AddedBlocks, AddedBlockList))
208 auto &CurrentBlocks = StreamData[
Idx].second;
210 }
else if (OldBlocks > NewBlocks) {
213 uint32_t RemovedBlocks = OldBlocks - NewBlocks;
215 auto RemovedBlockList = CurrentBlocks.drop_front(NewBlocks);
216 for (
auto P : RemovedBlockList)
217 FreeBlocks[
P] =
true;
218 StreamData[
Idx].second = CurrentBlocks.drop_back(RemovedBlocks);
228 return StreamData[StreamIdx].first;
232 return StreamData[StreamIdx].second;
235uint32_t MSFBuilder::computeDirectoryByteSize()
const {
242 for (
const auto &
D : StreamData) {
244 assert(ExpectedNumBlocks ==
D.second.size() &&
245 "Unexpected number of blocks");
266 if (NumDirectoryBlocks > DirectoryBlocks.size()) {
269 std::vector<uint32_t> ExtraBlocks;
270 uint32_t NumExtraBlocks = NumDirectoryBlocks - DirectoryBlocks.size();
271 ExtraBlocks.resize(NumExtraBlocks);
272 if (
auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks))
273 return std::move(EC);
275 }
else if (NumDirectoryBlocks < DirectoryBlocks.size()) {
276 uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks;
279 FreeBlocks[
B] =
true;
280 DirectoryBlocks.resize(NumDirectoryBlocks);
289 std::uninitialized_copy_n(DirectoryBlocks.begin(), NumDirectoryBlocks,
295 if (!StreamData.empty()) {
298 L.StreamMap.resize(StreamData.size());
300 Sizes[
I] = StreamData[
I].first;
303 std::uninitialized_copy_n(StreamData[
I].second.begin(),
304 StreamData[
I].second.size(), BlockList);
310 L.FreePageMap = FreeBlocks;
326 while (BI < Layout.SB->NumBlocks) {
327 uint8_t ThisByte = 0;
331 uint8_t Mask = uint8_t(IsFree) <<
I;
346 return L.takeError();
348 Layout = std::move(*L);
366 return make_error<MSFError>(
368 formatv(
"File size {0,1:N} too large for current PDB page size {1}",
376 if (DirectoryBlockMapSize > Layout.
SB->
BlockSize) {
378 formatv(
"The directory block map ({0} bytes) "
379 "doesn't fit in a block ({1} bytes)",
380 DirectoryBlockMapSize,
385 if (
auto EC = OutFileOrError.takeError())
386 return std::move(EC);
393 return std::move(EC);
401 return std::move(EC);
404 Layout, Buffer, Allocator);
407 return std::move(EC);
410 return std::move(EC);
414 return std::move(EC);
417 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.
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.
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, llvm::endianness::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(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
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