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/Casting.h" 22 #include "llvm/Support/Endian.h" 23 #include "llvm/Support/MathExtras.h" 24 #include "llvm/Support/raw_ostream.h" 25 #include <algorithm> 26 #include <optional> 27 #include <vector> 28 29 namespace llvm { 30 31 class BitstreamWriter { 32 /// Owned buffer, used to init Buffer if the provided stream doesn't happen to 33 /// be a buffer itself. 34 SmallVector<char, 0> OwnBuffer; 35 /// Internal buffer for unflushed bytes (unless there is no stream to flush 36 /// to, case in which these are "the bytes"). The writer backpatches, so it is 37 /// efficient to buffer. 38 SmallVectorImpl<char> &Buffer; 39 40 /// FS - The file stream that Buffer flushes to. If FS is a raw_fd_stream, the 41 /// writer will incrementally flush at subblock boundaries. Otherwise flushing 42 /// will happen at the end of BitstreamWriter's lifetime. 43 raw_ostream *const FS; 44 45 /// FlushThreshold - this is the threshold (unit B) to flush to FS, if FS is a 46 /// raw_fd_stream. 47 const uint64_t FlushThreshold; 48 49 /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. 50 unsigned CurBit = 0; 51 52 /// CurValue - The current value. Only bits < CurBit are valid. 53 uint32_t CurValue = 0; 54 55 /// CurCodeSize - This is the declared size of code values used for the 56 /// current block, in bits. 57 unsigned CurCodeSize = 2; 58 59 /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently 60 /// selected BLOCK ID. 61 unsigned BlockInfoCurBID = 0; 62 63 /// CurAbbrevs - Abbrevs installed at in this block. 64 std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs; 65 66 // Support for retrieving a section of the output, for purposes such as 67 // checksumming. 68 std::optional<size_t> BlockFlushingStartPos; 69 70 struct Block { 71 unsigned PrevCodeSize; 72 size_t StartSizeWord; 73 std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs; BlockBlock74 Block(unsigned PCS, size_t SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} 75 }; 76 77 /// BlockScope - This tracks the current blocks that we have entered. 78 std::vector<Block> BlockScope; 79 80 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. 81 /// These describe abbreviations that all blocks of the specified ID inherit. 82 struct BlockInfo { 83 unsigned BlockID; 84 std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs; 85 }; 86 std::vector<BlockInfo> BlockInfoRecords; 87 WriteWord(unsigned Value)88 void WriteWord(unsigned Value) { 89 Value = 90 support::endian::byte_swap<uint32_t, llvm::endianness::little>(Value); 91 Buffer.append(reinterpret_cast<const char *>(&Value), 92 reinterpret_cast<const char *>(&Value + 1)); 93 } 94 GetNumOfFlushedBytes()95 uint64_t GetNumOfFlushedBytes() const { 96 return fdStream() ? fdStream()->tell() : 0; 97 } 98 GetBufferOffset()99 size_t GetBufferOffset() const { 100 return Buffer.size() + GetNumOfFlushedBytes(); 101 } 102 GetWordIndex()103 size_t GetWordIndex() const { 104 size_t Offset = GetBufferOffset(); 105 assert((Offset & 3) == 0 && "Not 32-bit aligned"); 106 return Offset / 4; 107 } 108 flushAndClear()109 void flushAndClear() { 110 assert(FS); 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 /// If the related file stream is a raw_fd_stream, flush the buffer if its 120 /// size is above a threshold. If \p OnClosing is true, flushing happens 121 /// regardless of thresholds. 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 fdStream()133 raw_fd_stream *fdStream() { return dyn_cast_or_null<raw_fd_stream>(FS); } 134 fdStream()135 const raw_fd_stream *fdStream() const { 136 return dyn_cast_or_null<raw_fd_stream>(FS); 137 } 138 getInternalBufferFromStream(raw_ostream & OutStream)139 SmallVectorImpl<char> &getInternalBufferFromStream(raw_ostream &OutStream) { 140 if (auto *SV = dyn_cast<raw_svector_ostream>(&OutStream)) 141 return SV->buffer(); 142 return OwnBuffer; 143 } 144 145 public: 146 /// Create a BitstreamWriter over a raw_ostream \p OutStream. 147 /// If \p OutStream is a raw_svector_ostream, the BitstreamWriter will write 148 /// directly to the latter's buffer. In all other cases, the BitstreamWriter 149 /// will use an internal buffer and flush at the end of its lifetime. 150 /// 151 /// In addition, if \p is a raw_fd_stream supporting seek, tell, and read 152 /// (besides write), the BitstreamWriter will also flush incrementally, when a 153 /// subblock is finished, and if the FlushThreshold is passed. 154 /// 155 /// NOTE: \p FlushThreshold's unit is MB. 156 BitstreamWriter(raw_ostream &OutStream, uint32_t FlushThreshold = 512) Buffer(getInternalBufferFromStream (OutStream))157 : Buffer(getInternalBufferFromStream(OutStream)), 158 FS(!isa<raw_svector_ostream>(OutStream) ? &OutStream : nullptr), 159 FlushThreshold(uint64_t(FlushThreshold) << 20) {} 160 161 /// Convenience constructor for users that start with a vector - avoids 162 /// needing to wrap it in a raw_svector_ostream. BitstreamWriter(SmallVectorImpl<char> & Buff)163 BitstreamWriter(SmallVectorImpl<char> &Buff) 164 : Buffer(Buff), FS(nullptr), FlushThreshold(0) {} 165 ~BitstreamWriter()166 ~BitstreamWriter() { 167 FlushToWord(); 168 assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); 169 FlushToFile(/*OnClosing=*/true); 170 } 171 172 /// For scenarios where the user wants to access a section of the stream to 173 /// (for example) compute some checksum, disable flushing and remember the 174 /// position in the internal buffer where that happened. Must be paired with a 175 /// call to getMarkedBufferAndResumeFlushing. markAndBlockFlushing()176 void markAndBlockFlushing() { 177 assert(!BlockFlushingStartPos); 178 BlockFlushingStartPos = Buffer.size(); 179 } 180 181 /// resumes flushing, but does not flush, and returns the section in the 182 /// internal buffer starting from the position marked with 183 /// markAndBlockFlushing. The return should be processed before any additional 184 /// calls to this object, because those may cause a flush and invalidate the 185 /// return. getMarkedBufferAndResumeFlushing()186 StringRef getMarkedBufferAndResumeFlushing() { 187 assert(BlockFlushingStartPos); 188 size_t Start = *BlockFlushingStartPos; 189 BlockFlushingStartPos.reset(); 190 return {&Buffer[Start], Buffer.size() - Start}; 191 } 192 193 /// Retrieve the current position in the stream, in bits. GetCurrentBitNo()194 uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; } 195 196 /// Retrieve the number of bits currently used to encode an abbrev ID. GetAbbrevIDWidth()197 unsigned GetAbbrevIDWidth() const { return CurCodeSize; } 198 199 //===--------------------------------------------------------------------===// 200 // Basic Primitives for emitting bits to the stream. 201 //===--------------------------------------------------------------------===// 202 203 /// Backpatch a byte in the output at the given bit offset with the specified 204 /// value. BackpatchByte(uint64_t BitNo,uint8_t NewByte)205 void BackpatchByte(uint64_t BitNo, uint8_t NewByte) { 206 using namespace llvm::support; 207 uint64_t ByteNo = BitNo / 8; 208 uint64_t StartBit = BitNo & 7; 209 uint64_t NumOfFlushedBytes = GetNumOfFlushedBytes(); 210 211 if (ByteNo >= NumOfFlushedBytes) { 212 assert((!endian::readAtBitAlignment<uint8_t, llvm::endianness::little, 213 unaligned>( 214 &Buffer[ByteNo - NumOfFlushedBytes], StartBit)) && 215 "Expected to be patching over 0-value placeholders"); 216 endian::writeAtBitAlignment<uint8_t, llvm::endianness::little, unaligned>( 217 &Buffer[ByteNo - NumOfFlushedBytes], NewByte, StartBit); 218 return; 219 } 220 221 // If we don't have a raw_fd_stream, GetNumOfFlushedBytes() should have 222 // returned 0, and we shouldn't be here. 223 assert(fdStream() != nullptr); 224 // If the byte offset to backpatch is flushed, use seek to backfill data. 225 // First, save the file position to restore later. 226 uint64_t CurPos = fdStream()->tell(); 227 228 // Copy data to update into Bytes from the file FS and the buffer Out. 229 char Bytes[3]; // Use one more byte to silence a warning from Visual C++. 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 // When unaligned, copy existing data into Bytes from the file FS and the 235 // buffer Buffer so that it can be updated before writing. For debug builds 236 // read bytes unconditionally in order to check that the existing value is 0 237 // as expected. 238 #ifdef NDEBUG 239 if (StartBit) 240 #endif 241 { 242 fdStream()->seek(ByteNo); 243 ssize_t BytesRead = fdStream()->read(Bytes, BytesFromDisk); 244 (void)BytesRead; // silence warning 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]; 248 assert((!endian::readAtBitAlignment<uint8_t, llvm::endianness::little, 249 unaligned>(Bytes, StartBit)) && 250 "Expected to be patching over 0-value placeholders"); 251 } 252 253 // Update Bytes in terms of bit offset and value. 254 endian::writeAtBitAlignment<uint8_t, llvm::endianness::little, unaligned>( 255 Bytes, NewByte, StartBit); 256 257 // Copy updated data back to the file FS and the buffer Out. 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 // Restore the file position. 264 fdStream()->seek(CurPos); 265 } 266 BackpatchHalfWord(uint64_t BitNo,uint16_t Val)267 void BackpatchHalfWord(uint64_t BitNo, uint16_t Val) { 268 BackpatchByte(BitNo, (uint8_t)Val); 269 BackpatchByte(BitNo + 8, (uint8_t)(Val >> 8)); 270 } 271 BackpatchWord(uint64_t BitNo,unsigned Val)272 void BackpatchWord(uint64_t BitNo, unsigned Val) { 273 BackpatchHalfWord(BitNo, (uint16_t)Val); 274 BackpatchHalfWord(BitNo + 16, (uint16_t)(Val >> 16)); 275 } 276 BackpatchWord64(uint64_t BitNo,uint64_t Val)277 void BackpatchWord64(uint64_t BitNo, uint64_t Val) { 278 BackpatchWord(BitNo, (uint32_t)Val); 279 BackpatchWord(BitNo + 32, (uint32_t)(Val >> 32)); 280 } 281 Emit(uint32_t Val,unsigned NumBits)282 void Emit(uint32_t Val, unsigned NumBits) { 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 // Add the current word. 292 WriteWord(CurValue); 293 294 if (CurBit) 295 CurValue = Val >> (32-CurBit); 296 else 297 CurValue = 0; 298 CurBit = (CurBit+NumBits) & 31; 299 } 300 FlushToWord()301 void FlushToWord() { 302 if (CurBit) { 303 WriteWord(CurValue); 304 CurBit = 0; 305 CurValue = 0; 306 } 307 } 308 EmitVBR(uint32_t Val,unsigned NumBits)309 void EmitVBR(uint32_t Val, unsigned NumBits) { 310 assert(NumBits <= 32 && "Too many bits to emit!"); 311 uint32_t Threshold = 1U << (NumBits-1); 312 313 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 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 EmitVBR64(uint64_t Val,unsigned NumBits)323 void EmitVBR64(uint64_t Val, unsigned NumBits) { 324 assert(NumBits <= 32 && "Too many bits to emit!"); 325 if ((uint32_t)Val == Val) 326 return EmitVBR((uint32_t)Val, NumBits); 327 328 uint32_t Threshold = 1U << (NumBits-1); 329 330 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 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 338 Emit((uint32_t)Val, NumBits); 339 } 340 341 /// EmitCode - Emit the specified code. EmitCode(unsigned Val)342 void EmitCode(unsigned Val) { 343 Emit(Val, CurCodeSize); 344 } 345 346 //===--------------------------------------------------------------------===// 347 // Block Manipulation 348 //===--------------------------------------------------------------------===// 349 350 /// getBlockInfo - If there is block info for the specified ID, return it, 351 /// otherwise return null. getBlockInfo(unsigned BlockID)352 BlockInfo *getBlockInfo(unsigned BlockID) { 353 // Common case, the most recent entry matches BlockID. 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 EnterSubblock(unsigned BlockID,unsigned CodeLen)363 void EnterSubblock(unsigned BlockID, unsigned CodeLen) { 364 // Block header: 365 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] 366 EmitCode(bitc::ENTER_SUBBLOCK); 367 EmitVBR(BlockID, bitc::BlockIDWidth); 368 EmitVBR(CodeLen, bitc::CodeLenWidth); 369 FlushToWord(); 370 371 size_t BlockSizeWordIndex = GetWordIndex(); 372 unsigned OldCodeSize = CurCodeSize; 373 374 // Emit a placeholder, which will be replaced when the block is popped. 375 Emit(0, bitc::BlockSizeWidth); 376 377 CurCodeSize = CodeLen; 378 379 // Push the outer block's abbrev set onto the stack, start out with an 380 // empty abbrev set. 381 BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex); 382 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); 383 384 // If there is a blockinfo for this BlockID, add all the predefined abbrevs 385 // to the abbrev list. 386 if (BlockInfo *Info = getBlockInfo(BlockID)) 387 append_range(CurAbbrevs, Info->Abbrevs); 388 } 389 ExitBlock()390 void ExitBlock() { 391 assert(!BlockScope.empty() && "Block scope imbalance!"); 392 const Block &B = BlockScope.back(); 393 394 // Block tail: 395 // [END_BLOCK, <align4bytes>] 396 EmitCode(bitc::END_BLOCK); 397 FlushToWord(); 398 399 // Compute the size of the block, in words, not counting the size field. 400 size_t SizeInWords = GetWordIndex() - B.StartSizeWord - 1; 401 uint64_t BitNo = uint64_t(B.StartSizeWord) * 32; 402 403 // Update the block size field in the header of this sub-block. 404 BackpatchWord(BitNo, SizeInWords); 405 406 // Restore the inner block's code size and abbrev table. 407 CurCodeSize = B.PrevCodeSize; 408 CurAbbrevs = std::move(B.PrevAbbrevs); 409 BlockScope.pop_back(); 410 FlushToFile(); 411 } 412 413 //===--------------------------------------------------------------------===// 414 // Record Emission 415 //===--------------------------------------------------------------------===// 416 417 private: 418 /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev 419 /// record. This is a no-op, since the abbrev specifies the literal to use. 420 template<typename uintty> EmitAbbreviatedLiteral(const BitCodeAbbrevOp & Op,uintty V)421 void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) { 422 assert(Op.isLiteral() && "Not a literal"); 423 // If the abbrev specifies the literal value to use, don't emit 424 // anything. 425 assert(V == Op.getLiteralValue() && 426 "Invalid abbrev for record!"); 427 } 428 429 /// EmitAbbreviatedField - Emit a single scalar field value with the specified 430 /// encoding. 431 template<typename uintty> EmitAbbreviatedField(const BitCodeAbbrevOp & Op,uintty V)432 void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { 433 assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!"); 434 435 // Encode the value as we are commanded. 436 switch (Op.getEncoding()) { 437 default: llvm_unreachable("Unknown encoding!"); 438 case BitCodeAbbrevOp::Fixed: 439 if (Op.getEncodingData()) 440 Emit((unsigned)V, (unsigned)Op.getEncodingData()); 441 break; 442 case BitCodeAbbrevOp::VBR: 443 if (Op.getEncodingData()) 444 EmitVBR64(V, (unsigned)Op.getEncodingData()); 445 break; 446 case BitCodeAbbrevOp::Char6: 447 Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6); 448 break; 449 } 450 } 451 452 /// EmitRecordWithAbbrevImpl - This is the core implementation of the record 453 /// emission code. If BlobData is non-null, then it specifies an array of 454 /// data that should be emitted as part of the Blob or Array operand that is 455 /// known to exist at the end of the record. If Code is specified, then 456 /// it is the record code to emit before the Vals, which must not contain 457 /// the code. 458 template <typename uintty> EmitRecordWithAbbrevImpl(unsigned Abbrev,ArrayRef<uintty> Vals,StringRef Blob,std::optional<unsigned> Code)459 void EmitRecordWithAbbrevImpl(unsigned Abbrev, ArrayRef<uintty> Vals, 460 StringRef Blob, std::optional<unsigned> Code) { 461 const char *BlobData = Blob.data(); 462 unsigned BlobLen = (unsigned) Blob.size(); 463 unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; 464 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); 465 const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get(); 466 467 EmitCode(Abbrev); 468 469 unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos()); 470 if (Code) { 471 assert(e && "Expected non-empty abbreviation"); 472 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i++); 473 474 if (Op.isLiteral()) 475 EmitAbbreviatedLiteral(Op, *Code); 476 else { 477 assert(Op.getEncoding() != BitCodeAbbrevOp::Array && 478 Op.getEncoding() != BitCodeAbbrevOp::Blob && 479 "Expected literal or scalar"); 480 EmitAbbreviatedField(Op, *Code); 481 } 482 } 483 484 unsigned RecordIdx = 0; 485 for (; i != e; ++i) { 486 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); 487 if (Op.isLiteral()) { 488 assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); 489 EmitAbbreviatedLiteral(Op, Vals[RecordIdx]); 490 ++RecordIdx; 491 } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { 492 // Array case. 493 assert(i + 2 == e && "array op not second to last?"); 494 const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); 495 496 // If this record has blob data, emit it, otherwise we must have record 497 // entries to encode this way. 498 if (BlobData) { 499 assert(RecordIdx == Vals.size() && 500 "Blob data and record entries specified for array!"); 501 // Emit a vbr6 to indicate the number of elements present. 502 EmitVBR(static_cast<uint32_t>(BlobLen), 6); 503 504 // Emit each field. 505 for (unsigned i = 0; i != BlobLen; ++i) 506 EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]); 507 508 // Know that blob data is consumed for assertion below. 509 BlobData = nullptr; 510 } else { 511 // Emit a vbr6 to indicate the number of elements present. 512 EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6); 513 514 // Emit each field. 515 for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) 516 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]); 517 } 518 } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { 519 // If this record has blob data, emit it, otherwise we must have record 520 // entries to encode this way. 521 522 if (BlobData) { 523 assert(RecordIdx == Vals.size() && 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"); 528 emitBlob(Blob); 529 BlobData = nullptr; 530 } else { 531 emitBlob(Vals.slice(RecordIdx)); 532 } 533 } else { // Single scalar field. 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 544 public: 545 /// Emit a blob, including flushing before and tail-padding. 546 template <class UIntTy> 547 void emitBlob(ArrayRef<UIntTy> Bytes, bool ShouldEmitSize = true) { 548 // Emit a vbr6 to indicate the number of elements present. 549 if (ShouldEmitSize) 550 EmitVBR(static_cast<uint32_t>(Bytes.size()), 6); 551 552 // Flush to a 32-bit alignment boundary. 553 FlushToWord(); 554 555 // Emit literal bytes. 556 assert(llvm::all_of(Bytes, [](UIntTy B) { return isUInt<8>(B); })); 557 Buffer.append(Bytes.begin(), Bytes.end()); 558 559 // Align end to 32-bits. 560 while (GetBufferOffset() & 3) 561 Buffer.push_back(0); 562 } 563 void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) { 564 emitBlob(ArrayRef((const uint8_t *)Bytes.data(), Bytes.size()), 565 ShouldEmitSize); 566 } 567 568 /// EmitRecord - Emit the specified record to the stream, using an abbrev if 569 /// we have one to compress the output. 570 template <typename Container> 571 void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev = 0) { 572 if (!Abbrev) { 573 // If we don't have an abbrev to use, emit this in its fully unabbreviated 574 // form. 575 auto Count = static_cast<uint32_t>(std::size(Vals)); 576 EmitCode(bitc::UNABBREV_RECORD); 577 EmitVBR(Code, 6); 578 EmitVBR(Count, 6); 579 for (unsigned i = 0, e = Count; i != e; ++i) 580 EmitVBR64(Vals[i], 6); 581 return; 582 } 583 584 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), Code); 585 } 586 587 /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation. 588 /// Unlike EmitRecord, the code for the record should be included in Vals as 589 /// the first entry. 590 template <typename Container> EmitRecordWithAbbrev(unsigned Abbrev,const Container & Vals)591 void EmitRecordWithAbbrev(unsigned Abbrev, const Container &Vals) { 592 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), std::nullopt); 593 } 594 595 /// EmitRecordWithBlob - Emit the specified record to the stream, using an 596 /// abbrev that includes a blob at the end. The blob data to emit is 597 /// specified by the pointer and length specified at the end. In contrast to 598 /// EmitRecord, this routine expects that the first entry in Vals is the code 599 /// of the record. 600 template <typename Container> EmitRecordWithBlob(unsigned Abbrev,const Container & Vals,StringRef Blob)601 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, 602 StringRef Blob) { 603 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Blob, std::nullopt); 604 } 605 template <typename Container> EmitRecordWithBlob(unsigned Abbrev,const Container & Vals,const char * BlobData,unsigned BlobLen)606 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, 607 const char *BlobData, unsigned BlobLen) { 608 return EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), 609 StringRef(BlobData, BlobLen), std::nullopt); 610 } 611 612 /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records 613 /// that end with an array. 614 template <typename Container> EmitRecordWithArray(unsigned Abbrev,const Container & Vals,StringRef Array)615 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, 616 StringRef Array) { 617 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Array, std::nullopt); 618 } 619 template <typename Container> EmitRecordWithArray(unsigned Abbrev,const Container & Vals,const char * ArrayData,unsigned ArrayLen)620 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, 621 const char *ArrayData, unsigned ArrayLen) { 622 return EmitRecordWithAbbrevImpl( 623 Abbrev, ArrayRef(Vals), StringRef(ArrayData, ArrayLen), std::nullopt); 624 } 625 626 //===--------------------------------------------------------------------===// 627 // Abbrev Emission 628 //===--------------------------------------------------------------------===// 629 630 private: 631 // Emit the abbreviation as a DEFINE_ABBREV record. EncodeAbbrev(const BitCodeAbbrev & Abbv)632 void EncodeAbbrev(const BitCodeAbbrev &Abbv) { 633 EmitCode(bitc::DEFINE_ABBREV); 634 EmitVBR(Abbv.getNumOperandInfos(), 5); 635 for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos()); 636 i != e; ++i) { 637 const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(i); 638 Emit(Op.isLiteral(), 1); 639 if (Op.isLiteral()) { 640 EmitVBR64(Op.getLiteralValue(), 8); 641 } else { 642 Emit(Op.getEncoding(), 3); 643 if (Op.hasEncodingData()) 644 EmitVBR64(Op.getEncodingData(), 5); 645 } 646 } 647 } 648 public: 649 650 /// Emits the abbreviation \p Abbv to the stream. EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv)651 unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) { 652 EncodeAbbrev(*Abbv); 653 CurAbbrevs.push_back(std::move(Abbv)); 654 return static_cast<unsigned>(CurAbbrevs.size())-1 + 655 bitc::FIRST_APPLICATION_ABBREV; 656 } 657 658 //===--------------------------------------------------------------------===// 659 // BlockInfo Block Emission 660 //===--------------------------------------------------------------------===// 661 662 /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. EnterBlockInfoBlock()663 void EnterBlockInfoBlock() { 664 EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, 2); 665 BlockInfoCurBID = ~0U; 666 BlockInfoRecords.clear(); 667 } 668 private: 669 /// SwitchToBlockID - If we aren't already talking about the specified block 670 /// ID, emit a BLOCKINFO_CODE_SETBID record. SwitchToBlockID(unsigned BlockID)671 void SwitchToBlockID(unsigned BlockID) { 672 if (BlockInfoCurBID == BlockID) return; 673 SmallVector<unsigned, 2> V; 674 V.push_back(BlockID); 675 EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V); 676 BlockInfoCurBID = BlockID; 677 } 678 getOrCreateBlockInfo(unsigned BlockID)679 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { 680 if (BlockInfo *BI = getBlockInfo(BlockID)) 681 return *BI; 682 683 // Otherwise, add a new record. 684 BlockInfoRecords.emplace_back(); 685 BlockInfoRecords.back().BlockID = BlockID; 686 return BlockInfoRecords.back(); 687 } 688 689 public: 690 691 /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified 692 /// BlockID. EmitBlockInfoAbbrev(unsigned BlockID,std::shared_ptr<BitCodeAbbrev> Abbv)693 unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr<BitCodeAbbrev> Abbv) { 694 SwitchToBlockID(BlockID); 695 EncodeAbbrev(*Abbv); 696 697 // Add the abbrev to the specified block record. 698 BlockInfo &Info = getOrCreateBlockInfo(BlockID); 699 Info.Abbrevs.push_back(std::move(Abbv)); 700 701 return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; 702 } 703 }; 704 705 706 } // End llvm namespace 707 708 #endif 709