/// BlockScope - This tracks the codesize of parent blocks.
SmallVector<Block, 8> BlockScope;
+ /// FirstChar - This remembers the first byte of the stream.
+ const unsigned char *FirstChar;
public:
- BitstreamReader(const unsigned char *Start, const unsigned char *End)
- : NextChar(Start), LastChar(End) {
+ BitstreamReader() {
+ NextChar = FirstChar = LastChar = 0;
+ CurWord = 0;
+ BitsInCurWord = 0;
+ CurCodeSize = 0;
+ }
+
+ BitstreamReader(const unsigned char *Start, const unsigned char *End) {
+ init(Start, End);
+ }
+
+ void init(const unsigned char *Start, const unsigned char *End) {
+ NextChar = FirstChar = Start;
+ LastChar = End;
assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes");
CurWord = 0;
BitsInCurWord = 0;
// Abbrevs could still exist if the stream was broken. If so, don't leak
// them.
for (unsigned i = 0, e = CurAbbrevs.size(); i != e; ++i)
- delete CurAbbrevs[i];
+ CurAbbrevs[i]->dropRef();
for (unsigned S = 0, e = BlockScope.size(); S != e; ++S) {
std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs;
for (unsigned i = 0, e = Abbrevs.size(); i != e; ++i)
- delete Abbrevs[i];
+ Abbrevs[i]->dropRef();
}
}
/// GetCurrentBitNo - Return the bit # of the bit we are reading.
uint64_t GetCurrentBitNo() const {
- return CurWord * 32ULL + (32-CurCodeSize);
+ return (NextChar-FirstChar)*8 + (32-BitsInCurWord);
+ }
+
+ /// JumpToBit - Reset the stream to the specified bit number.
+ void JumpToBit(uint64_t BitNo) {
+ unsigned ByteNo = (BitNo/8) & ~3;
+ unsigned WordBitNo = BitNo & 31;
+ assert(ByteNo < (unsigned)(LastChar-FirstChar) && "Invalid location");
+
+ // Move the cursor to the right word.
+ NextChar = FirstChar+ByteNo;
+ BitsInCurWord = 0;
+
+ // Skip over any bits that are already consumed.
+ if (WordBitNo) {
+ NextChar -= 4;
+ Read(WordBitNo);
+ }
}
+ /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
+ unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
uint32_t Read(unsigned NumBits) {
// If the field is fully contained by CurWord, return it quickly.
/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, read and enter
/// the block, returning the BlockID of the block we just entered.
- bool EnterSubBlock() {
+ bool EnterSubBlock(unsigned *NumWordsP = 0) {
BlockScope.push_back(Block(CurCodeSize));
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
CurCodeSize = ReadVBR(bitc::CodeLenWidth);
SkipToWord();
unsigned NumWords = Read(bitc::BlockSizeWidth);
+ if (NumWordsP) *NumWordsP = NumWords;
// Validate that this block is sane.
if (CurCodeSize == 0 || AtEndOfStream() || NextChar+NumWords*4 > LastChar)
// Delete abbrevs from popped scope.
for (unsigned i = 0, e = CurAbbrevs.size(); i != e; ++i)
- delete CurAbbrevs[i];
+ CurAbbrevs[i]->dropRef();
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
BlockScope.pop_back();
return Code;
}
- unsigned AbbrevNo = AbbrevID-bitc::FIRST_ABBREV;
+ unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV;
assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo];