Chromium Code Reviews| 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..742b0b1921f6f60bf1955de28e90897b7377ea86 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,91 @@ 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 const size_t DefaultAbbrevListSize = 12; |
| + 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) { |
| + appendList(NewAbbrevs); |
| + } |
| + AbbrevList &operator=(const AbbrevList &Rhs) { |
| + clear(); |
| + appendList(Rhs); |
| + return *this; |
| + } |
| + // Creates a new (empty) abbreviation, appends it to this, and then returns |
| + // the new abbreviation. |
| + NaClBitCodeAbbrev *appendCreate() { |
| + NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev(); |
| + Abbrevs.push_back(Abbv); |
| + return Abbv; |
| + } |
| + // Appends the given abbreviation to this. |
| + void append(NaClBitCodeAbbrev *Abbrv) { |
| + Abbrv->addRef(); |
| + Abbrevs.push_back(Abbrv); |
| + } |
| + // Appends the contents of NewAbbrevs to this. |
| + void appendList(const AbbrevList &NewAbbrevs) { |
| + for (NaClBitCodeAbbrev *Abbrv : NewAbbrevs.Abbrevs) |
| + append(Abbrv); |
| + } |
| + // Returns last abbreviation on list, and returns an unique reference (i.e. |
|
Derek Schuff
2016/03/21 17:54:54
Does this comment still apply?
also an -> a
Karl
2016/03/21 19:27:56
Removed reference to unique reference.
|
| + // the reference count has been incremented before returning). |
| + NaClBitCodeAbbrev *last() { return Abbrevs.back(); } |
| + // Removes the last element of the list. |
| + void popLast() { |
| + Abbrevs.back()->dropRef(); |
| + Abbrevs.pop_back(); |
| + } |
| + // Empties abbreviation list. |
| + void clear() { |
| + while(!Abbrevs.empty()) |
| + popLast(); |
| + } |
| + // Allow read access to vector defining list. |
| + const AbbrevListVector &getVector() const { return Abbrevs; } |
| + ~AbbrevList() { clear(); } |
| + private: |
| + AbbrevListVector Abbrevs; |
| + }; |
| + |
| + /// 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 { |
| + 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; } |
| +#if 0 |
|
Derek Schuff
2016/03/21 17:54:54
wat
Karl
2016/03/21 19:27:56
Removed code.
|
| + // Allow read access to vector defining abbreviation list. |
| + const AbbrevListVector &getVector() const { |
| + return Abbrevs.getVector(); |
| + } |
| + // Appends Abbv to the abbreviation list |
| + void append(NaClBitCodeAbbrev *Abbv) { |
| + Abbrevs.append(Abbv); |
| + } |
| +#endif |
| + ~BlockInfo() {} |
| + private: |
| unsigned BlockID; |
| - std::vector<NaClBitCodeAbbrev*> Abbrevs; |
| + AbbrevList Abbrevs; |
| }; |
| + |
| private: |
| friend class NaClBitstreamCursor; |
| @@ -68,6 +148,9 @@ private: |
| std::vector<BlockInfo> BlockInfoRecords; |
| + // True if the BlockInfo block has been read. |
| + bool HasReadBlockInfoBlock = false; |
| + |
| /// \brief Holds the offset of the first byte after the header. |
| size_t InitialAddress; |
| @@ -106,17 +189,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 +200,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 +220,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(); |
| } |
| }; |
| @@ -205,7 +273,7 @@ public: |
| virtual ~NaClAbbrevListener() {} |
| /// Called to process the read abbreviation. |
| - virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, |
| + virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrv, |
| bool IsLocal) = 0; |
| /// Called after entering block. NumWords is the number of words |
| @@ -276,22 +344,65 @@ 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->getAbbrevs().getVector().size()), |
| + LocalAbbrevs(), CodeAbbrev(CodeAbbrev) {} |
| + Block(NaClBitstreamReader::BlockInfo *GlobalAbbrevs) |
| + : GlobalAbbrevs(GlobalAbbrevs), |
| + NumGlobalAbbrevs(GlobalAbbrevs->getAbbrevs().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; |
| + } |
| + NaClBitCodeAbbrev *appendLocalCreate() { |
| + return LocalAbbrevs.appendCreate(); |
| + } |
| + void moveLocalAbbrevToAbbrevList(NaClBitstreamReader::AbbrevList *List) { |
| + if (List != &LocalAbbrevs) { |
| + NaClBitCodeAbbrev *Abbv = LocalAbbrevs.last(); |
| + List->append(Abbv); |
| + LocalAbbrevs.popLast(); |
| + } |
| + } |
| + 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 +422,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 +460,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 +679,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: |
| @@ -602,24 +724,12 @@ public: |
| // [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 +767,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. |