mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
Added "random access" to the Deserializer to allow a client to jump to any
serialized block in the bitstream, including a block in an entirely different nesting than the current block. This is useful for deserializing objects from a bitstream in an order different from the order that they were serialized. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43973 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -80,7 +80,36 @@ class Deserializer {
|
|||||||
//===----------------------------------------------------------===//
|
//===----------------------------------------------------------===//
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef uint64_t Location;
|
struct Location {
|
||||||
|
uint64_t BitNo;
|
||||||
|
unsigned BlockID;
|
||||||
|
unsigned NumWords;
|
||||||
|
|
||||||
|
Location(uint64_t bit, unsigned bid, unsigned words)
|
||||||
|
: BitNo(bit), BlockID(bid), NumWords(words) {}
|
||||||
|
|
||||||
|
Location() : BitNo(0), BlockID(0), NumWords(0) {}
|
||||||
|
|
||||||
|
Location& operator=(Location& RHS) {
|
||||||
|
BitNo = RHS.BitNo;
|
||||||
|
BlockID = RHS.BlockID;
|
||||||
|
NumWords = RHS.NumWords;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Location& RHS) const { return BitNo == RHS.BitNo; }
|
||||||
|
bool operator!=(const Location& RHS) const { return BitNo != RHS.BitNo; }
|
||||||
|
|
||||||
|
bool contains(const Location& RHS) const {
|
||||||
|
if (RHS.BitNo < BitNo)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((RHS.BitNo - BitNo) >> 5 < NumWords)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------===//
|
//===----------------------------------------------------------===//
|
||||||
// Internal data members.
|
// Internal data members.
|
||||||
@@ -93,9 +122,10 @@ private:
|
|||||||
BumpPtrAllocator Allocator;
|
BumpPtrAllocator Allocator;
|
||||||
BPNode* FreeList;
|
BPNode* FreeList;
|
||||||
MapTy BPatchMap;
|
MapTy BPatchMap;
|
||||||
llvm::SmallVector<std::pair<Location,unsigned>,5> BlockStack;
|
llvm::SmallVector<Location,8> BlockStack;
|
||||||
unsigned AbbrevNo;
|
unsigned AbbrevNo;
|
||||||
unsigned RecordCode;
|
unsigned RecordCode;
|
||||||
|
Location StreamStart;
|
||||||
|
|
||||||
//===----------------------------------------------------------===//
|
//===----------------------------------------------------------===//
|
||||||
// Public Interface.
|
// Public Interface.
|
||||||
@@ -238,13 +268,18 @@ public:
|
|||||||
unsigned getAbbrevNo();
|
unsigned getAbbrevNo();
|
||||||
|
|
||||||
bool FinishedBlock(Location BlockLoc);
|
bool FinishedBlock(Location BlockLoc);
|
||||||
|
bool JumpTo(const Location& BlockLoc);
|
||||||
|
void Rewind() { JumpTo(StreamStart); }
|
||||||
|
|
||||||
bool AtEnd();
|
bool AtEnd();
|
||||||
bool inRecord();
|
bool inRecord();
|
||||||
void SkipBlock();
|
void SkipBlock();
|
||||||
|
bool SkipToBlock(unsigned BlockID);
|
||||||
|
|
||||||
unsigned getRecordCode();
|
unsigned getRecordCode();
|
||||||
|
|
||||||
|
BitstreamReader& getStream() { return Stream; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool AdvanceStream();
|
bool AdvanceStream();
|
||||||
void ReadRecord();
|
void ReadRecord();
|
||||||
|
@@ -21,6 +21,9 @@ using namespace llvm;
|
|||||||
|
|
||||||
Deserializer::Deserializer(BitstreamReader& stream)
|
Deserializer::Deserializer(BitstreamReader& stream)
|
||||||
: Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
|
: Stream(stream), RecIdx(0), FreeList(NULL), AbbrevNo(0), RecordCode(0) {
|
||||||
|
|
||||||
|
AdvanceStream();
|
||||||
|
if (!AtEnd()) StreamStart = BlockStack.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
Deserializer::~Deserializer() {
|
Deserializer::~Deserializer() {
|
||||||
@@ -60,12 +63,24 @@ bool Deserializer::AdvanceStream() {
|
|||||||
|
|
||||||
while (!Stream.AtEndOfStream()) {
|
while (!Stream.AtEndOfStream()) {
|
||||||
|
|
||||||
|
uint64_t Pos = Stream.GetCurrentBitNo();
|
||||||
AbbrevNo = Stream.ReadCode();
|
AbbrevNo = Stream.ReadCode();
|
||||||
|
|
||||||
switch (AbbrevNo) {
|
switch (AbbrevNo) {
|
||||||
case bitc::ENTER_SUBBLOCK: {
|
case bitc::ENTER_SUBBLOCK: {
|
||||||
unsigned id = Stream.ReadSubBlockID();
|
unsigned id = Stream.ReadSubBlockID();
|
||||||
BlockStack.push_back(std::make_pair(Stream.GetCurrentBitNo(),id));
|
|
||||||
|
// Determine the extent of the block. This is useful for jumping around
|
||||||
|
// the stream. This is hack: we read the header of the block, save
|
||||||
|
// the length, and then revert the bitstream to a location just before
|
||||||
|
// the block is entered.
|
||||||
|
uint64_t BPos = Stream.GetCurrentBitNo();
|
||||||
|
Stream.ReadVBR(bitc::CodeLenWidth); // Skip the code size.
|
||||||
|
Stream.SkipToWord();
|
||||||
|
unsigned NumWords = Stream.Read(bitc::BlockSizeWidth);
|
||||||
|
Stream.JumpToBit(BPos);
|
||||||
|
|
||||||
|
BlockStack.push_back(Location(Pos,id,NumWords));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,10 +106,10 @@ bool Deserializer::AdvanceStream() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Deserializer::ReadRecord() {
|
void Deserializer::ReadRecord() {
|
||||||
|
|
||||||
while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
|
while (AdvanceStream() && AbbrevNo == bitc::ENTER_SUBBLOCK) {
|
||||||
assert (!BlockStack.empty());
|
assert (!BlockStack.empty());
|
||||||
Stream.EnterSubBlock(BlockStack.back().second);
|
Stream.EnterSubBlock(BlockStack.back().BlockID);
|
||||||
AbbrevNo = 0;
|
AbbrevNo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,23 +124,116 @@ void Deserializer::ReadRecord() {
|
|||||||
|
|
||||||
void Deserializer::SkipBlock() {
|
void Deserializer::SkipBlock() {
|
||||||
assert (!inRecord());
|
assert (!inRecord());
|
||||||
assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
|
|
||||||
|
if (AtEnd())
|
||||||
|
return;
|
||||||
|
|
||||||
|
AdvanceStream();
|
||||||
|
|
||||||
|
assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
|
||||||
|
BlockStack.pop_back();
|
||||||
Stream.SkipBlock();
|
Stream.SkipBlock();
|
||||||
|
|
||||||
AbbrevNo = 0;
|
AbbrevNo = 0;
|
||||||
|
AdvanceStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Deserializer::SkipToBlock(unsigned BlockID) {
|
||||||
|
assert (!inRecord());
|
||||||
|
|
||||||
|
AdvanceStream();
|
||||||
|
assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
|
||||||
|
|
||||||
|
unsigned BlockLevel = BlockStack.size();
|
||||||
|
|
||||||
|
while (!AtEnd() &&
|
||||||
|
BlockLevel == BlockStack.size() &&
|
||||||
|
getCurrentBlockID() != BlockID)
|
||||||
|
SkipBlock();
|
||||||
|
|
||||||
|
return !(AtEnd() || BlockLevel != BlockStack.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Deserializer::Location Deserializer::getCurrentBlockLocation() {
|
Deserializer::Location Deserializer::getCurrentBlockLocation() {
|
||||||
if (!inRecord())
|
if (!inRecord())
|
||||||
AdvanceStream();
|
AdvanceStream();
|
||||||
|
|
||||||
return BlockStack.back().first;
|
return BlockStack.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Deserializer::JumpTo(const Location& Loc) {
|
||||||
|
|
||||||
|
assert (!inRecord());
|
||||||
|
|
||||||
|
// AdvanceStream();
|
||||||
|
|
||||||
|
// assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
|
||||||
|
assert (!BlockStack.empty());
|
||||||
|
|
||||||
|
uint64_t LastBPos = StreamStart.BitNo;
|
||||||
|
|
||||||
|
while (!BlockStack.empty()) {
|
||||||
|
|
||||||
|
LastBPos = BlockStack.back().BitNo;
|
||||||
|
|
||||||
|
// Determine of the current block contains the location of the block
|
||||||
|
// we are looking for.
|
||||||
|
if (BlockStack.back().contains(Loc)) {
|
||||||
|
// We found the enclosing block. We must first POP it off to
|
||||||
|
// destroy any accumulated context within the block scope. We then
|
||||||
|
// jump to the position of the block and enter it.
|
||||||
|
Stream.JumpToBit(LastBPos);
|
||||||
|
BlockStack.pop_back();
|
||||||
|
Stream.PopBlockScope();
|
||||||
|
|
||||||
|
AbbrevNo = 0;
|
||||||
|
AdvanceStream();
|
||||||
|
assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
|
||||||
|
|
||||||
|
Stream.EnterSubBlock(BlockStack.back().BlockID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This block does not contain the block we are looking for. Pop it.
|
||||||
|
BlockStack.pop_back();
|
||||||
|
Stream.PopBlockScope();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we have popped our way to the outermost scope. If so,
|
||||||
|
// we need to adjust our position.
|
||||||
|
if (BlockStack.empty()) {
|
||||||
|
Stream.JumpToBit(Loc.BitNo < LastBPos ? StreamStart.BitNo : LastBPos);
|
||||||
|
AbbrevNo = 0;
|
||||||
|
AdvanceStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
assert (AbbrevNo == bitc::ENTER_SUBBLOCK);
|
||||||
|
assert (!BlockStack.empty());
|
||||||
|
|
||||||
|
while (!AtEnd() && BlockStack.back() != Loc) {
|
||||||
|
if (BlockStack.back().contains(Loc)) {
|
||||||
|
Stream.EnterSubBlock(BlockStack.back().BlockID);
|
||||||
|
AbbrevNo = 0;
|
||||||
|
AdvanceStream();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SkipBlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AtEnd())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
assert (BlockStack.back() == Loc);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Deserializer::getCurrentBlockID() {
|
unsigned Deserializer::getCurrentBlockID() {
|
||||||
if (!inRecord())
|
if (!inRecord())
|
||||||
AdvanceStream();
|
AdvanceStream();
|
||||||
|
|
||||||
return BlockStack.back().second;
|
return BlockStack.back().BlockID;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned Deserializer::getRecordCode() {
|
unsigned Deserializer::getRecordCode() {
|
||||||
@@ -142,9 +250,9 @@ bool Deserializer::FinishedBlock(Location BlockLoc) {
|
|||||||
if (!inRecord())
|
if (!inRecord())
|
||||||
AdvanceStream();
|
AdvanceStream();
|
||||||
|
|
||||||
for (llvm::SmallVector<std::pair<Location,unsigned>,5>::reverse_iterator
|
for (llvm::SmallVector<Location,8>::reverse_iterator
|
||||||
I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
|
I=BlockStack.rbegin(), E=BlockStack.rend(); I!=E; ++I)
|
||||||
if (I->first == BlockLoc)
|
if (*I == BlockLoc)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
Reference in New Issue
Block a user