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

32

33

35

36

37

39

40

41

42

44

45

46

47 const uint64_t FlushThreshold;

48

49

50 unsigned CurBit = 0;

51

52

54

55

56

57 unsigned CurCodeSize = 2;

58

59

60

61 unsigned BlockInfoCurBID = 0;

62

63

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

65

66

67

68 std::optional<size_t> BlockFlushingStartPos;

69

70 struct Block {

71 unsigned PrevCodeSize;

72 size_t StartSizeWord;

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

74 Block(unsigned PCS, size_t SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {}

75 };

76

77

78 std::vector BlockScope;

79

80

81

82 struct BlockInfo {

83 unsigned BlockID;

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

85 };

86 std::vector BlockInfoRecords;

87

88 void WriteWord(unsigned Value) {

91 Buffer.append(reinterpret_cast<const char *>(&Value),

92 reinterpret_cast<const char *>(&Value + 1));

93 }

94

95 uint64_t GetNumOfFlushedBytes() const {

96 return fdStream() ? fdStream()->tell() : 0;

97 }

98

99 size_t GetBufferOffset() const {

100 return Buffer.size() + GetNumOfFlushedBytes();

101 }

102

103 size_t GetWordIndex() const {

104 size_t Offset = GetBufferOffset();

105 assert((Offset & 3) == 0 && "Not 32-bit aligned");

107 }

108

109 void flushAndClear() {

111 assert(!Buffer.empty());

112 assert(!BlockFlushingStartPos &&

113 "a call to markAndBlockFlushing should have been paired with a "

114 "call to getMarkedBufferAndResumeFlushing");

115 FS->write(Buffer.data(), Buffer.size());

116 Buffer.clear();

117 }

118

119

120

121

122 void FlushToFile(bool OnClosing = false) {

123 if (!FS || Buffer.empty())

124 return;

125 if (OnClosing)

126 return flushAndClear();

127 if (BlockFlushingStartPos)

128 return;

129 if (fdStream() && Buffer.size() > FlushThreshold)

130 flushAndClear();

131 }

132

134

137 }

138

141 return SV->buffer();

142 return OwnBuffer;

143 }

144

145public:

146

147

148

149

150

151

152

153

154

155

157 : Buffer(getInternalBufferFromStream(OutStream)),

159 FlushThreshold(uint64_t(FlushThreshold) << 20) {}

160

161

162

164 : Buffer(Buff), FS(nullptr), FlushThreshold(0) {}

165

168 assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");

169 FlushToFile(true);

170 }

171

172

173

174

175

177 assert(!BlockFlushingStartPos);

178 BlockFlushingStartPos = Buffer.size();

179 }

180

181

182

183

184

185

187 assert(BlockFlushingStartPos);

188 size_t Start = *BlockFlushingStartPos;

189 BlockFlushingStartPos.reset();

190 return {&Buffer[Start], Buffer.size() - Start};

191 }

192

193

195

196

198

199

200

201

202

203

204

208 uint64_t StartBit = BitNo & 7;

209 uint64_t NumOfFlushedBytes = GetNumOfFlushedBytes();

210

211 if (ByteNo >= NumOfFlushedBytes) {

214 &Buffer[ByteNo - NumOfFlushedBytes], StartBit)) &&

215 "Expected to be patching over 0-value placeholders");

217 &Buffer[ByteNo - NumOfFlushedBytes], NewByte, StartBit);

218 return;

219 }

220

221

222

223 assert(fdStream() != nullptr);

224

225

226 uint64_t CurPos = fdStream()->tell();

227

228

229 char Bytes[3];

230 size_t BytesNum = StartBit ? 2 : 1;

231 size_t BytesFromDisk = std::min(static_cast<uint64_t>(BytesNum), NumOfFlushedBytes - ByteNo);

232 size_t BytesFromBuffer = BytesNum - BytesFromDisk;

233

234

235

236

237

238#ifdef NDEBUG

239 if (StartBit)

240#endif

241 {

242 fdStream()->seek(ByteNo);

243 ssize_t BytesRead = fdStream()->read(Bytes, BytesFromDisk);

244 (void)BytesRead;

245 assert(BytesRead >= 0 && static_cast<size_t>(BytesRead) == BytesFromDisk);

246 for (size_t i = 0; i < BytesFromBuffer; ++i)

247 Bytes[BytesFromDisk + i] = Buffer[i];

250 "Expected to be patching over 0-value placeholders");

251 }

252

253

255 Bytes, NewByte, StartBit);

256

257

258 fdStream()->seek(ByteNo);

259 fdStream()->write(Bytes, BytesFromDisk);

260 for (size_t i = 0; i < BytesFromBuffer; ++i)

261 Buffer[i] = Bytes[BytesFromDisk + i];

262

263

264 fdStream()->seek(CurPos);

265 }

266

271

276

281

283 assert(NumBits && NumBits <= 32 && "Invalid value size!");

284 assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!");

285 CurValue |= Val << CurBit;

286 if (CurBit + NumBits < 32) {

287 CurBit += NumBits;

288 return;

289 }

290

291

292 WriteWord(CurValue);

293

294 if (CurBit)

295 CurValue = Val >> (32-CurBit);

296 else

297 CurValue = 0;

298 CurBit = (CurBit+NumBits) & 31;

299 }

300

302 if (CurBit) {

303 WriteWord(CurValue);

304 CurBit = 0;

305 CurValue = 0;

306 }

307 }

308

310 assert(NumBits <= 32 && "Too many bits to emit!");

311 uint32_t Threshold = 1U << (NumBits-1);

312

313

314 while (Val >= Threshold) {

315 Emit((Val & ((1U << (NumBits - 1)) - 1)) | (1U << (NumBits - 1)),

316 NumBits);

317 Val >>= NumBits-1;

318 }

319

320 Emit(Val, NumBits);

321 }

322

324 assert(NumBits <= 32 && "Too many bits to emit!");

327

328 uint32_t Threshold = 1U << (NumBits-1);

329

330

331 while (Val >= Threshold) {

332 Emit(((uint32_t)Val & ((1U << (NumBits - 1)) - 1)) |

333 (1U << (NumBits - 1)),

334 NumBits);

335 Val >>= NumBits-1;

336 }

337

339 }

340

341

343 Emit(Val, CurCodeSize);

344 }

345

346

347

348

349

350

351

353

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

355 return &BlockInfoRecords.back();

356

357 for (BlockInfo &BI : BlockInfoRecords)

358 if (BI.BlockID == BlockID)

359 return &BI;

360 return nullptr;

361 }

362

364

365

370

371 size_t BlockSizeWordIndex = GetWordIndex();

372 unsigned OldCodeSize = CurCodeSize;

373

374

376

377 CurCodeSize = CodeLen;

378

379

380

381 BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);

382 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);

383

384

385

388 }

389

391 assert(!BlockScope.empty() && "Block scope imbalance!");

392 const Block &B = BlockScope.back();

393

394

395

398

399

400 size_t SizeInWords = GetWordIndex() - B.StartSizeWord - 1;

402

403

405

406

407 CurCodeSize = B.PrevCodeSize;

408 CurAbbrevs = std::move(B.PrevAbbrevs);

409 BlockScope.pop_back();

410 FlushToFile();

411 }

412

413

414

415

416

417private:

418

419

420 template

421 void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) {

422 assert(Op.isLiteral() && "Not a literal");

423

424

425 assert(V == Op.getLiteralValue() &&

426 "Invalid abbrev for record!");

427 }

428

429

430

431 template

433 assert(Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!");

434

435

436 switch (Op.getEncoding()) {

439 if (Op.getEncodingData())

440 Emit((unsigned)V, (unsigned)Op.getEncodingData());

441 break;

443 if (Op.getEncodingData())

444 EmitVBR64(V, (unsigned)Op.getEncodingData());

445 break;

448 break;

449 }

450 }

451

452

453

454

455

456

457

458 template

459 void EmitRecordWithAbbrevImpl(unsigned Abbrev, ArrayRef Vals,

460 StringRef Blob, std::optional Code) {

461 const char *BlobData = Blob.data();

462 unsigned BlobLen = (unsigned) Blob.size();

464 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");

465 const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get();

466

468

470 if (Code) {

471 assert(e && "Expected non-empty abbreviation");

473

474 if (Op.isLiteral())

475 EmitAbbreviatedLiteral(Op, *Code);

476 else {

479 "Expected literal or scalar");

480 EmitAbbreviatedField(Op, *Code);

481 }

482 }

483

484 unsigned RecordIdx = 0;

485 for (; i != e; ++i) {

487 if (Op.isLiteral()) {

488 assert(RecordIdx < Vals.size() && "Invalid abbrev/record");

489 EmitAbbreviatedLiteral(Op, Vals[RecordIdx]);

490 ++RecordIdx;

492

493 assert(i + 2 == e && "array op not second to last?");

494 const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);

495

496

497

498 if (BlobData) {

500 "Blob data and record entries specified for array!");

501

502 EmitVBR(static_cast<uint32_t>(BlobLen), 6);

503

504

505 for (unsigned i = 0; i != BlobLen; ++i)

506 EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]);

507

508

509 BlobData = nullptr;

510 } else {

511

512 EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);

513

514

515 for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx)

516 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);

517 }

519

520

521

522 if (BlobData) {

524 "Blob data and record entries specified for blob operand!");

525

526 assert(Blob.data() == BlobData && "BlobData got moved");

527 assert(Blob.size() == BlobLen && "BlobLen got changed");

529 BlobData = nullptr;

530 } else {

532 }

533 } else {

534 assert(RecordIdx < Vals.size() && "Invalid abbrev/record");

535 EmitAbbreviatedField(Op, Vals[RecordIdx]);

536 ++RecordIdx;

537 }

538 }

539 assert(RecordIdx == Vals.size() && "Not all record operands emitted!");

540 assert(BlobData == nullptr &&

541 "Blob data specified for record that doesn't use it!");

542 }

543

544public:

545

546 template

548

549 if (ShouldEmitSize)

551

552

554

555

557 Buffer.append(Bytes.begin(), Bytes.end());

558

559

560 while (GetBufferOffset() & 3)

561 Buffer.push_back(0);

562 }

565 ShouldEmitSize);

566 }

567

568

569

570 template

571 void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev = 0) {

572 if (!Abbrev) {

573

574

575 auto Count = static_cast<uint32_t>(std::size(Vals));

579 for (unsigned i = 0, e = Count; i != e; ++i)

581 return;

582 }

583

584 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), Code);

585 }

586

587

588

589

590 template

592 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), std::nullopt);

593 }

594

595

596

597

598

599

600 template

603 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Blob, std::nullopt);

604 }

605 template

607 const char *BlobData, unsigned BlobLen) {

608 return EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals),

609 StringRef(BlobData, BlobLen), std::nullopt);

610 }

611

612

613

614 template

617 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Array, std::nullopt);

618 }

619 template

621 const char *ArrayData, unsigned ArrayLen) {

622 return EmitRecordWithAbbrevImpl(

623 Abbrev, ArrayRef(Vals), StringRef(ArrayData, ArrayLen), std::nullopt);

624 }

625

626

627

628

629

630private:

631

637 Emit(Op.isLiteral(), 1);

638 if (Op.isLiteral()) {

640 } else {

641 Emit(Op.getEncoding(), 3);

642 if (Op.hasEncodingData())

644 }

645 }

646 }

647public:

648

649

650 unsigned EmitAbbrev(std::shared_ptr Abbv) {

651 EncodeAbbrev(*Abbv);

652 CurAbbrevs.push_back(std::move(Abbv));

653 return static_cast<unsigned>(CurAbbrevs.size())-1 +

655 }

656

657

658

659

660

661

664 BlockInfoCurBID = ~0U;

665 BlockInfoRecords.clear();

666 }

667private:

668

669

670 void SwitchToBlockID(unsigned BlockID) {

671 if (BlockInfoCurBID == BlockID) return;

675 BlockInfoCurBID = BlockID;

676 }

677

678 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {

680 return *BI;

681

682

683 BlockInfoRecords.emplace_back();

684 BlockInfoRecords.back().BlockID = BlockID;

685 return BlockInfoRecords.back();

686 }

687

688public:

689

690

691

692 unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr Abbv) {

693 SwitchToBlockID(BlockID);

694 EncodeAbbrev(*Abbv);

695

696

697 BlockInfo &Info = getOrCreateBlockInfo(BlockID);

698 Info.Abbrevs.push_back(std::move(Abbv));

699

701 }

702};