Index: include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
diff --git a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
index 05cd91eb2aa92af2eb788d8c7289919604754b2e..9e63f3098576f553678467e2ba4f7b549cd3f8d9 100644 |
--- a/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
+++ b/include/llvm/Bitcode/NaCl/NaClBitstreamReader.h |
@@ -27,6 +27,7 @@ |
namespace llvm { |
class Deserializer; |
+class NaClBitstreamCursor; |
namespace naclbitc { |
@@ -55,12 +56,79 @@ raw_ostream &ErrorAt(raw_ostream &Out, ErrorLevel Level, |
/// 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 { |
+ // Models a raw list of abbreviations. |
+ static constexpr size_t DefaultAbbrevListSize = 12; |
Jim Stichnoth
2016/03/14 22:46:49
same comment about constexpr
Karl
2016/03/15 20:29:41
changed to "const".
|
+ using AbbrevListVector = SmallVector<NaClBitCodeAbbrev *, |
+ DefaultAbbrevListSize>; |
+ |
+ // Models and maintains a list of abbreviations. In particular, it maintains |
+ // updating reference counts of abbreviation operators within the abbreviation |
+ // list. |
+ class AbbrevList { |
+ public: |
+ AbbrevList() = default; |
+ explicit AbbrevList(const AbbrevList &NewAbbrevs) { |
+ push_back(NewAbbrevs); |
+ } |
+ AbbrevList &operator=(const AbbrevList &Rhs) { |
+ clear(); |
+ push_back(Rhs); |
+ return *this; |
+ } |
+ void push_back(NaClBitCodeAbbrev *Abbv) { |
+ Abbrevs.push_back(Abbv); |
Derek Schuff
2016/03/15 17:47:04
I don't really understand why you have to call add
Karl
2016/03/15 20:29:41
This is part of the confusing usage of reference c
|
+ } |
+ void push_back(const AbbrevList &NewAbbrevs) { |
Derek Schuff
2016/03/15 17:47:04
It seems a little weird that this is also called p
Karl
2016/03/15 20:29:41
Changed to appendList, to better clarify.
|
+ for (NaClBitCodeAbbrev *Abbrev : NewAbbrevs.Abbrevs) { |
+ Abbrev->addRef(); |
+ Abbrevs.push_back(Abbrev); |
+ } |
+ } |
+ // Empties abbreviation list. |
+ void clear() { |
+ while(!Abbrevs.empty()) { |
+ Abbrevs.back()->dropRef(); |
+ Abbrevs.pop_back(); |
+ } |
+ } |
+ const AbbrevListVector &getVector() const { return Abbrevs; } |
+ ~AbbrevList() { clear(); } |
+ private: |
+ AbbrevListVector Abbrevs; |
+ // Allow NaClBitstreamCursor to update, so that it can install abbreviations |
+ // as they are read. |
+ friend class NaClBitstreamCursor; |
+ }; |
+ |
+ /// This contains information about abbreviations in blocks defined in the |
+ /// BLOCKINFO_BLOCK block. These describe global abbreviations that apply to |
+ /// all succeeding blocks of the specified ID. |
+ class BlockInfo { |
Derek Schuff
2016/03/15 17:47:04
does a BLOCKINFO_BLOCK have information other than
Karl
2016/03/15 20:29:41
For LLVM, there is more information. for PNaCl bit
|
+ BlockInfo &operator=(const BlockInfo&) = delete; |
+ public: |
+ BlockInfo() = default; |
+ explicit BlockInfo(unsigned BlockID) |
+ : BlockID(BlockID), Abbrevs() {} |
+ BlockInfo(const BlockInfo&) = default; |
+ unsigned getBlockID() const { return BlockID; } |
+ void setBlockID(unsigned ID) { BlockID = ID; } |
+ AbbrevList &getAbbrevs() { return Abbrevs; } |
+ const AbbrevListVector &getVector() const { |
+ return Abbrevs.getVector(); |
+ } |
+ void push_back(NaClBitCodeAbbrev *Abbv) { |
+ Abbrevs.push_back(Abbv); |
+ } |
+ void destroy() { Abbrevs.clear(); } |
Derek Schuff
2016/03/15 17:47:04
Is destroy() used anywhere?
Karl
2016/03/15 20:29:41
Good catch. This clear has already been moved to A
|
+ ~BlockInfo() { destroy(); } |
+ private: |
unsigned BlockID; |
- std::vector<NaClBitCodeAbbrev*> Abbrevs; |
+ AbbrevList Abbrevs; |
+ // Allow NaClBitstreamCursor to update, so that it can install |
Jim Stichnoth
2016/03/14 22:46:49
reflow comment (I think)
here and below
Karl
2016/03/15 20:29:41
Done by removing need for friend class.
|
+ // abbreviations within a BlockInfo, as they are read. |
+ friend NaClBitstreamCursor; |
}; |
+ |
private: |
friend class NaClBitstreamCursor; |
@@ -68,6 +136,9 @@ private: |
std::vector<BlockInfo> BlockInfoRecords; |
+ // True if ReadBlockInfoBlock has been called. |
Derek Schuff
2016/03/15 17:47:04
Please fix the bug in English that the past and pr
Karl
2016/03/15 20:29:41
On 2016/03/15 17:47:04, Derek Schuff wrote:
> Plea
|
+ bool HasReadBlockInfoBlock = false; |
+ |
/// \brief Holds the offset of the first byte after the header. |
size_t InitialAddress; |
@@ -106,17 +177,7 @@ public: |
// Returns the memory object that is being read. |
MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } |
- ~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(); |
- } |
- } |
+ ~NaClBitstreamReader() {} |
/// \brief Returns the initial address (after the header) of the input stream. |
size_t getInitialAddress() const { |
@@ -127,21 +188,17 @@ public: |
// 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 { |
// Common case, the most recent entry matches BlockID. |
- if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) |
+ if (!BlockInfoRecords.empty() && |
+ BlockInfoRecords.back().getBlockID() == BlockID) |
return &BlockInfoRecords.back(); |
for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size()); |
i != e; ++i) |
- if (BlockInfoRecords[i].BlockID == BlockID) |
+ if (BlockInfoRecords[i].getBlockID() == BlockID) |
return &BlockInfoRecords[i]; |
return nullptr; |
} |
@@ -151,8 +208,7 @@ public: |
return *const_cast<BlockInfo*>(BI); |
// Otherwise, add a new record. |
- BlockInfoRecords.push_back(BlockInfo()); |
- BlockInfoRecords.back().BlockID = BlockID; |
+ BlockInfoRecords.push_back(BlockInfo(BlockID)); |
return BlockInfoRecords.back(); |
} |
}; |
@@ -276,22 +332,58 @@ private: |
/// 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. |
- NaClBitcodeSelectorAbbrev CurCodeSize; |
- |
- /// Abbrevs installed in this block. |
- std::vector<NaClBitCodeAbbrev*> CurAbbrevs; |
- |
- struct Block { |
- NaClBitcodeSelectorAbbrev PrevCodeSize; |
- std::vector<NaClBitCodeAbbrev*> PrevAbbrevs; |
- Block() : PrevCodeSize() {} |
- explicit Block(const NaClBitcodeSelectorAbbrev& PCS) |
- : PrevCodeSize(PCS) {} |
+ // Data specific to a block being scanned. |
+ class Block { |
+ public: |
+ Block() = delete; |
+ Block &operator=(const Block &Rhs) { |
+ GlobalAbbrevs = Rhs.GlobalAbbrevs; |
+ NumGlobalAbbrevs = Rhs.NumGlobalAbbrevs; |
+ LocalAbbrevs = Rhs.LocalAbbrevs; |
+ CodeAbbrev = Rhs.CodeAbbrev; |
+ return *this; |
+ } |
+ Block(NaClBitstreamReader::BlockInfo *GlobalAbbrevs, |
+ NaClBitcodeSelectorAbbrev& CodeAbbrev) |
+ : GlobalAbbrevs(GlobalAbbrevs), |
+ NumGlobalAbbrevs(GlobalAbbrevs->getVector().size()), |
+ LocalAbbrevs(), CodeAbbrev(CodeAbbrev) {} |
+ Block(NaClBitstreamReader::BlockInfo *GlobalAbbrevs) |
+ : GlobalAbbrevs(GlobalAbbrevs), |
+ NumGlobalAbbrevs(GlobalAbbrevs->getVector().size()), |
+ LocalAbbrevs(), CodeAbbrev() {} |
+ ~Block() = default; |
+ const NaClBitstreamReader::AbbrevList &getGlobalAbbrevs() const { |
+ return GlobalAbbrevs->getAbbrevs(); |
+ } |
+ unsigned getNumGlobalAbbrevs() const { return NumGlobalAbbrevs; } |
+ const NaClBitstreamReader::AbbrevList &getLocalAbbrevs() const { |
+ return LocalAbbrevs; |
+ } |
+ const NaClBitcodeSelectorAbbrev &getCodeAbbrev() const { |
+ return CodeAbbrev; |
+ } |
+ void setCodeAbbrev(NaClBitcodeSelectorAbbrev &Abbrev) { |
+ CodeAbbrev = Abbrev; |
+ } |
+ void addNewLocalAbbrev(NaClBitCodeAbbrev *Abbv) { |
+ LocalAbbrevs.push_back(Abbv); |
+ } |
+ private: |
+ friend class NaClBitstreamCursor; |
+ // The global abbreviations associated with this scope. |
+ NaClBitstreamReader::BlockInfo *GlobalAbbrevs; |
+ // Number of abbreviations when block was entered. Used to limit scope |
+ // of CurBlockInfo, since any abbreviation added inside a BlockInfo block |
+ // (within this block) must not effect global abbreviations. |
+ unsigned NumGlobalAbbrevs; |
+ NaClBitstreamReader::AbbrevList LocalAbbrevs; |
+ // This is the declared size of code values used for the current block, |
+ // in bits. |
+ NaClBitcodeSelectorAbbrev CodeAbbrev; |
}; |
- /// This tracks the codesize of parent blocks. |
+ /// This tracks the Block-specific information for each nested block. |
SmallVector<Block, 8> BlockScope; |
NaClBitstreamCursor(const NaClBitstreamCursor &) = delete; |
@@ -311,13 +403,20 @@ public: |
NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); |
Size = 0; |
BitsInCurWord = 0; |
+ if (BitStream) { |
+ BlockScope.push_back( |
+ Block(&BitStream->getOrCreateBlockInfo(naclbitc::TOP_LEVEL_BLOCKID))); |
+ } |
} |
~NaClBitstreamCursor() { |
freeState(); |
} |
- void freeState(); |
+ void freeState() { |
+ while (!BlockScope.empty()) |
+ BlockScope.pop_back(); |
+ } |
// Replaces the current bitstream error handler with the new |
// handler. Takes ownership of the new handler and deletes it when |
@@ -342,7 +441,9 @@ public: |
} |
/// Return the number of bits used to encode an abbrev #. |
- unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } |
+ unsigned getAbbrevIDWidth() const { |
+ return BlockScope.back().getCodeAbbrev().NumBits; |
+ } |
/// Return the bit # of the bit we are reading. |
uint64_t GetCurrentBitNo() const { |
@@ -559,9 +660,11 @@ private: |
public: |
unsigned ReadCode() { |
- return CurCodeSize.IsFixed |
- ? Read(CurCodeSize.NumBits) |
- : ReadVBR(CurCodeSize.NumBits); |
+ const NaClBitcodeSelectorAbbrev &CodeAbbrev = |
+ BlockScope.back().getCodeAbbrev(); |
+ return CodeAbbrev.IsFixed |
+ ? Read(CodeAbbrev.NumBits) |
+ : ReadVBR(CodeAbbrev.NumBits); |
} |
// Block header: |
@@ -596,30 +699,18 @@ public: |
bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr); |
bool ReadBlockEnd() { |
- if (BlockScope.empty()) return true; |
+ if (BlockScope.empty()) return true; |
Derek Schuff
2016/03/15 17:47:04
extra space?
Karl
2016/03/15 20:29:41
Done.
|
// Block tail: |
// [END_BLOCK, <align4bytes>] |
SkipToFourByteBoundary(); |
- popBlockScope(); |
+ BlockScope.pop_back(); |
return false; |
} |
private: |
- void popBlockScope() { |
- CurCodeSize = BlockScope.back().PrevCodeSize; |
- |
- // 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(); |
- } |
- |
//===--------------------------------------------------------------------===// |
// Record Processing |
//===--------------------------------------------------------------------===// |
@@ -657,9 +748,16 @@ public: |
/// Return the abbreviation for the specified AbbrevId. |
const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const { |
unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV; |
- if (AbbrevNo >= CurAbbrevs.size()) |
+ const Block &CurBlock = BlockScope.back(); |
+ const unsigned NumGlobalAbbrevs = CurBlock.getNumGlobalAbbrevs(); |
+ if (AbbrevNo < NumGlobalAbbrevs) |
+ return CurBlock.getGlobalAbbrevs().getVector()[AbbrevNo]; |
+ unsigned LocalAbbrevNo = AbbrevNo - NumGlobalAbbrevs; |
+ NaClBitstreamReader::AbbrevListVector |
+ LocalAbbrevs = CurBlock.getLocalAbbrevs().getVector(); |
+ if (LocalAbbrevNo >= LocalAbbrevs.size()) |
reportInvalidAbbrevNumber(AbbrevID); |
- return CurAbbrevs[AbbrevNo]; |
+ return LocalAbbrevs[LocalAbbrevNo]; |
} |
/// Read the current record and discard it. |