class ObjectFilePCHContainerReader : public PCHContainerReader {
StringRef getFormat() const override { return "obj"; }
- /// Initialize an llvm::BitstreamReader with the serialized
- /// AST inside the PCH container Buffer.
- void ExtractPCH(llvm::MemoryBufferRef Buffer,
- llvm::BitstreamReader &StreamFile) const override;
+ /// Returns the serialized AST inside the PCH container Buffer.
+ StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;
};
}
namespace llvm {
class raw_pwrite_stream;
-class BitstreamReader;
}
using llvm::StringRef;
/// Equivalent to the format passed to -fmodule-format=
virtual StringRef getFormat() const = 0;
- /// Initialize an llvm::BitstreamReader with the serialized AST inside
- /// the PCH container Buffer.
- virtual void ExtractPCH(llvm::MemoryBufferRef Buffer,
- llvm::BitstreamReader &StreamFile) const = 0;
+ /// Returns the serialized AST inside the PCH container Buffer.
+ virtual StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const = 0;
};
/// Implements write operations for a raw pass-through PCH container.
class RawPCHContainerReader : public PCHContainerReader {
StringRef getFormat() const override { return "raw"; }
- /// Initialize an llvm::BitstreamReader with Buffer.
- void ExtractPCH(llvm::MemoryBufferRef Buffer,
- llvm::BitstreamReader &StreamFile) const override;
+ /// Simply returns the buffer contained in Buffer.
+ StringRef ExtractPCH(llvm::MemoryBufferRef Buffer) const override;
};
/// A registry of PCHContainerWriter and -Reader objects for different formats.
/// \brief The global bit offset (or base) of this module
uint64_t GlobalBitOffset;
- /// \brief The bitstream reader from which we'll read the AST file.
- llvm::BitstreamReader StreamFile;
+ /// \brief The serialized bitstream data for this file.
+ StringRef Data;
/// \brief The main bitstream cursor for the main block.
llvm::BitstreamCursor Stream;
OutOfDate
};
- typedef ASTFileSignature(*ASTFileSignatureReader)(llvm::BitstreamReader &);
+ typedef ASTFileSignature(*ASTFileSignatureReader)(StringRef);
/// \brief Attempts to create a new module and add it to the list of known
/// modules.
CI, MainFileName, OutputFileName, std::move(OS), Buffer);
}
-void ObjectFilePCHContainerReader::ExtractPCH(
- llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const {
+StringRef
+ObjectFilePCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const {
+ StringRef PCH;
auto OFOrErr = llvm::object::ObjectFile::createObjectFile(Buffer);
if (OFOrErr) {
auto &OF = OFOrErr.get();
StringRef Name;
Section.getName(Name);
if ((!IsCOFF && Name == "__clangast") || (IsCOFF && Name == "clangast")) {
- StringRef Buf;
- Section.getContents(Buf);
- StreamFile = llvm::BitstreamReader(Buf);
- return;
+ Section.getContents(PCH);
+ return PCH;
}
}
}
if (EIB.convertToErrorCode() ==
llvm::object::object_error::invalid_file_type)
// As a fallback, treat the buffer as a raw AST.
- StreamFile = llvm::BitstreamReader(Buffer);
+ PCH = Buffer.getBuffer();
else
EIB.log(llvm::errs());
});
+ return PCH;
}
return llvm::make_unique<RawPCHContainerGenerator>(std::move(OS), Buffer);
}
-void RawPCHContainerReader::ExtractPCH(
- llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const {
- StreamFile = llvm::BitstreamReader(Buffer);
+StringRef
+RawPCHContainerReader::ExtractPCH(llvm::MemoryBufferRef Buffer) const {
+ return Buffer.getBuffer();
}
PCHContainerOperations::PCHContainerOperations() {
if (!Buffer)
return SDError::CouldNotLoad;
- llvm::BitstreamReader StreamFile(**Buffer);
- llvm::BitstreamCursor Stream(StreamFile);
+ llvm::BitstreamCursor Stream(**Buffer);
+ Optional<llvm::BitstreamBlockInfo> BlockInfo;
// Sniff for the signature.
if (Stream.Read(8) != 'D' ||
std::error_code EC;
switch (Stream.ReadSubBlockID()) {
- case llvm::bitc::BLOCKINFO_BLOCK_ID:
- if (Stream.ReadBlockInfoBlock())
+ case llvm::bitc::BLOCKINFO_BLOCK_ID: {
+ BlockInfo = Stream.ReadBlockInfoBlock();
+ if (!BlockInfo)
return SDError::MalformedBlockInfoBlock;
+ Stream.setBlockInfo(&*BlockInfo);
continue;
+ }
case BLOCK_META:
if ((EC = readMetaBlock(Stream)))
return EC;
BitstreamCursor &MacroCursor = I->MacroCursor;
// If there was no preprocessor block, skip this file.
- if (!MacroCursor.getBitStreamReader())
+ if (MacroCursor.getBitcodeBytes().empty())
continue;
BitstreamCursor Cursor = MacroCursor;
return Success;
}
-static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile);
+static ASTFileSignature readASTFileSignature(StringRef PCH);
/// \brief Whether \p Stream starts with the AST/PCH file magic number 'CPCH'.
static bool startsWithASTFileMagic(BitstreamCursor &Stream) {
ModuleFile &F = *M;
BitstreamCursor &Stream = F.Stream;
- PCHContainerRdr.ExtractPCH(F.Buffer->getMemBufferRef(), F.StreamFile);
- Stream.init(&F.StreamFile);
+ Stream = BitstreamCursor(PCHContainerRdr.ExtractPCH(*F.Buffer));
F.SizeInBits = F.Buffer->getBufferSize() * 8;
// Sniff for the signature.
// Nothing to do for now.
}
-/// \brief Reads and return the signature record from \p StreamFile's control
-/// block, or else returns 0.
-static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){
- BitstreamCursor Stream(StreamFile);
+/// \brief Reads and return the signature record from \p PCH's control block, or
+/// else returns 0.
+static ASTFileSignature readASTFileSignature(StringRef PCH) {
+ BitstreamCursor Stream(PCH);
if (!startsWithASTFileMagic(Stream))
return 0;
}
// Initialize the stream
- llvm::BitstreamReader StreamFile;
- PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile);
- BitstreamCursor Stream(StreamFile);
+ BitstreamCursor Stream(PCHContainerRdr.ExtractPCH(**Buffer));
// Sniff for the signature.
if (!startsWithASTFileMagic(Stream)) {
}
// Initialize the stream
- llvm::BitstreamReader StreamFile;
- PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile);
- BitstreamCursor Stream(StreamFile);
+ BitstreamCursor Stream(PCHContainerRdr.ExtractPCH(**Buffer));
// Sniff for the signature.
if (!startsWithASTFileMagic(Stream))
return std::make_pair(nullptr, EC_NotFound);
std::unique_ptr<llvm::MemoryBuffer> Buffer = std::move(BufferOrErr.get());
- /// \brief The bitstream reader from which we'll read the AST file.
- llvm::BitstreamReader Reader(*Buffer);
-
/// \brief The main bitstream cursor for the main block.
- llvm::BitstreamCursor Cursor(Reader);
+ llvm::BitstreamCursor Cursor(*Buffer);
// Sniff for the signature.
if (Cursor.Read(8) != 'B' ||
}
// Initialize the input stream
- llvm::BitstreamReader InStreamFile;
- PCHContainerRdr.ExtractPCH((*Buffer)->getMemBufferRef(), InStreamFile);
- llvm::BitstreamCursor InStream(InStreamFile);
+ llvm::BitstreamCursor InStream(PCHContainerRdr.ExtractPCH(**Buffer));
// Sniff for the signature.
if (InStream.Read(8) != 'C' ||
}
// Initialize the stream.
- PCHContainerRdr.ExtractPCH(ModuleEntry->Buffer->getMemBufferRef(),
- ModuleEntry->StreamFile);
+ ModuleEntry->Data = PCHContainerRdr.ExtractPCH(*ModuleEntry->Buffer);
}
if (ExpectedSignature) {
// If we've not read the control block yet, read the signature eagerly now
// so that we can check it.
if (!ModuleEntry->Signature)
- ModuleEntry->Signature = ReadSignature(ModuleEntry->StreamFile);
+ ModuleEntry->Signature = ReadSignature(ModuleEntry->Data);
if (ModuleEntry->Signature != ExpectedSignature) {
ErrorStr = ModuleEntry->Signature ? "signature mismatch"
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.
};
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 {
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:
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.
// 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) {
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.
}
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);
}
/// 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
/// 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;
//===--------------------------------------------------------------------===//
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
BitcodeReaderBase(MemoryBuffer *Buffer) : Buffer(Buffer) {}
std::unique_ptr<MemoryBuffer> Buffer;
- std::unique_ptr<BitstreamReader> StreamFile;
+ BitstreamBlockInfo BlockInfo;
BitstreamCursor Stream;
std::error_code 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();
}
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 {
}
}
-
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,
// 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) {
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.
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) {
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;
// 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
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)
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)
/// 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) {
}
// 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();
}
/// 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) {
}
// 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();
return true;
}
-static bool decodeMetadataStringsBlob(BitstreamReader &Reader, StringRef Indent,
+static bool decodeMetadataStringsBlob(StringRef Indent,
ArrayRef<uint64_t> Record,
StringRef Blob) {
if (Blob.empty())
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())
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();
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;
}
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;
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();
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) {
}
}
- 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() << "'";
static bool openBitcodeFile(StringRef Path,
std::unique_ptr<MemoryBuffer> &MemBuf,
- BitstreamReader &StreamFile,
BitstreamCursor &Stream,
CurStreamTypeType &CurStreamType) {
// Read the input file.
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];
/// 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()) {
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;
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: ";
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";
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";
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);
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());
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));
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)
}
// 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.
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));
}
}