mirror of
https://github.com/RPCSX/llvm.git
synced 2025-03-01 01:15:55 +00:00
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:
parent
ef0facce3e
commit
8fc9b4d314
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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";
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user