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) {
79 support::endian::byte_swap<uint32_t, llvm::endianness::little>(
Value);
81 reinterpret_cast<const char *
>(&
Value + 1));
84 uint64_t GetNumOfFlushedBytes()
const {
return FS ? FS->tell() : 0; }
86 size_t GetBufferOffset()
const {
return Out.
size() + GetNumOfFlushedBytes(); }
88 size_t GetWordIndex()
const {
89 size_t Offset = GetBufferOffset();
99 if (Out.
size() < FlushThreshold)
101 FS->write((
char *)&Out.
front(), Out.
size());
115 : Out(O), FS(FS), FlushThreshold(
uint64_t(FlushThreshold) << 20), CurBit(0),
116 CurValue(0), CurCodeSize(2) {}
119 assert(CurBit == 0 &&
"Unflushed data remaining");
120 assert(BlockScope.empty() && CurAbbrevs.empty() &&
"Block imbalance");
139 uint64_t NumOfFlushedBytes = GetNumOfFlushedBytes();
141 if (ByteNo >= NumOfFlushedBytes) {
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);
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;
170 ssize_t BytesRead = FS->read(Bytes, BytesFromDisk);
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");
181 endian::writeAtBitAlignment<uint8_t, llvm::endianness::little, unaligned>(
182 Bytes, NewByte, StartBit);
186 FS->write(Bytes, BytesFromDisk);
187 for (
size_t i = 0; i < BytesFromBuffer; ++i)
188 Out[i] = Bytes[BytesFromDisk + i];
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) {
222 CurValue = Val >> (32-CurBit);
225 CurBit = (CurBit+NumBits) & 31;
237 assert(NumBits <= 32 &&
"Too many bits to emit!");
238 uint32_t Threshold = 1U << (NumBits-1);
241 while (Val >= Threshold) {
242 Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits);
250 assert(NumBits <= 32 &&
"Too many bits to emit!");
254 uint32_t Threshold = 1U << (NumBits-1);
257 while (Val >= Threshold) {
258 Emit(((
uint32_t)Val & ((1 << (NumBits - 1)) - 1)) | (1 << (NumBits - 1)),
268 Emit(Val, CurCodeSize);
279 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
280 return &BlockInfoRecords.back();
282 for (BlockInfo &BI : BlockInfoRecords)
283 if (BI.BlockID == BlockID)
296 size_t BlockSizeWordIndex = GetWordIndex();
297 unsigned OldCodeSize = CurCodeSize;
302 CurCodeSize = CodeLen;
306 BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);
307 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
316 assert(!BlockScope.empty() &&
"Block scope imbalance!");
317 const Block &
B = BlockScope.back();
325 size_t SizeInWords = GetWordIndex() -
B.StartSizeWord - 1;
332 CurCodeSize =
B.PrevCodeSize;
333 CurAbbrevs = std::move(
B.PrevAbbrevs);
334 BlockScope.pop_back();
345 template<
typename u
intty>
347 assert(
Op.isLiteral() &&
"Not a literal");
351 "Invalid abbrev for record!");
356 template<
typename u
intty>
358 assert(!
Op.isLiteral() &&
"Literals should use EmitAbbreviatedLiteral!");
361 switch (
Op.getEncoding()) {
364 if (
Op.getEncodingData())
365 Emit((
unsigned)V, (
unsigned)
Op.getEncodingData());
368 if (
Op.getEncodingData())
383 template <
typename u
intty>
385 StringRef Blob, std::optional<unsigned> Code) {
386 const char *BlobData = Blob.
data();
389 assert(AbbrevNo < CurAbbrevs.size() &&
"Invalid abbrev #!");
396 assert(e &&
"Expected non-empty abbreviation");
400 EmitAbbreviatedLiteral(
Op, *Code);
404 "Expected literal or scalar");
405 EmitAbbreviatedField(
Op, *Code);
409 unsigned RecordIdx = 0;
410 for (; i !=
e; ++i) {
412 if (
Op.isLiteral()) {
413 assert(RecordIdx < Vals.
size() &&
"Invalid abbrev/record");
414 EmitAbbreviatedLiteral(
Op, Vals[RecordIdx]);
418 assert(i + 2 == e &&
"array op not second to last?");
425 "Blob data and record entries specified for array!");
430 for (
unsigned i = 0; i != BlobLen; ++i)
431 EmitAbbreviatedField(EltEnc, (
unsigned char)BlobData[i]);
440 for (
unsigned e = Vals.
size(); RecordIdx != e; ++RecordIdx)
441 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
449 "Blob data and record entries specified for blob operand!");
451 assert(Blob.
data() == BlobData &&
"BlobData got moved");
452 assert(Blob.
size() == BlobLen &&
"BlobLen got changed");
459 assert(RecordIdx < Vals.
size() &&
"Invalid abbrev/record");
460 EmitAbbreviatedField(
Op, Vals[RecordIdx]);
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!");
471 template <
class UIntTy>
485 while (GetBufferOffset() & 3)
495 template <
typename Container>
496 void EmitRecord(
unsigned Code,
const Container &Vals,
unsigned Abbrev = 0) {
500 auto Count =
static_cast<uint32_t>(std::size(Vals));
504 for (
unsigned i = 0, e = Count; i != e; ++i)
515 template <
typename Container>
525 template <
typename Container>
528 EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals), Blob, std::nullopt);
530 template <
typename Container>
532 const char *BlobData,
unsigned BlobLen) {
533 return EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals),
534 StringRef(BlobData, BlobLen), std::nullopt);
539 template <
typename Container>
542 EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals), Array, std::nullopt);
544 template <
typename Container>
546 const char *ArrayData,
unsigned ArrayLen) {
547 return EmitRecordWithAbbrevImpl(
564 if (
Op.isLiteral()) {
567 Emit(
Op.getEncoding(), 3);
568 if (
Op.hasEncodingData())
578 CurAbbrevs.push_back(std::move(Abbv));
579 return static_cast<unsigned>(CurAbbrevs.size())-1 +
590 BlockInfoCurBID = ~0U;
591 BlockInfoRecords.clear();
596 void SwitchToBlockID(
unsigned BlockID) {
597 if (BlockInfoCurBID == BlockID)
return;
599 V.push_back(BlockID);
601 BlockInfoCurBID = BlockID;
604 BlockInfo &getOrCreateBlockInfo(
unsigned BlockID) {
609 BlockInfoRecords.emplace_back();
610 BlockInfoRecords.back().BlockID = BlockID;
611 return BlockInfoRecords.back();
619 SwitchToBlockID(BlockID);
623 BlockInfo &
Info = getOrCreateBlockInfo(BlockID);
624 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
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...
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 range R to container C.