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