LLVM: include/llvm/Bitstream/BitstreamReader.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14#ifndef LLVM_BITSTREAM_BITSTREAMREADER_H

15#define LLVM_BITSTREAM_BITSTREAMREADER_H

16

23#include

24#include

25#include

26#include

27#include

28#include

29#include

30#include

31#include

32#include

33

34namespace llvm {

35

36

38public:

39

40

43 std::vector<std::shared_ptr> Abbrevs;

45 std::vector<std::pair<unsigned, std::string>> RecordNames;

46 };

47

48private:

49 std::vector BlockInfoRecords;

50

51public:

52

53

55

56 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)

57 return &BlockInfoRecords.back();

58

59 for (const BlockInfo &BI : BlockInfoRecords)

60 if (BI.BlockID == BlockID)

61 return &BI;

62 return nullptr;

63 }

64

67 return *const_cast<BlockInfo*>(BI);

68

69

70 BlockInfoRecords.emplace_back();

71 BlockInfoRecords.back().BlockID = BlockID;

72 return BlockInfoRecords.back();

73 }

74};

75

76

77

78

81 size_t NextChar = 0;

82

83public:

84

85

86

87

88

90

91private:

93

94

95

96 unsigned BitsInCurWord = 0;

97

98public:

101 : BitcodeBytes(BitcodeBytes) {}

103 : BitcodeBytes(arrayRefFromStringRef(BitcodeBytes)) {}

106

108

109 return pos <= BitcodeBytes.size();

110 }

111

113 return BitsInCurWord == 0 && BitcodeBytes.size() <= NextChar;

114 }

115

116

118 return uint64_t(NextChar)*CHAR_BIT - BitsInCurWord;

119 }

120

121

123

125

126

128 size_t ByteNo = size_t(BitNo/8) & ~(sizeof(word_t)-1);

129 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));

131

132

133 NextChar = ByteNo;

134 BitsInCurWord = 0;

135

136

137 if (WordBitNo) {

140 else

141 return Res.takeError();

142 }

143

145 }

146

147

149 return BitcodeBytes.data() + ByteNo;

150 }

151

152

153

154

156 assert(!(BitNo % 8) && "Expected bit on byte boundary");

158 }

159

161 if (NextChar >= BitcodeBytes.size())

163 "Unexpected end of file reading %u of %u bytes",

164 NextChar, BitcodeBytes.size());

165

166

167 const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar;

168 unsigned BytesRead;

169 if (BitcodeBytes.size() >= NextChar + sizeof(word_t)) {

170 BytesRead = sizeof(word_t);

171 CurWord =

172 support::endian::read<word_t, llvm::endianness::little>(NextCharPtr);

173 } else {

174

175 BytesRead = BitcodeBytes.size() - NextChar;

176 CurWord = 0;

177 for (unsigned B = 0; B != BytesRead; ++B)

178 CurWord |= uint64_t(NextCharPtr[B]) << (B * 8);

179 }

180 NextChar += BytesRead;

181 BitsInCurWord = BytesRead * 8;

183 }

184

186 static const unsigned BitsInWord = sizeof(word_t) * 8;

187

188 assert(NumBits && NumBits <= BitsInWord &&

189 "Cannot return zero or more than BitsInWord bits!");

190

191 static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f;

192

193

194 if (BitsInCurWord >= NumBits) {

195 word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits));

196

197

198 CurWord >>= (NumBits & Mask);

199

200 BitsInCurWord -= NumBits;

201 return R;

202 }

203

204 word_t R = BitsInCurWord ? CurWord : 0;

205 unsigned BitsLeft = NumBits - BitsInCurWord;

206

208 return std::move(fillResult);

209

210

211 if (BitsLeft > BitsInCurWord)

213 "Unexpected end of file reading %u of %u bits",

214 BitsInCurWord, BitsLeft);

215

216 word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));

217

218

219 CurWord >>= (BitsLeft & Mask);

220

221 BitsInCurWord -= BitsLeft;

222

223 R |= R2 << (NumBits - BitsLeft);

224

225 return R;

226 }

227

230 if (!MaybeRead)

231 return MaybeRead;

233

234 assert(NumBits <= 32 && NumBits >= 1 && "Invalid NumBits value");

235 const uint32_t MaskBitOrder = (NumBits - 1);

236 const uint32_t Mask = 1UL << MaskBitOrder;

237

238 if ((Piece & Mask) == 0)

239 return Piece;

240

242 unsigned NextBit = 0;

243 while (true) {

244 Result |= (Piece & (Mask - 1)) << NextBit;

245

246 if ((Piece & Mask) == 0)

247 return Result;

248

249 NextBit += NumBits-1;

250 if (NextBit >= 32)

252 "Unterminated VBR");

253

254 MaybeRead = Read(NumBits);

255 if (!MaybeRead)

256 return MaybeRead;

257 Piece = MaybeRead.get();

258 }

259 }

260

261

262

265 if (!MaybeRead)

266 return MaybeRead;

268 assert(NumBits <= 32 && NumBits >= 1 && "Invalid NumBits value");

269 const uint32_t MaskBitOrder = (NumBits - 1);

270 const uint32_t Mask = 1UL << MaskBitOrder;

271

272 if ((Piece & Mask) == 0)

274

276 unsigned NextBit = 0;

277 while (true) {

278 Result |= uint64_t(Piece & (Mask - 1)) << NextBit;

279

280 if ((Piece & Mask) == 0)

281 return Result;

282

283 NextBit += NumBits-1;

284 if (NextBit >= 64)

286 "Unterminated VBR");

287

288 MaybeRead = Read(NumBits);

289 if (!MaybeRead)

290 return MaybeRead;

291 Piece = MaybeRead.get();

292 }

293 }

294

296

297

298 if (sizeof(word_t) > 4 &&

299 BitsInCurWord >= 32) {

300 CurWord >>= BitsInCurWord-32;

301 BitsInCurWord = 32;

302 return;

303 }

304

305 BitsInCurWord = 0;

306 }

307

308

310

311

313

314

316

317

318 return Size < BitcodeBytes.size() * 8;

319 }

320};

321

322

323

325 enum {

326 Error,

327 EndBlock,

328

329 SubBlock,

330 Record

332

334

337 }

338

341 }

342

345 }

346

349 }

350};

351

352

353

354

355

356

358

359

360 unsigned CurCodeSize = 2;

361

362

363 std::vector<std::shared_ptr> CurAbbrevs;

364

365 struct Block {

366 unsigned PrevCodeSize;

367 std::vector<std::shared_ptr> PrevAbbrevs;

368

369 explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}

370 };

371

372

374

376

377public:

379

387

401

402

404

405

406 enum {

407

408

410

411

412

415

416

418 while (true) {

421

423 if (!MaybeCode)

425 unsigned Code = MaybeCode.get();

426

428

432 }

433

437 else

438 return MaybeSubBlock.takeError();

439 }

440

443

444

446 return std::move(Err);

447 continue;

448 }

449

451 }

452 }

453

454

455

457 while (true) {

458

460 if (!MaybeEntry)

461 return MaybeEntry;

463

465 return Entry;

466

467

469 return std::move(Err);

470 }

471 }

472

474

475

476

477

478

480

481

482

484

486 ;

487

488 else

489 return Res.takeError();

490

493 if (!MaybeNum)

495 size_t NumFourBytes = MaybeNum.get();

496

497

498

499 size_t SkipTo = GetCurrentBitNo() + NumFourBytes * 4 * 8;

502 "can't skip block: already at end of stream");

505 "can't skip to bit %zu from %" PRIu64, SkipTo,

507

509 return Res;

510

512 }

513

514

515 Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);

516

518 if (BlockScope.empty()) return true;

519

520

521

523

524 popBlockScope();

525 return false;

526 }

527

528private:

529 void popBlockScope() {

530 CurCodeSize = BlockScope.back().PrevCodeSize;

531

532 CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs);

534 }

535

536

537

538

539

540public:

541

544 if (AbbrevNo >= CurAbbrevs.size())

546 std::errc::illegal_byte_sequence, "Invalid abbrev number");

547 return CurAbbrevs[AbbrevNo].get();

548 }

549

550

552

556

557

558

559

561

562

563

564

565

566

569

570

571

573};

574

575}

576

577#endif

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

This file defines the SmallVector class.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

size_t size() const

size - Get the array size.

This class maintains the abbreviations read from a block info block.

const BlockInfo * getBlockInfo(unsigned BlockID) const

If there is block info for the specified ID, return it, otherwise return null.

BlockInfo & getOrCreateBlockInfo(unsigned BlockID)

This represents a position within a bitcode file, implemented on top of a SimpleBitstreamCursor.

Error JumpToBit(uint64_t BitNo)

Reset the stream to the specified bit number.

BitstreamCursor(StringRef BitcodeBytes)

uint64_t GetCurrentBitNo() const

Return the bit # of the bit we are reading.

Expected< unsigned > ReadSubBlockID()

Having read the ENTER_SUBBLOCK code, read the BlockID for the block.

static const size_t MaxChunkSize

Expected< BitstreamEntry > advance(unsigned Flags=0)

Advance the current bitstream, returning the next entry in the stream.

BitstreamCursor(MemoryBufferRef BitcodeBytes)

Expected< BitstreamEntry > advanceSkippingSubblocks(unsigned Flags=0)

This is a convenience function for clients that don't expect any subblocks.

Expected< const BitCodeAbbrev * > getAbbrev(unsigned AbbrevID)

Return the abbreviation for the specified AbbrevId.

void setBlockInfo(BitstreamBlockInfo *BI)

Set the block info to be used by this BitstreamCursor to interpret abbreviated records.

Expected< unsigned > readRecord(unsigned AbbrevID, SmallVectorImpl< uint64_t > &Vals, StringRef *Blob=nullptr)

Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP=nullptr)

Having read the ENTER_SUBBLOCK abbrevid, and enter the block.

@ AF_DontAutoprocessAbbrevs

If this flag is used, abbrev entries are returned just like normal records.

@ AF_DontPopBlockAtEnd

If this flag is used, the advance() method does not automatically pop the block scope when the end of...

Error SkipBlock()

Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body of this block.

Expected< unsigned > skipRecord(unsigned AbbrevID)

Read the current record and discard it, returning the code for the record.

BitstreamCursor(ArrayRef< uint8_t > BitcodeBytes)

BitstreamCursor()=default

Expected< unsigned > ReadCode()

Expected< std::optional< BitstreamBlockInfo > > ReadBlockInfoBlock(bool ReadBlockInfoNames=false)

Read and return a block info block from the bitstream.

Expected< uint32_t > ReadVBR(const unsigned NumBits)

unsigned getAbbrevIDWidth() const

Return the number of bits used to encode an abbrev #.

bool canSkipToPos(size_t pos) const

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.

Error takeError()

Take ownership of the stored error.

reference get()

Returns a reference to the stored T value.

This represents a position within a bitstream.

Error JumpToBit(uint64_t BitNo)

Reset the stream to the specified bit number.

const uint8_t * getPointerToBit(uint64_t BitNo, uint64_t NumBytes)

Get a pointer into the bitstream at the specified bit offset.

uint64_t GetCurrentBitNo() const

Return the bit # of the bit we are reading.

Expected< uint64_t > ReadVBR64(const unsigned NumBits)

SimpleBitstreamCursor()=default

size_t SizeInBytes() const

Return the size of the stream in bytes.

ArrayRef< uint8_t > getBitcodeBytes() const

Expected< word_t > Read(unsigned NumBits)

const uint8_t * getPointerToByte(uint64_t ByteNo, uint64_t NumBytes)

Get a pointer into the bitstream at the specified byte offset.

SimpleBitstreamCursor(StringRef BitcodeBytes)

SimpleBitstreamCursor(ArrayRef< uint8_t > BitcodeBytes)

SimpleBitstreamCursor(MemoryBufferRef BitcodeBytes)

size_t word_t

This is the current data we have pulled from the stream but have not returned to the client.

void SkipToFourByteBoundary()

uint64_t getCurrentByteNo() const

bool isSizePlausible(size_t Size) const

Check whether a reservation of Size elements is plausible.

void skipToEnd()

Skip to the end of the file.

Expected< uint32_t > ReadVBR(const unsigned NumBits)

bool canSkipToPos(size_t pos) const

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

@ DEFINE_ABBREV

DEFINE_ABBREV - Defines an abbrev for the current block.

@ FIRST_APPLICATION_ABBREV

This is an optimization pass for GlobalISel generic memory operations.

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

This contains information emitted to BLOCKINFO_BLOCK blocks.

std::vector< std::pair< unsigned, std::string > > RecordNames

std::vector< std::shared_ptr< BitCodeAbbrev > > Abbrevs

When advancing through a bitstream cursor, each advance can discover a few different kinds of entries...

static BitstreamEntry getSubBlock(unsigned ID)

static BitstreamEntry getRecord(unsigned AbbrevID)

enum llvm::BitstreamEntry::@196 Kind

static BitstreamEntry getEndBlock()

static BitstreamEntry getError()