1 //===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This header defines the BitstreamWriter class. This class can be used to 10 // write an arbitrary bitstream, regardless of its contents. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_BITSTREAM_BITSTREAMWRITER_H 15 #define LLVM_BITSTREAM_BITSTREAMWRITER_H 16 17 #include "llvm/ADT/ArrayRef.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/Bitstream/BitCodes.h" 21 #include "llvm/Support/Endian.h" 22 #include "llvm/Support/MathExtras.h" 23 #include "llvm/Support/raw_ostream.h" 24 #include <algorithm> 25 #include <optional> 26 #include <vector> 27 28 namespace llvm { 29 30 class BitstreamWriter { 31 /// Out - The buffer that keeps unflushed bytes. 32 SmallVectorImpl<char> &Out; 33 34 /// FS - The file stream that Out flushes to. If FS is nullptr, it does not 35 /// support read or seek, Out cannot be flushed until all data are written. 36 raw_fd_stream *FS; 37 38 /// FlushThreshold - If FS is valid, this is the threshold (unit B) to flush 39 /// FS. 40 const uint64_t FlushThreshold; 41 42 /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. 43 unsigned CurBit; 44 45 /// CurValue - The current value. Only bits < CurBit are valid. 46 uint32_t CurValue; 47 48 /// CurCodeSize - This is the declared size of code values used for the 49 /// current block, in bits. 50 unsigned CurCodeSize; 51 52 /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently 53 /// selected BLOCK ID. 54 unsigned BlockInfoCurBID; 55 56 /// CurAbbrevs - Abbrevs installed at in this block. 57 std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs; 58 59 struct Block { 60 unsigned PrevCodeSize; 61 size_t StartSizeWord; 62 std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs; 63 Block(unsigned PCS, size_t SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} 64 }; 65 66 /// BlockScope - This tracks the current blocks that we have entered. 67 std::vector<Block> BlockScope; 68 69 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. 70 /// These describe abbreviations that all blocks of the specified ID inherit. 71 struct BlockInfo { 72 unsigned BlockID; 73 std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs; 74 }; 75 std::vector<BlockInfo> BlockInfoRecords; 76 77 void WriteWord(unsigned Value) { 78 Value = 79 support::endian::byte_swap<uint32_t, llvm::endianness::little>(Value); 80 Out.append(reinterpret_cast<const char *>(&Value), 81 reinterpret_cast<const char *>(&Value + 1)); 82 } 83 84 uint64_t GetNumOfFlushedBytes() const { return FS ? FS->tell() : 0; } 85 86 size_t GetBufferOffset() const { return Out.size() + GetNumOfFlushedBytes(); } 87 88 size_t GetWordIndex() const { 89 size_t Offset = GetBufferOffset(); 90 assert((Offset & 3) == 0 && "Not 32-bit aligned"); 91 return Offset / 4; 92 } 93 94 /// If the related file stream supports reading, seeking and writing, flush 95 /// the buffer if its size is above a threshold. 96 void FlushToFile() { 97 if (!FS) 98 return; 99 if (Out.size() < FlushThreshold) 100 return; 101 FS->write((char *)&Out.front(), Out.size()); 102 Out.clear(); 103 } 104 105 public: 106 /// Create a BitstreamWriter that writes to Buffer \p O. 107 /// 108 /// \p FS is the file stream that \p O flushes to incrementally. If \p FS is 109 /// null, \p O does not flush incrementially, but writes to disk at the end. 110 /// 111 /// \p FlushThreshold is the threshold (unit M) to flush \p O if \p FS is 112 /// valid. Flushing only occurs at (sub)block boundaries. 113 BitstreamWriter(SmallVectorImpl<char> &O, raw_fd_stream *FS = nullptr, 114 uint32_t FlushThreshold = 512) 115 : Out(O), FS(FS), FlushThreshold(uint64_t(FlushThreshold) << 20), CurBit(0), 116 CurValue(0), CurCodeSize(2) {} 117 118 ~BitstreamWriter() { 119 assert(CurBit == 0 && "Unflushed data remaining"); 120 assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); 121 } 122 123 /// Retrieve the current position in the stream, in bits. 124 uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; } 125 126 /// Retrieve the number of bits currently used to encode an abbrev ID. 127 unsigned GetAbbrevIDWidth() const { return CurCodeSize; } 128 129 //===--------------------------------------------------------------------===// 130 // Basic Primitives for emitting bits to the stream. 131 //===--------------------------------------------------------------------===// 132 133 /// Backpatch a byte in the output at the given bit offset with the specified 134 /// value. 135 void BackpatchByte(uint64_t BitNo, uint8_t NewByte) { 136 using namespace llvm::support; 137 uint64_t ByteNo = BitNo / 8; 138 uint64_t StartBit = BitNo & 7; 139 uint64_t NumOfFlushedBytes = GetNumOfFlushedBytes(); 140 141 if (ByteNo >= NumOfFlushedBytes) { 142 assert((!endian::readAtBitAlignment<uint8_t, llvm::endianness::little, 143 unaligned>( 144 &Out[ByteNo - NumOfFlushedBytes], StartBit)) && 145 "Expected to be patching over 0-value placeholders"); 146 endian::writeAtBitAlignment<uint8_t, llvm::endianness::little, unaligned>( 147 &Out[ByteNo - NumOfFlushedBytes], NewByte, StartBit); 148 return; 149 } 150 151 // If the byte offset to backpatch is flushed, use seek to backfill data. 152 // First, save the file position to restore later. 153 uint64_t CurPos = FS->tell(); 154 155 // Copy data to update into Bytes from the file FS and the buffer Out. 156 char Bytes[3]; // Use one more byte to silence a warning from Visual C++. 157 size_t BytesNum = StartBit ? 2 : 1; 158 size_t BytesFromDisk = std::min(static_cast<uint64_t>(BytesNum), NumOfFlushedBytes - ByteNo); 159 size_t BytesFromBuffer = BytesNum - BytesFromDisk; 160 161 // When unaligned, copy existing data into Bytes from the file FS and the 162 // buffer Out so that it can be updated before writing. For debug builds 163 // read bytes unconditionally in order to check that the existing value is 0 164 // as expected. 165 #ifdef NDEBUG 166 if (StartBit) 167 #endif 168 { 169 FS->seek(ByteNo); 170 ssize_t BytesRead = FS->read(Bytes, BytesFromDisk); 171 (void)BytesRead; // silence warning 172 assert(BytesRead >= 0 && static_cast<size_t>(BytesRead) == BytesFromDisk); 173 for (size_t i = 0; i < BytesFromBuffer; ++i) 174 Bytes[BytesFromDisk + i] = Out[i]; 175 assert((!endian::readAtBitAlignment<uint8_t, llvm::endianness::little, 176 unaligned>(Bytes, StartBit)) && 177 "Expected to be patching over 0-value placeholders"); 178 } 179 180 // Update Bytes in terms of bit offset and value. 181 endian::writeAtBitAlignment<uint8_t, llvm::endianness::little, unaligned>( 182 Bytes, NewByte, StartBit); 183 184 // Copy updated data back to the file FS and the buffer Out. 185 FS->seek(ByteNo); 186 FS->write(Bytes, BytesFromDisk); 187 for (size_t i = 0; i < BytesFromBuffer; ++i) 188 Out[i] = Bytes[BytesFromDisk + i]; 189 190 // Restore the file position. 191 FS->seek(CurPos); 192 } 193 194 void BackpatchHalfWord(uint64_t BitNo, uint16_t Val) { 195 BackpatchByte(BitNo, (uint8_t)Val); 196 BackpatchByte(BitNo + 8, (uint8_t)(Val >> 8)); 197 } 198 199 void BackpatchWord(uint64_t BitNo, unsigned Val) { 200 BackpatchHalfWord(BitNo, (uint16_t)Val); 201 BackpatchHalfWord(BitNo + 16, (uint16_t)(Val >> 16)); 202 } 203 204 void BackpatchWord64(uint64_t BitNo, uint64_t Val) { 205 BackpatchWord(BitNo, (uint32_t)Val); 206 BackpatchWord(BitNo + 32, (uint32_t)(Val >> 32)); 207 } 208 209 void Emit(uint32_t Val, unsigned NumBits) { 210 assert(NumBits && NumBits <= 32 && "Invalid value size!"); 211 assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!"); 212 CurValue |= Val << CurBit; 213 if (CurBit + NumBits < 32) { 214 CurBit += NumBits; 215 return; 216 } 217 218 // Add the current word. 219 WriteWord(CurValue); 220 221 if (CurBit) 222 CurValue = Val >> (32-CurBit); 223 else 224 CurValue = 0; 225 CurBit = (CurBit+NumBits) & 31; 226 } 227 228 void FlushToWord() { 229 if (CurBit) { 230 WriteWord(CurValue); 231 CurBit = 0; 232 CurValue = 0; 233 } 234 } 235 236 void EmitVBR(uint32_t Val, unsigned NumBits) { 237 assert(NumBits <= 32 && "Too many bits to emit!"); 238 uint32_t Threshold = 1U << (NumBits-1); 239 240 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 241 while (Val >= Threshold) { 242 Emit((Val & ((1U << (NumBits - 1)) - 1)) | (1U << (NumBits - 1)), 243 NumBits); 244 Val >>= NumBits-1; 245 } 246 247 Emit(Val, NumBits); 248 } 249 250 void EmitVBR64(uint64_t Val, unsigned NumBits) { 251 assert(NumBits <= 32 && "Too many bits to emit!"); 252 if ((uint32_t)Val == Val) 253 return EmitVBR((uint32_t)Val, NumBits); 254 255 uint32_t Threshold = 1U << (NumBits-1); 256 257 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 258 while (Val >= Threshold) { 259 Emit(((uint32_t)Val & ((1U << (NumBits - 1)) - 1)) | 260 (1U << (NumBits - 1)), 261 NumBits); 262 Val >>= NumBits-1; 263 } 264 265 Emit((uint32_t)Val, NumBits); 266 } 267 268 /// EmitCode - Emit the specified code. 269 void EmitCode(unsigned Val) { 270 Emit(Val, CurCodeSize); 271 } 272 273 //===--------------------------------------------------------------------===// 274 // Block Manipulation 275 //===--------------------------------------------------------------------===// 276 277 /// getBlockInfo - If there is block info for the specified ID, return it, 278 /// otherwise return null. 279 BlockInfo *getBlockInfo(unsigned BlockID) { 280 // Common case, the most recent entry matches BlockID. 281 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) 282 return &BlockInfoRecords.back(); 283 284 for (BlockInfo &BI : BlockInfoRecords) 285 if (BI.BlockID == BlockID) 286 return &BI; 287 return nullptr; 288 } 289 290 void EnterSubblock(unsigned BlockID, unsigned CodeLen) { 291 // Block header: 292 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] 293 EmitCode(bitc::ENTER_SUBBLOCK); 294 EmitVBR(BlockID, bitc::BlockIDWidth); 295 EmitVBR(CodeLen, bitc::CodeLenWidth); 296 FlushToWord(); 297 298 size_t BlockSizeWordIndex = GetWordIndex(); 299 unsigned OldCodeSize = CurCodeSize; 300 301 // Emit a placeholder, which will be replaced when the block is popped. 302 Emit(0, bitc::BlockSizeWidth); 303 304 CurCodeSize = CodeLen; 305 306 // Push the outer block's abbrev set onto the stack, start out with an 307 // empty abbrev set. 308 BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex); 309 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); 310 311 // If there is a blockinfo for this BlockID, add all the predefined abbrevs 312 // to the abbrev list. 313 if (BlockInfo *Info = getBlockInfo(BlockID)) 314 append_range(CurAbbrevs, Info->Abbrevs); 315 } 316 317 void ExitBlock() { 318 assert(!BlockScope.empty() && "Block scope imbalance!"); 319 const Block &B = BlockScope.back(); 320 321 // Block tail: 322 // [END_BLOCK, <align4bytes>] 323 EmitCode(bitc::END_BLOCK); 324 FlushToWord(); 325 326 // Compute the size of the block, in words, not counting the size field. 327 size_t SizeInWords = GetWordIndex() - B.StartSizeWord - 1; 328 uint64_t BitNo = uint64_t(B.StartSizeWord) * 32; 329 330 // Update the block size field in the header of this sub-block. 331 BackpatchWord(BitNo, SizeInWords); 332 333 // Restore the inner block's code size and abbrev table. 334 CurCodeSize = B.PrevCodeSize; 335 CurAbbrevs = std::move(B.PrevAbbrevs); 336 BlockScope.pop_back(); 337 FlushToFile(); 338 } 339 340 //===--------------------------------------------------------------------===// 341 // Record Emission 342 //===--------------------------------------------------------------------===// 343 344 private: 345 /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev 346 /// record. This is a no-op, since the abbrev specifies the literal to use. 347 template<typename uintty> 348 void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) { 349 assert(Op.isLiteral() && "Not a literal"); 350 // If the abbrev specifies the literal value to use, don't emit 351 // anything. 352 assert(V == Op.getLiteralValue() && 353 "Invalid abbrev for record!"); 354 } 355 356 /// EmitAbbreviatedField - Emit a single scalar field value with the specified 357 /// encoding. 358 template<typename uintty> 359 void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { 360 assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!"); 361 362 // Encode the value as we are commanded. 363 switch (Op.getEncoding()) { 364 default: llvm_unreachable("Unknown encoding!"); 365 case BitCodeAbbrevOp::Fixed: 366 if (Op.getEncodingData()) 367 Emit((unsigned)V, (unsigned)Op.getEncodingData()); 368 break; 369 case BitCodeAbbrevOp::VBR: 370 if (Op.getEncodingData()) 371 EmitVBR64(V, (unsigned)Op.getEncodingData()); 372 break; 373 case BitCodeAbbrevOp::Char6: 374 Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6); 375 break; 376 } 377 } 378 379 /// EmitRecordWithAbbrevImpl - This is the core implementation of the record 380 /// emission code. If BlobData is non-null, then it specifies an array of 381 /// data that should be emitted as part of the Blob or Array operand that is 382 /// known to exist at the end of the record. If Code is specified, then 383 /// it is the record code to emit before the Vals, which must not contain 384 /// the code. 385 template <typename uintty> 386 void EmitRecordWithAbbrevImpl(unsigned Abbrev, ArrayRef<uintty> Vals, 387 StringRef Blob, std::optional<unsigned> Code) { 388 const char *BlobData = Blob.data(); 389 unsigned BlobLen = (unsigned) Blob.size(); 390 unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; 391 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); 392 const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get(); 393 394 EmitCode(Abbrev); 395 396 unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos()); 397 if (Code) { 398 assert(e && "Expected non-empty abbreviation"); 399 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i++); 400 401 if (Op.isLiteral()) 402 EmitAbbreviatedLiteral(Op, *Code); 403 else { 404 assert(Op.getEncoding() != BitCodeAbbrevOp::Array && 405 Op.getEncoding() != BitCodeAbbrevOp::Blob && 406 "Expected literal or scalar"); 407 EmitAbbreviatedField(Op, *Code); 408 } 409 } 410 411 unsigned RecordIdx = 0; 412 for (; i != e; ++i) { 413 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); 414 if (Op.isLiteral()) { 415 assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); 416 EmitAbbreviatedLiteral(Op, Vals[RecordIdx]); 417 ++RecordIdx; 418 } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { 419 // Array case. 420 assert(i + 2 == e && "array op not second to last?"); 421 const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); 422 423 // If this record has blob data, emit it, otherwise we must have record 424 // entries to encode this way. 425 if (BlobData) { 426 assert(RecordIdx == Vals.size() && 427 "Blob data and record entries specified for array!"); 428 // Emit a vbr6 to indicate the number of elements present. 429 EmitVBR(static_cast<uint32_t>(BlobLen), 6); 430 431 // Emit each field. 432 for (unsigned i = 0; i != BlobLen; ++i) 433 EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]); 434 435 // Know that blob data is consumed for assertion below. 436 BlobData = nullptr; 437 } else { 438 // Emit a vbr6 to indicate the number of elements present. 439 EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6); 440 441 // Emit each field. 442 for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) 443 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]); 444 } 445 } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { 446 // If this record has blob data, emit it, otherwise we must have record 447 // entries to encode this way. 448 449 if (BlobData) { 450 assert(RecordIdx == Vals.size() && 451 "Blob data and record entries specified for blob operand!"); 452 453 assert(Blob.data() == BlobData && "BlobData got moved"); 454 assert(Blob.size() == BlobLen && "BlobLen got changed"); 455 emitBlob(Blob); 456 BlobData = nullptr; 457 } else { 458 emitBlob(Vals.slice(RecordIdx)); 459 } 460 } else { // Single scalar field. 461 assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); 462 EmitAbbreviatedField(Op, Vals[RecordIdx]); 463 ++RecordIdx; 464 } 465 } 466 assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); 467 assert(BlobData == nullptr && 468 "Blob data specified for record that doesn't use it!"); 469 } 470 471 public: 472 /// Emit a blob, including flushing before and tail-padding. 473 template <class UIntTy> 474 void emitBlob(ArrayRef<UIntTy> Bytes, bool ShouldEmitSize = true) { 475 // Emit a vbr6 to indicate the number of elements present. 476 if (ShouldEmitSize) 477 EmitVBR(static_cast<uint32_t>(Bytes.size()), 6); 478 479 // Flush to a 32-bit alignment boundary. 480 FlushToWord(); 481 482 // Emit literal bytes. 483 assert(llvm::all_of(Bytes, [](UIntTy B) { return isUInt<8>(B); })); 484 Out.append(Bytes.begin(), Bytes.end()); 485 486 // Align end to 32-bits. 487 while (GetBufferOffset() & 3) 488 Out.push_back(0); 489 } 490 void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) { 491 emitBlob(ArrayRef((const uint8_t *)Bytes.data(), Bytes.size()), 492 ShouldEmitSize); 493 } 494 495 /// EmitRecord - Emit the specified record to the stream, using an abbrev if 496 /// we have one to compress the output. 497 template <typename Container> 498 void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev = 0) { 499 if (!Abbrev) { 500 // If we don't have an abbrev to use, emit this in its fully unabbreviated 501 // form. 502 auto Count = static_cast<uint32_t>(std::size(Vals)); 503 EmitCode(bitc::UNABBREV_RECORD); 504 EmitVBR(Code, 6); 505 EmitVBR(Count, 6); 506 for (unsigned i = 0, e = Count; i != e; ++i) 507 EmitVBR64(Vals[i], 6); 508 return; 509 } 510 511 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), Code); 512 } 513 514 /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation. 515 /// Unlike EmitRecord, the code for the record should be included in Vals as 516 /// the first entry. 517 template <typename Container> 518 void EmitRecordWithAbbrev(unsigned Abbrev, const Container &Vals) { 519 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), std::nullopt); 520 } 521 522 /// EmitRecordWithBlob - Emit the specified record to the stream, using an 523 /// abbrev that includes a blob at the end. The blob data to emit is 524 /// specified by the pointer and length specified at the end. In contrast to 525 /// EmitRecord, this routine expects that the first entry in Vals is the code 526 /// of the record. 527 template <typename Container> 528 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, 529 StringRef Blob) { 530 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Blob, std::nullopt); 531 } 532 template <typename Container> 533 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, 534 const char *BlobData, unsigned BlobLen) { 535 return EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), 536 StringRef(BlobData, BlobLen), std::nullopt); 537 } 538 539 /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records 540 /// that end with an array. 541 template <typename Container> 542 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, 543 StringRef Array) { 544 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Array, std::nullopt); 545 } 546 template <typename Container> 547 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, 548 const char *ArrayData, unsigned ArrayLen) { 549 return EmitRecordWithAbbrevImpl( 550 Abbrev, ArrayRef(Vals), StringRef(ArrayData, ArrayLen), std::nullopt); 551 } 552 553 //===--------------------------------------------------------------------===// 554 // Abbrev Emission 555 //===--------------------------------------------------------------------===// 556 557 private: 558 // Emit the abbreviation as a DEFINE_ABBREV record. 559 void EncodeAbbrev(const BitCodeAbbrev &Abbv) { 560 EmitCode(bitc::DEFINE_ABBREV); 561 EmitVBR(Abbv.getNumOperandInfos(), 5); 562 for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos()); 563 i != e; ++i) { 564 const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(i); 565 Emit(Op.isLiteral(), 1); 566 if (Op.isLiteral()) { 567 EmitVBR64(Op.getLiteralValue(), 8); 568 } else { 569 Emit(Op.getEncoding(), 3); 570 if (Op.hasEncodingData()) 571 EmitVBR64(Op.getEncodingData(), 5); 572 } 573 } 574 } 575 public: 576 577 /// Emits the abbreviation \p Abbv to the stream. 578 unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) { 579 EncodeAbbrev(*Abbv); 580 CurAbbrevs.push_back(std::move(Abbv)); 581 return static_cast<unsigned>(CurAbbrevs.size())-1 + 582 bitc::FIRST_APPLICATION_ABBREV; 583 } 584 585 //===--------------------------------------------------------------------===// 586 // BlockInfo Block Emission 587 //===--------------------------------------------------------------------===// 588 589 /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. 590 void EnterBlockInfoBlock() { 591 EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, 2); 592 BlockInfoCurBID = ~0U; 593 BlockInfoRecords.clear(); 594 } 595 private: 596 /// SwitchToBlockID - If we aren't already talking about the specified block 597 /// ID, emit a BLOCKINFO_CODE_SETBID record. 598 void SwitchToBlockID(unsigned BlockID) { 599 if (BlockInfoCurBID == BlockID) return; 600 SmallVector<unsigned, 2> V; 601 V.push_back(BlockID); 602 EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V); 603 BlockInfoCurBID = BlockID; 604 } 605 606 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { 607 if (BlockInfo *BI = getBlockInfo(BlockID)) 608 return *BI; 609 610 // Otherwise, add a new record. 611 BlockInfoRecords.emplace_back(); 612 BlockInfoRecords.back().BlockID = BlockID; 613 return BlockInfoRecords.back(); 614 } 615 616 public: 617 618 /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified 619 /// BlockID. 620 unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr<BitCodeAbbrev> Abbv) { 621 SwitchToBlockID(BlockID); 622 EncodeAbbrev(*Abbv); 623 624 // Add the abbrev to the specified block record. 625 BlockInfo &Info = getOrCreateBlockInfo(BlockID); 626 Info.Abbrevs.push_back(std::move(Abbv)); 627 628 return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; 629 } 630 }; 631 632 633 } // End llvm namespace 634 635 #endif 636