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

Side by Side Diff: include/llvm/Bitcode/NaCl/NaClBitstreamReader.h

Issue 940243003: PNaCl localmod mods in LLVM to 223109 (local files only) (Closed)
Patch Set: fix comment 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 unified diff | Download patch
OLDNEW
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 /// This class is used to read from a NaCl bitcode wire format stream,
31 /// bitcode wire format stream, maintaining information that is global 31 /// maintaining information that is global to decoding the entire file.
32 /// to decoding the entire file. While a file is being read, multiple 32 /// While a file is being read, multiple cursors can be independently
33 /// cursors can be independently advanced or skipped around within the 33 /// advanced or skipped around within the file. These are represented by
34 /// file. These are represented by the NaClBitstreamCursor class. 34 /// the NaClBitstreamCursor class.
35 class NaClBitstreamReader { 35 class NaClBitstreamReader {
36 public: 36 public:
37 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. 37 /// This contains information emitted to BLOCKINFO_BLOCK blocks. These
38 /// These describe abbreviations that all blocks of the specified ID inherit. 38 /// 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();
85 } 83 }
86 } 84 }
87 85
88 /// \brief Returns the initial address (after the header) of the input stream. 86 /// \brief Returns the initial address (after the header) of the input stream.
89 size_t getInitialAddress() const { 87 size_t getInitialAddress() const {
90 return InitialAddress; 88 return InitialAddress;
91 } 89 }
92 90
93 //===--------------------------------------------------------------------===// 91 //===--------------------------------------------------------------------===//
94 // Block Manipulation 92 // Block Manipulation
95 //===--------------------------------------------------------------------===// 93 //===--------------------------------------------------------------------===//
96 94
97 /// hasBlockInfoRecords - Return true if we've already read and processed the 95 /// Return true if we've already read and processed the block info block for
98 /// block info block for this Bitstream. We only process it for the first 96 /// this Bitstream. We only process it for the first cursor that walks over
99 /// cursor that walks over it. 97 /// it.
100 bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); } 98 bool hasBlockInfoRecords() const { return !BlockInfoRecords.empty(); }
101 99
102 /// getBlockInfo - If there is block info for the specified ID, return it, 100 /// If there is block info for the specified ID, return it, otherwise return
103 /// otherwise return null. 101 /// null.
104 const BlockInfo *getBlockInfo(unsigned BlockID) const { 102 const BlockInfo *getBlockInfo(unsigned BlockID) const {
105 // Common case, the most recent entry matches BlockID. 103 // Common case, the most recent entry matches BlockID.
106 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) 104 if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID)
107 return &BlockInfoRecords.back(); 105 return &BlockInfoRecords.back();
108 106
109 for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size()); 107 for (unsigned i = 0, e = static_cast<unsigned>(BlockInfoRecords.size());
110 i != e; ++i) 108 i != e; ++i)
111 if (BlockInfoRecords[i].BlockID == BlockID) 109 if (BlockInfoRecords[i].BlockID == BlockID)
112 return &BlockInfoRecords[i]; 110 return &BlockInfoRecords[i];
113 return 0; 111 return nullptr;
114 } 112 }
115 113
116 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { 114 BlockInfo &getOrCreateBlockInfo(unsigned BlockID) {
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 /// When advancing through a bitstream cursor, each advance can discover a few
128 /// NaClBitstreamEntry - When advancing through a bitstream cursor, 126 /// different kinds of entries:
129 /// each advance can discover a few different kinds of entries:
130 /// Error - Malformed bitcode was found.
131 /// 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.
133 /// SubBlock - This is the start of a new subblock of a specific ID.
134 /// Record - This is a record with a specific AbbrevID.
135 ///
136 struct NaClBitstreamEntry { 127 struct NaClBitstreamEntry {
137 enum { 128 enum {
138 Error, 129 Error, // Malformed bitcode was found.
139 EndBlock, 130 EndBlock, // We've reached the end of the current block, (or the end of the
140 SubBlock, 131 // file, which is treated like a series of EndBlock records.
141 Record 132 SubBlock, // This is the start of a new subblock of a specific ID.
133 Record // This is a record with a specific AbbrevID.
142 } Kind; 134 } Kind;
143 135
144 unsigned ID; 136 unsigned ID;
145 137
146 static NaClBitstreamEntry getError() { 138 static NaClBitstreamEntry getError() {
147 NaClBitstreamEntry E; E.Kind = Error; return E; 139 NaClBitstreamEntry E; E.Kind = Error; return E;
148 } 140 }
149 static NaClBitstreamEntry getEndBlock() { 141 static NaClBitstreamEntry getEndBlock() {
150 NaClBitstreamEntry E; E.Kind = EndBlock; return E; 142 NaClBitstreamEntry E; E.Kind = EndBlock; return E;
151 } 143 }
152 static NaClBitstreamEntry getSubBlock(unsigned ID) { 144 static NaClBitstreamEntry getSubBlock(unsigned ID) {
153 NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; 145 NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 187
196 /// The values of the bitcode record associated with the called 188 /// The values of the bitcode record associated with the called
197 /// virtual function. 189 /// virtual function.
198 NaClBitcodeRecordVector Values; 190 NaClBitcodeRecordVector Values;
199 191
200 /// Start bit for current record being processed in 192 /// Start bit for current record being processed in
201 /// NaClBitstreamCursor::ReadBlockInfoBlock. 193 /// NaClBitstreamCursor::ReadBlockInfoBlock.
202 uint64_t StartBit; 194 uint64_t StartBit;
203 }; 195 };
204 196
205 /// NaClBitstreamCursor - This represents a position within a bitcode 197 /// This represents a position within a bitcode file. There may be multiple
206 /// file. There may be multiple independent cursors reading within 198 /// independent cursors reading within one bitstream, each maintaining their
207 /// one bitstream, each maintaining their own local state. 199 /// own local state.
208 /// 200 ///
209 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects 201 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects
210 /// that should not be passed by value. 202 /// that should not be passed by value.
211 class NaClBitstreamCursor { 203 class NaClBitstreamCursor {
212 friend class Deserializer; 204 friend class Deserializer;
213 NaClBitstreamReader *BitStream; 205 NaClBitstreamReader *BitStream;
214 size_t NextChar; 206 size_t NextChar;
215 207
216 /// CurWord/word_t - This is the current data we have pulled from the stream 208 // The size of the bitcode. 0 if we don't know it yet.
217 /// but have not returned to the client. This is specifically and 209 size_t Size;
218 /// intentionally defined to follow the word size of the host machine for 210
219 /// efficiency. We use word_t in places that are aware of this to make it 211 /// This is the current data we have pulled from the stream but have not
220 /// perfectly explicit what is going on. 212 /// returned to the client. This is specifically and intentionally defined to
221 typedef uint32_t word_t; 213 /// follow the word size of the host machine for efficiency. We use word_t in
214 /// places that are aware of this to make it perfectly explicit what is going
215 /// on.
216 typedef size_t word_t;
222 word_t CurWord; 217 word_t CurWord;
223 218
224 /// BitsInCurWord - This is the number of bits in CurWord that are valid. This 219 /// This is the number of bits in CurWord that are valid. This
225 /// is always from [0...31/63] inclusive (depending on word size). 220 /// is always from [0...bits_of(word_t)-1] inclusive.
226 unsigned BitsInCurWord; 221 unsigned BitsInCurWord;
227 222
228 // CurCodeSize - This is the declared size of code values used for the current 223 /// This is the declared size of code values used for the current
229 // block, in bits. 224 /// block, in bits.
230 NaClBitcodeSelectorAbbrev CurCodeSize; 225 NaClBitcodeSelectorAbbrev CurCodeSize;
231 226
232 /// CurAbbrevs - Abbrevs installed at in this block. 227 /// Abbrevs installed in this block.
233 std::vector<NaClBitCodeAbbrev*> CurAbbrevs; 228 std::vector<NaClBitCodeAbbrev*> CurAbbrevs;
234 229
235 struct Block { 230 struct Block {
236 NaClBitcodeSelectorAbbrev PrevCodeSize; 231 NaClBitcodeSelectorAbbrev PrevCodeSize;
237 std::vector<NaClBitCodeAbbrev*> PrevAbbrevs; 232 std::vector<NaClBitCodeAbbrev*> PrevAbbrevs;
238 explicit Block() : PrevCodeSize() {} 233 Block() : PrevCodeSize() {}
239 explicit Block(const NaClBitcodeSelectorAbbrev& PCS) 234 explicit Block(const NaClBitcodeSelectorAbbrev& PCS)
240 : PrevCodeSize(PCS) {} 235 : PrevCodeSize(PCS) {}
241 }; 236 };
242 237
243 /// BlockScope - This tracks the codesize of parent blocks. 238 /// This tracks the codesize of parent blocks.
244 SmallVector<Block, 8> BlockScope; 239 SmallVector<Block, 8> BlockScope;
245 240
246 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION; 241 NaClBitstreamCursor(const NaClBitstreamCursor &) LLVM_DELETED_FUNCTION;
247 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT ION; 242 NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) LLVM_DELETED_FUNCT ION;
248 243
249 public: 244 public:
250 245 NaClBitstreamCursor() { init(nullptr); }
251 NaClBitstreamCursor() {
252 init(nullptr);
253 }
254 246
255 explicit NaClBitstreamCursor(NaClBitstreamReader &R) { init(&R); } 247 explicit NaClBitstreamCursor(NaClBitstreamReader &R) { init(&R); }
256 248
257 void init(NaClBitstreamReader *R) { 249 void init(NaClBitstreamReader *R) {
258 freeState(); 250 freeState();
259 BitStream = R; 251 BitStream = R;
260 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress(); 252 NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress();
261 CurWord = 0; 253 Size = 0;
262 BitsInCurWord = 0; 254 BitsInCurWord = 0;
263 } 255 }
264 256
265 ~NaClBitstreamCursor() { 257 ~NaClBitstreamCursor() {
266 freeState(); 258 freeState();
267 } 259 }
268 260
269 void freeState(); 261 void freeState();
270 262
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 { 263 bool canSkipToPos(size_t pos) const {
276 // 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.
277 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( 265 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
278 static_cast<uint64_t>(pos - 1)); 266 static_cast<uint64_t>(pos - 1));
279 } 267 }
280 268
281 bool AtEndOfStream() { 269 bool AtEndOfStream() {
282 return BitsInCurWord == 0 && isEndPos(NextChar); 270 if (BitsInCurWord != 0)
271 return false;
272 if (Size != 0)
273 return Size == NextChar;
274 fillCurWord();
275 return BitsInCurWord == 0;
283 } 276 }
284 277
285 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. 278 /// Return the number of bits used to encode an abbrev #.
286 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; } 279 unsigned getAbbrevIDWidth() const { return CurCodeSize.NumBits; }
287 280
288 /// GetCurrentBitNo - Return the bit # of the bit we are reading. 281 /// Return the bit # of the bit we are reading.
289 uint64_t GetCurrentBitNo() const { 282 uint64_t GetCurrentBitNo() const {
290 return NextChar*CHAR_BIT - BitsInCurWord; 283 return NextChar*CHAR_BIT - BitsInCurWord;
291 } 284 }
292 285
293 NaClBitstreamReader *getBitStreamReader() { 286 NaClBitstreamReader *getBitStreamReader() {
294 return BitStream; 287 return BitStream;
295 } 288 }
296 const NaClBitstreamReader *getBitStreamReader() const { 289 const NaClBitstreamReader *getBitStreamReader() const {
297 return BitStream; 290 return BitStream;
298 } 291 }
299 292
300 /// Flags that modify the behavior of advance(). 293 /// Flags that modify the behavior of advance().
301 enum { 294 enum {
302 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does 295 /// If this flag is used, the advance() method does not automatically pop
303 /// not automatically pop the block scope when the end of a block is 296 /// the block scope when the end of a block is reached.
304 /// reached.
305 AF_DontPopBlockAtEnd = 1, 297 AF_DontPopBlockAtEnd = 1,
306 298
307 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are 299 /// If this flag is used, abbrev entries are returned just like normal
308 /// returned just like normal records. 300 /// records.
309 AF_DontAutoprocessAbbrevs = 2 301 AF_DontAutoprocessAbbrevs = 2
310 }; 302 };
311 303
312 /// advance - Advance the current bitstream, returning the next entry in the 304 /// Advance the current bitstream, returning the next entry in the stream.
313 /// stream. Use the given abbreviation listener (if provided). 305 /// Use the given abbreviation listener (if provided).
314 NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) { 306 NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) {
315 while (1) { 307 while (1) {
316 unsigned Code = ReadCode(); 308 unsigned Code = ReadCode();
317 if (Code == naclbitc::END_BLOCK) { 309 if (Code == naclbitc::END_BLOCK) {
318 // 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.
319 if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) 311 if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
320 return NaClBitstreamEntry::getError(); 312 return NaClBitstreamEntry::getError();
321 return NaClBitstreamEntry::getEndBlock(); 313 return NaClBitstreamEntry::getEndBlock();
322 } 314 }
323 315
324 if (Code == naclbitc::ENTER_SUBBLOCK) 316 if (Code == naclbitc::ENTER_SUBBLOCK)
325 return NaClBitstreamEntry::getSubBlock(ReadSubBlockID()); 317 return NaClBitstreamEntry::getSubBlock(ReadSubBlockID());
326 318
327 if (Code == naclbitc::DEFINE_ABBREV && 319 if (Code == naclbitc::DEFINE_ABBREV &&
328 !(Flags & AF_DontAutoprocessAbbrevs)) { 320 !(Flags & AF_DontAutoprocessAbbrevs)) {
329 // 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
330 // them anyway. 322 // them anyway.
331 ReadAbbrevRecord(true, Listener); 323 ReadAbbrevRecord(true, Listener);
332 continue; 324 continue;
333 } 325 }
334 326
335 return NaClBitstreamEntry::getRecord(Code); 327 return NaClBitstreamEntry::getRecord(Code);
336 } 328 }
337 } 329 }
338 330
339 /// advanceSkippingSubblocks - This is a convenience function for clients that 331 /// This is a convenience function for clients that don't expect any
340 /// don't expect any subblocks. This just skips over them automatically. 332 /// subblocks. This just skips over them automatically.
341 NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { 333 NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
342 while (1) { 334 while (1) {
343 // If we found a normal entry, return it. 335 // If we found a normal entry, return it.
344 NaClBitstreamEntry Entry = advance(Flags, 0); 336 NaClBitstreamEntry Entry = advance(Flags, 0);
345 if (Entry.Kind != NaClBitstreamEntry::SubBlock) 337 if (Entry.Kind != NaClBitstreamEntry::SubBlock)
346 return Entry; 338 return Entry;
347 339
348 // 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.
349 if (SkipBlock()) 341 if (SkipBlock())
350 return NaClBitstreamEntry::getError(); 342 return NaClBitstreamEntry::getError();
351 } 343 }
352 } 344 }
353 345
354 /// JumpToBit - Reset the stream to the specified bit number. 346 /// Reset the stream to the specified bit number.
355 void JumpToBit(uint64_t BitNo) { 347 void JumpToBit(uint64_t BitNo) {
356 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); 348 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1);
357 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); 349 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1));
358 assert(canSkipToPos(ByteNo) && "Invalid location"); 350 assert(canSkipToPos(ByteNo) && "Invalid location");
359 351
360 // Move the cursor to the right word. 352 // Move the cursor to the right word.
361 NextChar = ByteNo; 353 NextChar = ByteNo;
362 BitsInCurWord = 0; 354 BitsInCurWord = 0;
363 CurWord = 0;
364 355
365 // Skip over any bits that are already consumed. 356 // Skip over any bits that are already consumed.
366 if (WordBitNo) { 357 if (WordBitNo)
367 if (sizeof(word_t) > 4) 358 Read(WordBitNo);
368 Read64(WordBitNo);
369 else
370 Read(WordBitNo);
371 }
372 } 359 }
373 360
374 uint32_t Read(unsigned NumBits) { 361 void fillCurWord() {
375 assert(NumBits && NumBits <= 32 && 362 assert(Size == 0 || NextChar < (unsigned)Size);
376 "Cannot return zero or more than 32 bits!"); 363
377 364 // Read the next word from the stream.
365 uint8_t Array[sizeof(word_t)] = {0};
366
367 uint64_t BytesRead =
368 BitStream->getBitcodeBytes().readBytes(Array, sizeof(Array), NextChar);
369
370 // If we run out of data, stop at the end of the stream.
371 if (BytesRead == 0) {
372 Size = NextChar;
373 return;
374 }
375
376 CurWord =
377 support::endian::read<word_t, support::little, support::unaligned>(
378 Array);
379 NextChar += BytesRead;
380 BitsInCurWord = BytesRead * 8;
381 }
382
383 word_t Read(unsigned NumBits) {
384 static const unsigned BitsInWord = sizeof(word_t) * 8;
385
386 assert(NumBits && NumBits <= BitsInWord &&
387 "Cannot return zero or more than BitsInWord bits!");
388
389 static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f;
390
378 // If the field is fully contained by CurWord, return it quickly. 391 // If the field is fully contained by CurWord, return it quickly.
379 if (BitsInCurWord >= NumBits) { 392 if (BitsInCurWord >= NumBits) {
380 uint32_t R = uint32_t(CurWord) & (~0U >> (32-NumBits)); 393 word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits));
381 CurWord >>= NumBits; 394
395 // Use a mask to avoid undefined behavior.
396 CurWord >>= (NumBits & Mask);
397
382 BitsInCurWord -= NumBits; 398 BitsInCurWord -= NumBits;
383 return R; 399 return R;
384 } 400 }
385 401
402 word_t R = BitsInCurWord ? CurWord : 0;
403 unsigned BitsLeft = NumBits - BitsInCurWord;
404
405 fillCurWord();
406
386 // If we run out of data, stop at the end of the stream. 407 // If we run out of data, stop at the end of the stream.
387 if (isEndPos(NextChar)) { 408 if (BitsLeft > BitsInCurWord)
388 CurWord = 0;
389 BitsInCurWord = 0;
390 return 0; 409 return 0;
391 }
392 410
393 uint32_t R = uint32_t(CurWord); 411 word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));
394 412
395 // Read the next word from the stream. 413 // Use a mask to avoid undefined behavior.
396 uint8_t Array[sizeof(word_t)] = {0}; 414 CurWord >>= (BitsLeft & Mask);
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 415
407 NextChar += sizeof(word_t); 416 BitsInCurWord -= BitsLeft;
408 417
409 // Extract NumBits-BitsInCurWord from what we just read. 418 R |= R2 << (NumBits - BitsLeft);
410 unsigned BitsLeft = NumBits-BitsInCurWord;
411 419
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; 420 return R;
424 } 421 }
425 422
426 uint64_t Read64(unsigned NumBits) {
427 if (NumBits <= 32) return Read(NumBits);
428
429 uint64_t V = Read(32);
430 return V | (uint64_t)Read(NumBits-32) << 32;
431 }
432
433 uint32_t ReadVBR(unsigned NumBits) { 423 uint32_t ReadVBR(unsigned NumBits) {
434 uint32_t Piece = Read(NumBits); 424 uint32_t Piece = Read(NumBits);
435 if ((Piece & (1U << (NumBits-1))) == 0) 425 if ((Piece & (1U << (NumBits-1))) == 0)
436 return Piece; 426 return Piece;
437 427
438 uint32_t Result = 0; 428 uint32_t Result = 0;
439 unsigned NextBit = 0; 429 unsigned NextBit = 0;
440 while (1) { 430 while (1) {
441 Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit; 431 Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit;
442 432
443 if ((Piece & (1U << (NumBits-1))) == 0) 433 if ((Piece & (1U << (NumBits-1))) == 0)
444 return Result; 434 return Result;
445 435
446 NextBit += NumBits-1; 436 NextBit += NumBits-1;
447 Piece = Read(NumBits); 437 Piece = Read(NumBits);
448 } 438 }
449 } 439 }
450 440
451 // ReadVBR64 - Read a VBR that may have a value up to 64-bits in size. The 441 // Read a VBR that may have a value up to 64-bits in size. The chunk size of
452 // chunk size of the VBR must still be <= 32 bits though. 442 // the VBR must still be <= 32 bits though.
453 uint64_t ReadVBR64(unsigned NumBits) { 443 uint64_t ReadVBR64(unsigned NumBits) {
454 uint32_t Piece = Read(NumBits); 444 uint32_t Piece = Read(NumBits);
455 if ((Piece & (1U << (NumBits-1))) == 0) 445 if ((Piece & (1U << (NumBits-1))) == 0)
456 return uint64_t(Piece); 446 return uint64_t(Piece);
457 447
458 uint64_t Result = 0; 448 uint64_t Result = 0;
459 unsigned NextBit = 0; 449 unsigned NextBit = 0;
460 while (1) { 450 while (1) {
461 Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit; 451 Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit;
462 452
463 if ((Piece & (1U << (NumBits-1))) == 0) 453 if ((Piece & (1U << (NumBits-1))) == 0)
464 return Result; 454 return Result;
465 455
466 NextBit += NumBits-1; 456 NextBit += NumBits-1;
467 Piece = Read(NumBits); 457 Piece = Read(NumBits);
468 } 458 }
469 } 459 }
470 460
471 private: 461 private:
472 void SkipToFourByteBoundary() { 462 void SkipToFourByteBoundary() {
473 // If word_t is 64-bits and if we've read less than 32 bits, just dump 463 // 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. 464 // the bits we have up to the next 32-bit boundary.
475 if (sizeof(word_t) > 4 && 465 if (sizeof(word_t) > 4 &&
476 BitsInCurWord >= 32) { 466 BitsInCurWord >= 32) {
477 CurWord >>= BitsInCurWord-32; 467 CurWord >>= BitsInCurWord-32;
478 BitsInCurWord = 32; 468 BitsInCurWord = 32;
479 return; 469 return;
480 } 470 }
481 471
482 BitsInCurWord = 0; 472 BitsInCurWord = 0;
483 CurWord = 0;
484 } 473 }
485 public: 474 public:
486 475
487 unsigned ReadCode() { 476 unsigned ReadCode() {
488 return CurCodeSize.IsFixed 477 return CurCodeSize.IsFixed
489 ? Read(CurCodeSize.NumBits) 478 ? Read(CurCodeSize.NumBits)
490 : ReadVBR(CurCodeSize.NumBits); 479 : ReadVBR(CurCodeSize.NumBits);
491 } 480 }
492 481
493 // Block header: 482 // Block header:
494 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] 483 // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]
495 484
496 /// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for 485 /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
497 /// the block.
498 unsigned ReadSubBlockID() { 486 unsigned ReadSubBlockID() {
499 return ReadVBR(naclbitc::BlockIDWidth); 487 return ReadVBR(naclbitc::BlockIDWidth);
500 } 488 }
501 489
502 /// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip 490 /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body
503 /// over the body of this block. If the block record is malformed, return 491 /// of this block. If the block record is malformed, return true.
504 /// true.
505 bool SkipBlock() { 492 bool SkipBlock() {
506 // 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
507 // don't care what code widths are used inside of it. 494 // don't care what code widths are used inside of it.
508 ReadVBR(naclbitc::CodeLenWidth); 495 ReadVBR(naclbitc::CodeLenWidth);
509 SkipToFourByteBoundary(); 496 SkipToFourByteBoundary();
510 unsigned NumFourBytes = Read(naclbitc::BlockSizeWidth); 497 unsigned NumFourBytes = Read(naclbitc::BlockSizeWidth);
511 498
512 // 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
513 // bogus. 500 // bogus.
514 size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8; 501 size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*8;
515 if (AtEndOfStream() || !canSkipToPos(SkipTo/8)) 502 if (AtEndOfStream() || !canSkipToPos(SkipTo/8))
516 return true; 503 return true;
517 504
518 JumpToBit(SkipTo); 505 JumpToBit(SkipTo);
519 return false; 506 return false;
520 } 507 }
521 508
522 /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter 509 /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true
523 /// the block, and return true if the block has an error. 510 /// if the block has an error.
524 bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0); 511 bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);
525 512
526 bool ReadBlockEnd() { 513 bool ReadBlockEnd() {
527 if (BlockScope.empty()) return true; 514 if (BlockScope.empty()) return true;
528 515
529 // Block tail: 516 // Block tail:
530 // [END_BLOCK, <align4bytes>] 517 // [END_BLOCK, <align4bytes>]
531 SkipToFourByteBoundary(); 518 SkipToFourByteBoundary();
532 519
533 popBlockScope(); 520 popBlockScope();
534 return false; 521 return false;
535 } 522 }
(...skipping 30 matching lines...) Expand all
566 inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op); 553 inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op);
567 554
568 // Reads the array abbreviation Op, NumArrayElements times, putting 555 // Reads the array abbreviation Op, NumArrayElements times, putting
569 // the read values in Vals. 556 // the read values in Vals.
570 inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op, 557 inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op,
571 unsigned NumArrayElements, 558 unsigned NumArrayElements,
572 SmallVectorImpl<uint64_t> &Vals); 559 SmallVectorImpl<uint64_t> &Vals);
573 560
574 public: 561 public:
575 562
576 /// getAbbrev - Return the abbreviation for the specified AbbrevId. 563 /// Return the abbreviation for the specified AbbrevId.
577 const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const { 564 const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const {
578 unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV; 565 unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV;
579 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); 566 assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!");
580 return CurAbbrevs[AbbrevNo]; 567 return CurAbbrevs[AbbrevNo];
581 } 568 }
582 569
583 /// skipRecord - Read the current record and discard it. 570 /// Read the current record and discard it.
584 void skipRecord(unsigned AbbrevID); 571 void skipRecord(unsigned AbbrevID);
585 572
586 unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals); 573 unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals);
587 574
588 //===--------------------------------------------------------------------===// 575 //===--------------------------------------------------------------------===//
589 // Abbrev Processing 576 // Abbrev Processing
590 //===--------------------------------------------------------------------===// 577 //===--------------------------------------------------------------------===//
591 // IsLocal indicates where the abbreviation occurs. If it is in the 578 // IsLocal indicates where the abbreviation occurs. If it is in the
592 // BlockInfo block, IsLocal is false. In all other cases, IsLocal is 579 // BlockInfo block, IsLocal is false. In all other cases, IsLocal is
593 // true. 580 // true.
594 void ReadAbbrevRecord(bool IsLocal, 581 void ReadAbbrevRecord(bool IsLocal,
595 NaClAbbrevListener *Listener); 582 NaClAbbrevListener *Listener);
596 583
597 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord, 584 // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord,
598 // except that no abbreviation is built. 585 // except that no abbreviation is built.
599 void SkipAbbrevRecord(); 586 void SkipAbbrevRecord();
600 587
601 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener); 588 bool ReadBlockInfoBlock(NaClAbbrevListener *Listener);
602 }; 589 };
603 590
604 } // End llvm namespace 591 } // End llvm namespace
605 592
606 #endif 593 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698