14#ifndef LLVM_BITSTREAM_BITSTREAMWRITER_H
15#define LLVM_BITSTREAM_BITSTREAMWRITER_H
54 unsigned BlockInfoCurBID;
57 std::vector<std::shared_ptr<BitCodeAbbrev>> CurAbbrevs;
60 unsigned PrevCodeSize;
62 std::vector<std::shared_ptr<BitCodeAbbrev>> PrevAbbrevs;
63 Block(
unsigned PCS,
size_t SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {}
67 std::vector<Block> BlockScope;
73 std::vector<std::shared_ptr<BitCodeAbbrev>> Abbrevs;
75 std::vector<BlockInfo> BlockInfoRecords;
77 void WriteWord(
unsigned Value) {
78 Value = support::endian::byte_swap<uint32_t, support::little>(
Value);
80 reinterpret_cast<const char *
>(&
Value + 1));
83 uint64_t GetNumOfFlushedBytes()
const {
return FS ? FS->tell() : 0; }
85 size_t GetBufferOffset()
const {
return Out.
size() + GetNumOfFlushedBytes(); }
87 size_t GetWordIndex()
const {
88 size_t Offset = GetBufferOffset();
98 if (Out.
size() < FlushThreshold)
100 FS->write((
char *)&Out.
front(), Out.
size());
114 : Out(O), FS(FS), FlushThreshold(
uint64_t(FlushThreshold) << 20), CurBit(0),
115 CurValue(0), CurCodeSize(2) {}
118 assert(CurBit == 0 &&
"Unflushed data remaining");
119 assert(BlockScope.empty() && CurAbbrevs.empty() &&
"Block imbalance");
138 uint64_t NumOfFlushedBytes = GetNumOfFlushedBytes();
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);
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;
168 ssize_t BytesRead = FS->read(Bytes, BytesFromDisk);
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>(
175 "Expected to be patching over 0-value placeholders");
179 endian::writeAtBitAlignment<uint8_t, little, unaligned>(Bytes, NewByte,
184 FS->write(Bytes, BytesFromDisk);
185 for (
size_t i = 0; i < BytesFromBuffer; ++i)
186 Out[i] = Bytes[BytesFromDisk + i];
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) {
220 CurValue = Val >> (32-CurBit);
223 CurBit = (CurBit+NumBits) & 31;
235 assert(NumBits <= 32 &&
"Too many bits to emit!");
236 uint32_t Threshold = 1U << (NumBits-1);
239 while (Val >= Threshold) {
240 Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits);
248 assert(NumBits <= 32 &&
"Too many bits to emit!");
252 uint32_t Threshold = 1U << (NumBits-1);
255 while (Val >= Threshold) {
256 Emit(((
uint32_t)Val & ((1 << (NumBits - 1)) - 1)) | (1 << (NumBits - 1)),
266 Emit(Val, CurCodeSize);
277 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
278 return &BlockInfoRecords.back();
280 for (BlockInfo &BI : BlockInfoRecords)
281 if (BI.BlockID == BlockID)
294 size_t BlockSizeWordIndex = GetWordIndex();
295 unsigned OldCodeSize = CurCodeSize;
300 CurCodeSize = CodeLen;
304 BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);
305 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
314 assert(!BlockScope.empty() &&
"Block scope imbalance!");
315 const Block &
B = BlockScope.back();
323 size_t SizeInWords = GetWordIndex() -
B.StartSizeWord - 1;
330 CurCodeSize =
B.PrevCodeSize;
331 CurAbbrevs = std::move(
B.PrevAbbrevs);
332 BlockScope.pop_back();
343 template<
typename u
intty>
345 assert(
Op.isLiteral() &&
"Not a literal");
349 "Invalid abbrev for record!");
354 template<
typename u
intty>
356 assert(!
Op.isLiteral() &&
"Literals should use EmitAbbreviatedLiteral!");
359 switch (
Op.getEncoding()) {
362 if (
Op.getEncodingData())
363 Emit((
unsigned)V, (
unsigned)
Op.getEncodingData());
366 if (
Op.getEncodingData())
381 template <
typename u
intty>
383 StringRef Blob, std::optional<unsigned> Code) {
384 const char *BlobData = Blob.
data();
387 assert(AbbrevNo < CurAbbrevs.size() &&
"Invalid abbrev #!");
394 assert(e &&
"Expected non-empty abbreviation");
398 EmitAbbreviatedLiteral(
Op, *Code);
402 "Expected literal or scalar");
403 EmitAbbreviatedField(
Op, *Code);
407 unsigned RecordIdx = 0;
408 for (; i !=
e; ++i) {
410 if (
Op.isLiteral()) {
411 assert(RecordIdx < Vals.
size() &&
"Invalid abbrev/record");
412 EmitAbbreviatedLiteral(
Op, Vals[RecordIdx]);
416 assert(i + 2 == e &&
"array op not second to last?");
423 "Blob data and record entries specified for array!");
428 for (
unsigned i = 0; i != BlobLen; ++i)
429 EmitAbbreviatedField(EltEnc, (
unsigned char)BlobData[i]);
438 for (
unsigned e = Vals.
size(); RecordIdx != e; ++RecordIdx)
439 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
447 "Blob data and record entries specified for blob operand!");
449 assert(Blob.
data() == BlobData &&
"BlobData got moved");
450 assert(Blob.
size() == BlobLen &&
"BlobLen got changed");
457 assert(RecordIdx < Vals.
size() &&
"Invalid abbrev/record");
458 EmitAbbreviatedField(
Op, Vals[RecordIdx]);
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!");
469 template <
class UIntTy>
483 while (GetBufferOffset() & 3)
493 template <
typename Container>
494 void EmitRecord(
unsigned Code,
const Container &Vals,
unsigned Abbrev = 0) {
498 auto Count =
static_cast<uint32_t>(std::size(Vals));
502 for (
unsigned i = 0, e = Count; i != e; ++i)
513 template <
typename Container>
523 template <
typename Container>
526 EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals), Blob, std::nullopt);
528 template <
typename Container>
530 const char *BlobData,
unsigned BlobLen) {
531 return EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals),
532 StringRef(BlobData, BlobLen), std::nullopt);
537 template <
typename Container>
540 EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals), Array, std::nullopt);
542 template <
typename Container>
544 const char *ArrayData,
unsigned ArrayLen) {
545 return EmitRecordWithAbbrevImpl(
562 if (
Op.isLiteral()) {
565 Emit(
Op.getEncoding(), 3);
566 if (
Op.hasEncodingData())
576 CurAbbrevs.push_back(std::move(Abbv));
577 return static_cast<unsigned>(CurAbbrevs.size())-1 +
588 BlockInfoCurBID = ~0U;
589 BlockInfoRecords.clear();
594 void SwitchToBlockID(
unsigned BlockID) {
595 if (BlockInfoCurBID == BlockID)
return;
597 V.push_back(BlockID);
599 BlockInfoCurBID = BlockID;
602 BlockInfo &getOrCreateBlockInfo(
unsigned BlockID) {
607 BlockInfoRecords.emplace_back();
608 BlockInfoRecords.back().BlockID = BlockID;
609 return BlockInfoRecords.back();
617 SwitchToBlockID(BlockID);
621 BlockInfo &
Info = getOrCreateBlockInfo(BlockID);
622 Info.Abbrevs.push_back(std::move(Abbv));
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
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),...
size_t size() const
size - Get the array size.
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.
BitCodeAbbrevOp - This describes one or more operands in an abbreviation.
static unsigned EncodeChar6(char C)
BitCodeAbbrev - This class represents an abbreviation record.
unsigned getNumOperandInfos() const
const BitCodeAbbrevOp & getOperandInfo(unsigned N) const
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.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr size_t size() const
size - Get the string size.
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
LLVM Value Representation.
A raw_ostream of a file for reading/writing/seeking.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BLOCKINFO_BLOCK_ID
BLOCKINFO_BLOCK is used to define metadata about blocks, for example, standard abbrevs that should be...
@ DEFINE_ABBREV
DEFINE_ABBREV - Defines an abbrev for the current block.
@ FIRST_APPLICATION_ABBREV
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.