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/ADT/OwningPtr.h" | 19 #include "llvm/ADT/OwningPtr.h" |
19 #include "llvm/Bitcode/BitCodes.h" | 20 #include "llvm/Bitcode/NaCl/NaClBitCodes.h" |
20 #include "llvm/Support/Endian.h" | 21 #include "llvm/Support/Endian.h" |
21 #include "llvm/Support/StreamableMemoryObject.h" | 22 #include "llvm/Support/StreamableMemoryObject.h" |
22 #include <climits> | 23 #include <climits> |
23 #include <string> | 24 #include <string> |
24 #include <vector> | 25 #include <vector> |
25 | 26 |
26 namespace llvm { | 27 namespace llvm { |
27 | 28 |
28 class Deserializer; | 29 class Deserializer; |
29 | 30 |
30 /// BitstreamReader - This class is used to read from an LLVM bitcode stream, | 31 /// NaClBitstreamReader - This class is used to read from an NaCl |
jvoung (off chromium)
2013/04/29 21:49:34
an NaCl -> a NaCl
Karl
2013/05/01 16:23:23
Done.
| |
31 /// maintaining information that is global to decoding the entire file. While | 32 /// bitcode wire format stream, maintaining information that is global |
32 /// a file is being read, multiple cursors can be independently advanced or | 33 /// to decoding the entire file. While a file is being read, multiple |
33 /// skipped around within the file. These are represented by the | 34 /// cursors can be independently advanced or skipped around within the |
34 /// BitstreamCursor class. | 35 /// file. These are represented by the NaClBitstreamCursor class. |
35 class BitstreamReader { | 36 class NaClBitstreamReader { |
36 public: | 37 public: |
37 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. | 38 /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. |
38 /// These describe abbreviations that all blocks of the specified ID inherit. | 39 /// These describe abbreviations that all blocks of the specified ID inherit. |
39 struct BlockInfo { | 40 struct BlockInfo { |
40 unsigned BlockID; | 41 unsigned BlockID; |
41 std::vector<BitCodeAbbrev*> Abbrevs; | 42 std::vector<BitCodeAbbrev*> Abbrevs; |
42 std::string Name; | 43 std::string Name; |
43 | 44 |
44 std::vector<std::pair<unsigned, std::string> > RecordNames; | 45 std::vector<std::pair<unsigned, std::string> > RecordNames; |
45 }; | 46 }; |
46 private: | 47 private: |
47 OwningPtr<StreamableMemoryObject> BitcodeBytes; | 48 OwningPtr<StreamableMemoryObject> BitcodeBytes; |
48 | 49 |
49 std::vector<BlockInfo> BlockInfoRecords; | 50 std::vector<BlockInfo> BlockInfoRecords; |
50 | 51 |
51 /// IgnoreBlockInfoNames - This is set to true if we don't care about the | 52 /// IgnoreBlockInfoNames - This is set to true if we don't care about the |
52 /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer | 53 /// block/record name information in the BlockInfo block. Only llvm-bcanalyzer |
53 /// uses this. | 54 /// uses this. |
54 bool IgnoreBlockInfoNames; | 55 bool IgnoreBlockInfoNames; |
55 | 56 |
56 BitstreamReader(const BitstreamReader&) LLVM_DELETED_FUNCTION; | 57 NaClBitstreamReader(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION; |
57 void operator=(const BitstreamReader&) LLVM_DELETED_FUNCTION; | 58 void operator=(const NaClBitstreamReader&) LLVM_DELETED_FUNCTION; |
58 public: | 59 public: |
59 BitstreamReader() : IgnoreBlockInfoNames(true) { | 60 NaClBitstreamReader() : IgnoreBlockInfoNames(true) { |
60 } | 61 } |
61 | 62 |
62 BitstreamReader(const unsigned char *Start, const unsigned char *End) { | 63 NaClBitstreamReader(const unsigned char *Start, const unsigned char *End) { |
63 IgnoreBlockInfoNames = true; | 64 IgnoreBlockInfoNames = true; |
64 init(Start, End); | 65 init(Start, End); |
65 } | 66 } |
66 | 67 |
67 BitstreamReader(StreamableMemoryObject *bytes) { | 68 NaClBitstreamReader(StreamableMemoryObject *bytes) { |
68 BitcodeBytes.reset(bytes); | 69 BitcodeBytes.reset(bytes); |
69 } | 70 } |
70 | 71 |
71 void init(const unsigned char *Start, const unsigned char *End) { | 72 void init(const unsigned char *Start, const unsigned char *End) { |
72 assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); | 73 assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); |
73 BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); | 74 BitcodeBytes.reset(getNonStreamedMemoryObject(Start, End)); |
74 } | 75 } |
75 | 76 |
76 StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; } | 77 StreamableMemoryObject &getBitcodeBytes() { return *BitcodeBytes; } |
77 | 78 |
78 ~BitstreamReader() { | 79 ~NaClBitstreamReader() { |
79 // Free the BlockInfoRecords. | 80 // Free the BlockInfoRecords. |
80 while (!BlockInfoRecords.empty()) { | 81 while (!BlockInfoRecords.empty()) { |
81 BlockInfo &Info = BlockInfoRecords.back(); | 82 BlockInfo &Info = BlockInfoRecords.back(); |
82 // Free blockinfo abbrev info. | 83 // Free blockinfo abbrev info. |
83 for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size()); | 84 for (unsigned i = 0, e = static_cast<unsigned>(Info.Abbrevs.size()); |
84 i != e; ++i) | 85 i != e; ++i) |
85 Info.Abbrevs[i]->dropRef(); | 86 Info.Abbrevs[i]->dropRef(); |
86 BlockInfoRecords.pop_back(); | 87 BlockInfoRecords.pop_back(); |
87 } | 88 } |
88 } | 89 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
120 return *const_cast<BlockInfo*>(BI); | 121 return *const_cast<BlockInfo*>(BI); |
121 | 122 |
122 // Otherwise, add a new record. | 123 // Otherwise, add a new record. |
123 BlockInfoRecords.push_back(BlockInfo()); | 124 BlockInfoRecords.push_back(BlockInfo()); |
124 BlockInfoRecords.back().BlockID = BlockID; | 125 BlockInfoRecords.back().BlockID = BlockID; |
125 return BlockInfoRecords.back(); | 126 return BlockInfoRecords.back(); |
126 } | 127 } |
127 }; | 128 }; |
128 | 129 |
129 | 130 |
130 /// BitstreamEntry - When advancing through a bitstream cursor, each advance can | 131 /// NaClBitstreamEntry - When advancing through a bitstream cursor, |
131 /// discover a few different kinds of entries: | 132 /// each advance can discover a few different kinds of entries: |
132 /// Error - Malformed bitcode was found. | 133 /// Error - Malformed bitcode was found. |
133 /// EndBlock - We've reached the end of the current block, (or the end of the | 134 /// EndBlock - We've reached the end of the current block, (or the end of the |
134 /// file, which is treated like a series of EndBlock records. | 135 /// file, which is treated like a series of EndBlock records. |
135 /// SubBlock - This is the start of a new subblock of a specific ID. | 136 /// SubBlock - This is the start of a new subblock of a specific ID. |
136 /// Record - This is a record with a specific AbbrevID. | 137 /// Record - This is a record with a specific AbbrevID. |
137 /// | 138 /// |
138 struct BitstreamEntry { | 139 struct NaClBitstreamEntry { |
139 enum { | 140 enum { |
140 Error, | 141 Error, |
141 EndBlock, | 142 EndBlock, |
142 SubBlock, | 143 SubBlock, |
143 Record | 144 Record |
144 } Kind; | 145 } Kind; |
145 | 146 |
146 unsigned ID; | 147 unsigned ID; |
147 | 148 |
148 static BitstreamEntry getError() { | 149 static NaClBitstreamEntry getError() { |
149 BitstreamEntry E; E.Kind = Error; return E; | 150 NaClBitstreamEntry E; E.Kind = Error; return E; |
150 } | 151 } |
151 static BitstreamEntry getEndBlock() { | 152 static NaClBitstreamEntry getEndBlock() { |
152 BitstreamEntry E; E.Kind = EndBlock; return E; | 153 NaClBitstreamEntry E; E.Kind = EndBlock; return E; |
153 } | 154 } |
154 static BitstreamEntry getSubBlock(unsigned ID) { | 155 static NaClBitstreamEntry getSubBlock(unsigned ID) { |
155 BitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; | 156 NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E; |
156 } | 157 } |
157 static BitstreamEntry getRecord(unsigned AbbrevID) { | 158 static NaClBitstreamEntry getRecord(unsigned AbbrevID) { |
158 BitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; | 159 NaClBitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E; |
159 } | 160 } |
160 }; | 161 }; |
161 | 162 |
162 /// BitstreamCursor - This represents a position within a bitcode file. There | 163 /// NaClBitstreamCursor - This represents a position within a bitcode |
163 /// may be multiple independent cursors reading within one bitstream, each | 164 /// file. There may be multiple independent cursors reading within |
164 /// maintaining their own local state. | 165 /// one bitstream, each maintaining their own local state. |
165 /// | 166 /// |
166 /// Unlike iterators, BitstreamCursors are heavy-weight objects that should not | 167 /// Unlike iterators, NaClBitstreamCursors are heavy-weight objects |
167 /// be passed by value. | 168 /// that should not be passed by value. |
168 class BitstreamCursor { | 169 class NaClBitstreamCursor { |
169 friend class Deserializer; | 170 friend class Deserializer; |
170 BitstreamReader *BitStream; | 171 NaClBitstreamReader *BitStream; |
171 size_t NextChar; | 172 size_t NextChar; |
172 | 173 |
173 | 174 |
174 /// CurWord/word_t - This is the current data we have pulled from the stream | 175 /// CurWord/word_t - This is the current data we have pulled from the stream |
175 /// but have not returned to the client. This is specifically and | 176 /// but have not returned to the client. This is specifically and |
176 /// intentionally defined to follow the word size of the host machine for | 177 /// intentionally defined to follow the word size of the host machine for |
177 /// efficiency. We use word_t in places that are aware of this to make it | 178 /// efficiency. We use word_t in places that are aware of this to make it |
178 /// perfectly explicit what is going on. | 179 /// perfectly explicit what is going on. |
179 typedef uint32_t word_t; | 180 typedef uint32_t word_t; |
180 word_t CurWord; | 181 word_t CurWord; |
(...skipping 13 matching lines...) Expand all Loading... | |
194 unsigned PrevCodeSize; | 195 unsigned PrevCodeSize; |
195 std::vector<BitCodeAbbrev*> PrevAbbrevs; | 196 std::vector<BitCodeAbbrev*> PrevAbbrevs; |
196 explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} | 197 explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} |
197 }; | 198 }; |
198 | 199 |
199 /// BlockScope - This tracks the codesize of parent blocks. | 200 /// BlockScope - This tracks the codesize of parent blocks. |
200 SmallVector<Block, 8> BlockScope; | 201 SmallVector<Block, 8> BlockScope; |
201 | 202 |
202 | 203 |
203 public: | 204 public: |
204 BitstreamCursor() : BitStream(0), NextChar(0) { | 205 NaClBitstreamCursor() : BitStream(0), NextChar(0) { |
205 } | 206 } |
206 BitstreamCursor(const BitstreamCursor &RHS) : BitStream(0), NextChar(0) { | 207 NaClBitstreamCursor(const NaClBitstreamCursor &RHS) |
208 : BitStream(0), NextChar(0) { | |
207 operator=(RHS); | 209 operator=(RHS); |
208 } | 210 } |
209 | 211 |
210 explicit BitstreamCursor(BitstreamReader &R) : BitStream(&R) { | 212 explicit NaClBitstreamCursor(NaClBitstreamReader &R) : BitStream(&R) { |
211 NextChar = 0; | 213 NextChar = 0; |
212 CurWord = 0; | 214 CurWord = 0; |
213 BitsInCurWord = 0; | 215 BitsInCurWord = 0; |
214 CurCodeSize = 2; | 216 CurCodeSize = 2; |
215 } | 217 } |
216 | 218 |
217 void init(BitstreamReader &R) { | 219 void init(NaClBitstreamReader &R) { |
218 freeState(); | 220 freeState(); |
219 | 221 |
220 BitStream = &R; | 222 BitStream = &R; |
221 NextChar = 0; | 223 NextChar = 0; |
222 CurWord = 0; | 224 CurWord = 0; |
223 BitsInCurWord = 0; | 225 BitsInCurWord = 0; |
224 CurCodeSize = 2; | 226 CurCodeSize = 2; |
225 } | 227 } |
226 | 228 |
227 ~BitstreamCursor() { | 229 ~NaClBitstreamCursor() { |
228 freeState(); | 230 freeState(); |
229 } | 231 } |
230 | 232 |
231 void operator=(const BitstreamCursor &RHS); | 233 void operator=(const NaClBitstreamCursor &RHS); |
232 | 234 |
233 void freeState(); | 235 void freeState(); |
234 | 236 |
235 bool isEndPos(size_t pos) { | 237 bool isEndPos(size_t pos) { |
236 return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); | 238 return BitStream->getBitcodeBytes().isObjectEnd(static_cast<uint64_t>(pos)); |
237 } | 239 } |
238 | 240 |
239 bool canSkipToPos(size_t pos) const { | 241 bool canSkipToPos(size_t pos) const { |
240 // pos can be skipped to if it is a valid address or one byte past the end. | 242 // pos can be skipped to if it is a valid address or one byte past the end. |
241 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( | 243 return pos == 0 || BitStream->getBitcodeBytes().isValidAddress( |
(...skipping 11 matching lines...) Expand all Loading... | |
253 } | 255 } |
254 | 256 |
255 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. | 257 /// getAbbrevIDWidth - Return the number of bits used to encode an abbrev #. |
256 unsigned getAbbrevIDWidth() const { return CurCodeSize; } | 258 unsigned getAbbrevIDWidth() const { return CurCodeSize; } |
257 | 259 |
258 /// GetCurrentBitNo - Return the bit # of the bit we are reading. | 260 /// GetCurrentBitNo - Return the bit # of the bit we are reading. |
259 uint64_t GetCurrentBitNo() const { | 261 uint64_t GetCurrentBitNo() const { |
260 return NextChar*CHAR_BIT - BitsInCurWord; | 262 return NextChar*CHAR_BIT - BitsInCurWord; |
261 } | 263 } |
262 | 264 |
263 BitstreamReader *getBitStreamReader() { | 265 NaClBitstreamReader *getBitStreamReader() { |
264 return BitStream; | 266 return BitStream; |
265 } | 267 } |
266 const BitstreamReader *getBitStreamReader() const { | 268 const NaClBitstreamReader *getBitStreamReader() const { |
267 return BitStream; | 269 return BitStream; |
268 } | 270 } |
269 | 271 |
270 /// Flags that modify the behavior of advance(). | 272 /// Flags that modify the behavior of advance(). |
271 enum { | 273 enum { |
272 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does | 274 /// AF_DontPopBlockAtEnd - If this flag is used, the advance() method does |
273 /// not automatically pop the block scope when the end of a block is | 275 /// not automatically pop the block scope when the end of a block is |
274 /// reached. | 276 /// reached. |
275 AF_DontPopBlockAtEnd = 1, | 277 AF_DontPopBlockAtEnd = 1, |
276 | 278 |
277 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are | 279 /// AF_DontAutoprocessAbbrevs - If this flag is used, abbrev entries are |
278 /// returned just like normal records. | 280 /// returned just like normal records. |
279 AF_DontAutoprocessAbbrevs = 2 | 281 AF_DontAutoprocessAbbrevs = 2 |
280 }; | 282 }; |
281 | 283 |
282 /// advance - Advance the current bitstream, returning the next entry in the | 284 /// advance - Advance the current bitstream, returning the next entry in the |
283 /// stream. | 285 /// stream. |
284 BitstreamEntry advance(unsigned Flags = 0) { | 286 NaClBitstreamEntry advance(unsigned Flags = 0) { |
285 while (1) { | 287 while (1) { |
286 unsigned Code = ReadCode(); | 288 unsigned Code = ReadCode(); |
287 if (Code == bitc::END_BLOCK) { | 289 if (Code == bitc::END_BLOCK) { |
288 // Pop the end of the block unless Flags tells us not to. | 290 // Pop the end of the block unless Flags tells us not to. |
289 if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) | 291 if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd()) |
290 return BitstreamEntry::getError(); | 292 return NaClBitstreamEntry::getError(); |
291 return BitstreamEntry::getEndBlock(); | 293 return NaClBitstreamEntry::getEndBlock(); |
292 } | 294 } |
293 | 295 |
294 if (Code == bitc::ENTER_SUBBLOCK) | 296 if (Code == bitc::ENTER_SUBBLOCK) |
295 return BitstreamEntry::getSubBlock(ReadSubBlockID()); | 297 return NaClBitstreamEntry::getSubBlock(ReadSubBlockID()); |
296 | 298 |
297 if (Code == bitc::DEFINE_ABBREV && | 299 if (Code == bitc::DEFINE_ABBREV && |
298 !(Flags & AF_DontAutoprocessAbbrevs)) { | 300 !(Flags & AF_DontAutoprocessAbbrevs)) { |
299 // We read and accumulate abbrev's, the client can't do anything with | 301 // We read and accumulate abbrev's, the client can't do anything with |
300 // them anyway. | 302 // them anyway. |
301 ReadAbbrevRecord(); | 303 ReadAbbrevRecord(); |
302 continue; | 304 continue; |
303 } | 305 } |
304 | 306 |
305 return BitstreamEntry::getRecord(Code); | 307 return NaClBitstreamEntry::getRecord(Code); |
306 } | 308 } |
307 } | 309 } |
308 | 310 |
309 /// advanceSkippingSubblocks - This is a convenience function for clients that | 311 /// advanceSkippingSubblocks - This is a convenience function for clients that |
310 /// don't expect any subblocks. This just skips over them automatically. | 312 /// don't expect any subblocks. This just skips over them automatically. |
311 BitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { | 313 NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) { |
312 while (1) { | 314 while (1) { |
313 // If we found a normal entry, return it. | 315 // If we found a normal entry, return it. |
314 BitstreamEntry Entry = advance(Flags); | 316 NaClBitstreamEntry Entry = advance(Flags); |
315 if (Entry.Kind != BitstreamEntry::SubBlock) | 317 if (Entry.Kind != NaClBitstreamEntry::SubBlock) |
316 return Entry; | 318 return Entry; |
317 | 319 |
318 // If we found a sub-block, just skip over it and check the next entry. | 320 // If we found a sub-block, just skip over it and check the next entry. |
319 if (SkipBlock()) | 321 if (SkipBlock()) |
320 return BitstreamEntry::getError(); | 322 return NaClBitstreamEntry::getError(); |
321 } | 323 } |
322 } | 324 } |
323 | 325 |
324 /// JumpToBit - Reset the stream to the specified bit number. | 326 /// JumpToBit - Reset the stream to the specified bit number. |
325 void JumpToBit(uint64_t BitNo) { | 327 void JumpToBit(uint64_t BitNo) { |
326 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); | 328 uintptr_t ByteNo = uintptr_t(BitNo/8) & ~(sizeof(word_t)-1); |
327 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); | 329 unsigned WordBitNo = unsigned(BitNo & (sizeof(word_t)*8-1)); |
328 assert(canSkipToPos(ByteNo) && "Invalid location"); | 330 assert(canSkipToPos(ByteNo) && "Invalid location"); |
329 | 331 |
330 // Move the cursor to the right word. | 332 // Move the cursor to the right word. |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 // Abbrev Processing | 551 // Abbrev Processing |
550 //===--------------------------------------------------------------------===// | 552 //===--------------------------------------------------------------------===// |
551 void ReadAbbrevRecord(); | 553 void ReadAbbrevRecord(); |
552 | 554 |
553 bool ReadBlockInfoBlock(); | 555 bool ReadBlockInfoBlock(); |
554 }; | 556 }; |
555 | 557 |
556 } // End llvm namespace | 558 } // End llvm namespace |
557 | 559 |
558 #endif | 560 #endif |
OLD | NEW |