OLD | NEW |
---|---|
1 //===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===// | 1 //===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===// |
2 // Low-level bitstream reader interface | 2 // Low-level bitstream reader interface |
3 // | 3 // |
4 // The LLVM Compiler Infrastructure | 4 // The LLVM Compiler Infrastructure |
5 // | 5 // |
6 // This file is distributed under the University of Illinois Open Source | 6 // This file is distributed under the University of Illinois Open Source |
7 // License. See LICENSE.TXT for details. | 7 // License. See LICENSE.TXT for details. |
8 // | 8 // |
9 //===----------------------------------------------------------------------===// | 9 //===----------------------------------------------------------------------===// |
10 // | 10 // |
11 // 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 |
12 // read an arbitrary bitstream, regardless of its contents. | 12 // read an arbitrary bitstream, regardless of its contents. |
13 // | 13 // |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | 15 |
16 #ifndef LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H | 16 #ifndef LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H |
17 #define LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H | 17 #define LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H |
18 | 18 |
19 #include "llvm/ADT/SmallVector.h" | 19 #include "llvm/ADT/SmallVector.h" |
20 #include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h" | 20 #include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h" |
21 #include "llvm/Support/Endian.h" | 21 #include "llvm/Support/Endian.h" |
22 #include "llvm/Support/StreamableMemoryObject.h" | 22 #include "llvm/Support/StreamingMemoryObject.h" |
23 #include <climits> | 23 #include <climits> |
24 #include <vector> | 24 #include <vector> |
25 | 25 |
26 namespace llvm { | 26 namespace llvm { |
27 | 27 |
28 class Deserializer; | 28 class Deserializer; |
29 | 29 |
30 /// NaClBitstreamReader - This class is used to read from a NaCl | 30 /// NaClBitstreamReader - This class is used to read from a NaCl |
31 /// bitcode wire format stream, maintaining information that is global | 31 /// bitcode wire format stream, maintaining information that is global |
32 /// to decoding the entire file. While a file is being read, multiple | 32 /// to decoding the entire file. While a file is being read, multiple |
33 /// cursors can be independently advanced or skipped around within the | 33 /// cursors can be independently advanced or skipped around within the |
34 /// file. These are represented by the NaClBitstreamCursor class. | 34 /// file. These are represented by the NaClBitstreamCursor class. |
35 class NaClBitstreamReader { | 35 class NaClBitstreamReader { |
36 public: | 36 public: |
37 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. | 37 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. |
38 /// These describe abbreviations that all blocks of the specified ID inherit. | 38 /// These describe abbreviations that all blocks of the specified ID inherit. |
39 struct BlockInfo { | 39 struct BlockInfo { |
40 unsigned BlockID; | 40 unsigned BlockID; |
41 std::vector<NaClBitCodeAbbrev*> Abbrevs; | 41 std::vector<NaClBitCodeAbbrev*> Abbrevs; |
42 }; | 42 }; |
43 private: | 43 private: |
44 std::unique_ptr<StreamableMemoryObject> BitcodeBytes; | 44 std::unique_ptr<MemoryObject> BitcodeBytes; |
45 | 45 |
46 std::vector<BlockInfo> BlockInfoRecords; | 46 std::vector<BlockInfo> BlockInfoRecords; |
47 | 47 |
48 /// \brief Holds the offset of the first byte after the header. | 48 /// \brief Holds the offset of the first byte after the header. |
49 size_t InitialAddress; | 49 size_t InitialAddress; |
50 | 50 |
51 NaClBitstreamReader(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION; | 51 NaClBitstreamReader(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION; |
52 void operator=(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION; | 52 void operator=(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION; |
53 public: | 53 public: |
54 NaClBitstreamReader() : InitialAddress(0) {} | 54 NaClBitstreamReader() : InitialAddress(0) {} |
55 | 55 |
56 NaClBitstreamReader(const unsigned char *Start, const unsigned char *End, | 56 NaClBitstreamReader(const unsigned char *Start, const unsigned char *End, |
57 size_t MyInitialAddress=0) { | 57 size_t MyInitialAddress=0) { |
58 InitialAddress = MyInitialAddress; | 58 InitialAddress = MyInitialAddress; |
59 init(Start, End); | 59 init(Start, End); |
60 } | 60 } |
61 | 61 |
62 NaClBitstreamReader(StreamableMemoryObject *Bytes, | 62 NaClBitstreamReader(MemoryObject *Bytes, size_t MyInitialAddress=0) |
63 size_t MyInitialAddress=0) | 63 : InitialAddress(MyInitialAddress) { |
64 : InitialAddress(MyInitialAddress) | |
65 { | |
66 BitcodeBytes.reset(Bytes); | 64 BitcodeBytes.reset(Bytes); |
67 } | 65 } |
68 | 66 |
69 void init(const unsigned char *Start, const unsigned char *End) { | 67 void init(const unsigned char *Start, const unsigned char *End) { |
70 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"); |
71 BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); | 69 BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); |
72 } | 70 } |
73 | 71 |
74 StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; } | 72 MemoryObject &getBitcodeBytes() { return *BitcodeBytes; } |
75 | 73 |
76 ~NaClBitstreamReader() { | 74 ~NaClBitstreamReader() { |
77 // Free the BlockInfoRecords. | 75 // Free the BlockInfoRecords. |
78 while (!BlockInfoRecords.empty()) { | 76 while (!BlockInfoRecords.empty()) { |
79 BlockInfo &Info = BlockInfoRecords.back(); | 77 BlockInfo &Info = BlockInfoRecords.back(); |
80 // Free blockinfo abbrev info. | 78 // Free blockinfo abbrev info. |
81 for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size()); | 79 for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size()); |
82 i != e; ++i) | 80 i != e; ++i) |
83 Info.Abbrevs[i]->dropRef(); | 81 Info.Abbrevs[i]->dropRef(); |
84 BlockInfoRecords.pop_back(); | 82 BlockInfoRecords.pop_back(); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 if (const BlockInfo *BI = getBlockInfo(BlockID)) | 115 if (const BlockInfo *BI = getBlockInfo(BlockID)) |
118 return *const_cast<BlockInfo*>(BI); | 116 return *const_cast<BlockInfo*>(BI); |
119 | 117 |
120 // Otherwise, add a new record. | 118 // Otherwise, add a new record. |
121 BlockInfoRecords.push_back(BlockInfo()); | 119 BlockInfoRecords.push_back(BlockInfo()); |
122 BlockInfoRecords.back().BlockID = BlockID; | 120 BlockInfoRecords.back().BlockID = BlockID; |
123 return BlockInfoRecords.back(); | 121 return BlockInfoRecords.back(); |
124 } | 122 } |
125 }; | 123 }; |
126 | 124 |
127 | 125 |
128 /// NaClBitstreamEntry - When advancing through a bitstream cursor, | 126 /// NaClBitstreamEntry - When advancing through a bitstream cursor, |
129 /// each advance can discover a few different kinds of entries: | 127 /// each advance can discover a few different kinds of entries: |
130 /// Error - Malformed bitcode was found. | 128 /// Error - Malformed bitcode was found. |
131 /// EndBlock - We've reached the end of the current block, (or the end of the | 129 /// EndBlock - We've reached the end of the current block, (or the end of the |
132 /// file, which is treated like a series of EndBlock records. | 130 /// file, which is treated like a series of EndBlock records. |
133 /// SubBlock - This is the start of a new subblock of a specific ID. | 131 /// SubBlock - This is the start of a new subblock of a specific ID. |
134 /// Record - This is a record with a specific AbbrevID. | 132 /// Record - This is a record with a specific AbbrevID. |
135 /// | 133 /// |
136 struct NaClBitstreamEntry { | 134 struct NaClBitstreamEntry { |
137 enum { | 135 enum { |
138 Error, | 136 Error, |
139 EndBlock, | 137 EndBlock, |
140 SubBlock, | 138 SubBlock, |
141 Record | 139 Record |
142 } Kind; | 140 } Kind; |
143 | 141 |
144 unsigned ID; | 142 unsigned ID; |
145 | 143 |
146 static NaClBitstreamEntry getError() { | 144 static NaClBitstreamEntry getError() { |
147 NaClBitstreamEntry E; E.Kind = Error; return E; | 145 NaClBitstreamEntry E; E.Kind = Error; return E; |
148 } | 146 } |
149 static NaClBitstreamEntry getEndBlock() { | 147 static NaClBitstreamEntry getEndBlock() { |
150 NaClBitstreamEntry E; E.Kind = EndBlock; return E; | 148 NaClBitstreamEntry E; E.Kind = EndBlock; return E; |
151 } | 149 } |
152 static NaClBitstreamEntry getSubBlock(unsigned ID) { | 150 static NaClBitstreamEntry getSubBlock(unsigned ID) { |
153 NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; | 151 NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
206 /// file. There may be multiple independent cursors reading within | 204 /// file. There may be multiple independent cursors reading within |
207 /// one bitstream, each maintaining their own local state. | 205 /// one bitstream, each maintaining their own local state. |
208 /// | 206 /// |
209 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects | 207 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects |
210 /// that should not be passed by value. | 208 /// that should not be passed by value. |
211 class NaClBitstreamCursor { | 209 class NaClBitstreamCursor { |
212 friend class Deserializer; | 210 friend class Deserializer; |
213 NaClBitstreamReader *BitStream; | 211 NaClBitstreamReader *BitStream; |
214 size_t NextChar; | 212 size_t NextChar; |
215 | 213 |
214 // The size of the bitcode. 0 if we don't know it yet. | |
215 size_t Size; | |
216 | |
216 /// CurWord/word_t - This is the current data we have pulled from the stream | 217 /// CurWord/word_t - This is the current data we have pulled from the stream |
217 /// but have not returned to the client. This is specifically and | 218 /// but have not returned to the client. This is specifically and |
218 /// intentionally defined to follow the word size of the host machine for | 219 /// intentionally defined to follow the word size of the host machine for |
219 /// efficiency. We use word_t in places that are aware of this to make it | 220 /// efficiency. We use word_t in places that are aware of this to make it |
220 /// perfectly explicit what is going on. | 221 /// perfectly explicit what is going on. |
221 typedef uint32_t word_t; | 222 typedef uint32_t word_t; |
222 word_t CurWord; | 223 word_t CurWord; |
223 | 224 |
224 /// BitsInCurWord - This is the number of bits in CurWord that are valid. This | 225 /// BitsInCurWord - This is the number of bits in CurWord that are valid. This |
225 /// is always from [0...31/63] inclusive (depending on word size). | 226 /// is always from [0...31/63] inclusive (depending on word size). |
226 unsigned BitsInCurWord; | 227 unsigned BitsInCurWord; |
227 | 228 |
228 // CurCodeSize - This is the declared size of code values used for the current | 229 // CurCodeSize - This is the declared size of code values used for the current |
229 // block, in bits. | 230 // block, in bits. |
230 NaClBitcodeSelectorAbbrev CurCodeSize; | 231 NaClBitcodeSelectorAbbrev CurCodeSize; |
231 | 232 |
232 /// CurAbbrevs - Abbrevs installed at in this block. | 233 /// CurAbbrevs - Abbrevs installed at in this block. |
233 std::vector<NaClBitCodeAbbrev*> CurAbbrevs; | 234 std::vector<NaClBitCodeAbbrev*> CurAbbrevs; |
234 | 235 |
235 struct Block { | 236 struct Block { |
236 NaClBitcodeSelectorAbbrev PrevCodeSize; | 237 NaClBitcodeSelectorAbbrev PrevCodeSize; |
237 std::vector<NaClBitCodeAbbrev*> PrevAbbrevs; | 238 std::vector<NaClBitCodeAbbrev*> PrevAbbrevs; |
238 explicit Block() : PrevCodeSize() {} | 239 Block() : PrevCodeSize() {} |
239 explicit Block(const NaClBitcodeSelectorAbbrev& PCS) | 240 explicit Block(const NaClBitcodeSelectorAbbrev& PCS) |
240 : PrevCodeSize(PCS) {} | 241 : PrevCodeSize(PCS) {} |
241 }; | 242 }; |
242 | 243 |
243 /// BlockScope - This tracks the codesize of parent blocks. | 244 /// BlockScope - This tracks the codesize of parent blocks. |
244 SmallVector<Block, 8> BlockScope; | 245 SmallVector<Block, 8> BlockScope; |
245 | 246 |
246 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION; | 247 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION; |
247 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT ION; | 248 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT ION; |
248 | 249 |
249 public: | 250 public: |
250 | |
251 NaClBitstreamCursor() { | 251 NaClBitstreamCursor() { |
252 init(nullptr); | 252 init(nullptr); |
253 } | 253 } |
254 | 254 |
255 explicit NaClBitstreamCursor(NaClBitstreamReader &R) { init(&R); } | 255 explicit NaClBitstreamCursor(NaClBitstreamReader &R) { init(&R); } |
256 | 256 |
257 void init(NaClBitstreamReader *R) { | 257 void init(NaClBitstreamReader *R) { |
258 freeState(); | 258 freeState(); |
259 BitStream = R; | 259 BitStream = R; |
260 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); | 260 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); |
261 CurWord = 0; | 261 Size = 0; |
262 BitsInCurWord = 0; | 262 BitsInCurWord = 0; |
263 } | 263 } |
264 | 264 |
265 ~NaClBitstreamCursor() { | 265 ~NaClBitstreamCursor() { |
266 freeState(); | 266 freeState(); |
267 } | 267 } |
268 | 268 |
269 void freeState(); | 269 void freeState(); |
270 | 270 |
271 bool isEndPos(size_t pos) { | |
272 return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); | |
273 } | |
274 | |
275 bool canSkipToPos(size_t pos) const { | 271 bool canSkipToPos(size_t pos) const { |
276 // pos can be skipped to if it is a valid address or one byte past the end. | 272 // pos can be skipped to if it is a valid address or one byte past the end. |
277 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( | 273 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( |
278 static_cast<uint64_t>(pos - 1)); | 274 static_cast<uint64_t>(pos - 1)); |
279 } | 275 } |
280 | 276 |
281 bool AtEndOfStream() { | 277 bool AtEndOfStream() { |
282 return BitsInCurWord == 0 && isEndPos(NextChar); | 278 if (BitsInCurWord != 0) |
279 return false; | |
280 if (Size != 0 && Size == NextChar) | |
281 return true; | |
282 fillCurWord(); | |
283 return BitsInCurWord == 0; | |
283 } | 284 } |
284 | 285 |
285 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. | 286 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. |
286 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } | 287 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } |
287 | 288 |
288 /// GetCurrentBitNo - Return the bit # of the bit we are reading. | 289 /// GetCurrentBitNo - Return the bit # of the bit we are reading. |
289 uint64_t GetCurrentBitNo() const { | 290 uint64_t GetCurrentBitNo() const { |
290 return NextChar*CHAR_BIT - BitsInCurWord; | 291 return NextChar*CHAR_BIT - BitsInCurWord; |
291 } | 292 } |
292 | 293 |
293 NaClBitstreamReader *getBitStreamReader() { | 294 NaClBitstreamReader *getBitStreamReader() { |
294 return BitStream; | 295 return BitStream; |
295 } | 296 } |
296 const NaClBitstreamReader *getBitStreamReader() const { | 297 const NaClBitstreamReader *getBitStreamReader() const { |
297 return BitStream; | 298 return BitStream; |
298 } | 299 } |
299 | 300 |
300 /// Flags that modify the behavior of advance(). | 301 /// Flags that modify the behavior of advance(). |
301 enum { | 302 enum { |
302 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does | 303 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does |
303 /// not automatically pop the block scope when the end of a block is | 304 /// not automatically pop the block scope when the end of a block is |
304 /// reached. | 305 /// reached. |
305 AF_DontPopBlockAtEnd = 1, | 306 AF_DontPopBlockAtEnd = 1, |
306 | 307 |
307 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are | 308 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are |
308 /// returned just like normal records. | 309 /// returned just like normal records. |
309 AF_DontAutoprocessAbbrevs = 2 | 310 AF_DontAutoprocessAbbrevs = 2 |
310 }; | 311 }; |
311 | 312 |
312 /// advance - Advance the current bitstream, returning the next entry in the | 313 /// advance - Advance the current bitstream, returning the next entry in the |
313 /// stream. Use the given abbreviation listener (if provided). | 314 /// stream. Use the given abbreviation listener (if provided). |
314 NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) { | 315 NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) { |
315 while (1) { | 316 while (1) { |
316 unsigned Code = ReadCode(); | 317 unsigned Code = ReadCode(); |
317 if (Code == naclbitc::END_BLOCK) { | 318 if (Code == naclbitc::END_BLOCK) { |
318 // Pop the end of the block unless Flags tells us not to. | 319 // Pop the end of the block unless Flags tells us not to. |
319 if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) | 320 if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) |
320 return NaClBitstreamEntry::getError(); | 321 return NaClBitstreamEntry::getError(); |
321 return NaClBitstreamEntry::getEndBlock(); | 322 return NaClBitstreamEntry::getEndBlock(); |
322 } | 323 } |
323 | 324 |
324 if (Code == naclbitc::ENTER_SUBBLOCK) | 325 if (Code == naclbitc::ENTER_SUBBLOCK) |
325 return NaClBitstreamEntry::getSubBlock(ReadSubBlockID()); | 326 return NaClBitstreamEntry::getSubBlock(ReadSubBlockID()); |
326 | 327 |
327 if (Code == naclbitc::DEFINE_ABBREV && | 328 if (Code == naclbitc::DEFINE_ABBREV && |
328 !(Flags & AF_DontAutoprocessAbbrevs)) { | 329 !(Flags & AF_DontAutoprocessAbbrevs)) { |
329 // We read and accumulate abbrev's, the client can't do anything with | 330 // We read and accumulate abbrev's, the client can't do anything with |
330 // them anyway. | 331 // them anyway. |
331 ReadAbbrevRecord(true, Listener); | 332 ReadAbbrevRecord(true, Listener); |
332 continue; | 333 continue; |
333 } | 334 } |
334 | 335 |
335 return NaClBitstreamEntry::getRecord(Code); | 336 return NaClBitstreamEntry::getRecord(Code); |
336 } | 337 } |
337 } | 338 } |
338 | 339 |
339 /// advanceSkippingSubblocks - This is a convenience function for clients that | 340 /// advanceSkippingSubblocks - This is a convenience function for clients that |
340 /// don't expect any subblocks. This just skips over them automatically. | 341 /// don't expect any subblocks. This just skips over them automatically. |
341 NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { | 342 NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { |
342 while (1) { | 343 while (1) { |
343 // If we found a normal entry, return it. | 344 // If we found a normal entry, return it. |
344 NaClBitstreamEntry Entry = advance(Flags, 0); | 345 NaClBitstreamEntry Entry = advance(Flags, 0); |
345 if (Entry.Kind != NaClBitstreamEntry::SubBlock) | 346 if (Entry.Kind != NaClBitstreamEntry::SubBlock) |
346 return Entry; | 347 return Entry; |
347 | 348 |
348 // If we found a sub-block, just skip over it and check the next entry. | 349 // If we found a sub-block, just skip over it and check the next entry. |
349 if (SkipBlock()) | 350 if (SkipBlock()) |
350 return NaClBitstreamEntry::getError(); | 351 return NaClBitstreamEntry::getError(); |
351 } | 352 } |
352 } | 353 } |
353 | 354 |
354 /// JumpToBit - Reset the stream to the specified bit number. | 355 /// JumpToBit - Reset the stream to the specified bit number. |
355 void JumpToBit(uint64_t BitNo) { | 356 void JumpToBit(uint64_t BitNo) { |
356 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); | 357 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); |
357 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); | 358 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); |
358 assert(canSkipToPos(ByteNo) && "Invalid location"); | 359 assert(canSkipToPos(ByteNo) && "Invalid location"); |
359 | 360 |
360 // Move the cursor to the right word. | 361 // Move the cursor to the right word. |
361 NextChar = ByteNo; | 362 NextChar = ByteNo; |
362 BitsInCurWord = 0; | 363 BitsInCurWord = 0; |
363 CurWord = 0; | |
364 | 364 |
365 // Skip over any bits that are already consumed. | 365 // Skip over any bits that are already consumed. |
366 if (WordBitNo) { | 366 if (WordBitNo) { |
367 if (sizeof(word_t) > 4) | 367 if (sizeof(word_t) > 4) |
368 Read64(WordBitNo); | 368 Read64(WordBitNo); |
369 else | 369 else |
370 Read(WordBitNo); | 370 Read(WordBitNo); |
371 } | 371 } |
372 } | 372 } |
373 | 373 |
374 void fillCurWord() { | |
375 assert(Size == 0 || NextChar < (unsigned)Size); | |
376 | |
377 // Read the next word from the stream. | |
378 uint8_t Array[sizeof(word_t)] = {0}; | |
379 | |
380 uint64_t BytesRead = | |
381 BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar); | |
382 | |
383 // If we run out of data, stop at the end of the stream. | |
384 if (BytesRead == 0) { | |
385 Size = NextChar; | |
386 return; | |
387 } | |
388 assert(BytesRead == sizeof(Array)); | |
Karl
2015/02/20 17:07:02
Should this be an assert (i.e. has the length been
jvoung (off chromium)
2015/02/20 17:38:21
Hmm looks like the assert is gone in the new Bitst
| |
389 | |
390 // Handle big-endian byte-swapping if necessary. | |
391 support::detail::packed_endian_specific_integral< | |
392 word_t, support::little, support::unaligned> EndianValue; | |
393 memcpy(&EndianValue, Array, sizeof(Array)); | |
394 | |
395 CurWord = EndianValue; | |
396 NextChar += sizeof(word_t); | |
397 BitsInCurWord = sizeof(word_t) * 8; | |
398 } | |
399 | |
374 uint32_t Read(unsigned NumBits) { | 400 uint32_t Read(unsigned NumBits) { |
375 assert(NumBits && NumBits <= 32 && | 401 assert(NumBits && NumBits <= 32 && |
376 "Cannot return zero or more than 32 bits!"); | 402 "Cannot return zero or more than 32 bits!"); |
377 | 403 |
378 // If the field is fully contained by CurWord, return it quickly. | 404 // If the field is fully contained by CurWord, return it quickly. |
379 if (BitsInCurWord >= NumBits) { | 405 if (BitsInCurWord >= NumBits) { |
380 uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); | 406 uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); |
381 CurWord >>= NumBits; | 407 |
408 // Use a mask to avoid undefined behavior. | |
409 CurWord >>= (NumBits & 0x1f); | |
Karl
2015/02/20 17:07:02
Is the mask necessary? Doesn't the assert above gu
jvoung (off chromium)
2015/02/20 17:38:21
Yes, in case asserts are turned off.
Otherwise it
| |
410 | |
382 BitsInCurWord -= NumBits; | 411 BitsInCurWord -= NumBits; |
383 return R; | 412 return R; |
384 } | 413 } |
385 | 414 |
415 uint32_t R = BitsInCurWord ? uint32_t(CurWord) : 0; | |
416 unsigned BitsLeft = NumBits - BitsInCurWord; | |
417 | |
418 fillCurWord(); | |
419 | |
386 // If we run out of data, stop at the end of the stream. | 420 // If we run out of data, stop at the end of the stream. |
387 if (isEndPos(NextChar)) { | 421 if (BitsLeft > BitsInCurWord) |
388 CurWord = 0; | |
389 BitsInCurWord = 0; | |
390 return 0; | 422 return 0; |
391 } | |
392 | 423 |
393 uint32_t R = uint32_t(CurWord); | 424 uint32_t R2 = uint32_t(CurWord) & (~0U >> (sizeof(word_t) * 8 - BitsLeft)); |
394 | 425 |
395 // Read the next word from the stream. | 426 // Use a mask to avoid undefined behavior. |
396 uint8_t Array[sizeof(word_t)] = {0}; | 427 CurWord >>= (BitsLeft & 0x1f); |
397 | |
398 BitStream->getBitcodeBytes().readBytes(NextChar, sizeof(Array), Array); | |
399 | |
400 // Handle big-endian byte-swapping if necessary. | |
401 support::detail::packed_endian_specific_integral | |
402 <word_t, support::little, support::unaligned> EndianValue; | |
403 memcpy(&EndianValue, Array, sizeof(Array)); | |
404 | |
405 CurWord = EndianValue; | |
406 | 428 |
407 NextChar += sizeof(word_t); | 429 BitsInCurWord -= BitsLeft; |
408 | 430 |
409 // Extract NumBits-BitsInCurWord from what we just read. | 431 R |= uint32_t(R2 << (NumBits - BitsLeft)); |
410 unsigned BitsLeft = NumBits-BitsInCurWord; | |
411 | 432 |
412 // Be careful here, BitsLeft is in the range [1..32]/[1..64] inclusive. | |
413 R |= uint32_t((CurWord & (word_t(~0ULL) >> (sizeof(word_t)*8-BitsLeft))) | |
414 << BitsInCurWord); | |
415 | |
416 // BitsLeft bits have just been used up from CurWord. BitsLeft is in the | |
417 // range [1..32]/[1..64] so be careful how we shift. | |
418 if (BitsLeft != sizeof(word_t)*8) | |
419 CurWord >>= BitsLeft; | |
420 else | |
421 CurWord = 0; | |
422 BitsInCurWord = sizeof(word_t)*8-BitsLeft; | |
423 return R; | 433 return R; |
424 } | 434 } |
425 | 435 |
426 uint64_t Read64(unsigned NumBits) { | 436 uint64_t Read64(unsigned NumBits) { |
427 if (NumBits <= 32) return Read(NumBits); | 437 if (NumBits <= 32) return Read(NumBits); |
428 | 438 |
429 uint64_t V = Read(32); | 439 uint64_t V = Read(32); |
430 return V | (uint64_t)Read(NumBits-32) << 32; | 440 return V | (uint64_t)Read(NumBits-32) << 32; |
431 } | 441 } |
432 | 442 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 private: | 481 private: |
472 void SkipToFourByteBoundary() { | 482 void SkipToFourByteBoundary() { |
473 // If word_t is 64-bits and if we've read less than 32 bits, just dump | 483 // If word_t is 64-bits and if we've read less than 32 bits, just dump |
474 // the bits we have up to the next 32-bit boundary. | 484 // the bits we have up to the next 32-bit boundary. |
475 if (sizeof(word_t) > 4 && | 485 if (sizeof(word_t) > 4 && |
476 BitsInCurWord >= 32) { | 486 BitsInCurWord >= 32) { |
477 CurWord >>= BitsInCurWord-32; | 487 CurWord >>= BitsInCurWord-32; |
478 BitsInCurWord = 32; | 488 BitsInCurWord = 32; |
479 return; | 489 return; |
480 } | 490 } |
481 | 491 |
482 BitsInCurWord = 0; | 492 BitsInCurWord = 0; |
483 CurWord = 0; | |
484 } | 493 } |
485 public: | 494 public: |
486 | 495 |
487 unsigned ReadCode() { | 496 unsigned ReadCode() { |
488 return CurCodeSize.IsFixed | 497 return CurCodeSize.IsFixed |
489 ? Read(CurCodeSize.NumBits) | 498 ? Read(CurCodeSize.NumBits) |
490 : ReadVBR(CurCodeSize.NumBits); | 499 : ReadVBR(CurCodeSize.NumBits); |
491 } | 500 } |
492 | 501 |
493 // Block header: | 502 // Block header: |
(...skipping 21 matching lines...) Expand all Loading... | |
515 if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) | 524 if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) |
516 return true; | 525 return true; |
517 | 526 |
518 JumpToBit(SkipTo); | 527 JumpToBit(SkipTo); |
519 return false; | 528 return false; |
520 } | 529 } |
521 | 530 |
522 /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter | 531 /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter |
523 /// the block, and return true if the block has an error. | 532 /// the block, and return true if the block has an error. |
524 bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0); | 533 bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0); |
525 | 534 |
526 bool ReadBlockEnd() { | 535 bool ReadBlockEnd() { |
527 if (BlockScope.empty()) return true; | 536 if (BlockScope.empty()) return true; |
528 | 537 |
529 // Block tail: | 538 // Block tail: |
530 // [END_BLOCK, <align4bytes>] | 539 // [END_BLOCK, <align4bytes>] |
531 SkipToFourByteBoundary(); | 540 SkipToFourByteBoundary(); |
532 | 541 |
533 popBlockScope(); | 542 popBlockScope(); |
534 return false; | 543 return false; |
535 } | 544 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
597 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord, | 606 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord, |
598 // except that no abbreviation is built. | 607 // except that no abbreviation is built. |
599 void SkipAbbrevRecord(); | 608 void SkipAbbrevRecord(); |
600 | 609 |
601 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener); | 610 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener); |
602 }; | 611 }; |
603 | 612 |
604 } // End llvm namespace | 613 } // End llvm namespace |
605 | 614 |
606 #endif | 615 #endif |
OLD | NEW |