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

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

Issue 939073008: Rebased PNaCl localmods in LLVM to 223109 (Closed)
Patch Set: undo localmod Created 5 years, 9 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
(Empty)
1 //===- NaClBitcodeParser.h -----------------------------------*- C++ -*-===//
2 // Low-level bitcode driver to parse PNaCl bitcode files.
3 //
4 // The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10 //
11 // Parses and processes low-level PNaCl bitcode files. Defines class
12 // NaClBitcodeParser.
13 //
14 // The concepts of PNaCl bitcode files are basically the same as for
15 // LLVM bitcode files (see http://llvm.org/docs/BitCodeFormat.html for
16 // details).
17 //
18 // The bitstream format is an abstract encoding of structured data,
19 // very similar to XML in some ways. Like XML, bitstream files contain
20 // tags, and nested structures, and you can parse the file without
21 // having to understand the tags. Unlike XML, the bitstream format is
22 // a binary encoding, and provides a mechanism for the file to
23 // self-describe "abbreviations". Abbreviations are effectively size
24 // optimizations for the content.
25 //
26 // The bitcode file is conceptually a sequence of "blocks", defining
27 // the content. Blocks contain a sequence of records and
28 // blocks. Nested content is defined using nested blocks. A (data)
29 // "record" is a tag, and a vector of (unsigned integer) values.
30 //
31 // Blocks are identified using Block IDs. Each kind of block has a
32 // unique block "ID". Records have two elements:
33 //
34 // a) A "code" identifying what type of record it is.
35 // b) A vector of "values" defining the contents of the record.
36 //
37 // The bitstream "reader" (defined in NaClBitstreamReader.h) defines
38 // the implementation that converts the low-level bit file into
39 // records and blocks. The bit stream is processed by moving a
40 // "cursor" over the sequence of bits.
41 //
42 // The bitstream reader assumes that each block/record is read in by
43 // first reading the "entry". The entry defines whether it corresponds
44 // to one of the following:
45 //
46 // a) At the beginning of a (possibly nested) block
47 // b) At the end of the current block.
48 // c) The input defines an abberviation.
49 // d) The input defines a record.
50 //
51 // An entry contains two values, a "kind" and an "ID". The kind
52 // defines which of the four cases above occurs. The ID provides
53 // identifying information on how to further process the input. For
54 // case (a), the ID is the identifier associated with the the block
55 // being processed. For case (b) and (c) the ID is ignored. For case
56 // (d) the ID identifies the abbreviation that should be used to parse
57 // the values.
58 //
59 // The class NaClBitcodeParser defines a bitcode parser that extracts
60 // the blocks and records, which are then processed using virtual
61 // callbacks. In general, you will want to implement derived classes
62 // for each type of block, so that the corresponding data is processed
63 // appropriately.
64 //
65 // The class NaClBitcodeParser parses a bitcode block, and defines a
66 // set of callbacks for that block, including:
67 //
68 // a) EnterBlock: What to do once we have entered the block.
69 // b) ProcessRecord: What to do with each parsed record.
70 // c) ParseBlock: Parse the (nested) block with the given ID.
71 // d) ExitBlock: What to do once we have finished processing the block.
72 //
73 // Note that a separate instance of NaClBitcodeParser (or a
74 // corresponding derived class) is created for each nested block. Each
75 // instance is responsible for only parsing a single block. Method
76 // ParseBlock creates new instances to parse nested blocks. Method
77 // GetEnclosingParser() can be used to refer to the parser associated
78 // with the enclosing block.
79 //
80 // Currently, the default processing of abbreviations is handled by
81 // the PNaCl bitstream reader, rather than by the parser. A hook,
82 // ProcessBlockInfo exists if you want to do some processing before the
83 // BlockInfo block is exited.
84 //
85 // If you need to process abbreviations processed by the PNaCl
86 // bitstream reader, you must explicitly define a
87 // NaClBitcodeParserListener to listen (within the bitstream reader),
88 // and make appropriate call backs to the NaClBitcodeParser.
89 // The listener is glued to parsers using method SetListener.
90 //
91 // TODO(kschimpf): Define an intermediate derived class of
92 // NaClBitcodeParser that defines callbacks based on the actual
93 // structure of PNaCl bitcode files. That is, it has callbacks for
94 // each of the types of blocks (i.e. module, types, global variables,
95 // function, symbol tables etc). This derivied class can then be used
96 // as the base class for the bitcode reader.
97 // ===----------------------------------------------------------------------===/ /
98
99 #ifndef LLVM_BITCODE_NACL_NACLBITCODEPARSER_H
100 #define LLVM_BITCODE_NACL_NACLBITCODEPARSER_H
101
102 #include "llvm/Bitcode/NaCl/NaClBitstreamReader.h"
103 #include "llvm/Support/raw_ostream.h"
104 #include <vector>
105
106 namespace llvm {
107
108 namespace naclbitc {
109 // Special record codes used to model codes for predefined records.
110 // They are very large so that they do not conflict with existing
111 // record codes for user-defined blocks.
112 enum SpecialBlockCodes {
113 BLK_CODE_ENTER = 65535,
114 BLK_CODE_EXIT = 65534,
115 BLK_CODE_DEFINE_ABBREV = 65533,
116 BLK_CODE_HEADER = 65532
117 };
118
119 }
120
121 class NaClBitcodeRecord;
122 class NaClBitcodeParser;
123 class NaClBitcodeParserListener;
124
125 // Defines the base class for data extracted from the input bitstream
126 // (i.e blocks and records).
127 class NaClBitcodeData {
128 void operator=(const NaClBitcodeData&) LLVM_DELETED_FUNCTION;
129
130 public:
131 /// Create data element to be read from input cursor.
132 explicit NaClBitcodeData(NaClBitstreamCursor &Cursor)
133 : Cursor(Cursor), StartBit(Cursor.GetCurrentBitNo())
134 {}
135
136 /// Create copy of the given data element.
137 explicit NaClBitcodeData(const NaClBitcodeData &Data)
138 : Cursor(Data.Cursor), StartBit(Data.StartBit)
139 {}
140
141 /// Returns the bitstream reader being used.
142 NaClBitstreamReader &GetReader() const {
143 return *Cursor.getBitStreamReader();
144 }
145
146 /// Returns the cursor position within the bitstream.
147 NaClBitstreamCursor &GetCursor() const {
148 return Cursor;
149 }
150
151 /// Returns the number of bits defined by the data.
152 uint64_t GetNumBits() const {
153 return GetCursor().GetCurrentBitNo() - StartBit;
154 }
155
156 /// Returns the first bit of the stream data.
157 uint64_t GetStartBit() const {
158 return StartBit;
159 }
160
161 protected:
162 /// Change the start bit for the data to the new value.
163 void SetStartBit(uint64_t NewValue) {
164 StartBit = NewValue;
165 }
166
167 private:
168 // The bitstream cursor defining location within the bitcode file.
169 NaClBitstreamCursor &Cursor;
170
171 // Start bit for the record.
172 uint64_t StartBit;
173 };
174
175 /// Models the block defined by a (begin) block record, through the
176 /// (end) block record.
177 class NaClBitcodeBlock : public NaClBitcodeData {
178 NaClBitcodeBlock(const NaClBitcodeBlock &) LLVM_DELETED_FUNCTION;
179 void operator=(const NaClBitcodeBlock &) LLVM_DELETED_FUNCTION;
180
181 public:
182 /// Given the found (begin) block record for block BlockID, create
183 /// the corresponding data associated with that block.
184 NaClBitcodeBlock(unsigned BlockID, const NaClBitcodeRecord &Record);
185
186 /// Create block data for block BlockID, using the input cursor.
187 NaClBitcodeBlock(unsigned BlockID, NaClBitstreamCursor &Cursor)
188 : NaClBitcodeData(Cursor),
189 BlockID(BlockID),
190 EnclosingBlock(0)
191 {
192 LocalStartBit = GetStartBit();
193 }
194
195 /// Print the contents out to the given stream.
196 void Print(raw_ostream& os) const;
197
198 /// Returns pointer to the enclosing block.
199 const NaClBitcodeBlock *GetEnclosingBlock() const {
200 return EnclosingBlock;
201 }
202
203 /// Returns the block ID of the block.
204 unsigned GetBlockID() const {
205 return BlockID;
206 }
207
208 /// Returns the number of bits in the block associated with the
209 /// bitcode parser parsing this block, excluding nested blocks.
210 unsigned GetLocalNumBits() const {
211 return GetCursor().GetCurrentBitNo() - LocalStartBit;
212 }
213
214 protected:
215 // The block ID associated with this record.
216 unsigned BlockID;
217 // The enclosing block, if defined.
218 const NaClBitcodeBlock *EnclosingBlock;
219 // Start bit for the block, updated to skip nested blocks.
220 uint64_t LocalStartBit;
221
222 // Note: We friend class NaClBitcodeParser, so that it can
223 // update field LocalStartBit.
224 friend class NaClBitcodeParser;
225 };
226
227 typedef NaClBitcodeRecordVector NaClRecordVector;
228
229 class NaClBitcodeRecordData {
230 public:
231 // The selector code associated with the record.
232 unsigned Code;
233 // The sequence of values defining the parsed record.
234 NaClRecordVector Values;
235
236 void Print(raw_ostream &strm) const;
237 };
238
239 inline raw_ostream &operator<<(raw_ostream &Strm,
240 const NaClBitcodeRecordData &Data) {
241 Data.Print(Strm);
242 return Strm;
243 }
244
245 /// Simple container class to convert the values of the corresponding
246 /// read record to a simpler form, only containing values.
247 struct NaClBitcodeValues {
248 public:
249 NaClBitcodeValues(const NaClBitcodeRecordData &Record)
250 : Record(Record) {}
251
252 size_t size() const {
253 return Record.Values.size()+1;
254 }
255
256 uint64_t operator[](size_t index) const {
257 return index == 0 ? Record.Code : Record.Values[index-1];
258 }
259
260 private:
261 const NaClBitcodeRecordData &Record;
262 };
263
264 /// Defines the data associated with reading a block record in the
265 /// PNaCl bitcode stream.
266 class NaClBitcodeRecord : public NaClBitcodeData {
267 public:
268 /// Type for vector of values representing a record.
269 typedef NaClRecordVector RecordVector;
270
271 /// Creates a bitcode record, starting at the position defined
272 /// by cursor.
273 explicit NaClBitcodeRecord(const NaClBitcodeBlock &Block)
274 : NaClBitcodeData(Block.GetCursor()),
275 Block(Block)
276 {}
277
278 /// Print the contents out to the given stream.
279 void Print(raw_ostream& os) const;
280
281 /// The block the record appears in.
282 const NaClBitcodeBlock &GetBlock() const {
283 return Block;
284 }
285
286 /// Returns the block ID associated with the record.
287 unsigned GetBlockID() const {
288 return Block.GetBlockID();
289 }
290
291 /// Returns the kind of entry read from the input stream.
292 unsigned GetEntryKind() const {
293 return Entry.Kind;
294 }
295
296 /// Returns the code value (i.e. selector) associated with the
297 /// record.
298 unsigned GetCode() const {
299 return Data.Code;
300 }
301
302 /// Returns the EntryID (e.g. abbreviation if !=
303 /// naclbitc::UNABBREV_RECORD) associated with the record. Note:
304 /// for block-enter, block-exit, and define-abbreviation, EntryID is
305 /// not the corresponding abbreviation.
306 unsigned GetEntryID() const {
307 return Entry.ID;
308 }
309
310 /// Returns the (value) record associated with the read record.
311 const RecordVector &GetValues() const {
312 return Data.Values;
313 }
314
315 /// Allows lower level access to data representing record.
316 const NaClBitcodeRecordData &GetRecordData() const {
317 return Data;
318 }
319
320 /// Returns true if the record was read using an abbreviation.
321 bool UsedAnAbbreviation() const {
322 return GetEntryKind() == NaClBitstreamEntry::Record &&
323 GetEntryID() != naclbitc::UNABBREV_RECORD;
324 }
325
326 /// Returns the abbrevation index used to read the record.
327 /// Returns naclbitc::UNABBREV_RECORD if not applicable.
328 unsigned GetAbbreviationIndex() const {
329 return UsedAnAbbreviation()
330 ? GetEntryID() : static_cast<unsigned>(naclbitc::UNABBREV_RECORD);
331 }
332
333 /// Destructively change the abbreviation ID to the given value.
334 void SetAbbreviationIndex(unsigned Index) {
335 Entry.ID = Index;
336 }
337
338 protected:
339 // The block associated with the record.
340 const NaClBitcodeBlock &Block;
341 // The data of the record.
342 NaClBitcodeRecordData Data;
343 // The entry (i.e. value(s) preceding the record that define what
344 // value comes next).
345 NaClBitstreamEntry Entry;
346
347 private:
348 // Allows class NaClBitcodeParser to read values into the
349 // record, thereby hiding the details of how to read values.
350 friend class NaClBitcodeParser;
351 friend class NaClBitcodeParserListener;
352
353 /// Read bitstream entry. Defines what construct appears next in the
354 /// bitstream.
355 void ReadEntry() {
356 SetStartBit(GetCursor().GetCurrentBitNo());
357 Entry = GetCursor().
358 advance(NaClBitstreamCursor::AF_DontAutoprocessAbbrevs, 0);
359 }
360
361 /// Reads in a record's values, if the entry defines a record (Must
362 /// be called after ReadEntry).
363 void ReadValues() {
364 Data.Values.clear();
365 Data.Code = GetCursor().readRecord(Entry.ID, Data.Values);
366 }
367
368 NaClBitcodeRecord(const NaClBitcodeRecord &Rcd) LLVM_DELETED_FUNCTION;
369 void operator=(const NaClBitcodeRecord &Rcd) LLVM_DELETED_FUNCTION;
370 };
371
372 inline raw_ostream &operator<<(raw_ostream &Strm,
373 const NaClBitcodeRecord &Record) {
374 Record.Print(Strm);
375 return Strm;
376 }
377
378 /// Defines a listener to handle abbreviations within a bitcode file.
379 /// In particular, abbreviations and the BlockInfo block are made more
380 /// explicit, and then sent to the parser through virtuals
381 /// ProcessAbbreviation and SetBID.
382 class NaClBitcodeParserListener : public NaClAbbrevListener {
383 friend class NaClBitcodeParser;
384 public:
385 // Constructs a listener for the given parser. Note: All nested
386 // parsers automatically inherit this listener.
387 NaClBitcodeParserListener(NaClBitcodeParser *Parser)
388 : Parser(Parser), GlobalBlockID(naclbitc::BLOCKINFO_BLOCK_ID) {
389 }
390
391 virtual ~NaClBitcodeParserListener() {}
392
393 private:
394 virtual void BeginBlockInfoBlock(unsigned NumWords);
395
396 virtual void SetBID();
397
398 virtual void EndBlockInfoBlock();
399
400 virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev,
401 bool IsLocal);
402
403 /// The block parser currently being listened to.
404 NaClBitcodeParser *Parser;
405
406 /// The block ID to use if a global abbreviation. Note: This field is
407 /// updated by calls to method SetBID.
408 unsigned GlobalBlockID;
409 };
410
411 /// Parses a block in the PNaCl bitcode stream.
412 class NaClBitcodeParser {
413 // Allow listener privledges, so that it can update/call the parser
414 // using a clean API.
415 friend class NaClBitcodeParserListener;
416 public:
417
418 // Creates a parser to parse the the block at the given cursor in
419 // the PNaCl bitcode stream. This instance is a "dummy" instance
420 // that starts the parser.
421 explicit NaClBitcodeParser(NaClBitstreamCursor &Cursor)
422 : EnclosingParser(0),
423 Block(ILLEGAL_BLOCK_ID, Cursor),
424 Record(Block),
425 Listener(0),
426 ErrStream(&errs())
427 {}
428
429 virtual ~NaClBitcodeParser();
430
431 /// Reads the (top-level) block associated with the given block
432 /// record at the stream cursor. Returns true if unable to parse.
433 /// Can be called multiple times to parse multiple blocks.
434 bool Parse();
435
436 // Called once the bitstream reader has entered the corresponding
437 // subblock. Argument NumWords is set to the number of words in the
438 // corresponding subblock.
439 virtual void EnterBlock(unsigned /*NumWords*/) {}
440
441 // Called when the corresponding EndBlock of the block being parsed
442 // is found.
443 virtual void ExitBlock() {}
444
445 // Called after a BlockInfo block is parsed.
446 virtual void ProcessBlockInfo() {}
447
448 // Called after each record (within the block) is read (into field Record).
449 virtual void ProcessRecord() {}
450
451 // Called if a SetBID record is encountered in the BlockInfo block,
452 // and the parser has a listener.
453 virtual void SetBID() {}
454
455 // Called to process an abbreviation if the parser has a listener.
456 virtual void ProcessAbbreviation(unsigned /*BlockID*/,
457 NaClBitCodeAbbrev * /*Abbrev*/,
458 bool /*IsLocal*/) {}
459
460 // Creates an instance of the NaClBitcodeParser to use to parse the
461 // block with the given block ID, and then call's method
462 // ParseThisBlock() to parse the corresponding block. Note:
463 // Each derived class should define it's own version of this
464 // method, following the pattern below.
465 virtual bool ParseBlock(unsigned BlockID) {
466 // Default implementation just builds a parser that does nothing.
467 NaClBitcodeParser Parser(BlockID, this);
468 return Parser.ParseThisBlock();
469 }
470
471 // Changes the stream to print errors to, and returns the old error stream.
472 // There are two use cases:
473 // 1) To change (from the default errs()) inside the constructor of the
474 // derived class. In this context, it will be used for all error
475 // messages for the derived class.
476 // 2) Temporarily modify it for a single error message. In this context,
477 // the method Error() is overridden in the derived class, and
478 // calls this method twice. Once before calling base method Error(),
479 // and followed by a second call to restore the default error stream.
480 raw_ostream &setErrStream(raw_ostream &Stream) {
481 raw_ostream &OldErrStream = *ErrStream;
482 ErrStream = &Stream;
483 return OldErrStream;
484 }
485
486 // Called when error occurs. Message is the error to report. Always
487 // returns true (the error return value of Parse).
488 virtual bool Error(const std::string &Message) {
489 *ErrStream << "Error: " << Message << "\n";
490 return true;
491 }
492
493 // Returns the number of bits in this block, including nested blocks.
494 unsigned GetBlockNumBits() const {
495 return Block.GetNumBits();
496 }
497
498 // Returns the number of bits in this block, excluding nested blocks.
499 unsigned GetBlockLocalNumBits() const {
500 return Block.GetLocalNumBits();
501 }
502
503 /// Returns the block ID associated with the Parser.
504 unsigned GetBlockID() const {
505 return Block.GetBlockID();
506 }
507
508 NaClBitcodeBlock &GetBlock() {
509 return Block;
510 }
511
512 /// Returns the enclosing parser of this block.
513 NaClBitcodeParser *GetEnclosingParser() const {
514 // Note: The top-level parser instance is a dummy instance
515 // and is not considered an enclosing parser.
516 return EnclosingParser->EnclosingParser ? EnclosingParser : 0;
517 }
518
519 // Parses the block using the parser defined by
520 // ParseBlock(unsigned). Returns true if unable to parse the
521 // block. Note: Should only be called by virtual ParseBlock(unsigned).
522 bool ParseThisBlock() {
523 bool Results;
524 if (Listener) {
525 NaClBitcodeParser *CallingParser = Listener->Parser;
526 Listener->Parser = this;
527 Results = ParseThisBlockInternal();
528 Listener->Parser = CallingParser;
529 } else {
530 Results = ParseThisBlockInternal();
531 }
532 return Results;
533 }
534
535 /// Skips the current block, assuming the parser is at the beginning
536 /// of the block. That is, Record.GetEntryKind() equals
537 /// NaClBitstreamEntry::SubBlock. Returns false if
538 /// successful. Otherwise returns 1.
539 bool SkipBlock() {
540 if (Record.GetEntryKind() != NaClBitstreamEntry::SubBlock)
541 return Error("SkipBlock on non-block record");
542 return Record.GetCursor().SkipBlock();
543 }
544
545 protected:
546 // The containing parser.
547 NaClBitcodeParser *EnclosingParser;
548
549 // The block the parser is associated with.
550 NaClBitcodeBlock Block;
551
552 // The current record (within the block) being processed.
553 NaClBitcodeRecord Record;
554
555 // The listener (if any) to use.
556 NaClBitcodeParserListener *Listener;
557
558 // The error stream to use if non-null (uses errs() if null).
559 raw_ostream *ErrStream;
560
561 // Creates a block parser to parse the block associated with the
562 // bitcode entry that defines the beginning of a block. This
563 // instance actually parses the corresponding block.
564 NaClBitcodeParser(unsigned BlockID, NaClBitcodeParser *EnclosingParser)
565 : EnclosingParser(EnclosingParser),
566 Block(BlockID, EnclosingParser->Record),
567 Record(Block),
568 Listener(EnclosingParser->Listener),
569 ErrStream(EnclosingParser->ErrStream)
570 {}
571
572 /// Defines the listener for this block, and all enclosing blocks,
573 /// to be the given listener. Should be set in the constructor.
574 void SetListener(NaClBitcodeParserListener* UseListener) {
575 Listener = UseListener;
576 }
577
578 private:
579 // Special constant identifying the top-level instance.
580 static const unsigned ILLEGAL_BLOCK_ID = UINT_MAX;
581
582 // Parses the block. Returns true if unable to parse the
583 // block. Note: Should only be called by virtual ParseThisBlock.
584 bool ParseThisBlockInternal() {
585 bool Results;
586 if (GetBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) {
587 Results = ParseBlockInfoInternal();
588 } else {
589 Results = ParseBlockInternal();
590 ExitBlock();
591 }
592 return Results;
593 }
594
595 // Parses a BlockInfo block, where processing is handled through
596 // a listener in the bitstream reader.
597 bool ParseBlockInfoInternal();
598
599 // Parses the non-BlockInfo block. Returns true if unable to parse the
600 // block.
601 bool ParseBlockInternal();
602
603
604 void operator=(const NaClBitcodeParser &Parser) LLVM_DELETED_FUNCTION;
605 NaClBitcodeParser(const NaClBitcodeParser &Parser) LLVM_DELETED_FUNCTION;
606
607 };
608
609 } // namespace llvm
610
611 #endif
OLDNEW
« no previous file with comments | « include/llvm/Bitcode/NaCl/NaClBitcodeMunge.h ('k') | include/llvm/Bitcode/NaCl/NaClBitcodeSizeDist.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698