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