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 & ((1U << (NumBits - 1)) - 1)) | (1U << (NumBits - 1)),
251 assert(NumBits <= 32 &&
"Too many bits to emit!");
255 uint32_t Threshold = 1U << (NumBits-1);
258 while (Val >= Threshold) {
260 (1U << (NumBits - 1)),
270 Emit(Val, CurCodeSize);
281 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
282 return &BlockInfoRecords.back();
284 for (BlockInfo &BI : BlockInfoRecords)
285 if (BI.BlockID == BlockID)
298 size_t BlockSizeWordIndex = GetWordIndex();
299 unsigned OldCodeSize = CurCodeSize;
304 CurCodeSize = CodeLen;
308 BlockScope.emplace_back(OldCodeSize, BlockSizeWordIndex);
309 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
318 assert(!BlockScope.empty() &&
"Block scope imbalance!");
319 const Block &
B = BlockScope.back();
327 size_t SizeInWords = GetWordIndex() -
B.StartSizeWord - 1;
334 CurCodeSize =
B.PrevCodeSize;
335 CurAbbrevs = std::move(
B.PrevAbbrevs);
336 BlockScope.pop_back();
347 template<
typename u
intty>
349 assert(
Op.isLiteral() &&
"Not a literal");
353 "Invalid abbrev for record!");
358 template<
typename u
intty>
360 assert(!
Op.isLiteral() &&
"Literals should use EmitAbbreviatedLiteral!");
363 switch (
Op.getEncoding()) {
366 if (
Op.getEncodingData())
367 Emit((
unsigned)V, (
unsigned)
Op.getEncodingData());
370 if (
Op.getEncodingData())
385 template <
typename u
intty>
387 StringRef Blob, std::optional<unsigned> Code) {
388 const char *BlobData = Blob.
data();
391 assert(AbbrevNo < CurAbbrevs.size() &&
"Invalid abbrev #!");
398 assert(e &&
"Expected non-empty abbreviation");
402 EmitAbbreviatedLiteral(
Op, *Code);
406 "Expected literal or scalar");
407 EmitAbbreviatedField(
Op, *Code);
411 unsigned RecordIdx = 0;
412 for (; i !=
e; ++i) {
414 if (
Op.isLiteral()) {
415 assert(RecordIdx < Vals.
size() &&
"Invalid abbrev/record");
416 EmitAbbreviatedLiteral(
Op, Vals[RecordIdx]);
420 assert(i + 2 == e &&
"array op not second to last?");
427 "Blob data and record entries specified for array!");
432 for (
unsigned i = 0; i != BlobLen; ++i)
433 EmitAbbreviatedField(EltEnc, (
unsigned char)BlobData[i]);
442 for (
unsigned e = Vals.
size(); RecordIdx != e; ++RecordIdx)
443 EmitAbbreviatedField(EltEnc, Vals[RecordIdx]);
451 "Blob data and record entries specified for blob operand!");
453 assert(Blob.
data() == BlobData &&
"BlobData got moved");
454 assert(Blob.
size() == BlobLen &&
"BlobLen got changed");
461 assert(RecordIdx < Vals.
size() &&
"Invalid abbrev/record");
462 EmitAbbreviatedField(
Op, Vals[RecordIdx]);
466 assert(RecordIdx == Vals.
size() &&
"Not all record operands emitted!");
467 assert(BlobData ==
nullptr &&
468 "Blob data specified for record that doesn't use it!");
473 template <
class UIntTy>
487 while (GetBufferOffset() & 3)
497 template <
typename Container>
498 void EmitRecord(
unsigned Code,
const Container &Vals,
unsigned Abbrev = 0) {
502 auto Count =
static_cast<uint32_t>(std::size(Vals));
506 for (
unsigned i = 0, e = Count; i != e; ++i)
517 template <
typename Container>
527 template <
typename Container>
530 EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals), Blob, std::nullopt);
532 template <
typename Container>
534 const char *BlobData,
unsigned BlobLen) {
535 return EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals),
536 StringRef(BlobData, BlobLen), std::nullopt);
541 template <
typename Container>
544 EmitRecordWithAbbrevImpl(Abbrev,
ArrayRef(Vals), Array, std::nullopt);
546 template <
typename Container>
548 const char *ArrayData,
unsigned ArrayLen) {
549 return EmitRecordWithAbbrevImpl(
566 if (
Op.isLiteral()) {
569 Emit(
Op.getEncoding(), 3);
570 if (
Op.hasEncodingData())
580 CurAbbrevs.push_back(std::move(Abbv));
581 return static_cast<unsigned>(CurAbbrevs.size())-1 +
592 BlockInfoCurBID = ~0U;
593 BlockInfoRecords.clear();
598 void SwitchToBlockID(
unsigned BlockID) {
599 if (BlockInfoCurBID == BlockID)
return;
601 V.push_back(BlockID);
603 BlockInfoCurBID = BlockID;
606 BlockInfo &getOrCreateBlockInfo(
unsigned BlockID) {
611 BlockInfoRecords.emplace_back();
612 BlockInfoRecords.back().BlockID = BlockID;
613 return BlockInfoRecords.back();
621 SwitchToBlockID(BlockID);
625 BlockInfo &
Info = getOrCreateBlockInfo(BlockID);
626 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.
constexpr 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.