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 = support::endian::byte_swap<uint32_t, support::little>(Value);
79 Out.append(reinterpret_cast<const char *>(&Value),
80 reinterpret_cast<const char *>(&Value + 1));
81 }
82
83 uint64_t GetNumOfFlushedBytes() const { return FS ? FS->tell() : 0; }
84
85 size_t GetBufferOffset() const { return Out.size() + GetNumOfFlushedBytes(); }
86
87 size_t GetWordIndex() const {
88 size_t Offset = GetBufferOffset();
89 assert((Offset & 3) == 0 && "Not 32-bit aligned");
90 return Offset / 4;
91 }
92
93 /// If the related file stream supports reading, seeking and writing, flush
94 /// the buffer if its size is above a threshold.
95 void FlushToFile() {
96 if (!FS)
97 return;
98 if (Out.size() < FlushThreshold)
99 return;
100 FS->write((char *)&Out.front(), Out.size());
101 Out.clear();
102 }
103
104public:
105 /// Create a BitstreamWriter that writes to Buffer \p O.
106 ///
107 /// \p FS is the file stream that \p O flushes to incrementally. If \p FS is
108 /// null, \p O does not flush incrementially, but writes to disk at the end.
109 ///
110 /// \p FlushThreshold is the threshold (unit M) to flush \p O if \p FS is
111 /// valid. Flushing only occurs at (sub)block boundaries.
113 uint32_t FlushThreshold = 512)
114 : Out(O), FS(FS), FlushThreshold(uint64_t(FlushThreshold) << 20), CurBit(0),
115 CurValue(0), CurCodeSize(2) {}
116
118 assert(CurBit == 0 && "Unflushed data remaining");
119 assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance");
120 }
121
122 /// Retrieve the current position in the stream, in bits.
123 uint64_t GetCurrentBitNo() const { return GetBufferOffset() * 8 + CurBit; }
124
125 /// Retrieve the number of bits currently used to encode an abbrev ID.
126 unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
127
128 //===--------------------------------------------------------------------===//
129 // Basic Primitives for emitting bits to the stream.
130 //===--------------------------------------------------------------------===//
131
132 /// Backpatch a byte in the output at the given bit offset with the specified
133 /// value.
134 void BackpatchByte(uint64_t BitNo, uint8_t NewByte) {
135 using namespace llvm::support;
136 uint64_t ByteNo = BitNo / 8;
137 uint64_t StartBit = BitNo & 7;
138 uint64_t NumOfFlushedBytes = GetNumOfFlushedBytes();
139
140 if (ByteNo >= NumOfFlushedBytes) {
141 assert((!endian::readAtBitAlignment<uint8_t, little, unaligned>(
142 &Out[ByteNo - NumOfFlushedBytes], StartBit)) &&
143 "Expected to be patching over 0-value placeholders");
144 endian::writeAtBitAlignment<uint8_t, little, unaligned>(
145 &Out[ByteNo - NumOfFlushedBytes], NewByte, StartBit);
146 return;
147 }
148
149 // If the byte offset to backpatch is flushed, use seek to backfill data.
150 // First, save the file position to restore later.
151 uint64_t CurPos = FS->tell();
152
153 // Copy data to update into Bytes from the file FS and the buffer Out.
154 char Bytes[3]; // Use one more byte to silence a warning from Visual C++.
155 size_t BytesNum = StartBit ? 2 : 1;
156 size_t BytesFromDisk = std::min(static_cast<uint64_t>(BytesNum), NumOfFlushedBytes - ByteNo);
157 size_t BytesFromBuffer = BytesNum - BytesFromDisk;
158
159 // When unaligned, copy existing data into Bytes from the file FS and the
160 // buffer Out so that it can be updated before writing. For debug builds
161 // read bytes unconditionally in order to check that the existing value is 0
162 // as expected.
163#ifdef NDEBUG
164 if (StartBit)
165#endif
166 {
167 FS->seek(ByteNo);
168 ssize_t BytesRead = FS->read(Bytes, BytesFromDisk);
169 (void)BytesRead; // silence warning
170 assert(BytesRead >= 0 && static_cast<size_t>(BytesRead) == BytesFromDisk);
171 for (size_t i = 0; i < BytesFromBuffer; ++i)
172 Bytes[BytesFromDisk + i] = Out[i];
173 assert((!endian::readAtBitAlignment<uint8_t, little, unaligned>(
174 Bytes, StartBit)) &&
175 "Expected to be patching over 0-value placeholders");
176 }
177
178 // Update Bytes in terms of bit offset and value.
179 endian::writeAtBitAlignment<uint8_t, little, unaligned>(Bytes, NewByte,
180 StartBit);
181
182 // Copy updated data back to the file FS and the buffer Out.
183 FS->seek(ByteNo);
184 FS->write(Bytes, BytesFromDisk);
185 for (size_t i = 0; i < BytesFromBuffer; ++i)
186 Out[i] = Bytes[BytesFromDisk + i];
187
188 // Restore the file position.
189 FS->seek(CurPos);
190 }
191
193 BackpatchByte(BitNo, (uint8_t)Val);
194 BackpatchByte(BitNo + 8, (uint8_t)(Val >> 8));
195 }
196
197 void BackpatchWord(uint64_t BitNo, unsigned Val) {
198 BackpatchHalfWord(BitNo, (uint16_t)Val);
199 BackpatchHalfWord(BitNo + 16, (uint16_t)(Val >> 16));
200 }
201
203 BackpatchWord(BitNo, (uint32_t)Val);
204 BackpatchWord(BitNo + 32, (uint32_t)(Val >> 32));
205 }
206
207 void Emit(uint32_t Val, unsigned NumBits) {
208 assert(NumBits && NumBits <= 32 && "Invalid value size!");
209 assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!");
210 CurValue |= Val << CurBit;
211 if (CurBit + NumBits < 32) {
212 CurBit += NumBits;
213 return;
214 }
215
216 // Add the current word.
217 WriteWord(CurValue);
218
219 if (CurBit)
220 CurValue = Val >> (32-CurBit);
221 else
222 CurValue = 0;
223 CurBit = (CurBit+NumBits) & 31;
224 }
225
226 void FlushToWord() {
227 if (CurBit) {
228 WriteWord(CurValue);
229 CurBit = 0;
230 CurValue = 0;
231 }
232 }
233
234 void EmitVBR(uint32_t Val, unsigned NumBits) {
235 assert(NumBits <= 32 && "Too many bits to emit!");
236 uint32_t Threshold = 1U << (NumBits-1);
237
238 // Emit the bits with VBR encoding, NumBits-1 bits at a time.
239 while (Val >= Threshold) {
240 Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits);
241 Val >>= NumBits-1;
242 }
243
244 Emit(Val, NumBits);
245 }
246
247 void EmitVBR64(uint64_t Val, unsigned NumBits) {
248 assert(NumBits <= 32 && "Too many bits to emit!");
249 if ((uint32_t)Val == Val)
250 return EmitVBR((uint32_t)Val, NumBits);
251
252 uint32_t Threshold = 1U << (NumBits-1);
253
254 // Emit the bits with VBR encoding, NumBits-1 bits at a time.
255 while (Val >= Threshold) {
256 Emit(((uint32_t)Val & ((1 << (NumBits - 1)) - 1)) | (1 << (NumBits - 1)),
257 NumBits);
258 Val >>= NumBits-1;
259 }
260
261 Emit((uint32_t)Val, NumBits);
262 }
263
264 /// EmitCode - Emit the specified code.
265 void EmitCode(unsigned Val) {
266 Emit(Val, CurCodeSize);
267 }
268
269 //===--------------------------------------------------------------------===//
270 // Block Manipulation
271 //===--------------------------------------------------------------------===//
272
273 /// getBlockInfo - If there is block info for the specified ID, return it,
274 /// otherwise return null.
275 BlockInfo *getBlockInfo(unsigned BlockID) {
276 // Common case, the most recent entry matches BlockID.
277 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
278 return &BlockInfoRecords.back();
279
280 for (BlockInfo &BI : BlockInfoRecords)
281 if (BI.BlockID == BlockID)
282 return &BI;
283 return nullptr;
284 }
285
286 void EnterSubblock(unsigned BlockID, unsigned CodeLen) {
287 // Block header:
288 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
290 EmitVBR(BlockID, bitc::BlockIDWidth);
291 EmitVBR(CodeLen, bitc::CodeLenWidth);
292 FlushToWord();
293
294 size_t BlockSizeWordIndex = GetWordIndex();
295 unsigned OldCodeSize = CurCodeSize;
296
297 // Emit a placeholder, which will be replaced when the block is popped.
299
300 CurCodeSize = CodeLen;
301
302 // Push the outer block's abbrev set onto the stack, start out with an
303 // empty abbrev set.
304 BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);
305 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
306
307 // If there is a blockinfo for this BlockID, add all the predefined abbrevs
308 // to the abbrev list.
309 if (BlockInfo *Info = getBlockInfo(BlockID))
310 append_range(CurAbbrevs, Info->Abbrevs);
311 }
312
313 void ExitBlock() {
314 assert(!BlockScope.empty() && "Block scope imbalance!");
315 const Block &B = BlockScope.back();
316
317 // Block tail:
318 // [END_BLOCK, <align4bytes>]
320 FlushToWord();
321
322 // Compute the size of the block, in words, not counting the size field.
323 size_t SizeInWords = GetWordIndex() - B.StartSizeWord - 1;
324 uint64_t BitNo = uint64_t(B.StartSizeWord) * 32;
325
326 // Update the block size field in the header of this sub-block.
327 BackpatchWord(BitNo, SizeInWords);
328
329 // Restore the inner block's code size and abbrev table.
330 CurCodeSize = B.PrevCodeSize;
331 CurAbbrevs = std::move(B.PrevAbbrevs);
332 BlockScope.pop_back();
333 FlushToFile();
334 }
335
336 //===--------------------------------------------------------------------===//
337 // Record Emission
338 //===--------------------------------------------------------------------===//
339
340private:
341 /// EmitAbbreviatedLiteral - Emit a literal value according to its abbrev
342 /// record. This is a no-op, since the abbrev specifies the literal to use.
343 template<typename uintty>
344 void EmitAbbreviatedLiteral(const BitCodeAbbrevOp &Op, uintty V) {
345 assert(Op.isLiteral() && "Not a literal");
346 // If the abbrev specifies the literal value to use, don't emit
347 // anything.
348 assert(V == Op.getLiteralValue() &&
349 "Invalid abbrev for record!");
350 }
351
352 /// EmitAbbreviatedField - Emit a single scalar field value with the specified
353 /// encoding.
354 template<typename uintty>
355 void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) {
356 assert(!Op.isLiteral() && "Literals should use EmitAbbreviatedLiteral!");
357
358 // Encode the value as we are commanded.
359 switch (Op.getEncoding()) {
360 default: llvm_unreachable("Unknown encoding!");
362 if (Op.getEncodingData())
363 Emit((unsigned)V, (unsigned)Op.getEncodingData());
364 break;
366 if (Op.getEncodingData())
367 EmitVBR64(V, (unsigned)Op.getEncodingData());
368 break;
371 break;
372 }
373 }
374
375 /// EmitRecordWithAbbrevImpl - This is the core implementation of the record
376 /// emission code. If BlobData is non-null, then it specifies an array of
377 /// data that should be emitted as part of the Blob or Array operand that is
378 /// known to exist at the end of the record. If Code is specified, then
379 /// it is the record code to emit before the Vals, which must not contain
380 /// the code.
381 template <typename uintty>
382 void EmitRecordWithAbbrevImpl(unsigned Abbrev, ArrayRef<uintty> Vals,
383 StringRef Blob, std::optional<unsigned> Code) {
384 const char *BlobData = Blob.data();
385 unsigned BlobLen = (unsigned) Blob.size();
386 unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV;
387 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
388 const BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo].get();
389
390 EmitCode(Abbrev);
391
392 unsigned i = 0, e = static_cast<unsigned>(Abbv->getNumOperandInfos());
393 if (Code) {
394 assert(e && "Expected non-empty abbreviation");
395 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i++);
396
397 if (Op.isLiteral())
398 EmitAbbreviatedLiteral(Op, *Code);
399 else {
400 assert(Op.getEncoding() != BitCodeAbbrevOp::Array &&
401 Op.getEncoding() != BitCodeAbbrevOp::Blob &&
402 "Expected literal or scalar");
403 EmitAbbreviatedField(Op, *Code);
404 }
405 }
406
407 unsigned RecordIdx = 0;
408 for (; i != e; ++i) {
409 const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
410 if (Op.isLiteral()) {
411 assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
412 EmitAbbreviatedLiteral(Op, Vals[RecordIdx]);
413 ++RecordIdx;
414 } else if (Op.getEncoding() == BitCodeAbbrevOp::Array) {
415 // Array case.
416 assert(i + 2 == e && "array op not second to last?");
417 const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
418
419 // If this record has blob data, emit it, otherwise we must have record
420 // entries to encode this way.
421 if (BlobData) {
422 assert(RecordIdx == Vals.size() &&
423 "Blob data and record entries specified for array!");
424 // Emit a vbr6 to indicate the number of elements present.
425 EmitVBR(static_cast<uint32_t>(BlobLen), 6);
426
427 // Emit each field.
428 for (unsigned i = 0; i != BlobLen; ++i)
429 EmitAbbreviatedField(EltEnc, (unsigned char)BlobData[i]);
430
431 // Know that blob data is consumed for assertion below.
432 BlobData = nullptr;
433 } else {
434 // Emit a vbr6 to indicate the number of elements present.
435 EmitVBR(static_cast<uint32_t>(Vals.size()-RecordIdx), 6);
436
437 // Emit each field.
438 for (unsigned e = Vals.size(); RecordIdx != e; ++RecordIdx)
439 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
440 }
441 } else if (Op.getEncoding() == BitCodeAbbrevOp::Blob) {
442 // If this record has blob data, emit it, otherwise we must have record
443 // entries to encode this way.
444
445 if (BlobData) {
446 assert(RecordIdx == Vals.size() &&
447 "Blob data and record entries specified for blob operand!");
448
449 assert(Blob.data() == BlobData && "BlobData got moved");
450 assert(Blob.size() == BlobLen && "BlobLen got changed");
451 emitBlob(Blob);
452 BlobData = nullptr;
453 } else {
454 emitBlob(Vals.slice(RecordIdx));
455 }
456 } else { // Single scalar field.
457 assert(RecordIdx < Vals.size() && "Invalid abbrev/record");
458 EmitAbbreviatedField(Op, Vals[RecordIdx]);
459 ++RecordIdx;
460 }
461 }
462 assert(RecordIdx == Vals.size() && "Not all record operands emitted!");
463 assert(BlobData == nullptr &&
464 "Blob data specified for record that doesn't use it!");
465 }
466
467public:
468 /// Emit a blob, including flushing before and tail-padding.
469 template <class UIntTy>
470 void emitBlob(ArrayRef<UIntTy> Bytes, bool ShouldEmitSize = true) {
471 // Emit a vbr6 to indicate the number of elements present.
472 if (ShouldEmitSize)
473 EmitVBR(static_cast<uint32_t>(Bytes.size()), 6);
474
475 // Flush to a 32-bit alignment boundary.
476 FlushToWord();
477
478 // Emit literal bytes.
479 assert(llvm::all_of(Bytes, [](UIntTy B) { return isUInt<8>(B); }));
480 Out.append(Bytes.begin(), Bytes.end());
481
482 // Align end to 32-bits.
483 while (GetBufferOffset() & 3)
484 Out.push_back(0);
485 }
486 void emitBlob(StringRef Bytes, bool ShouldEmitSize = true) {
487 emitBlob(ArrayRef((const uint8_t *)Bytes.data(), Bytes.size()),
488 ShouldEmitSize);
489 }
490
491 /// EmitRecord - Emit the specified record to the stream, using an abbrev if
492 /// we have one to compress the output.
493 template <typename Container>
494 void EmitRecord(unsigned Code, const Container &Vals, unsigned Abbrev = 0) {
495 if (!Abbrev) {
496 // If we don't have an abbrev to use, emit this in its fully unabbreviated
497 // form.
498 auto Count = static_cast<uint32_t>(std::size(Vals));
500 EmitVBR(Code, 6);
501 EmitVBR(Count, 6);
502 for (unsigned i = 0, e = Count; i != e; ++i)
503 EmitVBR64(Vals[i], 6);
504 return;
505 }
506
507 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), Code);
508 }
509
510 /// EmitRecordWithAbbrev - Emit a record with the specified abbreviation.
511 /// Unlike EmitRecord, the code for the record should be included in Vals as
512 /// the first entry.
513 template <typename Container>
514 void EmitRecordWithAbbrev(unsigned Abbrev, const Container &Vals) {
515 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), StringRef(), std::nullopt);
516 }
517
518 /// EmitRecordWithBlob - Emit the specified record to the stream, using an
519 /// abbrev that includes a blob at the end. The blob data to emit is
520 /// specified by the pointer and length specified at the end. In contrast to
521 /// EmitRecord, this routine expects that the first entry in Vals is the code
522 /// of the record.
523 template <typename Container>
524 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals,
525 StringRef Blob) {
526 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Blob, std::nullopt);
527 }
528 template <typename Container>
529 void EmitRecordWithBlob(unsigned Abbrev, const Container &Vals,
530 const char *BlobData, unsigned BlobLen) {
531 return EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals),
532 StringRef(BlobData, BlobLen), std::nullopt);
533 }
534
535 /// EmitRecordWithArray - Just like EmitRecordWithBlob, works with records
536 /// that end with an array.
537 template <typename Container>
538 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals,
539 StringRef Array) {
540 EmitRecordWithAbbrevImpl(Abbrev, ArrayRef(Vals), Array, std::nullopt);
541 }
542 template <typename Container>
543 void EmitRecordWithArray(unsigned Abbrev, const Container &Vals,
544 const char *ArrayData, unsigned ArrayLen) {
545 return EmitRecordWithAbbrevImpl(
546 Abbrev, ArrayRef(Vals), StringRef(ArrayData, ArrayLen), std::nullopt);
547 }
548
549 //===--------------------------------------------------------------------===//
550 // Abbrev Emission
551 //===--------------------------------------------------------------------===//
552
553private:
554 // Emit the abbreviation as a DEFINE_ABBREV record.
555 void EncodeAbbrev(const BitCodeAbbrev &Abbv) {
557 EmitVBR(Abbv.getNumOperandInfos(), 5);
558 for (unsigned i = 0, e = static_cast<unsigned>(Abbv.getNumOperandInfos());
559 i != e; ++i) {
560 const BitCodeAbbrevOp &Op = Abbv.getOperandInfo(i);
561 Emit(Op.isLiteral(), 1);
562 if (Op.isLiteral()) {
563 EmitVBR64(Op.getLiteralValue(), 8);
564 } else {
565 Emit(Op.getEncoding(), 3);
566 if (Op.hasEncodingData())
567 EmitVBR64(Op.getEncodingData(), 5);
568 }
569 }
570 }
571public:
572
573 /// Emits the abbreviation \p Abbv to the stream.
574 unsigned EmitAbbrev(std::shared_ptr<BitCodeAbbrev> Abbv) {
575 EncodeAbbrev(*Abbv);
576 CurAbbrevs.push_back(std::move(Abbv));
577 return static_cast<unsigned>(CurAbbrevs.size())-1 +
579 }
580
581 //===--------------------------------------------------------------------===//
582 // BlockInfo Block Emission
583 //===--------------------------------------------------------------------===//
584
585 /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK.
588 BlockInfoCurBID = ~0U;
589 BlockInfoRecords.clear();
590 }
591private:
592 /// SwitchToBlockID - If we aren't already talking about the specified block
593 /// ID, emit a BLOCKINFO_CODE_SETBID record.
594 void SwitchToBlockID(unsigned BlockID) {
595 if (BlockInfoCurBID == BlockID) return;
597 V.push_back(BlockID);
599 BlockInfoCurBID = BlockID;
600 }
601
602 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
603 if (BlockInfo *BI = getBlockInfo(BlockID))
604 return *BI;
605
606 // Otherwise, add a new record.
607 BlockInfoRecords.emplace_back();
608 BlockInfoRecords.back().BlockID = BlockID;
609 return BlockInfoRecords.back();
610 }
611
612public:
613
614 /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified
615 /// BlockID.
616 unsigned EmitBlockInfoAbbrev(unsigned BlockID, std::shared_ptr<BitCodeAbbrev> Abbv) {
617 SwitchToBlockID(BlockID);
618 EncodeAbbrev(*Abbv);
619
620 // Add the abbrev to the specified block record.
621 BlockInfo &Info = getOrCreateBlockInfo(BlockID);
622 Info.Abbrevs.push_back(std::move(Abbv));
623
624 return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV;
625 }
626};
627
628
629} // End llvm namespace
630
631#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
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
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:1727
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:2037