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