13 using namespace llvm::msf;
14 using namespace llvm::support;
18 const uint32_t kFreePageMap0Block = 1;
19 const uint32_t kFreePageMap1Block = 2;
20 const uint32_t kNumReservedPages = 3;
22 const uint32_t kDefaultFreePageMap = kFreePageMap0Block;
23 const uint32_t kDefaultBlockMapAddr = kNumReservedPages;
28 : Allocator(Allocator), IsGrowable(CanGrow),
29 FreePageMap(kDefaultFreePageMap), BlockSize(BlockSize),
30 MininumBlocks(MinBlockCount), BlockMapAddr(kDefaultBlockMapAddr),
31 FreeBlocks(MinBlockCount,
true) {
32 FreeBlocks[kSuperBlockBlock] =
false;
33 FreeBlocks[kFreePageMap0Block] =
false;
34 FreeBlocks[kFreePageMap1Block] =
false;
35 FreeBlocks[BlockMapAddr] =
false;
40 uint32_t MinBlockCount,
bool CanGrow) {
43 "The requested block size is unsupported");
51 if (Addr == BlockMapAddr)
54 if (Addr >= FreeBlocks.
size()) {
57 "Cannot grow the number of blocks");
58 FreeBlocks.
resize(Addr + 1,
true);
62 return make_error<MSFError>(
64 "Requested block map address is already in use");
65 FreeBlocks[BlockMapAddr] =
true;
66 FreeBlocks[Addr] =
false;
76 for (
auto B : DirectoryBlocks)
78 for (
auto B : DirBlocks) {
81 "Attempt to reuse an allocated block");
83 FreeBlocks[
B] =
false;
86 DirectoryBlocks = DirBlocks;
96 if (NumFreeBlocks < NumBlocks) {
99 "There are no free Blocks in the file");
100 uint32_t AllocBlocks = NumBlocks - NumFreeBlocks;
101 FreeBlocks.
resize(AllocBlocks + FreeBlocks.
size(),
true);
107 assert(Block != -1 &&
"We ran out of Blocks!");
110 Blocks[I++] = NextBlock;
111 FreeBlocks.
reset(NextBlock);
113 }
while (--NumBlocks > 0);
133 if (ReqBlocks != Blocks.
size())
134 return make_error<MSFError>(
136 "Incorrect number of blocks for requested stream size");
137 for (
auto Block : Blocks) {
138 if (Block >= FreeBlocks.
size())
139 FreeBlocks.
resize(Block + 1,
true);
141 if (!FreeBlocks.
test(Block))
142 return make_error<MSFError>(
144 "Attempt to re-use an already allocated block");
147 for (
auto Block : Blocks) {
148 FreeBlocks.
reset(Block);
150 StreamData.push_back(std::make_pair(Size, Blocks));
151 return StreamData.size() - 1;
156 std::vector<uint32_t> NewBlocks;
157 NewBlocks.resize(ReqBlocks);
158 if (
auto EC = allocateBlocks(ReqBlocks, NewBlocks))
159 return std::move(EC);
160 StreamData.push_back(std::make_pair(Size, NewBlocks));
161 return StreamData.size() - 1;
172 if (NewBlocks > OldBlocks) {
173 uint32_t AddedBlocks = NewBlocks - OldBlocks;
175 std::vector<uint32_t> AddedBlockList;
176 AddedBlockList.resize(AddedBlocks);
177 if (
auto EC = allocateBlocks(AddedBlocks, AddedBlockList))
179 auto &CurrentBlocks = StreamData[Idx].second;
180 CurrentBlocks.insert(CurrentBlocks.end(), AddedBlockList.begin(),
181 AddedBlockList.end());
182 }
else if (OldBlocks > NewBlocks) {
185 uint32_t RemovedBlocks = OldBlocks - NewBlocks;
187 auto RemovedBlockList = CurrentBlocks.
drop_front(NewBlocks);
188 for (
auto P : RemovedBlockList)
189 FreeBlocks[
P] =
true;
190 StreamData[Idx].second = CurrentBlocks.drop_back(RemovedBlocks);
193 StreamData[Idx].first = Size;
200 return StreamData[StreamIdx].first;
204 return StreamData[StreamIdx].second;
207 uint32_t MSFBuilder::computeDirectoryByteSize()
const {
214 for (
const auto &
D : StreamData) {
216 assert(ExpectedNumBlocks ==
D.second.size() &&
217 "Unexpected number of blocks");
236 if (NumDirectoryBlocks > DirectoryBlocks.size()) {
239 std::vector<uint32_t> ExtraBlocks;
240 uint32_t NumExtraBlocks = NumDirectoryBlocks - DirectoryBlocks.size();
241 ExtraBlocks.resize(NumExtraBlocks);
242 if (
auto EC = allocateBlocks(NumExtraBlocks, ExtraBlocks))
243 return std::move(EC);
244 DirectoryBlocks.insert(DirectoryBlocks.end(), ExtraBlocks.begin(),
246 }
else if (NumDirectoryBlocks < DirectoryBlocks.size()) {
247 uint32_t NumUnnecessaryBlocks = DirectoryBlocks.size() - NumDirectoryBlocks;
250 FreeBlocks[
B] =
true;
251 DirectoryBlocks.resize(NumDirectoryBlocks);
260 std::uninitialized_copy_n(DirectoryBlocks.begin(), NumDirectoryBlocks,
266 if (StreamData.size() > 0) {
269 L.StreamMap.resize(StreamData.size());
270 for (
uint32_t I = 0; I < StreamData.size(); ++
I) {
271 Sizes[
I] = StreamData[
I].first;
274 std::uninitialized_copy_n(StreamData[I].second.begin(),
275 StreamData[
I].second.size(), BlockList);
void resize(unsigned N, bool t=false)
resize - Grow or shrink the bitvector.
char MagicBytes[sizeof(Magic)]
void setFreePageMap(uint32_t Fpm)
int find_first() const
find_first - Returns the index of the first set bit, -1 if none of the bits are set.
size_type size() const
size - Returns the number of bits in this bitvector.
uint32_t getStreamSize(uint32_t StreamIdx) const
Get the size of a stream by index.
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 setBlockMapAddr(uint32_t Addr)
Request the block map to be at a specific block address.
int find_next(unsigned Prev) const
find_next - Returns the index of the next set bit following the "Prev" bit.
uint32_t getMinimumBlockCount()
static GCRegistry::Add< StatepointGC > D("statepoint-example","an example strategy for statepoint")
Tagged union holding either a T or a Error.
uint32_t getTotalBlockCount() const
Get the total number of blocks in the MSF file.
uint32_t getNumStreams() const
Get the total number of streams in the MSF layout.
Error setDirectoryBlocksHint(ArrayRef< uint32_t > DirBlocks)
support::ulittle32_t BlockSize
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
size_t size() const
size - Get the array size.
support::ulittle32_t BlockMapAddr
INITIALIZE_PASS(HexagonEarlyIfConversion,"hexagon-eif","Hexagon early if conversion", false, false) bool HexagonEarlyIfConversion MachineBasicBlock * SB
size_type count() const
count - Returns the number of bits which are set.
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Allocate memory in an ever growing pool, as if by bump-pointer.
LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * Allocate(size_t Size, size_t Alignment)
Allocate space at the specified alignment.
Greedy Register Allocator
static const char Magic[]
Expected< MSFLayout > build()
Finalize the layout and build the headers and structures that describe the MSF layout and can be writ...
support::ulittle32_t Unknown1
Error setStreamSize(uint32_t Idx, uint32_t Size)
Update the size of an existing stream.
uint32_t getNumUsedBlocks() const
Get the total number of blocks that will be allocated to actual data in this MSF file.
static const int BlockSize
static ErrorSuccess success()
Create a success value.
ArrayRef< uint32_t > getStreamBlocks(uint32_t StreamIdx) const
Get the list of blocks allocated to a particular stream.
bool test(unsigned Idx) const
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.
uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize)
void setUnknown1(uint32_t Unk1)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
detail::packed_endian_specific_integral< uint32_t, little, unaligned > ulittle32_t
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
support::ulittle32_t FreeBlockMapBlock
Lightweight error class with error context and mandatory checking.
bool isValidBlockSize(uint32_t Size)
bool isBlockFree(uint32_t Idx) const
Check whether a particular block is allocated or free.
support::ulittle32_t NumDirectoryBytes
support::ulittle32_t NumBlocks