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
29namespace llvm {
30
31class 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;
74 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
88 void WriteWord(unsigned Value) {
89 Value =
90 support::endian::byte_swap<uint32_t, llvm::endianness::little>(value: Value);
91 Buffer.append(in_start: reinterpret_cast<const char *>(&Value),
92 in_end: 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");
106 return Offset / 4;
107 }
108
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(Ptr: Buffer.data(), Size: 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
133 raw_fd_stream *fdStream() { return dyn_cast_or_null<raw_fd_stream>(Val: FS); }
134
135 const raw_fd_stream *fdStream() const {
136 return dyn_cast_or_null<raw_fd_stream>(Val: FS);
137 }
138
139 SmallVectorImpl<char> &getInternalBufferFromStream(raw_ostream &OutStream) {
140 if (auto *SV = dyn_cast<raw_svector_ostream>(Val: &OutStream))
141 return SV->buffer();
142 return OwnBuffer;
143 }
144
145public:
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)
157 : Buffer(getInternalBufferFromStream(OutStream)),
158 FS(!isa<raw_svector_ostream>(Val: 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.
163 BitstreamWriter(SmallVectorImpl<char> &Buff)
164 : Buffer(Buff), FS(nullptr), FlushThreshold(0) {}
165
166 ~BitstreamWriter() {
167 FlushToWord();
168 assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
169 FlushToFile(/*OnClosing=*/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.
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.
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.
194 uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
195
196 /// Retrieve the number of bits currently used to encode an abbrev ID.
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.
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 memory: &Buffer[ByteNo - NumOfFlushedBytes], value: NewByte, startBit: 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(a: static_cast<uint64_t>(BytesNum), b: 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(off: ByteNo);
243 ssize_t BytesRead = fdStream()->read(Ptr: Bytes, Size: 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 memory: Bytes, value: NewByte, startBit: StartBit);
256
257 // Copy updated data back to the file FS and the buffer Out.
258 fdStream()->seek(off: ByteNo);
259 fdStream()->write(Ptr: Bytes, Size: 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(off: CurPos);
265 }
266
267 void BackpatchHalfWord(uint64_t BitNo, uint16_t Val) {
268 BackpatchByte(BitNo, NewByte: (uint8_t)Val);
269 BackpatchByte(BitNo: BitNo + 8, NewByte: (uint8_t)(Val >> 8));
270 }
271
272 void BackpatchWord(uint64_t BitNo, unsigned Val) {
273 BackpatchHalfWord(BitNo, Val: (uint16_t)Val);
274 BackpatchHalfWord(BitNo: BitNo + 16, Val: (uint16_t)(Val >> 16));
275 }
276
277 void BackpatchWord64(uint64_t BitNo, uint64_t Val) {
278 BackpatchWord(BitNo, Val: (uint32_t)Val);
279 BackpatchWord(BitNo: BitNo + 32, Val: (uint32_t)(Val >> 32));
280 }
281
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(Value: CurValue);
293
294 if (CurBit)
295 CurValue = Val >> (32-CurBit);
296 else
297 CurValue = 0;
298 CurBit = (CurBit+NumBits) & 31;
299 }
300
301 void FlushToWord() {
302 if (CurBit) {
303 WriteWord(Value: CurValue);
304 CurBit = 0;
305 CurValue = 0;
306 }
307 }
308
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: (Val & ((1U << (NumBits - 1)) - 1)) | (1U << (NumBits - 1)),
316 NumBits);
317 Val >>= NumBits-1;
318 }
319
320 Emit(Val, NumBits);
321 }
322
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(Val: (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(Val: ((uint32_t)Val & ((1U << (NumBits - 1)) - 1)) |
333 (1U << (NumBits - 1)),
334 NumBits);
335 Val >>= NumBits-1;
336 }
337
338 Emit(Val: (uint32_t)Val, NumBits);
339 }
340
341 /// EmitCode - Emit the specified code.
342 void EmitCode(unsigned Val) {
343 Emit(Val, NumBits: 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.
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
363 void EnterSubblock(unsigned BlockID, unsigned CodeLen) {
364 // Block header:
365 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
366 EmitCode(Val: bitc::ENTER_SUBBLOCK);
367 EmitVBR(Val: BlockID, NumBits: bitc::BlockIDWidth);
368 EmitVBR(Val: CodeLen, NumBits: 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(Val: 0, NumBits: 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(args&: OldCodeSize, args&: BlockSizeWordIndex);
382 BlockScope.back().PrevAbbrevs.swap(x&: 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(C&: CurAbbrevs, R&: Info->Abbrevs);
388 }
389
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(Val: 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, Val: 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
417private:
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>
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>
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(Val: (unsigned)V, NumBits: (unsigned)Op.getEncodingData());
441 break;
442 case BitCodeAbbrevOp::VBR:
443 if (Op.getEncodingData())
444 EmitVBR64(Val: V, NumBits: (unsigned)Op.getEncodingData());
445 break;
446 case BitCodeAbbrevOp::Char6:
447 Emit(Val: BitCodeAbbrevOp::EncodeChar6(C: (char)V), NumBits: 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>
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(Val: 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(N: i++);
473
474 if (Op.isLiteral())
475 EmitAbbreviatedLiteral(Op, V: *Code);
476 else {
477 assert(Op.getEncoding() != BitCodeAbbrevOp::Array &&
478 Op.getEncoding() != BitCodeAbbrevOp::Blob &&
479 "Expected literal or scalar");
480 EmitAbbreviatedField(Op, V: *Code);
481 }
482 }
483
484 unsigned RecordIdx = 0;
485 for (; i != e; ++i) {
486 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(N: 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(N: ++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(Val: static_cast<uint32_t>(BlobLen), NumBits: 6);
503
504 // Emit each field.
505 for (unsigned i = 0; i != BlobLen; ++i)
506 EmitAbbreviatedField(Op: EltEnc, V: (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(Val: static_cast<uint32_t>(Vals.size()-RecordIdx), NumBits: 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(Bytes: 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
544public:
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(Val: static_cast<uint32_t>(Bytes.size()), NumBits: 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(Elt: 0);
562 }
563 void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) {
564 emitBlob(Bytes: 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(Val: bitc::UNABBREV_RECORD);
577 EmitVBR(Val: Code, NumBits: 6);
578 EmitVBR(Val: Count, NumBits: 6);
579 for (unsigned i = 0, e = Count; i != e; ++i)
580 EmitVBR64(Val: Vals[i], NumBits: 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>
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>
601 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals,
602 StringRef Blob) {
603 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Blob, std::nullopt);
604 }
605 template <typename Container>
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>
615 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals,
616 StringRef Array) {
617 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Array, std::nullopt);
618 }
619 template <typename Container>
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
630private:
631 // Emit the abbreviation as a DEFINE_ABBREV record.
632 void EncodeAbbrev(const BitCodeAbbrev &Abbv) {
633 EmitCode(Val: bitc::DEFINE_ABBREV);
634 EmitVBR(Val: Abbv.getNumOperandInfos(), NumBits: 5);
635 for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos());
636 i != e; ++i) {
637 const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(N: i);
638 Emit(Val: Op.isLiteral(), NumBits: 1);
639 if (Op.isLiteral()) {
640 EmitVBR64(Val: Op.getLiteralValue(), NumBits: 8);
641 } else {
642 Emit(Val: Op.getEncoding(), NumBits: 3);
643 if (Op.hasEncodingData())
644 EmitVBR64(Val: Op.getEncodingData(), NumBits: 5);
645 }
646 }
647 }
648public:
649
650 /// Emits the abbreviation \p Abbv to the stream.
651 unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) {
652 EncodeAbbrev(Abbv: *Abbv);
653 CurAbbrevs.push_back(x: 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.
663 void EnterBlockInfoBlock() {
664 EnterSubblock(BlockID: bitc::BLOCKINFO_BLOCK_ID, CodeLen: 2);
665 BlockInfoCurBID = ~0U;
666 BlockInfoRecords.clear();
667 }
668private:
669 /// SwitchToBlockID - If we aren't already talking about the specified block
670 /// ID, emit a BLOCKINFO_CODE_SETBID record.
671 void SwitchToBlockID(unsigned BlockID) {
672 if (BlockInfoCurBID == BlockID) return;
673 SmallVector<unsigned, 2> V;
674 V.push_back(Elt: BlockID);
675 EmitRecord(Code: bitc::BLOCKINFO_CODE_SETBID, Vals: V);
676 BlockInfoCurBID = BlockID;
677 }
678
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
689public:
690
691 /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified
692 /// BlockID.
693 unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr<BitCodeAbbrev> Abbv) {
694 SwitchToBlockID(BlockID);
695 EncodeAbbrev(Abbv: *Abbv);
696
697 // Add the abbrev to the specified block record.
698 BlockInfo &Info = getOrCreateBlockInfo(BlockID);
699 Info.Abbrevs.push_back(x: 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

source code of llvm/include/llvm/Bitstream/BitstreamWriter.h