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

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

Issue 14314016: Copy LLVM bitcode reader to generate a PNaCl wire format reader. (Closed) Base URL: http://git.chromium.org/native_client/pnacl-llvm.git@master
Patch Set: Created 7 years, 7 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 //===- 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/NaClLLVMBitCodes.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 a NaCl
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h » ('j') | include/llvm/Bitcode/NaCl/NaClLLVMBitCodes.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698