| OLD | NEW |
| 1 //===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===// | 1 //===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===// |
| 2 // Low-level bitstream reader interface |
| 2 // | 3 // |
| 3 // The LLVM Compiler Infrastructure | 4 // The LLVM Compiler Infrastructure |
| 4 // | 5 // |
| 5 // This file is distributed under the University of Illinois Open Source | 6 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 7 // License. See LICENSE.TXT for details. |
| 7 // | 8 // |
| 8 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
| 9 // | 10 // |
| 10 // This header defines the BitstreamReader class. This class can be used to | 11 // This header defines the BitstreamReader class. This class can be used to |
| 11 // read an arbitrary bitstream, regardless of its contents. | 12 // read an arbitrary bitstream, regardless of its contents. |
| 12 // | 13 // |
| 13 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
| 14 | 15 |
| 15 #ifndef LLVM_BITCODE_BITSTREAMREADER_H | 16 #ifndef LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H |
| 16 #define LLVM_BITCODE_BITSTREAMREADER_H | 17 #define LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H |
| 17 | 18 |
| 18 #include "llvm/Bitcode/BitCodes.h" | 19 #include "llvm/ADT/SmallVector.h" |
| 20 #include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h" |
| 19 #include "llvm/Support/Endian.h" | 21 #include "llvm/Support/Endian.h" |
| 20 #include "llvm/Support/StreamingMemoryObject.h" | 22 #include "llvm/Support/StreamingMemoryObject.h" |
| 21 #include <climits> | 23 #include <climits> |
| 22 #include <string> | |
| 23 #include <vector> | 24 #include <vector> |
| 24 | 25 |
| 25 namespace llvm { | 26 namespace llvm { |
| 26 | 27 |
| 27 class Deserializer; | 28 class Deserializer; |
| 28 | 29 |
| 29 /// This class is used to read from an LLVM bitcode stream, maintaining | 30 /// This class is used to read from a NaCl bitcode wire format stream, |
| 30 /// information that is global to decoding the entire file. While a file is | 31 /// maintaining information that is global to decoding the entire file. |
| 31 /// being read, multiple cursors can be independently advanced or skipped around | 32 /// While a file is being read, multiple cursors can be independently |
| 32 /// within the file. These are represented by the BitstreamCursor class. | 33 /// advanced or skipped around within the file. These are represented by |
| 33 class BitstreamReader { | 34 /// the NaClBitstreamCursor class. |
| 35 class NaClBitstreamReader { |
| 34 public: | 36 public: |
| 35 /// This contains information emitted to BLOCKINFO_BLOCK blocks. These | 37 /// This contains information emitted to BLOCKINFO_BLOCK blocks. These |
| 36 /// describe abbreviations that all blocks of the specified ID inherit. | 38 /// describe abbreviations that all blocks of the specified ID inherit. |
| 37 struct BlockInfo { | 39 struct BlockInfo { |
| 38 unsigned BlockID; | 40 unsigned BlockID; |
| 39 std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> Abbrevs; | 41 std::vector<NaClBitCodeAbbrev*> Abbrevs; |
| 40 std::string Name; | |
| 41 | |
| 42 std::vector<std::pair<unsigned, std::string> > RecordNames; | |
| 43 }; | 42 }; |
| 44 private: | 43 private: |
| 45 std::unique_ptr<MemoryObject> BitcodeBytes; | 44 std::unique_ptr<MemoryObject> BitcodeBytes; |
| 46 | 45 |
| 47 std::vector<BlockInfo> BlockInfoRecords; | 46 std::vector<BlockInfo> BlockInfoRecords; |
| 48 | 47 |
| 49 /// This is set to true if we don't care about the block/record name | 48 /// \brief Holds the offset of the first byte after the header. |
| 50 /// information in the BlockInfo block. Only llvm-bcanalyzer uses this. | 49 size_t InitialAddress; |
| 51 bool IgnoreBlockInfoNames; | |
| 52 | 50 |
| 53 BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION; | 51 NaClBitstreamReader(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION; |
| 54 void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION; | 52 void operator=(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION; |
| 55 public: | 53 public: |
| 56 BitstreamReader() : IgnoreBlockInfoNames(true) { | 54 NaClBitstreamReader() : InitialAddress(0) {} |
| 57 } | |
| 58 | 55 |
| 59 BitstreamReader(const unsigned char *Start, const unsigned char *End) | 56 NaClBitstreamReader(const unsigned char *Start, const unsigned char *End, |
| 60 : IgnoreBlockInfoNames(true) { | 57 size_t MyInitialAddress=0) { |
| 58 InitialAddress = MyInitialAddress; |
| 61 init(Start, End); | 59 init(Start, End); |
| 62 } | 60 } |
| 63 | 61 |
| 64 BitstreamReader(MemoryObject *bytes) : IgnoreBlockInfoNames(true) { | 62 NaClBitstreamReader(MemoryObject *Bytes, size_t MyInitialAddress=0) |
| 65 BitcodeBytes.reset(bytes); | 63 : InitialAddress(MyInitialAddress) { |
| 66 } | 64 BitcodeBytes.reset(Bytes); |
| 67 | |
| 68 BitstreamReader(BitstreamReader &&Other) { | |
| 69 *this = std::move(Other); | |
| 70 } | |
| 71 | |
| 72 BitstreamReader &operator=(BitstreamReader &&Other) { | |
| 73 BitcodeBytes = std::move(Other.BitcodeBytes); | |
| 74 // Explicitly swap block info, so that nothing gets destroyed twice. | |
| 75 std::swap(BlockInfoRecords, Other.BlockInfoRecords); | |
| 76 IgnoreBlockInfoNames = Other.IgnoreBlockInfoNames; | |
| 77 return *this; | |
| 78 } | 65 } |
| 79 | 66 |
| 80 void init(const unsigned char *Start, const unsigned char *End) { | 67 void init(const unsigned char *Start, const unsigned char *End) { |
| 81 assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); | 68 assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); |
| 82 BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); | 69 BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); |
| 83 } | 70 } |
| 84 | 71 |
| 85 MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } | 72 MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } |
| 86 | 73 |
| 87 /// This is called by clients that want block/record name information. | 74 ~NaClBitstreamReader() { |
| 88 void CollectBlockInfoNames() { IgnoreBlockInfoNames = false; } | 75 // Free the BlockInfoRecords. |
| 89 bool isIgnoringBlockInfoNames() { return IgnoreBlockInfoNames; } | 76 while (!BlockInfoRecords.empty()) { |
| 77 BlockInfo &Info = BlockInfoRecords.back(); |
| 78 // Free blockinfo abbrev info. |
| 79 for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size()); |
| 80 i != e; ++i) |
| 81 Info.Abbrevs[i]->dropRef(); |
| 82 BlockInfoRecords.pop_back(); |
| 83 } |
| 84 } |
| 85 |
| 86 /// \brief Returns the initial address (after the header) of the input stream. |
| 87 size_t getInitialAddress() const { |
| 88 return InitialAddress; |
| 89 } |
| 90 | 90 |
| 91 //===--------------------------------------------------------------------===// | 91 //===--------------------------------------------------------------------===// |
| 92 // Block Manipulation | 92 // Block Manipulation |
| 93 //===--------------------------------------------------------------------===// | 93 //===--------------------------------------------------------------------===// |
| 94 | 94 |
| 95 /// Return true if we've already read and processed the block info block for | 95 /// Return true if we've already read and processed the block info block for |
| 96 /// this Bitstream. We only process it for the first cursor that walks over | 96 /// this Bitstream. We only process it for the first cursor that walks over |
| 97 /// it. | 97 /// it. |
| 98 bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } | 98 bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } |
| 99 | 99 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 113 | 113 |
| 114 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { | 114 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { |
| 115 if (const BlockInfo *BI = getBlockInfo(BlockID)) | 115 if (const BlockInfo *BI = getBlockInfo(BlockID)) |
| 116 return *const_cast<BlockInfo*>(BI); | 116 return *const_cast<BlockInfo*>(BI); |
| 117 | 117 |
| 118 // Otherwise, add a new record. | 118 // Otherwise, add a new record. |
| 119 BlockInfoRecords.push_back(BlockInfo()); | 119 BlockInfoRecords.push_back(BlockInfo()); |
| 120 BlockInfoRecords.back().BlockID = BlockID; | 120 BlockInfoRecords.back().BlockID = BlockID; |
| 121 return BlockInfoRecords.back(); | 121 return BlockInfoRecords.back(); |
| 122 } | 122 } |
| 123 | |
| 124 /// Takes block info from the other bitstream reader. | |
| 125 /// | |
| 126 /// This is a "take" operation because BlockInfo records are non-trivial, and | |
| 127 /// indeed rather expensive. | |
| 128 void takeBlockInfo(BitstreamReader &&Other) { | |
| 129 assert(!hasBlockInfoRecords()); | |
| 130 BlockInfoRecords = std::move(Other.BlockInfoRecords); | |
| 131 } | |
| 132 }; | 123 }; |
| 133 | 124 |
| 134 /// When advancing through a bitstream cursor, each advance can discover a few | 125 /// When advancing through a bitstream cursor, each advance can discover a few |
| 135 /// different kinds of entries: | 126 /// different kinds of entries: |
| 136 struct BitstreamEntry { | 127 struct NaClBitstreamEntry { |
| 137 enum { | 128 enum { |
| 138 Error, // Malformed bitcode was found. | 129 Error, // Malformed bitcode was found. |
| 139 EndBlock, // We've reached the end of the current block, (or the end of the | 130 EndBlock, // We've reached the end of the current block, (or the end of the |
| 140 // file, which is treated like a series of EndBlock records. | 131 // file, which is treated like a series of EndBlock records. |
| 141 SubBlock, // This is the start of a new subblock of a specific ID. | 132 SubBlock, // This is the start of a new subblock of a specific ID. |
| 142 Record // This is a record with a specific AbbrevID. | 133 Record // This is a record with a specific AbbrevID. |
| 143 } Kind; | 134 } Kind; |
| 144 | 135 |
| 145 unsigned ID; | 136 unsigned ID; |
| 146 | 137 |
| 147 static BitstreamEntry getError() { | 138 static NaClBitstreamEntry getError() { |
| 148 BitstreamEntry E; E.Kind = Error; return E; | 139 NaClBitstreamEntry E; E.Kind = Error; return E; |
| 149 } | 140 } |
| 150 static BitstreamEntry getEndBlock() { | 141 static NaClBitstreamEntry getEndBlock() { |
| 151 BitstreamEntry E; E.Kind = EndBlock; return E; | 142 NaClBitstreamEntry E; E.Kind = EndBlock; return E; |
| 152 } | 143 } |
| 153 static BitstreamEntry getSubBlock(unsigned ID) { | 144 static NaClBitstreamEntry getSubBlock(unsigned ID) { |
| 154 BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; | 145 NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; |
| 155 } | 146 } |
| 156 static BitstreamEntry getRecord(unsigned AbbrevID) { | 147 static NaClBitstreamEntry getRecord(unsigned AbbrevID) { |
| 157 BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; | 148 NaClBitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; |
| 158 } | 149 } |
| 159 }; | 150 }; |
| 160 | 151 |
| 152 /// Models default view of a bitcode record. |
| 153 typedef SmallVector<uint64_t, 8> NaClBitcodeRecordVector; |
| 154 |
| 155 /// Class NaClAbbrevListener is used to allow instances of class |
| 156 /// NaClBitcodeParser to listen to record details when processing |
| 157 /// abbreviations. The major reason for using a listener is that the |
| 158 /// NaCl bitcode reader would require a major rewrite (including the |
| 159 /// introduction of more overhead) if we were to lift abbreviations up |
| 160 /// to the bitcode reader. That is, not only would we have to lift the |
| 161 /// block processing up into the readers (i.e. many blocks in |
| 162 /// NaClBitcodeReader and NaClBitcodeParser), but add many new API's |
| 163 /// to allow the readers to update internals of the bit stream reader |
| 164 /// appropriately. |
| 165 class NaClAbbrevListener { |
| 166 NaClAbbrevListener(const NaClAbbrevListener&) LLVM_DELETED_FUNCTION; |
| 167 void operator=(const NaClAbbrevListener&) LLVM_DELETED_FUNCTION; |
| 168 public: |
| 169 NaClAbbrevListener() {} |
| 170 virtual ~NaClAbbrevListener() {} |
| 171 |
| 172 /// Called to process the read abbreviation. |
| 173 virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, |
| 174 bool IsLocal) = 0; |
| 175 |
| 176 /// Called after entering block. NumWords is the number of words |
| 177 /// in the block. |
| 178 virtual void BeginBlockInfoBlock(unsigned NumWords) = 0; |
| 179 |
| 180 /// Called if a naclbitc::BLOCKINFO_CODE_SETBID record is found in |
| 181 /// NaClBitstreamCursor::ReadBlockInfoBlock. |
| 182 virtual void SetBID() = 0; |
| 183 |
| 184 /// Called just before an EndBlock record is processed by |
| 185 /// NaClBitstreamCursor::ReadBlockInfoBlock |
| 186 virtual void EndBlockInfoBlock() = 0; |
| 187 |
| 188 /// The values of the bitcode record associated with the called |
| 189 /// virtual function. |
| 190 NaClBitcodeRecordVector Values; |
| 191 |
| 192 /// Start bit for current record being processed in |
| 193 /// NaClBitstreamCursor::ReadBlockInfoBlock. |
| 194 uint64_t StartBit; |
| 195 }; |
| 196 |
| 161 /// This represents a position within a bitcode file. There may be multiple | 197 /// This represents a position within a bitcode file. There may be multiple |
| 162 /// independent cursors reading within one bitstream, each maintaining their own | 198 /// independent cursors reading within one bitstream, each maintaining their |
| 163 /// local state. | 199 /// own local state. |
| 164 /// | 200 /// |
| 165 /// Unlike iterators, BitstreamCursors are heavy-weight objects that should not | 201 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects |
| 166 /// be passed by value. | 202 /// that should not be passed by value. |
| 167 class BitstreamCursor { | 203 class NaClBitstreamCursor { |
| 168 friend class Deserializer; | 204 friend class Deserializer; |
| 169 BitstreamReader *BitStream; | 205 NaClBitstreamReader *BitStream; |
| 170 size_t NextChar; | 206 size_t NextChar; |
| 171 | 207 |
| 172 // The size of the bicode. 0 if we don't know it yet. | 208 // The size of the bitcode. 0 if we don't know it yet. |
| 173 size_t Size; | 209 size_t Size; |
| 174 | 210 |
| 175 /// This is the current data we have pulled from the stream but have not | 211 /// This is the current data we have pulled from the stream but have not |
| 176 /// returned to the client. This is specifically and intentionally defined to | 212 /// returned to the client. This is specifically and intentionally defined to |
| 177 /// follow the word size of the host machine for efficiency. We use word_t in | 213 /// follow the word size of the host machine for efficiency. We use word_t in |
| 178 /// places that are aware of this to make it perfectly explicit what is going | 214 /// places that are aware of this to make it perfectly explicit what is going |
| 179 /// on. | 215 /// on. |
| 180 typedef size_t word_t; | 216 typedef size_t word_t; |
| 181 word_t CurWord; | 217 word_t CurWord; |
| 182 | 218 |
| 183 /// This is the number of bits in CurWord that are valid. This is always from | 219 /// This is the number of bits in CurWord that are valid. This |
| 184 /// [0...bits_of(size_t)-1] inclusive. | 220 /// is always from [0...bits_of(word_t)-1] inclusive. |
| 185 unsigned BitsInCurWord; | 221 unsigned BitsInCurWord; |
| 186 | 222 |
| 187 // This is the declared size of code values used for the current block, in | 223 /// This is the declared size of code values used for the current |
| 188 // bits. | 224 /// block, in bits. |
| 189 unsigned CurCodeSize; | 225 NaClBitcodeSelectorAbbrev CurCodeSize; |
| 190 | 226 |
| 191 /// Abbrevs installed at in this block. | 227 /// Abbrevs installed in this block. |
| 192 std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> CurAbbrevs; | 228 std::vector<NaClBitCodeAbbrev*> CurAbbrevs; |
| 193 | 229 |
| 194 struct Block { | 230 struct Block { |
| 195 unsigned PrevCodeSize; | 231 NaClBitcodeSelectorAbbrev PrevCodeSize; |
| 196 std::vector<IntrusiveRefCntPtr<BitCodeAbbrev>> PrevAbbrevs; | 232 std::vector<NaClBitCodeAbbrev*> PrevAbbrevs; |
| 197 explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} | 233 Block() : PrevCodeSize() {} |
| 234 explicit Block(const NaClBitcodeSelectorAbbrev& PCS) |
| 235 : PrevCodeSize(PCS) {} |
| 198 }; | 236 }; |
| 199 | 237 |
| 200 /// This tracks the codesize of parent blocks. | 238 /// This tracks the codesize of parent blocks. |
| 201 SmallVector<Block, 8> BlockScope; | 239 SmallVector<Block, 8> BlockScope; |
| 202 | 240 |
| 241 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION; |
| 242 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT
ION; |
| 203 | 243 |
| 204 public: | 244 public: |
| 205 BitstreamCursor() { init(nullptr); } | 245 NaClBitstreamCursor() { init(nullptr); } |
| 206 | 246 |
| 207 explicit BitstreamCursor(BitstreamReader &R) { init(&R); } | 247 explicit NaClBitstreamCursor(NaClBitstreamReader &R) { init(&R); } |
| 208 | 248 |
| 209 void init(BitstreamReader *R) { | 249 void init(NaClBitstreamReader *R) { |
| 210 freeState(); | 250 freeState(); |
| 211 | |
| 212 BitStream = R; | 251 BitStream = R; |
| 213 NextChar = 0; | 252 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); |
| 214 Size = 0; | 253 Size = 0; |
| 215 BitsInCurWord = 0; | 254 BitsInCurWord = 0; |
| 216 CurCodeSize = 2; | 255 } |
| 256 |
| 257 ~NaClBitstreamCursor() { |
| 258 freeState(); |
| 217 } | 259 } |
| 218 | 260 |
| 219 void freeState(); | 261 void freeState(); |
| 220 | 262 |
| 221 bool canSkipToPos(size_t pos) const { | 263 bool canSkipToPos(size_t pos) const { |
| 222 // pos can be skipped to if it is a valid address or one byte past the end. | 264 // pos can be skipped to if it is a valid address or one byte past the end. |
| 223 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( | 265 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( |
| 224 static_cast<uint64_t>(pos - 1)); | 266 static_cast<uint64_t>(pos - 1)); |
| 225 } | 267 } |
| 226 | 268 |
| 227 bool AtEndOfStream() { | 269 bool AtEndOfStream() { |
| 228 if (BitsInCurWord != 0) | 270 if (BitsInCurWord != 0) |
| 229 return false; | 271 return false; |
| 230 if (Size != 0) | 272 if (Size != 0) |
| 231 return Size == NextChar; | 273 return Size == NextChar; |
| 232 fillCurWord(); | 274 fillCurWord(); |
| 233 return BitsInCurWord == 0; | 275 return BitsInCurWord == 0; |
| 234 } | 276 } |
| 235 | 277 |
| 236 /// Return the number of bits used to encode an abbrev #. | 278 /// Return the number of bits used to encode an abbrev #. |
| 237 unsigned getAbbrevIDWidth() const { return CurCodeSize; } | 279 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } |
| 238 | 280 |
| 239 /// Return the bit # of the bit we are reading. | 281 /// Return the bit # of the bit we are reading. |
| 240 uint64_t GetCurrentBitNo() const { | 282 uint64_t GetCurrentBitNo() const { |
| 241 return NextChar*CHAR_BIT - BitsInCurWord; | 283 return NextChar*CHAR_BIT - BitsInCurWord; |
| 242 } | 284 } |
| 243 | 285 |
| 244 BitstreamReader *getBitStreamReader() { | 286 NaClBitstreamReader *getBitStreamReader() { |
| 245 return BitStream; | 287 return BitStream; |
| 246 } | 288 } |
| 247 const BitstreamReader *getBitStreamReader() const { | 289 const NaClBitstreamReader *getBitStreamReader() const { |
| 248 return BitStream; | 290 return BitStream; |
| 249 } | 291 } |
| 250 | 292 |
| 251 /// Flags that modify the behavior of advance(). | 293 /// Flags that modify the behavior of advance(). |
| 252 enum { | 294 enum { |
| 253 /// If this flag is used, the advance() method does not automatically pop | 295 /// If this flag is used, the advance() method does not automatically pop |
| 254 /// the block scope when the end of a block is reached. | 296 /// the block scope when the end of a block is reached. |
| 255 AF_DontPopBlockAtEnd = 1, | 297 AF_DontPopBlockAtEnd = 1, |
| 256 | 298 |
| 257 /// If this flag is used, abbrev entries are returned just like normal | 299 /// If this flag is used, abbrev entries are returned just like normal |
| 258 /// records. | 300 /// records. |
| 259 AF_DontAutoprocessAbbrevs = 2 | 301 AF_DontAutoprocessAbbrevs = 2 |
| 260 }; | 302 }; |
| 261 | 303 |
| 262 /// Advance the current bitstream, returning the next entry in the stream. | 304 /// Advance the current bitstream, returning the next entry in the stream. |
| 263 BitstreamEntry advance(unsigned Flags = 0) { | 305 /// Use the given abbreviation listener (if provided). |
| 306 NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) { |
| 264 while (1) { | 307 while (1) { |
| 265 unsigned Code = ReadCode(); | 308 unsigned Code = ReadCode(); |
| 266 if (Code == bitc::END_BLOCK) { | 309 if (Code == naclbitc::END_BLOCK) { |
| 267 // Pop the end of the block unless Flags tells us not to. | 310 // Pop the end of the block unless Flags tells us not to. |
| 268 if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) | 311 if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) |
| 269 return BitstreamEntry::getError(); | 312 return NaClBitstreamEntry::getError(); |
| 270 return BitstreamEntry::getEndBlock(); | 313 return NaClBitstreamEntry::getEndBlock(); |
| 271 } | 314 } |
| 272 | 315 |
| 273 if (Code == bitc::ENTER_SUBBLOCK) | 316 if (Code == naclbitc::ENTER_SUBBLOCK) |
| 274 return BitstreamEntry::getSubBlock(ReadSubBlockID()); | 317 return NaClBitstreamEntry::getSubBlock(ReadSubBlockID()); |
| 275 | 318 |
| 276 if (Code == bitc::DEFINE_ABBREV && | 319 if (Code == naclbitc::DEFINE_ABBREV && |
| 277 !(Flags & AF_DontAutoprocessAbbrevs)) { | 320 !(Flags & AF_DontAutoprocessAbbrevs)) { |
| 278 // We read and accumulate abbrev's, the client can't do anything with | 321 // We read and accumulate abbrev's, the client can't do anything with |
| 279 // them anyway. | 322 // them anyway. |
| 280 ReadAbbrevRecord(); | 323 ReadAbbrevRecord(true, Listener); |
| 281 continue; | 324 continue; |
| 282 } | 325 } |
| 283 | 326 |
| 284 return BitstreamEntry::getRecord(Code); | 327 return NaClBitstreamEntry::getRecord(Code); |
| 285 } | 328 } |
| 286 } | 329 } |
| 287 | 330 |
| 288 /// This is a convenience function for clients that don't expect any | 331 /// This is a convenience function for clients that don't expect any |
| 289 /// subblocks. This just skips over them automatically. | 332 /// subblocks. This just skips over them automatically. |
| 290 BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { | 333 NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { |
| 291 while (1) { | 334 while (1) { |
| 292 // If we found a normal entry, return it. | 335 // If we found a normal entry, return it. |
| 293 BitstreamEntry Entry = advance(Flags); | 336 NaClBitstreamEntry Entry = advance(Flags, 0); |
| 294 if (Entry.Kind != BitstreamEntry::SubBlock) | 337 if (Entry.Kind != NaClBitstreamEntry::SubBlock) |
| 295 return Entry; | 338 return Entry; |
| 296 | 339 |
| 297 // If we found a sub-block, just skip over it and check the next entry. | 340 // If we found a sub-block, just skip over it and check the next entry. |
| 298 if (SkipBlock()) | 341 if (SkipBlock()) |
| 299 return BitstreamEntry::getError(); | 342 return NaClBitstreamEntry::getError(); |
| 300 } | 343 } |
| 301 } | 344 } |
| 302 | 345 |
| 303 /// Reset the stream to the specified bit number. | 346 /// Reset the stream to the specified bit number. |
| 304 void JumpToBit(uint64_t BitNo) { | 347 void JumpToBit(uint64_t BitNo) { |
| 305 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); | 348 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); |
| 306 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); | 349 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); |
| 307 assert(canSkipToPos(ByteNo) && "Invalid location"); | 350 assert(canSkipToPos(ByteNo) && "Invalid location"); |
| 308 | 351 |
| 309 // Move the cursor to the right word. | 352 // Move the cursor to the right word. |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 424 CurWord >>= BitsInCurWord-32; | 467 CurWord >>= BitsInCurWord-32; |
| 425 BitsInCurWord = 32; | 468 BitsInCurWord = 32; |
| 426 return; | 469 return; |
| 427 } | 470 } |
| 428 | 471 |
| 429 BitsInCurWord = 0; | 472 BitsInCurWord = 0; |
| 430 } | 473 } |
| 431 public: | 474 public: |
| 432 | 475 |
| 433 unsigned ReadCode() { | 476 unsigned ReadCode() { |
| 434 return Read(CurCodeSize); | 477 return CurCodeSize.IsFixed |
| 478 ? Read(CurCodeSize.NumBits) |
| 479 : ReadVBR(CurCodeSize.NumBits); |
| 435 } | 480 } |
| 436 | 481 |
| 437 | |
| 438 // Block header: | 482 // Block header: |
| 439 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] | 483 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] |
| 440 | 484 |
| 441 /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. | 485 /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block. |
| 442 unsigned ReadSubBlockID() { | 486 unsigned ReadSubBlockID() { |
| 443 return ReadVBR(bitc::BlockIDWidth); | 487 return ReadVBR(naclbitc::BlockIDWidth); |
| 444 } | 488 } |
| 445 | 489 |
| 446 /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body | 490 /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body |
| 447 /// of this block. If the block record is malformed, return true. | 491 /// of this block. If the block record is malformed, return true. |
| 448 bool SkipBlock() { | 492 bool SkipBlock() { |
| 449 // Read and ignore the codelen value. Since we are skipping this block, we | 493 // Read and ignore the codelen value. Since we are skipping this block, we |
| 450 // don't care what code widths are used inside of it. | 494 // don't care what code widths are used inside of it. |
| 451 ReadVBR(bitc::CodeLenWidth); | 495 ReadVBR(naclbitc::CodeLenWidth); |
| 452 SkipToFourByteBoundary(); | 496 SkipToFourByteBoundary(); |
| 453 unsigned NumFourBytes = Read(bitc::BlockSizeWidth); | 497 unsigned NumFourBytes = Read(naclbitc::BlockSizeWidth); |
| 454 | 498 |
| 455 // Check that the block wasn't partially defined, and that the offset isn't | 499 // Check that the block wasn't partially defined, and that the offset isn't |
| 456 // bogus. | 500 // bogus. |
| 457 size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; | 501 size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; |
| 458 if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) | 502 if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) |
| 459 return true; | 503 return true; |
| 460 | 504 |
| 461 JumpToBit(SkipTo); | 505 JumpToBit(SkipTo); |
| 462 return false; | 506 return false; |
| 463 } | 507 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 475 | 519 |
| 476 popBlockScope(); | 520 popBlockScope(); |
| 477 return false; | 521 return false; |
| 478 } | 522 } |
| 479 | 523 |
| 480 private: | 524 private: |
| 481 | 525 |
| 482 void popBlockScope() { | 526 void popBlockScope() { |
| 483 CurCodeSize = BlockScope.back().PrevCodeSize; | 527 CurCodeSize = BlockScope.back().PrevCodeSize; |
| 484 | 528 |
| 485 CurAbbrevs = std::move(BlockScope.back().PrevAbbrevs); | 529 // Delete abbrevs from popped scope. |
| 530 for (unsigned i = 0, e = static_cast<unsigned>(CurAbbrevs.size()); |
| 531 i != e; ++i) |
| 532 CurAbbrevs[i]->dropRef(); |
| 533 |
| 534 BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); |
| 486 BlockScope.pop_back(); | 535 BlockScope.pop_back(); |
| 487 } | 536 } |
| 488 | 537 |
| 489 //===--------------------------------------------------------------------===// | 538 //===--------------------------------------------------------------------===// |
| 490 // Record Processing | 539 // Record Processing |
| 491 //===--------------------------------------------------------------------===// | 540 //===--------------------------------------------------------------------===// |
| 492 | 541 |
| 542 private: |
| 543 void skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op); |
| 544 |
| 545 // Reads the next Value using the abbreviation Op. Returns true only |
| 546 // if Op is an array (and sets Value to the number of elements in the |
| 547 // array). |
| 548 inline bool readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op, |
| 549 uint64_t &Value); |
| 550 |
| 551 // Reads and returns the next value using the abbreviation Op, |
| 552 // assuming Op appears after an array abbreviation. |
| 553 inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op); |
| 554 |
| 555 // Reads the array abbreviation Op, NumArrayElements times, putting |
| 556 // the read values in Vals. |
| 557 inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op, |
| 558 unsigned NumArrayElements, |
| 559 SmallVectorImpl<uint64_t> &Vals); |
| 560 |
| 493 public: | 561 public: |
| 494 | 562 |
| 495 /// Return the abbreviation for the specified AbbrevId. | 563 /// Return the abbreviation for the specified AbbrevId. |
| 496 const BitCodeAbbrev *getAbbrev(unsigned AbbrevID) { | 564 const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const { |
| 497 unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; | 565 unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV; |
| 498 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); | 566 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); |
| 499 return CurAbbrevs[AbbrevNo].get(); | 567 return CurAbbrevs[AbbrevNo]; |
| 500 } | 568 } |
| 501 | 569 |
| 502 /// Read the current record and discard it. | 570 /// Read the current record and discard it. |
| 503 void skipRecord(unsigned AbbrevID); | 571 void skipRecord(unsigned AbbrevID); |
| 504 | 572 |
| 505 unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals, | 573 unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals); |
| 506 StringRef *Blob = nullptr); | |
| 507 | 574 |
| 508 //===--------------------------------------------------------------------===// | 575 //===--------------------------------------------------------------------===// |
| 509 // Abbrev Processing | 576 // Abbrev Processing |
| 510 //===--------------------------------------------------------------------===// | 577 //===--------------------------------------------------------------------===// |
| 511 void ReadAbbrevRecord(); | 578 // IsLocal indicates where the abbreviation occurs. If it is in the |
| 579 // BlockInfo block, IsLocal is false. In all other cases, IsLocal is |
| 580 // true. |
| 581 void ReadAbbrevRecord(bool IsLocal, |
| 582 NaClAbbrevListener *Listener); |
| 512 | 583 |
| 513 bool ReadBlockInfoBlock(); | 584 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord, |
| 585 // except that no abbreviation is built. |
| 586 void SkipAbbrevRecord(); |
| 587 |
| 588 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener); |
| 514 }; | 589 }; |
| 515 | 590 |
| 516 } // End llvm namespace | 591 } // End llvm namespace |
| 517 | 592 |
| 518 #endif | 593 #endif |
| OLD | NEW |