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; BlockBlock63 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 WriteWord(unsigned Value)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 GetNumOfFlushedBytes()84 uint64_t GetNumOfFlushedBytes() const { return FS ? FS->tell() : 0; } 85 GetBufferOffset()86 size_t GetBufferOffset() const { return Out.size() + GetNumOfFlushedBytes(); } 87 GetWordIndex()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. FlushToFile()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) Out(O)115 : Out(O), FS(FS), FlushThreshold(uint64_t(FlushThreshold) << 20), CurBit(0), 116 CurValue(0), CurCodeSize(2) {} 117 ~BitstreamWriter()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. GetCurrentBitNo()124 uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; } 125 126 /// Retrieve the number of bits currently used to encode an abbrev ID. GetAbbrevIDWidth()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. BackpatchByte(uint64_t BitNo,uint8_t NewByte)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 BackpatchHalfWord(uint64_t BitNo,uint16_t Val)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 BackpatchWord(uint64_t BitNo,unsigned Val)199 void BackpatchWord(uint64_t BitNo, unsigned Val) { 200 BackpatchHalfWord(BitNo, (uint16_t)Val); 201 BackpatchHalfWord(BitNo + 16, (uint16_t)(Val >> 16)); 202 } 203 BackpatchWord64(uint64_t BitNo,uint64_t Val)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 Emit(uint32_t Val,unsigned NumBits)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 FlushToWord()228 void FlushToWord() { 229 if (CurBit) { 230 WriteWord(CurValue); 231 CurBit = 0; 232 CurValue = 0; 233 } 234 } 235 EmitVBR(uint32_t Val,unsigned NumBits)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 & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits); 243 Val >>= NumBits-1; 244 } 245 246 Emit(Val, NumBits); 247 } 248 EmitVBR64(uint64_t Val,unsigned NumBits)249 void EmitVBR64(uint64_t Val, unsigned NumBits) { 250 assert(NumBits <= 32 && "Too many bits to emit!"); 251 if ((uint32_t)Val == Val) 252 return EmitVBR((uint32_t)Val, NumBits); 253 254 uint32_t Threshold = 1U << (NumBits-1); 255 256 // Emit the bits with VBR encoding, NumBits-1 bits at a time. 257 while (Val >= Threshold) { 258 Emit(((uint32_t)Val & ((1 << (NumBits - 1)) - 1)) | (1 << (NumBits - 1)), 259 NumBits); 260 Val >>= NumBits-1; 261 } 262 263 Emit((uint32_t)Val, NumBits); 264 } 265 266 /// EmitCode - Emit the specified code. EmitCode(unsigned Val)267 void EmitCode(unsigned Val) { 268 Emit(Val, CurCodeSize); 269 } 270 271 //===--------------------------------------------------------------------===// 272 // Block Manipulation 273 //===--------------------------------------------------------------------===// 274 275 /// getBlockInfo - If there is block info for the specified ID, return it, 276 /// otherwise return null. getBlockInfo(unsigned BlockID)277 BlockInfo *getBlockInfo(unsigned BlockID) { 278 // Common case, the most recent entry matches BlockID. 279 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) 280 return &BlockInfoRecords.back(); 281 282 for (BlockInfo &BI : BlockInfoRecords) 283 if (BI.BlockID == BlockID) 284 return &BI; 285 return nullptr; 286 } 287 EnterSubblock(unsigned BlockID,unsigned CodeLen)288 void EnterSubblock(unsigned BlockID, unsigned CodeLen) { 289 // Block header: 290 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] 291 EmitCode(bitc::ENTER_SUBBLOCK); 292 EmitVBR(BlockID, bitc::BlockIDWidth); 293 EmitVBR(CodeLen, bitc::CodeLenWidth); 294 FlushToWord(); 295 296 size_t BlockSizeWordIndex = GetWordIndex(); 297 unsigned OldCodeSize = CurCodeSize; 298 299 // Emit a placeholder, which will be replaced when the block is popped. 300 Emit(0, bitc::BlockSizeWidth); 301 302 CurCodeSize = CodeLen; 303 304 // Push the outer block's abbrev set onto the stack, start out with an 305 // empty abbrev set. 306 BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex); 307 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); 308 309 // If there is a blockinfo for this BlockID, add all the predefined abbrevs 310 // to the abbrev list. 311 if (BlockInfo *Info = getBlockInfo(BlockID)) 312 append_range(CurAbbrevs, Info->Abbrevs); 313 } 314 ExitBlock()315 void ExitBlock() { 316 assert(!BlockScope.empty() && "Block scope imbalance!"); 317 const Block &B = BlockScope.back(); 318 319 // Block tail: 320 // [END_BLOCK, <align4bytes>] 321 EmitCode(bitc::END_BLOCK); 322 FlushToWord(); 323 324 // Compute the size of the block, in words, not counting the size field. 325 size_t SizeInWords = GetWordIndex() - B.StartSizeWord - 1; 326 uint64_t BitNo = uint64_t(B.StartSizeWord) * 32; 327 328 // Update the block size field in the header of this sub-block. 329 BackpatchWord(BitNo, SizeInWords); 330 331 // Restore the inner block's code size and abbrev table. 332 CurCodeSize = B.PrevCodeSize; 333 CurAbbrevs = std::move(B.PrevAbbrevs); 334 BlockScope.pop_back(); 335 FlushToFile(); 336 } 337 338 //===--------------------------------------------------------------------===// 339 // Record Emission 340 //===--------------------------------------------------------------------===// 341 342 private: 343 /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev 344 /// record. This is a no-op, since the abbrev specifies the literal to use. 345 template<typename uintty> EmitAbbreviatedLiteral(const BitCodeAbbrevOp & Op,uintty V)346 void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) { 347 assert(Op.isLiteral() && "Not a literal"); 348 // If the abbrev specifies the literal value to use, don't emit 349 // anything. 350 assert(V == Op.getLiteralValue() && 351 "Invalid abbrev for record!"); 352 } 353 354 /// EmitAbbreviatedField - Emit a single scalar field value with the specified 355 /// encoding. 356 template<typename uintty> EmitAbbreviatedField(const BitCodeAbbrevOp & Op,uintty V)357 void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { 358 assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!"); 359 360 // Encode the value as we are commanded. 361 switch (Op.getEncoding()) { 362 default: llvm_unreachable("Unknown encoding!"); 363 case BitCodeAbbrevOp::Fixed: 364 if (Op.getEncodingData()) 365 Emit((unsigned)V, (unsigned)Op.getEncodingData()); 366 break; 367 case BitCodeAbbrevOp::VBR: 368 if (Op.getEncodingData()) 369 EmitVBR64(V, (unsigned)Op.getEncodingData()); 370 break; 371 case BitCodeAbbrevOp::Char6: 372 Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6); 373 break; 374 } 375 } 376 377 /// EmitRecordWithAbbrevImpl - This is the core implementation of the record 378 /// emission code. If BlobData is non-null, then it specifies an array of 379 /// data that should be emitted as part of the Blob or Array operand that is 380 /// known to exist at the end of the record. If Code is specified, then 381 /// it is the record code to emit before the Vals, which must not contain 382 /// the code. 383 template <typename uintty> EmitRecordWithAbbrevImpl(unsigned Abbrev,ArrayRef<uintty> Vals,StringRef Blob,std::optional<unsigned> Code)384 void EmitRecordWithAbbrevImpl(unsigned Abbrev, ArrayRef<uintty> Vals, 385 StringRef Blob, std::optional<unsigned> Code) { 386 const char *BlobData = Blob.data(); 387 unsigned BlobLen = (unsigned) Blob.size(); 388 unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; 389 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); 390 const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get(); 391 392 EmitCode(Abbrev); 393 394 unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos()); 395 if (Code) { 396 assert(e && "Expected non-empty abbreviation"); 397 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i++); 398 399 if (Op.isLiteral()) 400 EmitAbbreviatedLiteral(Op, *Code); 401 else { 402 assert(Op.getEncoding() != BitCodeAbbrevOp::Array && 403 Op.getEncoding() != BitCodeAbbrevOp::Blob && 404 "Expected literal or scalar"); 405 EmitAbbreviatedField(Op, *Code); 406 } 407 } 408 409 unsigned RecordIdx = 0; 410 for (; i != e; ++i) { 411 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); 412 if (Op.isLiteral()) { 413 assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); 414 EmitAbbreviatedLiteral(Op, Vals[RecordIdx]); 415 ++RecordIdx; 416 } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) { 417 // Array case. 418 assert(i + 2 == e && "array op not second to last?"); 419 const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); 420 421 // If this record has blob data, emit it, otherwise we must have record 422 // entries to encode this way. 423 if (BlobData) { 424 assert(RecordIdx == Vals.size() && 425 "Blob data and record entries specified for array!"); 426 // Emit a vbr6 to indicate the number of elements present. 427 EmitVBR(static_cast<uint32_t>(BlobLen), 6); 428 429 // Emit each field. 430 for (unsigned i = 0; i != BlobLen; ++i) 431 EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]); 432 433 // Know that blob data is consumed for assertion below. 434 BlobData = nullptr; 435 } else { 436 // Emit a vbr6 to indicate the number of elements present. 437 EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6); 438 439 // Emit each field. 440 for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx) 441 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]); 442 } 443 } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) { 444 // If this record has blob data, emit it, otherwise we must have record 445 // entries to encode this way. 446 447 if (BlobData) { 448 assert(RecordIdx == Vals.size() && 449 "Blob data and record entries specified for blob operand!"); 450 451 assert(Blob.data() == BlobData && "BlobData got moved"); 452 assert(Blob.size() == BlobLen && "BlobLen got changed"); 453 emitBlob(Blob); 454 BlobData = nullptr; 455 } else { 456 emitBlob(Vals.slice(RecordIdx)); 457 } 458 } else { // Single scalar field. 459 assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); 460 EmitAbbreviatedField(Op, Vals[RecordIdx]); 461 ++RecordIdx; 462 } 463 } 464 assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); 465 assert(BlobData == nullptr && 466 "Blob data specified for record that doesn't use it!"); 467 } 468 469 public: 470 /// Emit a blob, including flushing before and tail-padding. 471 template <class UIntTy> 472 void emitBlob(ArrayRef<UIntTy> Bytes, bool ShouldEmitSize = true) { 473 // Emit a vbr6 to indicate the number of elements present. 474 if (ShouldEmitSize) 475 EmitVBR(static_cast<uint32_t>(Bytes.size()), 6); 476 477 // Flush to a 32-bit alignment boundary. 478 FlushToWord(); 479 480 // Emit literal bytes. 481 assert(llvm::all_of(Bytes, [](UIntTy B) { return isUInt<8>(B); })); 482 Out.append(Bytes.begin(), Bytes.end()); 483 484 // Align end to 32-bits. 485 while (GetBufferOffset() & 3) 486 Out.push_back(0); 487 } 488 void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) { 489 emitBlob(ArrayRef((const uint8_t *)Bytes.data(), Bytes.size()), 490 ShouldEmitSize); 491 } 492 493 /// EmitRecord - Emit the specified record to the stream, using an abbrev if 494 /// we have one to compress the output. 495 template <typename Container> 496 void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev = 0) { 497 if (!Abbrev) { 498 // If we don't have an abbrev to use, emit this in its fully unabbreviated 499 // form. 500 auto Count = static_cast<uint32_t>(std::size(Vals)); 501 EmitCode(bitc::UNABBREV_RECORD); 502 EmitVBR(Code, 6); 503 EmitVBR(Count, 6); 504 for (unsigned i = 0, e = Count; i != e; ++i) 505 EmitVBR64(Vals[i], 6); 506 return; 507 } 508 509 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), Code); 510 } 511 512 /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation. 513 /// Unlike EmitRecord, the code for the record should be included in Vals as 514 /// the first entry. 515 template <typename Container> EmitRecordWithAbbrev(unsigned Abbrev,const Container & Vals)516 void EmitRecordWithAbbrev(unsigned Abbrev, const Container &Vals) { 517 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), std::nullopt); 518 } 519 520 /// EmitRecordWithBlob - Emit the specified record to the stream, using an 521 /// abbrev that includes a blob at the end. The blob data to emit is 522 /// specified by the pointer and length specified at the end. In contrast to 523 /// EmitRecord, this routine expects that the first entry in Vals is the code 524 /// of the record. 525 template <typename Container> EmitRecordWithBlob(unsigned Abbrev,const Container & Vals,StringRef Blob)526 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, 527 StringRef Blob) { 528 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Blob, std::nullopt); 529 } 530 template <typename Container> EmitRecordWithBlob(unsigned Abbrev,const Container & Vals,const char * BlobData,unsigned BlobLen)531 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, 532 const char *BlobData, unsigned BlobLen) { 533 return EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), 534 StringRef(BlobData, BlobLen), std::nullopt); 535 } 536 537 /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records 538 /// that end with an array. 539 template <typename Container> EmitRecordWithArray(unsigned Abbrev,const Container & Vals,StringRef Array)540 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, 541 StringRef Array) { 542 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Array, std::nullopt); 543 } 544 template <typename Container> EmitRecordWithArray(unsigned Abbrev,const Container & Vals,const char * ArrayData,unsigned ArrayLen)545 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, 546 const char *ArrayData, unsigned ArrayLen) { 547 return EmitRecordWithAbbrevImpl( 548 Abbrev, ArrayRef(Vals), StringRef(ArrayData, ArrayLen), std::nullopt); 549 } 550 551 //===--------------------------------------------------------------------===// 552 // Abbrev Emission 553 //===--------------------------------------------------------------------===// 554 555 private: 556 // Emit the abbreviation as a DEFINE_ABBREV record. EncodeAbbrev(const BitCodeAbbrev & Abbv)557 void EncodeAbbrev(const BitCodeAbbrev &Abbv) { 558 EmitCode(bitc::DEFINE_ABBREV); 559 EmitVBR(Abbv.getNumOperandInfos(), 5); 560 for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos()); 561 i != e; ++i) { 562 const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(i); 563 Emit(Op.isLiteral(), 1); 564 if (Op.isLiteral()) { 565 EmitVBR64(Op.getLiteralValue(), 8); 566 } else { 567 Emit(Op.getEncoding(), 3); 568 if (Op.hasEncodingData()) 569 EmitVBR64(Op.getEncodingData(), 5); 570 } 571 } 572 } 573 public: 574 575 /// Emits the abbreviation \p Abbv to the stream. EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv)576 unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) { 577 EncodeAbbrev(*Abbv); 578 CurAbbrevs.push_back(std::move(Abbv)); 579 return static_cast<unsigned>(CurAbbrevs.size())-1 + 580 bitc::FIRST_APPLICATION_ABBREV; 581 } 582 583 //===--------------------------------------------------------------------===// 584 // BlockInfo Block Emission 585 //===--------------------------------------------------------------------===// 586 587 /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. EnterBlockInfoBlock()588 void EnterBlockInfoBlock() { 589 EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, 2); 590 BlockInfoCurBID = ~0U; 591 BlockInfoRecords.clear(); 592 } 593 private: 594 /// SwitchToBlockID - If we aren't already talking about the specified block 595 /// ID, emit a BLOCKINFO_CODE_SETBID record. SwitchToBlockID(unsigned BlockID)596 void SwitchToBlockID(unsigned BlockID) { 597 if (BlockInfoCurBID == BlockID) return; 598 SmallVector<unsigned, 2> V; 599 V.push_back(BlockID); 600 EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V); 601 BlockInfoCurBID = BlockID; 602 } 603 getOrCreateBlockInfo(unsigned BlockID)604 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { 605 if (BlockInfo *BI = getBlockInfo(BlockID)) 606 return *BI; 607 608 // Otherwise, add a new record. 609 BlockInfoRecords.emplace_back(); 610 BlockInfoRecords.back().BlockID = BlockID; 611 return BlockInfoRecords.back(); 612 } 613 614 public: 615 616 /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified 617 /// BlockID. EmitBlockInfoAbbrev(unsigned BlockID,std::shared_ptr<BitCodeAbbrev> Abbv)618 unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr<BitCodeAbbrev> Abbv) { 619 SwitchToBlockID(BlockID); 620 EncodeAbbrev(*Abbv); 621 622 // Add the abbrev to the specified block record. 623 BlockInfo &Info = getOrCreateBlockInfo(BlockID); 624 Info.Abbrevs.push_back(std::move(Abbv)); 625 626 return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; 627 } 628 }; 629 630 631 } // End llvm namespace 632 633 #endif 634