Bitcode: Decouple block info block state from reader.

As proposed on llvm-dev:
http://lists.llvm.org/pipermail/llvm-dev/2016-October/106630.html

Move block info block state to a new class, BitstreamBlockInfo.
Clients may set the block info for a particular cursor with the
BitstreamCursor::setBlockInfo() method.

At this point BitstreamReader is not much more than a container for an
ArrayRef<uint8_t>, so remove it and replace all uses with direct uses
of memory buffers.

Differential Revision: https://reviews.llvm.org/D26259

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286207 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Peter Collingbourne 2016-11-08 04:17:11 +00:00
parent ef0facce3e
commit 8fc9b4d314
5 changed files with 117 additions and 198 deletions

View File

@ -35,11 +35,8 @@
namespace llvm {
/// 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 {
/// This class maintains the abbreviations read from a block info block.
class BitstreamBlockInfo {
public:
/// This contains information emitted to BLOCKINFO_BLOCK blocks. These
/// describe abbreviations that all blocks of the specified ID inherit.
@ -51,39 +48,9 @@ public:
};
private:
ArrayRef<uint8_t> BitcodeBytes;
std::vector<BlockInfo> BlockInfoRecords;
/// 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 = true;
public:
BitstreamReader() = default;
BitstreamReader(ArrayRef<uint8_t> BitcodeBytes)
: BitcodeBytes(BitcodeBytes) {}
BitstreamReader(StringRef BitcodeBytes)
: BitcodeBytes(reinterpret_cast<const uint8_t *>(BitcodeBytes.data()),
BitcodeBytes.size()) {}
BitstreamReader(MemoryBufferRef BitcodeBytes)
: BitstreamReader(BitcodeBytes.getBuffer()) {}
ArrayRef<uint8_t> getBitcodeBytes() { return BitcodeBytes; }
/// This is called by clients that want block/record name information.
void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; }
//===--------------------------------------------------------------------===//
// Block Manipulation
//===--------------------------------------------------------------------===//
/// 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(); }
/// If there is block info for the specified ID, return it, otherwise return
/// null.
const BlockInfo *getBlockInfo(unsigned BlockID) const {
@ -107,22 +74,13 @@ public:
BlockInfoRecords.back().BlockID = BlockID;
return BlockInfoRecords.back();
}
/// Takes block info from the other bitstream reader.
///
/// This is a "take" operation because BlockInfo records are non-trivial, and
/// indeed rather expensive.
void takeBlockInfo(BitstreamReader &&Other) {
assert(!hasBlockInfoRecords());
BlockInfoRecords = std::move(Other.BlockInfoRecords);
}
};
/// This represents a position within a bitstream. There may be multiple
/// independent cursors reading within one bitstream, each maintaining their
/// own local state.
class SimpleBitstreamCursor {
BitstreamReader *R = nullptr;
ArrayRef<uint8_t> BitcodeBytes;
size_t NextChar = 0;
public:
@ -144,17 +102,21 @@ public:
static const size_t MaxChunkSize = sizeof(word_t) * 8;
SimpleBitstreamCursor() = default;
explicit SimpleBitstreamCursor(BitstreamReader &R) : R(&R) {}
explicit SimpleBitstreamCursor(BitstreamReader *R) : R(R) {}
explicit SimpleBitstreamCursor(ArrayRef<uint8_t> BitcodeBytes)
: BitcodeBytes(BitcodeBytes) {}
explicit SimpleBitstreamCursor(StringRef BitcodeBytes)
: BitcodeBytes(reinterpret_cast<const uint8_t *>(BitcodeBytes.data()),
BitcodeBytes.size()) {}
explicit SimpleBitstreamCursor(MemoryBufferRef BitcodeBytes)
: SimpleBitstreamCursor(BitcodeBytes.getBuffer()) {}
bool canSkipToPos(size_t pos) const {
// pos can be skipped to if it is a valid address or one byte past the end.
return pos <= R->getBitcodeBytes().size();
return pos <= BitcodeBytes.size();
}
bool AtEndOfStream() {
return BitsInCurWord == 0 && R->getBitcodeBytes().size() <= NextChar;
return BitsInCurWord == 0 && BitcodeBytes.size() <= NextChar;
}
/// Return the bit # of the bit we are reading.
@ -165,8 +127,7 @@ public:
// Return the byte # of the current bit.
uint64_t getCurrentByteNo() const { return GetCurrentBitNo() / 8; }
BitstreamReader *getBitStreamReader() { return R; }
const BitstreamReader *getBitStreamReader() const { return R; }
ArrayRef<uint8_t> getBitcodeBytes() const { return BitcodeBytes; }
/// Reset the stream to the specified bit number.
void JumpToBit(uint64_t BitNo) {
@ -183,27 +144,9 @@ public:
Read(WordBitNo);
}
/// Reset the stream to the bit pointed at by the specified pointer.
///
/// The pointer must be a dereferenceable pointer into the bytes in the
/// underlying memory object.
void jumpToPointer(const uint8_t *Pointer) {
auto *Pointer0 = getPointerToByte(0, 1);
assert((intptr_t)Pointer0 <= (intptr_t)Pointer &&
"Expected pointer into bitstream");
JumpToBit(8 * (Pointer - Pointer0));
assert((intptr_t)getPointerToByte(getCurrentByteNo(), 1) ==
(intptr_t)Pointer &&
"Expected to reach pointer");
}
void jumpToPointer(const char *Pointer) {
jumpToPointer((const uint8_t *)Pointer);
}
/// Get a pointer into the bitstream at the specified byte offset.
const uint8_t *getPointerToByte(uint64_t ByteNo, uint64_t NumBytes) {
return R->getBitcodeBytes().data() + ByteNo;
return BitcodeBytes.data() + ByteNo;
}
/// Get a pointer into the bitstream at the specified bit offset.
@ -215,21 +158,20 @@ public:
}
void fillCurWord() {
ArrayRef<uint8_t> Buf = R->getBitcodeBytes();
if (NextChar >= Buf.size())
if (NextChar >= BitcodeBytes.size())
report_fatal_error("Unexpected end of file");
// Read the next word from the stream.
const uint8_t *NextCharPtr = Buf.data() + NextChar;
const uint8_t *NextCharPtr = BitcodeBytes.data() + NextChar;
unsigned BytesRead;
if (Buf.size() >= NextChar + sizeof(word_t)) {
if (BitcodeBytes.size() >= NextChar + sizeof(word_t)) {
BytesRead = sizeof(word_t);
CurWord =
support::endian::read<word_t, support::little, support::unaligned>(
NextCharPtr);
} else {
// Short read.
BytesRead = Buf.size() - NextChar;
BytesRead = BitcodeBytes.size() - NextChar;
CurWord = 0;
for (unsigned B = 0; B != BytesRead; ++B)
CurWord |= uint64_t(NextCharPtr[B]) << (B * 8);
@ -330,7 +272,7 @@ public:
}
/// Skip to the end of the file.
void skipToEnd() { NextChar = R->getBitcodeBytes().size(); }
void skipToEnd() { NextChar = BitcodeBytes.size(); }
};
/// When advancing through a bitstream cursor, each advance can discover a few
@ -386,27 +328,25 @@ class BitstreamCursor : SimpleBitstreamCursor {
/// This tracks the codesize of parent blocks.
SmallVector<Block, 8> BlockScope;
BitstreamBlockInfo *BlockInfo = nullptr;
public:
static const size_t MaxChunkSize = sizeof(word_t) * 8;
BitstreamCursor() = default;
explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
void init(BitstreamReader *R) {
freeState();
SimpleBitstreamCursor::operator=(SimpleBitstreamCursor(R));
CurCodeSize = 2;
}
void freeState();
explicit BitstreamCursor(ArrayRef<uint8_t> BitcodeBytes)
: SimpleBitstreamCursor(BitcodeBytes) {}
explicit BitstreamCursor(StringRef BitcodeBytes)
: SimpleBitstreamCursor(BitcodeBytes) {}
explicit BitstreamCursor(MemoryBufferRef BitcodeBytes)
: SimpleBitstreamCursor(BitcodeBytes) {}
using SimpleBitstreamCursor::canSkipToPos;
using SimpleBitstreamCursor::AtEndOfStream;
using SimpleBitstreamCursor::getBitcodeBytes;
using SimpleBitstreamCursor::GetCurrentBitNo;
using SimpleBitstreamCursor::getCurrentByteNo;
using SimpleBitstreamCursor::getPointerToByte;
using SimpleBitstreamCursor::getBitStreamReader;
using SimpleBitstreamCursor::JumpToBit;
using SimpleBitstreamCursor::fillCurWord;
using SimpleBitstreamCursor::Read;
@ -549,7 +489,17 @@ public:
//===--------------------------------------------------------------------===//
void ReadAbbrevRecord();
bool ReadBlockInfoBlock();
/// Read and return a block info block from the bitstream. If an error was
/// encountered, return None.
///
/// \param ReadBlockInfoNames Whether to read block/record name information in
/// the BlockInfo block. Only llvm-bcanalyzer uses this.
Optional<BitstreamBlockInfo>
ReadBlockInfoBlock(bool ReadBlockInfoNames = false);
/// Set the block info to be used by this BitstreamCursor to interpret
/// abbreviated records.
void setBlockInfo(BitstreamBlockInfo *BI) { BlockInfo = BI; }
};
} // end llvm namespace

View File

@ -233,7 +233,7 @@ protected:
BitcodeReaderBase(MemoryBuffer *Buffer) : Buffer(Buffer) {}
std::unique_ptr<MemoryBuffer> Buffer;
std::unique_ptr<BitstreamReader> StreamFile;
BitstreamBlockInfo BlockInfo;
BitstreamCursor Stream;
std::error_code initStream();
@ -256,8 +256,8 @@ std::error_code BitcodeReaderBase::initStream() {
if (SkipBitcodeWrapperHeader(BufPtr, BufEnd, true))
return error("Invalid bitcode wrapper header");
StreamFile.reset(new BitstreamReader(ArrayRef<uint8_t>(BufPtr, BufEnd)));
Stream.init(&*StreamFile);
Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, BufEnd));
Stream.setBlockInfo(&BlockInfo);
return std::error_code();
}
@ -2211,8 +2211,7 @@ std::error_code BitcodeReader::parseMetadataStrings(ArrayRef<uint64_t> Record,
return error("Invalid record: metadata strings corrupt offset");
StringRef Lengths = Blob.slice(0, StringsOffset);
SimpleBitstreamCursor R(*StreamFile);
R.jumpToPointer(Lengths.begin());
SimpleBitstreamCursor R(Lengths);
StringRef Strings = Blob.drop_front(StringsOffset);
do {
@ -3759,9 +3758,12 @@ std::error_code BitcodeReader::parseBitcodeVersion() {
}
}
bool BitcodeReaderBase::readBlockInfo() {
return Stream.ReadBlockInfoBlock();
Optional<BitstreamBlockInfo> NewBlockInfo = Stream.ReadBlockInfoBlock();
if (!NewBlockInfo)
return true;
BlockInfo = std::move(*NewBlockInfo);
return false;
}
std::error_code BitcodeReader::parseModule(uint64_t ResumeBit,

View File

@ -18,14 +18,6 @@ using namespace llvm;
// BitstreamCursor implementation
//===----------------------------------------------------------------------===//
void BitstreamCursor::freeState() {
// Free all the Abbrevs.
CurAbbrevs.clear();
// Free all the Abbrevs in the block scope.
BlockScope.clear();
}
/// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
/// the block, and return true if the block has an error.
bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
@ -34,10 +26,12 @@ bool BitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
// Add the abbrevs specific to this block to the CurAbbrevs list.
if (const BitstreamReader::BlockInfo *Info =
getBitStreamReader()->getBlockInfo(BlockID)) {
CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
Info->Abbrevs.end());
if (BlockInfo) {
if (const BitstreamBlockInfo::BlockInfo *Info =
BlockInfo->getBlockInfo(BlockID)) {
CurAbbrevs.insert(CurAbbrevs.end(), Info->Abbrevs.begin(),
Info->Abbrevs.end());
}
}
// Get the codesize of this block.
@ -318,15 +312,14 @@ void BitstreamCursor::ReadAbbrevRecord() {
CurAbbrevs.push_back(Abbv);
}
bool BitstreamCursor::ReadBlockInfoBlock() {
// We expect the client to read the block info block at most once.
if (getBitStreamReader()->hasBlockInfoRecords())
report_fatal_error("Duplicate read of block info block");
Optional<BitstreamBlockInfo>
BitstreamCursor::ReadBlockInfoBlock(bool ReadBlockInfoNames) {
if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return None;
if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true;
BitstreamBlockInfo NewBlockInfo;
SmallVector<uint64_t, 64> Record;
BitstreamReader::BlockInfo *CurBlockInfo = nullptr;
BitstreamBlockInfo::BlockInfo *CurBlockInfo = nullptr;
// Read all the records for this module.
while (true) {
@ -335,9 +328,9 @@ bool BitstreamCursor::ReadBlockInfoBlock() {
switch (Entry.Kind) {
case llvm::BitstreamEntry::SubBlock: // Handled for us already.
case llvm::BitstreamEntry::Error:
return true;
return None;
case llvm::BitstreamEntry::EndBlock:
return false;
return std::move(NewBlockInfo);
case llvm::BitstreamEntry::Record:
// The interesting case.
break;
@ -345,7 +338,7 @@ bool BitstreamCursor::ReadBlockInfoBlock() {
// Read abbrev records, associate them with CurBID.
if (Entry.ID == bitc::DEFINE_ABBREV) {
if (!CurBlockInfo) return true;
if (!CurBlockInfo) return None;
ReadAbbrevRecord();
// ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the
@ -360,13 +353,12 @@ bool BitstreamCursor::ReadBlockInfoBlock() {
switch (readRecord(Entry.ID, Record)) {
default: break; // Default behavior, ignore unknown content.
case bitc::BLOCKINFO_CODE_SETBID:
if (Record.size() < 1) return true;
CurBlockInfo =
&getBitStreamReader()->getOrCreateBlockInfo((unsigned)Record[0]);
if (Record.size() < 1) return None;
CurBlockInfo = &NewBlockInfo.getOrCreateBlockInfo((unsigned)Record[0]);
break;
case bitc::BLOCKINFO_CODE_BLOCKNAME: {
if (!CurBlockInfo) return true;
if (getBitStreamReader()->isIgnoringBlockInfoNames())
if (!CurBlockInfo) return None;
if (!ReadBlockInfoNames)
break; // Ignore name.
std::string Name;
for (unsigned i = 0, e = Record.size(); i != e; ++i)
@ -375,8 +367,8 @@ bool BitstreamCursor::ReadBlockInfoBlock() {
break;
}
case bitc::BLOCKINFO_CODE_SETRECORDNAME: {
if (!CurBlockInfo) return true;
if (getBitStreamReader()->isIgnoringBlockInfoNames())
if (!CurBlockInfo) return None;
if (!ReadBlockInfoNames)
break; // Ignore name.
std::string Name;
for (unsigned i = 1, e = Record.size(); i != e; ++i)

View File

@ -84,7 +84,7 @@ enum CurStreamTypeType {
/// GetBlockName - Return a symbolic block name if known, otherwise return
/// null.
static const char *GetBlockName(unsigned BlockID,
const BitstreamReader &StreamFile,
const BitstreamBlockInfo &BlockInfo,
CurStreamTypeType CurStreamType) {
// Standard blocks for all bitcode files.
if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
@ -94,8 +94,8 @@ static const char *GetBlockName(unsigned BlockID,
}
// Check to see if we have a blockinfo record for this block, with a name.
if (const BitstreamReader::BlockInfo *Info =
StreamFile.getBlockInfo(BlockID)) {
if (const BitstreamBlockInfo::BlockInfo *Info =
BlockInfo.getBlockInfo(BlockID)) {
if (!Info->Name.empty())
return Info->Name.c_str();
}
@ -128,7 +128,7 @@ static const char *GetBlockName(unsigned BlockID,
/// GetCodeName - Return a symbolic code name if known, otherwise return
/// null.
static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
const BitstreamReader &StreamFile,
const BitstreamBlockInfo &BlockInfo,
CurStreamTypeType CurStreamType) {
// Standard blocks for all bitcode files.
if (BlockID < bitc::FIRST_APPLICATION_BLOCKID) {
@ -144,8 +144,8 @@ static const char *GetCodeName(unsigned CodeID, unsigned BlockID,
}
// Check to see if we have a blockinfo record for this record, with a name.
if (const BitstreamReader::BlockInfo *Info =
StreamFile.getBlockInfo(BlockID)) {
if (const BitstreamBlockInfo::BlockInfo *Info =
BlockInfo.getBlockInfo(BlockID)) {
for (unsigned i = 0, e = Info->RecordNames.size(); i != e; ++i)
if (Info->RecordNames[i].first == CodeID)
return Info->RecordNames[i].second.c_str();
@ -419,7 +419,7 @@ static bool ReportError(const Twine &Err) {
return true;
}
static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent,
static bool decodeMetadataStringsBlob(StringRef Indent,
ArrayRef<uint64_t> Record,
StringRef Blob) {
if (Blob.empty())
@ -433,9 +433,7 @@ static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent,
outs() << " num-strings = " << NumStrings << " {\n";
StringRef Lengths = Blob.slice(0, StringsOffset);
SimpleBitstreamCursor R(Reader);
R.jumpToPointer(Lengths.begin());
SimpleBitstreamCursor R(Lengths);
StringRef Strings = Blob.drop_front(StringsOffset);
do {
if (R.AtEndOfStream())
@ -455,20 +453,20 @@ static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent,
return false;
}
static bool decodeBlob(unsigned Code, unsigned BlockID, BitstreamReader &Reader,
StringRef Indent, ArrayRef<uint64_t> Record,
StringRef Blob) {
static bool decodeBlob(unsigned Code, unsigned BlockID, StringRef Indent,
ArrayRef<uint64_t> Record, StringRef Blob) {
if (BlockID != bitc::METADATA_BLOCK_ID)
return true;
if (Code != bitc::METADATA_STRINGS)
return true;
return decodeMetadataStringsBlob(Reader, Indent, Record, Blob);
return decodeMetadataStringsBlob(Indent, Record, Blob);
}
/// ParseBlock - Read a block, updating statistics, etc.
static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
unsigned IndentLevel, CurStreamTypeType CurStreamType) {
static bool ParseBlock(BitstreamCursor &Stream, BitstreamBlockInfo &BlockInfo,
unsigned BlockID, unsigned IndentLevel,
CurStreamTypeType CurStreamType) {
std::string Indent(IndentLevel*2, ' ');
uint64_t BlockBitStart = Stream.GetCurrentBitNo();
@ -481,8 +479,12 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
bool DumpRecords = Dump;
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
if (Dump) outs() << Indent << "<BLOCKINFO_BLOCK/>\n";
if (BitstreamCursor(Stream).ReadBlockInfoBlock())
Optional<BitstreamBlockInfo> NewBlockInfo =
Stream.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
if (!NewBlockInfo)
return ReportError("Malformed BlockInfoBlock");
BlockInfo = std::move(*NewBlockInfo);
Stream.JumpToBit(BlockBitStart);
// It's not really interesting to dump the contents of the blockinfo block.
DumpRecords = false;
}
@ -497,8 +499,7 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
const char *BlockName = nullptr;
if (DumpRecords) {
outs() << Indent << "<";
if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader(),
CurStreamType)))
if ((BlockName = GetBlockName(BlockID, BlockInfo, CurStreamType)))
outs() << BlockName;
else
outs() << "UnknownBlock" << BlockID;
@ -540,7 +541,8 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
case BitstreamEntry::SubBlock: {
uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
if (ParseBlock(Stream, Entry.ID, IndentLevel+1, CurStreamType))
if (ParseBlock(Stream, BlockInfo, Entry.ID, IndentLevel + 1,
CurStreamType))
return true;
++BlockStats.NumSubBlocks;
uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
@ -582,14 +584,11 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
if (DumpRecords) {
outs() << Indent << " <";
if (const char *CodeName =
GetCodeName(Code, BlockID, *Stream.getBitStreamReader(),
CurStreamType))
GetCodeName(Code, BlockID, BlockInfo, CurStreamType))
outs() << CodeName;
else
outs() << "UnknownCode" << Code;
if (NonSymbolic &&
GetCodeName(Code, BlockID, *Stream.getBitStreamReader(),
CurStreamType))
if (NonSymbolic && GetCodeName(Code, BlockID, BlockInfo, CurStreamType))
outs() << " codeid=" << Code;
const BitCodeAbbrev *Abbv = nullptr;
if (Entry.ID != bitc::UNABBREV_RECORD) {
@ -654,8 +653,7 @@ static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID,
}
}
if (Blob.data() && decodeBlob(Code, BlockID, *Stream.getBitStreamReader(),
Indent, Record, Blob)) {
if (Blob.data() && decodeBlob(Code, BlockID, Indent, Record, Blob)) {
outs() << " blob data = ";
if (ShowBinaryBlobs) {
outs() << "'";
@ -690,7 +688,6 @@ static void PrintSize(uint64_t Bits) {
static bool openBitcodeFile(StringRef Path,
std::unique_ptr<MemoryBuffer> &MemBuf,
BitstreamReader &StreamFile,
BitstreamCursor &Stream,
CurStreamTypeType &CurStreamType) {
// Read the input file.
@ -731,9 +728,7 @@ static bool openBitcodeFile(StringRef Path,
return ReportError("Invalid bitcode wrapper header");
}
StreamFile = BitstreamReader(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
Stream = BitstreamCursor(StreamFile);
StreamFile.CollectBlockInfoNames();
Stream = BitstreamCursor(ArrayRef<uint8_t>(BufPtr, EndBufPtr));
// Read the stream signature.
char Signature[6];
@ -757,22 +752,21 @@ static bool openBitcodeFile(StringRef Path,
/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
static int AnalyzeBitcode() {
std::unique_ptr<MemoryBuffer> StreamBuffer;
BitstreamReader StreamFile;
BitstreamCursor Stream;
BitstreamBlockInfo BlockInfo;
CurStreamTypeType CurStreamType;
if (openBitcodeFile(InputFilename, StreamBuffer, StreamFile, Stream,
CurStreamType))
if (openBitcodeFile(InputFilename, StreamBuffer, Stream, CurStreamType))
return true;
Stream.setBlockInfo(&BlockInfo);
// Read block info from BlockInfoFilename, if specified.
// The block info must be a top-level block.
if (!BlockInfoFilename.empty()) {
std::unique_ptr<MemoryBuffer> BlockInfoBuffer;
BitstreamReader BlockInfoFile;
BitstreamCursor BlockInfoCursor;
CurStreamTypeType BlockInfoStreamType;
if (openBitcodeFile(BlockInfoFilename, BlockInfoBuffer, BlockInfoFile,
BlockInfoCursor, BlockInfoStreamType))
if (openBitcodeFile(BlockInfoFilename, BlockInfoBuffer, BlockInfoCursor,
BlockInfoStreamType))
return true;
while (!BlockInfoCursor.AtEndOfStream()) {
@ -782,15 +776,16 @@ static int AnalyzeBitcode() {
unsigned BlockID = BlockInfoCursor.ReadSubBlockID();
if (BlockID == bitc::BLOCKINFO_BLOCK_ID) {
if (BlockInfoCursor.ReadBlockInfoBlock())
Optional<BitstreamBlockInfo> NewBlockInfo =
BlockInfoCursor.ReadBlockInfoBlock(/*ReadBlockInfoNames=*/true);
if (!NewBlockInfo)
return ReportError("Malformed BlockInfoBlock in block info file");
BlockInfo = std::move(*NewBlockInfo);
break;
}
BlockInfoCursor.SkipBlock();
}
StreamFile.takeBlockInfo(std::move(BlockInfoFile));
}
unsigned NumTopBlocks = 0;
@ -803,14 +798,14 @@ static int AnalyzeBitcode() {
unsigned BlockID = Stream.ReadSubBlockID();
if (ParseBlock(Stream, BlockID, 0, CurStreamType))
if (ParseBlock(Stream, BlockInfo, BlockID, 0, CurStreamType))
return true;
++NumTopBlocks;
}
if (Dump) outs() << "\n\n";
uint64_t BufferSizeBits = StreamFile.getBitcodeBytes().size() * CHAR_BIT;
uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT;
// Print a summary of the read file.
outs() << "Summary of " << InputFilename << ":\n";
outs() << " Total size: ";
@ -829,8 +824,8 @@ static int AnalyzeBitcode() {
for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
E = BlockIDStats.end(); I != E; ++I) {
outs() << " Block ID #" << I->first;
if (const char *BlockName = GetBlockName(I->first, StreamFile,
CurStreamType))
if (const char *BlockName =
GetBlockName(I->first, BlockInfo, CurStreamType))
outs() << " (" << BlockName << ")";
outs() << ":\n";
@ -894,9 +889,8 @@ static int AnalyzeBitcode() {
outs() << " ";
outs() << " ";
if (const char *CodeName =
GetCodeName(FreqPairs[i].second, I->first, StreamFile,
CurStreamType))
if (const char *CodeName = GetCodeName(FreqPairs[i].second, I->first,
BlockInfo, CurStreamType))
outs() << CodeName << "\n";
else
outs() << "UnknownCode" << FreqPairs[i].second << "\n";

View File

@ -20,8 +20,7 @@ TEST(BitstreamReaderTest, AtEndOfStream) {
uint8_t Bytes[4] = {
0x00, 0x01, 0x02, 0x03
};
BitstreamReader Reader(Bytes);
BitstreamCursor Cursor(Reader);
BitstreamCursor Cursor(Bytes);
EXPECT_FALSE(Cursor.AtEndOfStream());
(void)Cursor.Read(8);
@ -40,24 +39,21 @@ TEST(BitstreamReaderTest, AtEndOfStreamJump) {
uint8_t Bytes[4] = {
0x00, 0x01, 0x02, 0x03
};
BitstreamReader Reader(Bytes);
BitstreamCursor Cursor(Reader);
BitstreamCursor Cursor(Bytes);
Cursor.JumpToBit(32);
EXPECT_TRUE(Cursor.AtEndOfStream());
}
TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
BitstreamReader Reader(ArrayRef<uint8_t>{});
BitstreamCursor Cursor(Reader);
BitstreamCursor Cursor(ArrayRef<uint8_t>{});
EXPECT_TRUE(Cursor.AtEndOfStream());
}
TEST(BitstreamReaderTest, getCurrentByteNo) {
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03};
BitstreamReader Reader(Bytes);
SimpleBitstreamCursor Cursor(Reader);
SimpleBitstreamCursor Cursor(Bytes);
for (unsigned I = 0, E = 32; I != E; ++I) {
EXPECT_EQ(I / 8, Cursor.getCurrentByteNo());
@ -68,8 +64,7 @@ TEST(BitstreamReaderTest, getCurrentByteNo) {
TEST(BitstreamReaderTest, getPointerToByte) {
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
BitstreamReader Reader(Bytes);
SimpleBitstreamCursor Cursor(Reader);
SimpleBitstreamCursor Cursor(Bytes);
for (unsigned I = 0, E = 8; I != E; ++I) {
EXPECT_EQ(Bytes + I, Cursor.getPointerToByte(I, 1));
@ -78,25 +73,13 @@ TEST(BitstreamReaderTest, getPointerToByte) {
TEST(BitstreamReaderTest, getPointerToBit) {
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
BitstreamReader Reader(Bytes);
SimpleBitstreamCursor Cursor(Reader);
SimpleBitstreamCursor Cursor(Bytes);
for (unsigned I = 0, E = 8; I != E; ++I) {
EXPECT_EQ(Bytes + I, Cursor.getPointerToBit(I * 8, 1));
}
}
TEST(BitstreamReaderTest, jumpToPointer) {
uint8_t Bytes[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
BitstreamReader Reader(Bytes);
SimpleBitstreamCursor Cursor(Reader);
for (unsigned I : {0, 6, 2, 7}) {
Cursor.jumpToPointer(Bytes + I);
EXPECT_EQ(I, Cursor.getCurrentByteNo());
}
}
TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
SmallVector<uint8_t, 1> BlobData;
for (unsigned I = 0, E = 1024; I != E; ++I)
@ -129,9 +112,8 @@ TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
}
// Stream the buffer into the reader.
BitstreamReader R(
BitstreamCursor Stream(
ArrayRef<uint8_t>((const uint8_t *)Buffer.begin(), Buffer.size()));
BitstreamCursor Stream(R);
// Header. Included in test so that we can run llvm-bcanalyzer to debug
// when there are problems.
@ -161,8 +143,7 @@ TEST(BitstreamReaderTest, readRecordWithBlobWhileStreaming) {
TEST(BitstreamReaderTest, shortRead) {
uint8_t Bytes[] = {8, 7, 6, 5, 4, 3, 2, 1};
for (unsigned I = 1; I != 8; ++I) {
BitstreamReader Reader(ArrayRef<uint8_t>(Bytes, I));
SimpleBitstreamCursor Cursor(Reader);
SimpleBitstreamCursor Cursor(ArrayRef<uint8_t>(Bytes, I));
EXPECT_EQ(8ull, Cursor.Read(8));
}
}