#include "llvm/Bitcode/BitCodes.h"
#include <climits>
+#include <string>
#include <vector>
namespace llvm {
struct BlockInfo {
unsigned BlockID;
std::vector<BitCodeAbbrev*> Abbrevs;
+ std::string Name;
+
+ std::vector<std::pair<unsigned, std::string> > RecordNames;
};
private:
/// FirstChar/LastChar - This remembers the first and last bytes of the
std::vector<BlockInfo> BlockInfoRecords;
+ /// IgnoreBlockInfoNames - This is set to true if we don't care about the
+ /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer
+ /// uses this.
+ bool IgnoreBlockInfoNames;
+
+ BitstreamReader(const BitstreamReader&); // NOT IMPLEMENTED
+ void operator=(const BitstreamReader&); // NOT IMPLEMENTED
public:
- BitstreamReader() : FirstChar(0), LastChar(0) {
+ BitstreamReader() : FirstChar(0), LastChar(0), IgnoreBlockInfoNames(true) {
}
BitstreamReader(const unsigned char *Start, const unsigned char *End) {
+ IgnoreBlockInfoNames = true;
init(Start, End);
}
const unsigned char *getFirstChar() const { return FirstChar; }
const unsigned char *getLastChar() const { return LastChar; }
+ /// CollectBlockInfoNames - This is called by clients that want block/record
+ /// name information.
+ void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
+ bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; }
+
//===--------------------------------------------------------------------===//
// Block Manipulation
//===--------------------------------------------------------------------===//
+ /// hasBlockInfoRecords - Return true if we've already read and processed the
+ /// block info block for this Bitstream. We only process it for the first
+ /// cursor that walks over it.
+ bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); }
+
/// getBlockInfo - If there is block info for the specified ID, return it,
/// otherwise return null.
- BlockInfo *getBlockInfo(unsigned BlockID) {
+ const BlockInfo *getBlockInfo(unsigned BlockID) const {
// Common case, the most recent entry matches BlockID.
if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
return &BlockInfoRecords.back();
}
BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
- if (BlockInfo *BI = getBlockInfo(BlockID))
- return *BI;
+ if (const BlockInfo *BI = getBlockInfo(BlockID))
+ return *const_cast<BlockInfo*>(BI);
// Otherwise, add a new record.
BlockInfoRecords.push_back(BlockInfo());
/// BlockScope - This tracks the codesize of parent blocks.
SmallVector<Block, 8> BlockScope;
- BitstreamCursor(const BitstreamCursor&); // NOT YET IMPLEMENTED.
- void operator=(const BitstreamCursor&); // NOT YET IMPLEMENTED.
public:
BitstreamCursor() : BitStream(0), NextChar(0) {
}
+ BitstreamCursor(const BitstreamCursor &RHS) : BitStream(0), NextChar(0) {
+ operator=(RHS);
+ }
+
explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) {
NextChar = R.getFirstChar();
assert(NextChar && "Bitstream not initialized yet");
freeState();
}
+ void operator=(const BitstreamCursor &RHS) {
+ freeState();
+
+ BitStream = RHS.BitStream;
+ NextChar = RHS.NextChar;
+ CurWord = RHS.CurWord;
+ BitsInCurWord = RHS.BitsInCurWord;
+ CurCodeSize = RHS.CurCodeSize;
+
+ // Copy abbreviations, and bump ref counts.
+ CurAbbrevs = RHS.CurAbbrevs;
+ for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
+ i != e; ++i)
+ CurAbbrevs[i]->addRef();
+
+ // Copy block scope and bump ref counts.
+ for (unsigned S = 0, e = static_cast<unsigned>(BlockScope.size());
+ S != e; ++S) {
+ std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs;
+ for (unsigned i = 0, e = static_cast<unsigned>(Abbrevs.size());
+ i != e; ++i)
+ Abbrevs[i]->addRef();
+ }
+ }
+
void freeState() {
// Free all the Abbrevs.
for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
return (NextChar-BitStream->getFirstChar())*CHAR_BIT - BitsInCurWord;
}
+ BitstreamReader *getBitStreamReader() {
+ return BitStream;
+ }
+ const BitstreamReader *getBitStreamReader() const {
+ return BitStream;
+ }
+
/// JumpToBit - Reset the stream to the specified bit number.
void JumpToBit(uint64_t BitNo) {
uint32_t Read(unsigned NumBits) {
+ assert(NumBits <= 32 && "Cannot return more than 32 bits!");
// If the field is fully contained by CurWord, return it quickly.
if (BitsInCurWord >= NumBits) {
uint32_t R = CurWord & ((1U << NumBits)-1);
}
}
+ // ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The
+ // chunk size of the VBR must still be <= 32 bits though.
uint64_t ReadVBR64(unsigned NumBits) {
- uint64_t Piece = Read(NumBits);
+ uint32_t Piece = Read(NumBits);
if ((Piece & (1U << (NumBits-1))) == 0)
- return Piece;
+ return uint64_t(Piece);
uint64_t Result = 0;
unsigned NextBit = 0;
while (1) {
- Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit;
+ Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit;
if ((Piece & (1U << (NumBits-1))) == 0)
return Result;
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
// Add the abbrevs specific to this block to the CurAbbrevs list.
- if (BitstreamReader::BlockInfo *Info = BitStream->getBlockInfo(BlockID)) {
+ if (const BitstreamReader::BlockInfo *Info =
+ BitStream->getBlockInfo(BlockID)) {
for (unsigned i = 0, e = static_cast<unsigned>(Info->Abbrevs.size());
i != e; ++i) {
CurAbbrevs.push_back(Info->Abbrevs[i]);
public:
bool ReadBlockInfoBlock() {
+ // If this is the second stream to get to the block info block, skip it.
+ if (BitStream->hasBlockInfoRecords())
+ return SkipBlock();
+
if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true;
SmallVector<uint64_t, 64> Record;
if (Record.size() < 1) return true;
CurBlockInfo = &BitStream->getOrCreateBlockInfo((unsigned)Record[0]);
break;
+ case bitc::BLOCKINFO_CODE_BLOCKNAME: {
+ if (!CurBlockInfo) return true;
+ if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name.
+ std::string Name;
+ for (unsigned i = 0, e = Record.size(); i != e; ++i)
+ Name += (char)Record[i];
+ CurBlockInfo->Name = Name;
+ break;
+ }
+ case bitc::BLOCKINFO_CODE_SETRECORDNAME: {
+ if (!CurBlockInfo) return true;
+ if (BitStream->isIgnoringBlockInfoNames()) break; // Ignore name.
+ std::string Name;
+ for (unsigned i = 1, e = Record.size(); i != e; ++i)
+ Name += (char)Record[i];
+ CurBlockInfo->RecordNames.push_back(std::make_pair((unsigned)Record[0],
+ Name));
+ break;
+ }
}
}
}