summaryrefslogtreecommitdiff
path: root/include/llvm/Bitcode
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2013-01-19 21:35:24 +0000
committerChris Lattner <sabre@nondot.org>2013-01-19 21:35:24 +0000
commit63246aa04f23767875bfe6f533285915a766b82d (patch)
tree3e8b20360dbb7070b6eed3c11bbaff92fa09c3ab /include/llvm/Bitcode
parent35f63ddc8fd2edad63393e2c111e47aea7940b81 (diff)
downloadllvm-63246aa04f23767875bfe6f533285915a766b82d.tar.gz
llvm-63246aa04f23767875bfe6f533285915a766b82d.tar.bz2
llvm-63246aa04f23767875bfe6f533285915a766b82d.tar.xz
Add a new BitstreamEntry concept, and add two helper methods for walking
through a BitstreamCursor that produce it: advance() and advanceSkippingSubblocks(), representing the two most common ways clients want to walk through bitcode. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172919 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/llvm/Bitcode')
-rw-r--r--include/llvm/Bitcode/BitstreamReader.h97
1 files changed, 91 insertions, 6 deletions
diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h
index bdc71ae406..2ca92081e3 100644
--- a/include/llvm/Bitcode/BitstreamReader.h
+++ b/include/llvm/Bitcode/BitstreamReader.h
@@ -27,6 +27,11 @@ namespace llvm {
class Deserializer;
+/// BitstreamReader - This class is used to read from an LLVM bitcode stream,
+/// maintaining information that is global to decoding the entire file. While
+/// a file is being read, multiple cursors can be independently advanced or
+/// skipped around within the file. These are represented by the
+/// BitstreamCursor class.
class BitstreamReader {
public:
/// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks.
@@ -119,9 +124,48 @@ public:
BlockInfoRecords.back().BlockID = BlockID;
return BlockInfoRecords.back();
}
+};
+
+
+/// BitstreamEntry - When advancing through a bitstream cursor, each advance can
+/// discover a few different kinds of entries:
+/// Error - Malformed bitcode was found.
+/// EndBlock - We've reached the end of the current block, (or the end of the
+/// file, which is treated like a series of EndBlock records.
+/// SubBlock - This is the start of a new subblock of a specific ID.
+/// Record - This is a record with a specific AbbrevID.
+///
+struct BitstreamEntry {
+ enum {
+ Error,
+ EndBlock,
+ SubBlock,
+ Record
+ } Kind;
+
+ unsigned ID;
+ static BitstreamEntry getError() {
+ BitstreamEntry E; E.Kind = Error; return E;
+ }
+ static BitstreamEntry getEndBlock() {
+ BitstreamEntry E; E.Kind = EndBlock; return E;
+ }
+ static BitstreamEntry getSubBlock(unsigned ID) {
+ BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
+ }
+ static BitstreamEntry getRecord(unsigned AbbrevID) {
+ BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
+ }
};
+
+/// BitstreamCursor - This represents a position within a bitcode file. There
+/// may be multiple independent cursors reading within one bitstream, each
+/// maintaining their own local state.
+///
+/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
+/// be passed by value.
class BitstreamCursor {
friend class Deserializer;
BitstreamReader *BitStream;
@@ -151,6 +195,7 @@ class BitstreamCursor {
/// BlockScope - This tracks the codesize of parent blocks.
SmallVector<Block, 8> BlockScope;
+
public:
BitstreamCursor() : BitStream(0), NextChar(0) {
}
@@ -183,9 +228,6 @@ public:
void freeState();
- /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
- unsigned GetAbbrevIDWidth() const { return CurCodeSize; }
-
bool isEndPos(size_t pos) {
return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos));
}
@@ -212,6 +254,9 @@ public:
return isEndPos(NextChar) && BitsInCurWord == 0;
}
+ /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #.
+ unsigned getAbbrevIDWidth() const { return CurCodeSize; }
+
/// GetCurrentBitNo - Return the bit # of the bit we are reading.
uint64_t GetCurrentBitNo() const {
return NextChar*CHAR_BIT - BitsInCurWord;
@@ -224,6 +269,46 @@ public:
return BitStream;
}
+
+ /// advance - Advance the current bitstream, returning the next entry in the
+ /// stream.
+ BitstreamEntry advance() {
+ while (1) {
+ unsigned Code = ReadCode();
+ if (Code == bitc::END_BLOCK) {
+ if (ReadBlockEnd())
+ return BitstreamEntry::getError();
+ return BitstreamEntry::getEndBlock();
+ }
+
+ if (Code == bitc::ENTER_SUBBLOCK)
+ return BitstreamEntry::getSubBlock(ReadSubBlockID());
+
+ if (Code == bitc::DEFINE_ABBREV) {
+ // We read and accumulate abbrev's, the client can't do anything with
+ // them anyway.
+ ReadAbbrevRecord();
+ continue;
+ }
+
+ return BitstreamEntry::getRecord(Code);
+ }
+ }
+
+ /// advanceSkippingSubblocks - This is a convenience function for clients that
+ /// don't expect any subblocks. This just skips over them automatically.
+ BitstreamEntry advanceSkippingSubblocks() {
+ while (1) {
+ // If we found a normal entry, return it.
+ BitstreamEntry Entry = advance();
+ if (Entry.Kind != BitstreamEntry::SubBlock)
+ return Entry;
+
+ // If we found a sub-block, just skip over it and check the next entry.
+ if (SkipBlock())
+ return BitstreamEntry::getError();
+ }
+ }
/// JumpToBit - Reset the stream to the specified bit number.
void JumpToBit(uint64_t BitNo) {
@@ -375,12 +460,13 @@ public:
// [END_BLOCK, <align4bytes>]
SkipToWord();
- PopBlockScope();
+ popBlockScope();
return false;
}
private:
- void PopBlockScope() {
+
+ void popBlockScope() {
CurCodeSize = BlockScope.back().PrevCodeSize;
// Delete abbrevs from popped scope.
@@ -443,7 +529,6 @@ public:
//===--------------------------------------------------------------------===//
// Abbrev Processing
//===--------------------------------------------------------------------===//
-
void ReadAbbrevRecord();
bool ReadBlockInfoBlock();