LLVM 18.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"
21#include "llvm/Support/Endian.h"
24#include <algorithm>
25#include <optional>
26#include <vector>
27
28namespace llvm {
29
31 /// Out - The buffer that keeps unflushed bytes.
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);
80 Out.append(reinterpret_cast<const char *>(&Value),
81 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((char *)&Out.front(), 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.
114 uint32_t FlushThreshold = 512)
115 : Out(O), FS(FS), FlushThreshold(uint64_t(FlushThreshold) << 20), CurBit(0),
116 CurValue(0), CurCodeSize(2) {}
117
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) {
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];
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
195 BackpatchByte(BitNo, (uint8_t)Val);
196 BackpatchByte(BitNo + 8, (uint8_t)(Val >> 8));
197 }
198
199 void BackpatchWord(uint64_t BitNo, unsigned Val) {
200 BackpatchHalfWord(BitNo, (uint16_t)Val);
201 BackpatchHalfWord(BitNo + 16, (uint16_t)(Val >> 16));
202 }
203
205 BackpatchWord(BitNo, (uint32_t)Val);
206 BackpatchWord(BitNo + 32, (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(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(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 & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits);
243 Val >>= NumBits-1;
244 }
245
246 Emit(Val, NumBits);
247 }
248
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.
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.
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
288 void EnterSubblock(unsigned BlockID, unsigned CodeLen) {
289 // Block header:
290 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
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.
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
315 void ExitBlock() {
316 assert(!BlockScope.empty() && "Block scope imbalance!");
317 const Block &B = BlockScope.back();
318
319 // Block tail:
320 // [END_BLOCK, <align4bytes>]
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
342private:
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>
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>
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!");
364 if (Op.getEncodingData())
365 Emit((unsigned)V, (unsigned)Op.getEncodingData());
366 break;
368 if (Op.getEncodingData())
369 EmitVBR64(V, (unsigned)Op.getEncodingData());
370 break;
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>
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
469public:
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));
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>
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>
526 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals,
527 StringRef Blob) {
528 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Blob, std::nullopt);
529 }
530 template <typename Container>
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>
540 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals,
541 StringRef Array) {
542 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Array, std::nullopt);
543 }
544 template <typename Container>
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
555private:
556 // Emit the abbreviation as a DEFINE_ABBREV record.
557 void EncodeAbbrev(const BitCodeAbbrev &Abbv) {
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 }
573public:
574
575 /// Emits the abbreviation \p Abbv to the stream.
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 +
581 }
582
583 //===--------------------------------------------------------------------===//
584 // BlockInfo Block Emission
585 //===--------------------------------------------------------------------===//
586
587 /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
590 BlockInfoCurBID = ~0U;
591 BlockInfoRecords.clear();
592 }
593private:
594 /// SwitchToBlockID - If we aren't already talking about the specified block
595 /// ID, emit a BLOCKINFO_CODE_SETBID record.
596 void SwitchToBlockID(unsigned BlockID) {
597 if (BlockInfoCurBID == BlockID) return;
599 V.push_back(BlockID);
601 BlockInfoCurBID = BlockID;
602 }
603
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
614public:
615
616 /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified
617 /// BlockID.
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
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
dxil metadata DXIL Metadata Emit
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:154
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
iterator begin() const
Definition: ArrayRef.h:153
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:195
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 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 ...
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...
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)
BitstreamWriter(SmallVectorImpl< char > &O, raw_fd_stream *FS=nullptr, uint32_t FlushThreshold=512)
Create a BitstreamWriter that writes to Buffer O.
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.
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:687
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
LLVM Value Representation.
Definition: Value.h:74
A raw_ostream of a file for reading/writing/seeking.
Definition: raw_ostream.h:611
#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:31
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:111
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
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:1726
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition: STLExtras.h:2042