Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(17)

Unified Diff: include/llvm/Bitcode/NaCl/NaClBitstreamReader.h

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « include/llvm/Bitcode/NaCl/NaClBitcodeWriterPass.h ('k') | include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: include/llvm/Bitcode/NaCl/NaClBitstreamReader.h
diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h
similarity index 57%
copy from include/llvm/Bitcode/BitstreamReader.h
copy to include/llvm/Bitcode/NaCl/NaClBitstreamReader.h
index ecf82352779e2037c5574dabf94de83a1bba2b7f..dd53fd041db0a648068125fc3bd875f87a333835 100644
--- a/include/llvm/Bitcode/BitstreamReader.h
+++ b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h
@@ -1,4 +1,5 @@
-//===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===//
+//===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===//
+// Low-level bitstream reader interface
//
// The LLVM Compiler Infrastructure
//
@@ -12,69 +13,55 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_BITCODE_BITSTREAMREADER_H
-#define LLVM_BITCODE_BITSTREAMREADER_H
+#ifndef LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H
+#define LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H
-#include "llvm/Bitcode/BitCodes.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/StreamingMemoryObject.h"
#include <climits>
-#include <string>
#include <vector>
namespace llvm {
class Deserializer;
-/// 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 is used to read from a NaCl bitcode wire format 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 NaClBitstreamCursor class.
+class NaClBitstreamReader {
public:
/// This contains information emitted to BLOCKINFO_BLOCK blocks. These
/// describe abbreviations that all blocks of the specified ID inherit.
struct BlockInfo {
unsigned BlockID;
- std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs;
- std::string Name;
-
- std::vector<std::pair<unsigned, std::string> > RecordNames;
+ std::vector<NaClBitCodeAbbrev*> Abbrevs;
};
private:
std::unique_ptr<MemoryObject> 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;
+ /// \brief Holds the offset of the first byte after the header.
+ size_t InitialAddress;
- BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION;
- void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION;
+ NaClBitstreamReader(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION;
+ void operator=(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION;
public:
- BitstreamReader() : IgnoreBlockInfoNames(true) {
- }
+ NaClBitstreamReader() : InitialAddress(0) {}
- BitstreamReader(const unsigned char *Start, const unsigned char *End)
- : IgnoreBlockInfoNames(true) {
+ NaClBitstreamReader(const unsigned char *Start, const unsigned char *End,
+ size_t MyInitialAddress=0) {
+ InitialAddress = MyInitialAddress;
init(Start, End);
}
- BitstreamReader(MemoryObject *bytes) : IgnoreBlockInfoNames(true) {
- BitcodeBytes.reset(bytes);
- }
-
- BitstreamReader(BitstreamReader &&Other) {
- *this = std::move(Other);
- }
-
- BitstreamReader &operator=(BitstreamReader &&Other) {
- BitcodeBytes = std::move(Other.BitcodeBytes);
- // Explicitly swap block info, so that nothing gets destroyed twice.
- std::swap(BlockInfoRecords, Other.BlockInfoRecords);
- IgnoreBlockInfoNames = Other.IgnoreBlockInfoNames;
- return *this;
+ NaClBitstreamReader(MemoryObject *Bytes, size_t MyInitialAddress=0)
+ : InitialAddress(MyInitialAddress) {
+ BitcodeBytes.reset(Bytes);
}
void init(const unsigned char *Start, const unsigned char *End) {
@@ -84,9 +71,22 @@ public:
MemoryObject &getBitcodeBytes() { return *BitcodeBytes; }
- /// This is called by clients that want block/record name information.
- void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; }
- bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; }
+ ~NaClBitstreamReader() {
+ // Free the BlockInfoRecords.
+ while (!BlockInfoRecords.empty()) {
+ BlockInfo &Info = BlockInfoRecords.back();
+ // Free blockinfo abbrev info.
+ for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size());
+ i != e; ++i)
+ Info.Abbrevs[i]->dropRef();
+ BlockInfoRecords.pop_back();
+ }
+ }
+
+ /// \brief Returns the initial address (after the header) of the input stream.
+ size_t getInitialAddress() const {
+ return InitialAddress;
+ }
//===--------------------------------------------------------------------===//
// Block Manipulation
@@ -120,20 +120,11 @@ 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);
- }
};
/// When advancing through a bitstream cursor, each advance can discover a few
/// different kinds of entries:
-struct BitstreamEntry {
+struct NaClBitstreamEntry {
enum {
Error, // Malformed bitcode was found.
EndBlock, // We've reached the end of the current block, (or the end of the
@@ -144,32 +135,77 @@ struct BitstreamEntry {
unsigned ID;
- static BitstreamEntry getError() {
- BitstreamEntry E; E.Kind = Error; return E;
+ static NaClBitstreamEntry getError() {
+ NaClBitstreamEntry E; E.Kind = Error; return E;
}
- static BitstreamEntry getEndBlock() {
- BitstreamEntry E; E.Kind = EndBlock; return E;
+ static NaClBitstreamEntry getEndBlock() {
+ NaClBitstreamEntry E; E.Kind = EndBlock; return E;
}
- static BitstreamEntry getSubBlock(unsigned ID) {
- BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
+ static NaClBitstreamEntry getSubBlock(unsigned ID) {
+ NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
}
- static BitstreamEntry getRecord(unsigned AbbrevID) {
- BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
+ static NaClBitstreamEntry getRecord(unsigned AbbrevID) {
+ NaClBitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
}
};
+/// Models default view of a bitcode record.
+typedef SmallVector<uint64_t, 8> NaClBitcodeRecordVector;
+
+/// Class NaClAbbrevListener is used to allow instances of class
+/// NaClBitcodeParser to listen to record details when processing
+/// abbreviations. The major reason for using a listener is that the
+/// NaCl bitcode reader would require a major rewrite (including the
+/// introduction of more overhead) if we were to lift abbreviations up
+/// to the bitcode reader. That is, not only would we have to lift the
+/// block processing up into the readers (i.e. many blocks in
+/// NaClBitcodeReader and NaClBitcodeParser), but add many new API's
+/// to allow the readers to update internals of the bit stream reader
+/// appropriately.
+class NaClAbbrevListener {
+ NaClAbbrevListener(const NaClAbbrevListener&) LLVM_DELETED_FUNCTION;
+ void operator=(const NaClAbbrevListener&) LLVM_DELETED_FUNCTION;
+public:
+ NaClAbbrevListener() {}
+ virtual ~NaClAbbrevListener() {}
+
+ /// Called to process the read abbreviation.
+ virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev,
+ bool IsLocal) = 0;
+
+ /// Called after entering block. NumWords is the number of words
+ /// in the block.
+ virtual void BeginBlockInfoBlock(unsigned NumWords) = 0;
+
+ /// Called if a naclbitc::BLOCKINFO_CODE_SETBID record is found in
+ /// NaClBitstreamCursor::ReadBlockInfoBlock.
+ virtual void SetBID() = 0;
+
+ /// Called just before an EndBlock record is processed by
+ /// NaClBitstreamCursor::ReadBlockInfoBlock
+ virtual void EndBlockInfoBlock() = 0;
+
+ /// The values of the bitcode record associated with the called
+ /// virtual function.
+ NaClBitcodeRecordVector Values;
+
+ /// Start bit for current record being processed in
+ /// NaClBitstreamCursor::ReadBlockInfoBlock.
+ uint64_t StartBit;
+};
+
/// This represents a position within a bitcode file. There may be multiple
-/// independent cursors reading within one bitstream, each maintaining their own
-/// local state.
+/// independent cursors reading within one bitstream, each maintaining their
+/// own local state.
///
-/// Unlike iterators, BitstreamCursors are heavy-weight objects that should not
-/// be passed by value.
-class BitstreamCursor {
+/// Unlike iterators, NaClBitstreamCursors are heavy-weight objects
+/// that should not be passed by value.
+class NaClBitstreamCursor {
friend class Deserializer;
- BitstreamReader *BitStream;
+ NaClBitstreamReader *BitStream;
size_t NextChar;
- // The size of the bicode. 0 if we don't know it yet.
+ // The size of the bitcode. 0 if we don't know it yet.
size_t Size;
/// This is the current data we have pulled from the stream but have not
@@ -180,40 +216,46 @@ class BitstreamCursor {
typedef size_t word_t;
word_t CurWord;
- /// This is the number of bits in CurWord that are valid. This is always from
- /// [0...bits_of(size_t)-1] inclusive.
+ /// This is the number of bits in CurWord that are valid. This
+ /// is always from [0...bits_of(word_t)-1] inclusive.
unsigned BitsInCurWord;
- // This is the declared size of code values used for the current block, in
- // bits.
- unsigned CurCodeSize;
+ /// This is the declared size of code values used for the current
+ /// block, in bits.
+ NaClBitcodeSelectorAbbrev CurCodeSize;
- /// Abbrevs installed at in this block.
- std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs;
+ /// Abbrevs installed in this block.
+ std::vector<NaClBitCodeAbbrev*> CurAbbrevs;
struct Block {
- unsigned PrevCodeSize;
- std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs;
- explicit Block(unsigned PCS) : PrevCodeSize(PCS) {}
+ NaClBitcodeSelectorAbbrev PrevCodeSize;
+ std::vector<NaClBitCodeAbbrev*> PrevAbbrevs;
+ Block() : PrevCodeSize() {}
+ explicit Block(const NaClBitcodeSelectorAbbrev& PCS)
+ : PrevCodeSize(PCS) {}
};
/// This tracks the codesize of parent blocks.
SmallVector<Block, 8> BlockScope;
+ NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION;
+ NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION;
public:
- BitstreamCursor() { init(nullptr); }
+ NaClBitstreamCursor() { init(nullptr); }
- explicit BitstreamCursor(BitstreamReader &R) { init(&R); }
+ explicit NaClBitstreamCursor(NaClBitstreamReader &R) { init(&R); }
- void init(BitstreamReader *R) {
+ void init(NaClBitstreamReader *R) {
freeState();
-
BitStream = R;
- NextChar = 0;
+ NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress();
Size = 0;
BitsInCurWord = 0;
- CurCodeSize = 2;
+ }
+
+ ~NaClBitstreamCursor() {
+ freeState();
}
void freeState();
@@ -234,17 +276,17 @@ public:
}
/// Return the number of bits used to encode an abbrev #.
- unsigned getAbbrevIDWidth() const { return CurCodeSize; }
+ unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; }
/// Return the bit # of the bit we are reading.
uint64_t GetCurrentBitNo() const {
return NextChar*CHAR_BIT - BitsInCurWord;
}
- BitstreamReader *getBitStreamReader() {
+ NaClBitstreamReader *getBitStreamReader() {
return BitStream;
}
- const BitstreamReader *getBitStreamReader() const {
+ const NaClBitstreamReader *getBitStreamReader() const {
return BitStream;
}
@@ -259,44 +301,45 @@ public:
AF_DontAutoprocessAbbrevs = 2
};
- /// Advance the current bitstream, returning the next entry in the stream.
- BitstreamEntry advance(unsigned Flags = 0) {
+ /// Advance the current bitstream, returning the next entry in the stream.
+ /// Use the given abbreviation listener (if provided).
+ NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) {
while (1) {
unsigned Code = ReadCode();
- if (Code == bitc::END_BLOCK) {
+ if (Code == naclbitc::END_BLOCK) {
// Pop the end of the block unless Flags tells us not to.
if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
- return BitstreamEntry::getError();
- return BitstreamEntry::getEndBlock();
+ return NaClBitstreamEntry::getError();
+ return NaClBitstreamEntry::getEndBlock();
}
- if (Code == bitc::ENTER_SUBBLOCK)
- return BitstreamEntry::getSubBlock(ReadSubBlockID());
+ if (Code == naclbitc::ENTER_SUBBLOCK)
+ return NaClBitstreamEntry::getSubBlock(ReadSubBlockID());
- if (Code == bitc::DEFINE_ABBREV &&
+ if (Code == naclbitc::DEFINE_ABBREV &&
!(Flags & AF_DontAutoprocessAbbrevs)) {
// We read and accumulate abbrev's, the client can't do anything with
// them anyway.
- ReadAbbrevRecord();
+ ReadAbbrevRecord(true, Listener);
continue;
}
- return BitstreamEntry::getRecord(Code);
+ return NaClBitstreamEntry::getRecord(Code);
}
}
/// This is a convenience function for clients that don't expect any
/// subblocks. This just skips over them automatically.
- BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
+ NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
while (1) {
// If we found a normal entry, return it.
- BitstreamEntry Entry = advance(Flags);
- if (Entry.Kind != BitstreamEntry::SubBlock)
+ NaClBitstreamEntry Entry = advance(Flags, 0);
+ if (Entry.Kind != NaClBitstreamEntry::SubBlock)
return Entry;
// If we found a sub-block, just skip over it and check the next entry.
if (SkipBlock())
- return BitstreamEntry::getError();
+ return NaClBitstreamEntry::getError();
}
}
@@ -431,16 +474,17 @@ private:
public:
unsigned ReadCode() {
- return Read(CurCodeSize);
+ return CurCodeSize.IsFixed
+ ? Read(CurCodeSize.NumBits)
+ : ReadVBR(CurCodeSize.NumBits);
}
-
// Block header:
// [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
/// Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
unsigned ReadSubBlockID() {
- return ReadVBR(bitc::BlockIDWidth);
+ return ReadVBR(naclbitc::BlockIDWidth);
}
/// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body
@@ -448,9 +492,9 @@ public:
bool SkipBlock() {
// Read and ignore the codelen value. Since we are skipping this block, we
// don't care what code widths are used inside of it.
- ReadVBR(bitc::CodeLenWidth);
+ ReadVBR(naclbitc::CodeLenWidth);
SkipToFourByteBoundary();
- unsigned NumFourBytes = Read(bitc::BlockSizeWidth);
+ unsigned NumFourBytes = Read(naclbitc::BlockSizeWidth);
// Check that the block wasn't partially defined, and that the offset isn't
// bogus.
@@ -482,7 +526,12 @@ private:
void popBlockScope() {
CurCodeSize = BlockScope.back().PrevCodeSize;
- CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs);
+ // Delete abbrevs from popped scope.
+ for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size());
+ i != e; ++i)
+ CurAbbrevs[i]->dropRef();
+
+ BlockScope.back().PrevAbbrevs.swap(CurAbbrevs);
BlockScope.pop_back();
}
@@ -490,27 +539,53 @@ private:
// Record Processing
//===--------------------------------------------------------------------===//
+private:
+ void skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op);
+
+ // Reads the next Value using the abbreviation Op. Returns true only
+ // if Op is an array (and sets Value to the number of elements in the
+ // array).
+ inline bool readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op,
+ uint64_t &Value);
+
+ // Reads and returns the next value using the abbreviation Op,
+ // assuming Op appears after an array abbreviation.
+ inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op);
+
+ // Reads the array abbreviation Op, NumArrayElements times, putting
+ // the read values in Vals.
+ inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op,
+ unsigned NumArrayElements,
+ SmallVectorImpl<uint64_t> &Vals);
+
public:
/// Return the abbreviation for the specified AbbrevId.
- const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) {
- unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV;
+ const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const {
+ unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV;
assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
- return CurAbbrevs[AbbrevNo].get();
+ return CurAbbrevs[AbbrevNo];
}
/// Read the current record and discard it.
void skipRecord(unsigned AbbrevID);
-
- unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals,
- StringRef *Blob = nullptr);
+
+ unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals);
//===--------------------------------------------------------------------===//
// Abbrev Processing
//===--------------------------------------------------------------------===//
- void ReadAbbrevRecord();
-
- bool ReadBlockInfoBlock();
+ // IsLocal indicates where the abbreviation occurs. If it is in the
+ // BlockInfo block, IsLocal is false. In all other cases, IsLocal is
+ // true.
+ void ReadAbbrevRecord(bool IsLocal,
+ NaClAbbrevListener *Listener);
+
+ // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord,
+ // except that no abbreviation is built.
+ void SkipAbbrevRecord();
+
+ bool ReadBlockInfoBlock(NaClAbbrevListener *Listener);
};
} // End llvm namespace
« no previous file with comments | « include/llvm/Bitcode/NaCl/NaClBitcodeWriterPass.h ('k') | include/llvm/Bitcode/NaCl/NaClBitstreamWriter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698