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
28namespace llvm {
29
30class 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: Value);
80 Out.append(in_start: reinterpret_cast<const char *>(&Value),
81 in_end: 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(Ptr: (char *)&Out.front(), Size: Out.size());
102 Out.clear();
103 }
104
105public:
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 memory: &Out[ByteNo - NumOfFlushedBytes], value: NewByte, startBit: 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(a: static_cast<uint64_t>(BytesNum), b: 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(off: ByteNo);
170 ssize_t BytesRead = FS->read(Ptr: Bytes, Size: 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 memory: Bytes, value: NewByte, startBit: StartBit);
183
184 // Copy updated data back to the file FS and the buffer Out.
185 FS->seek(off: ByteNo);
186 FS->write(Ptr: Bytes, Size: 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(off: CurPos);
192 }
193
194 void BackpatchHalfWord(uint64_t BitNo, uint16_t Val) {
195 BackpatchByte(BitNo, NewByte: (uint8_t)Val);
196 BackpatchByte(BitNo: BitNo + 8, NewByte: (uint8_t)(Val >> 8));
197 }
198
199 void BackpatchWord(uint64_t BitNo, unsigned Val) {
200 BackpatchHalfWord(BitNo, Val: (uint16_t)Val);
201 BackpatchHalfWord(BitNo: BitNo + 16, Val: (uint16_t)(Val >> 16));
202 }
203
204 void BackpatchWord64(uint64_t BitNo, uint64_t Val) {
205 BackpatchWord(BitNo, Val: (uint32_t)Val);
206 BackpatchWord(BitNo: BitNo + 32, Val: (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(Value: 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(Value: 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: (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(Val: (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(Val: ((uint32_t)Val & ((1U << (NumBits - 1)) - 1)) |
260 (1U << (NumBits - 1)),
261 NumBits);
262 Val >>= NumBits-1;
263 }
264
265 Emit(Val: (uint32_t)Val, NumBits);
266 }
267
268 /// EmitCode - Emit the specified code.
269 void EmitCode(unsigned Val) {
270 Emit(Val, NumBits: 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(Val: bitc::ENTER_SUBBLOCK);
294 EmitVBR(Val: BlockID, NumBits: bitc::BlockIDWidth);
295 EmitVBR(Val: CodeLen, NumBits: 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(Val: 0, NumBits: 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(args&: OldCodeSize, args&: BlockSizeWordIndex);
309 BlockScope.back().PrevAbbrevs.swap(x&: 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(C&: CurAbbrevs, R&: 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(Val: 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, Val: 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
344private:
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(Val: (unsigned)V, NumBits: (unsigned)Op.getEncodingData());
368 break;
369 case BitCodeAbbrevOp::VBR:
370 if (Op.getEncodingData())
371 EmitVBR64(Val: V, NumBits: (unsigned)Op.getEncodingData());
372 break;
373 case BitCodeAbbrevOp::Char6:
374 Emit(Val: BitCodeAbbrevOp::EncodeChar6(C: (char)V), NumBits: 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(Val: 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(N: i++);
400
401 if (Op.isLiteral())
402 EmitAbbreviatedLiteral(Op, V: *Code);
403 else {
404 assert(Op.getEncoding() != BitCodeAbbrevOp::Array &&
405 Op.getEncoding() != BitCodeAbbrevOp::Blob &&
406 "Expected literal or scalar");
407 EmitAbbreviatedField(Op, V: *Code);
408 }
409 }
410
411 unsigned RecordIdx = 0;
412 for (; i != e; ++i) {
413 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(N: 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(N: ++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(Val: static_cast<uint32_t>(BlobLen), NumBits: 6);
430
431 // Emit each field.
432 for (unsigned i = 0; i != BlobLen; ++i)
433 EmitAbbreviatedField(Op: EltEnc, V: (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(Val: static_cast<uint32_t>(Vals.size()-RecordIdx), NumBits: 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(Bytes: 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
471public:
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(Val: static_cast<uint32_t>(Bytes.size()), NumBits: 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(Elt: 0);
489 }
490 void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) {
491 emitBlob(Bytes: 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(Val: bitc::UNABBREV_RECORD);
504 EmitVBR(Val: Code, NumBits: 6);
505 EmitVBR(Val: Count, NumBits: 6);
506 for (unsigned i = 0, e = Count; i != e; ++i)
507 EmitVBR64(Val: Vals[i], NumBits: 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
557private:
558 // Emit the abbreviation as a DEFINE_ABBREV record.
559 void EncodeAbbrev(const BitCodeAbbrev &Abbv) {
560 EmitCode(Val: bitc::DEFINE_ABBREV);
561 EmitVBR(Val: Abbv.getNumOperandInfos(), NumBits: 5);
562 for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos());
563 i != e; ++i) {
564 const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(N: i);
565 Emit(Val: Op.isLiteral(), NumBits: 1);
566 if (Op.isLiteral()) {
567 EmitVBR64(Val: Op.getLiteralValue(), NumBits: 8);
568 } else {
569 Emit(Val: Op.getEncoding(), NumBits: 3);
570 if (Op.hasEncodingData())
571 EmitVBR64(Val: Op.getEncodingData(), NumBits: 5);
572 }
573 }
574 }
575public:
576
577 /// Emits the abbreviation \p Abbv to the stream.
578 unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) {
579 EncodeAbbrev(Abbv: *Abbv);
580 CurAbbrevs.push_back(x: 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(BlockID: bitc::BLOCKINFO_BLOCK_ID, CodeLen: 2);
592 BlockInfoCurBID = ~0U;
593 BlockInfoRecords.clear();
594 }
595private:
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(Elt: BlockID);
602 EmitRecord(Code: bitc::BLOCKINFO_CODE_SETBID, Vals: 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
616public:
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: *Abbv);
623
624 // Add the abbrev to the specified block record.
625 BlockInfo &Info = getOrCreateBlockInfo(BlockID);
626 Info.Abbrevs.push_back(x: 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

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