LLVM 20.0.0git
BitstreamWriter.h
Go to the documentation of this file.
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"
19#include "llvm/ADT/StringRef.h"
22#include "llvm/Support/Endian.h"
25#include <algorithm>
26#include <optional>
27#include <vector>
28
29namespace llvm {
30
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.
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);
91 Buffer.append(reinterpret_cast<const char *>(&Value),
92 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(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
133 raw_fd_stream *fdStream() { return dyn_cast_or_null<raw_fd_stream>(FS); }
134
135 const raw_fd_stream *fdStream() const {
136 return dyn_cast_or_null<raw_fd_stream>(FS);
137 }
138
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
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>(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.
164 : Buffer(Buff), FS(nullptr), FlushThreshold(0) {}
165
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.
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.
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) {
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];
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
268 BackpatchByte(BitNo, (uint8_t)Val);
269 BackpatchByte(BitNo + 8, (uint8_t)(Val >> 8));
270 }
271
272 void BackpatchWord(uint64_t BitNo, unsigned Val) {
273 BackpatchHalfWord(BitNo, (uint16_t)Val);
274 BackpatchHalfWord(BitNo + 16, (uint16_t)(Val >> 16));
275 }
276
278 BackpatchWord(BitNo, (uint32_t)Val);
279 BackpatchWord(BitNo + 32, (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(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(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 & ((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((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.
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.
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]
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.
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
390 void ExitBlock() {
391 assert(!BlockScope.empty() && "Block scope imbalance!");
392 const Block &B = BlockScope.back();
393
394 // Block tail:
395 // [END_BLOCK, <align4bytes>]
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
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!");
439 if (Op.getEncodingData())
440 Emit((unsigned)V, (unsigned)Op.getEncodingData());
441 break;
443 if (Op.getEncodingData())
444 EmitVBR64(V, (unsigned)Op.getEncodingData());
445 break;
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(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
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(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));
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>
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) {
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 }
648public:
649
650 /// Emits the abbreviation \p Abbv to the stream.
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 +
656 }
657
658 //===--------------------------------------------------------------------===//
659 // BlockInfo Block Emission
660 //===--------------------------------------------------------------------===//
661
662 /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
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;
674 V.push_back(BlockID);
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);
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
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
iterator end() const
Definition: ArrayRef.h:157
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:168
iterator begin() const
Definition: ArrayRef.h:156
ArrayRef< T > slice(size_t N, size_t M) const
slice(n, m) - Chop off the first N elements of the array, and keep M elements in the array.
Definition: ArrayRef.h:198
BitCodeAbbrevOp - This describes one or more operands in an abbreviation.
Definition: BitCodes.h:33
static unsigned EncodeChar6(char C)
Definition: BitCodes.h:83
BitCodeAbbrev - This class represents an abbreviation record.
Definition: BitCodes.h:103
unsigned getNumOperandInfos() const
Definition: BitCodes.h:112
const BitCodeAbbrevOp & getOperandInfo(unsigned N) const
Definition: BitCodes.h:115
unsigned EmitAbbrev(std::shared_ptr< BitCodeAbbrev > Abbv)
Emits the abbreviation Abbv to the stream.
void markAndBlockFlushing()
For scenarios where the user wants to access a section of the stream to (for example) compute some ch...
StringRef getMarkedBufferAndResumeFlushing()
resumes flushing, but does not flush, and returns the section in the internal buffer starting from th...
void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev=0)
EmitRecord - Emit the specified record to the stream, using an abbrev if we have one to compress the ...
BitstreamWriter(SmallVectorImpl< char > &Buff)
Convenience constructor for users that start with a vector - avoids needing to wrap it in a raw_svect...
void Emit(uint32_t Val, unsigned NumBits)
void emitBlob(ArrayRef< UIntTy > Bytes, bool ShouldEmitSize=true)
Emit a blob, including flushing before and tail-padding.
void EmitCode(unsigned Val)
EmitCode - Emit the specified code.
void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, const char *BlobData, unsigned BlobLen)
void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, const char *ArrayData, unsigned ArrayLen)
void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals, StringRef Blob)
EmitRecordWithBlob - Emit the specified record to the stream, using an abbrev that includes a blob at...
BitstreamWriter(raw_ostream &OutStream, uint32_t FlushThreshold=512)
Create a BitstreamWriter over a raw_ostream OutStream.
void BackpatchByte(uint64_t BitNo, uint8_t NewByte)
Backpatch a byte in the output at the given bit offset with the specified value.
unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr< BitCodeAbbrev > Abbv)
EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified BlockID.
BlockInfo * getBlockInfo(unsigned BlockID)
getBlockInfo - If there is block info for the specified ID, return it, otherwise return null.
void EmitVBR64(uint64_t Val, unsigned NumBits)
void EmitRecordWithArray(unsigned Abbrev, const Container &Vals, StringRef Array)
EmitRecordWithArray - Just like EmitRecordWithBlob, works with records that end with an array.
void EnterBlockInfoBlock()
EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
void EmitVBR(uint32_t Val, unsigned NumBits)
void BackpatchWord(uint64_t BitNo, unsigned Val)
void BackpatchWord64(uint64_t BitNo, uint64_t Val)
void emitBlob(StringRef Bytes, bool ShouldEmitSize=true)
void BackpatchHalfWord(uint64_t BitNo, uint16_t Val)
void EnterSubblock(unsigned BlockID, unsigned CodeLen)
unsigned GetAbbrevIDWidth() const
Retrieve the number of bits currently used to encode an abbrev ID.
uint64_t GetCurrentBitNo() const
Retrieve the current position in the stream, in bits.
void EmitRecordWithAbbrev(unsigned Abbrev, const Container &Vals)
EmitRecordWithAbbrev - Emit a record with the specified abbreviation.
This class represents an Operation in the Expression.
bool empty() const
Definition: SmallVector.h:81
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:683
void push_back(const T &Elt)
Definition: SmallVector.h:413
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:286
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:150
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:144
LLVM Value Representation.
Definition: Value.h:74
uint64_t seek(uint64_t off)
Flushes the stream and repositions the underlying file descriptor position to the offset specified fr...
A raw_ostream of a file for reading/writing/seeking.
Definition: raw_ostream.h:628
ssize_t read(char *Ptr, size_t Size)
This reads the Size bytes into a buffer pointed by Ptr.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:147
raw_ostream & write(unsigned char C)
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:691
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BLOCKINFO_CODE_SETBID
Definition: BitCodeEnums.h:81
@ BLOCKINFO_BLOCK_ID
BLOCKINFO_BLOCK is used to define metadata about blocks, for example, standard abbrevs that should be...
Definition: BitCodeEnums.h:69
@ DEFINE_ABBREV
DEFINE_ABBREV - Defines an abbrev for the current block.
Definition: BitCodeEnums.h:53
@ FIRST_APPLICATION_ABBREV
Definition: BitCodeEnums.h:60
constexpr double e
Definition: MathExtras.h:47
value_type readAtBitAlignment(const void *memory, uint64_t startBit)
Read a value of a particular endianness from memory, for a location that starts at the given bit offs...
Definition: Endian.h:127
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1739
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2115
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition: Casting.h:548