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.
82 //
83 // If you need to process abbreviations processed by the PNaCl
84 // bitstream reader, you must explicitly define a
85 // NaClBitcodeParserListener to listen (within the bitstream reader),
86 // and make appropriate call backs to the NaClBitcodeParser.
87 // The listener is glued to parsers using method SetListener.
88 //
89 // TODO(kschimpf): Define an intermediate derived class of
90 // NaClBitcodeParser that defines callbacks based on the actual
91 // structure of PNaCl bitcode files.  That is, it has callbacks for
92 // each of the types of blocks (i.e. module, types, global variables,
93 // function, symbol tables etc). This derivied class can then be used
94 // as the base class for the bitcode reader.
95 // ===----------------------------------------------------------------------===//
96 
97 #ifndef LLVM_BITCODE_NACL_NACLBITCODEPARSER_H
98 #define LLVM_BITCODE_NACL_NACLBITCODEPARSER_H
99 
100 #include "llvm/Bitcode/NaCl/NaClBitcodeDefs.h"
101 #include "llvm/Bitcode/NaCl/NaClBitstreamReader.h"
102 #include "llvm/Support/raw_ostream.h"
103 #include <vector>
104 
105 namespace llvm {
106 
107 class NaClBitcodeRecord;
108 class NaClBitcodeParser;
109 class NaClBitcodeParserListener;
110 
111 // Defines the base class for data extracted from the input bitstream
112 // (i.e blocks and records).
113 class NaClBitcodeData {
114   void operator=(const NaClBitcodeData &) = delete;
115 
116 public:
117   /// Create data element to be read from input cursor.
NaClBitcodeData(NaClBitstreamCursor & Cursor)118   explicit NaClBitcodeData(NaClBitstreamCursor &Cursor)
119       : Cursor(Cursor), StartBit(Cursor.GetCurrentBitNo()) {}
120 
121   /// Create copy of the given data element.
NaClBitcodeData(const NaClBitcodeData & Data)122   explicit NaClBitcodeData(const NaClBitcodeData &Data)
123       : Cursor(Data.Cursor), StartBit(Data.StartBit) {}
124 
125   /// Returns the bitstream reader being used.
GetReader()126   NaClBitstreamReader &GetReader() const {
127     return *Cursor.getBitStreamReader();
128   }
129 
130   /// Returns the cursor position within the bitstream.
GetCursor()131   NaClBitstreamCursor &GetCursor() const { return Cursor; }
132 
133   /// Returns the number of bits defined by the data.
GetNumBits()134   uint64_t GetNumBits() const {
135     return GetCursor().GetCurrentBitNo() - StartBit;
136   }
137 
138   /// Returns the first bit of the stream data.
GetStartBit()139   uint64_t GetStartBit() const { return StartBit; }
140 
141 protected:
142   /// Change the start bit for the data to the new value.
SetStartBit(uint64_t NewValue)143   void SetStartBit(uint64_t NewValue) { StartBit = NewValue; }
144 
145 private:
146   // The bitstream cursor defining location within the bitcode file.
147   NaClBitstreamCursor &Cursor;
148 
149   // Start bit for the record.
150   uint64_t StartBit;
151 };
152 
153 /// Models the block defined by a (begin) block record, through the
154 /// (end) block record.
155 class NaClBitcodeBlock : public NaClBitcodeData {
156   NaClBitcodeBlock(const NaClBitcodeBlock &) = delete;
157   void operator=(const NaClBitcodeBlock &) = delete;
158 
159 public:
160   /// Given the found (begin) block record for block BlockID, create
161   /// the corresponding data associated with that block.
162   NaClBitcodeBlock(unsigned BlockID, const NaClBitcodeRecord &Record);
163 
164   /// Create block data for block BlockID, using the input cursor.
NaClBitcodeBlock(unsigned BlockID,NaClBitstreamCursor & Cursor)165   NaClBitcodeBlock(unsigned BlockID, NaClBitstreamCursor &Cursor)
166       : NaClBitcodeData(Cursor), BlockID(BlockID), EnclosingBlock(0) {
167     LocalStartBit = GetStartBit();
168   }
169 
170   /// Print the contents out to the given stream.
171   void Print(raw_ostream &os) const;
172 
173   /// Returns pointer to the enclosing block.
GetEnclosingBlock()174   const NaClBitcodeBlock *GetEnclosingBlock() const { return EnclosingBlock; }
175 
176   /// Returns the block ID of the block.
GetBlockID()177   unsigned GetBlockID() const { return BlockID; }
178 
179   /// Returns the number of bits in the block associated with the
180   /// bitcode parser parsing this block, excluding nested blocks.
GetLocalNumBits()181   unsigned GetLocalNumBits() const {
182     return GetCursor().GetCurrentBitNo() - LocalStartBit;
183   }
184 
185 protected:
186   // The block ID associated with this record.
187   unsigned BlockID;
188   // The enclosing block, if defined.
189   const NaClBitcodeBlock *EnclosingBlock;
190   // Start bit for the block, updated to skip nested blocks.
191   uint64_t LocalStartBit;
192 
193   // Note: We friend class NaClBitcodeParser, so that it can
194   // update field LocalStartBit.
195   friend class NaClBitcodeParser;
196 };
197 
198 typedef NaClBitcodeRecordVector NaClRecordVector;
199 
200 class NaClBitcodeRecordData {
201   NaClBitcodeRecordData &operator=(const NaClBitcodeRecordData &) = delete;
202 
203 public:
NaClBitcodeRecordData(unsigned Code,const NaClRecordVector & Values)204   NaClBitcodeRecordData(unsigned Code, const NaClRecordVector &Values)
205       : Code(Code), Values(Values) {}
NaClBitcodeRecordData(const NaClBitcodeRecordData & Record)206   explicit NaClBitcodeRecordData(const NaClBitcodeRecordData &Record)
207       : Code(Record.Code), Values(Record.Values) {}
NaClBitcodeRecordData()208   NaClBitcodeRecordData() : Code(0) {}
209   // The selector code associated with the record.
210   unsigned Code;
211   // The sequence of values defining the parsed record.
212   NaClRecordVector Values;
213 
214   void Print(raw_ostream &strm) const;
215 };
216 
217 inline raw_ostream &operator<<(raw_ostream &Strm,
218                                const NaClBitcodeRecordData &Data) {
219   Data.Print(Strm);
220   return Strm;
221 }
222 
223 /// Simple container class to convert the values of the corresponding
224 /// read record to a simpler form, only containing values.
225 struct NaClBitcodeValues {
226 public:
NaClBitcodeValuesNaClBitcodeValues227   NaClBitcodeValues(const NaClBitcodeRecordData &Record) : Record(Record) {}
228 
sizeNaClBitcodeValues229   size_t size() const { return Record.Values.size() + 1; }
230 
231   uint64_t operator[](size_t index) const {
232     return index == 0 ? Record.Code : Record.Values[index - 1];
233   }
234 
235 private:
236   const NaClBitcodeRecordData &Record;
237 };
238 
239 /// Defines the data associated with reading a block record in the
240 /// PNaCl bitcode stream.
241 class NaClBitcodeRecord : public NaClBitcodeData {
242 public:
243   /// Type for vector of values representing a record.
244   typedef NaClRecordVector RecordVector;
245 
246   /// Creates a bitcode record, starting at the position defined
247   /// by cursor.
NaClBitcodeRecord(const NaClBitcodeBlock & Block)248   explicit NaClBitcodeRecord(const NaClBitcodeBlock &Block)
249       : NaClBitcodeData(Block.GetCursor()), Block(Block) {}
250 
251   /// Print the contents out to the given stream.
252   void Print(raw_ostream &os) const;
253 
254   /// The block the record appears in.
GetBlock()255   const NaClBitcodeBlock &GetBlock() const { return Block; }
256 
257   /// Returns the block ID associated with the record.
GetBlockID()258   unsigned GetBlockID() const { return Block.GetBlockID(); }
259 
260   /// Returns the kind of entry read from the input stream.
GetEntryKind()261   unsigned GetEntryKind() const { return Entry.Kind; }
262 
263   /// Returns the code value (i.e. selector) associated with the
264   /// record.
GetCode()265   unsigned GetCode() const { return Data.Code; }
266 
267   /// Returns the EntryID (e.g. abbreviation if !=
268   /// naclbitc::UNABBREV_RECORD) associated with the record. Note:
269   /// for block-enter, block-exit, and define-abbreviation, EntryID is
270   /// not the corresponding abbreviation.
GetEntryID()271   unsigned GetEntryID() const { return Entry.ID; }
272 
273   /// Returns the (value) record associated with the read record.
GetValues()274   const RecordVector &GetValues() const { return Data.Values; }
275 
276   /// Allows lower level access to data representing record.
GetRecordData()277   const NaClBitcodeRecordData &GetRecordData() const { return Data; }
278 
279   /// Returns true if the record was read using an abbreviation.
UsedAnAbbreviation()280   bool UsedAnAbbreviation() const {
281     return GetEntryKind() == NaClBitstreamEntry::Record &&
282            GetEntryID() != naclbitc::UNABBREV_RECORD;
283   }
284 
285   /// Returns the abbrevation index used to read the record.
286   /// Returns naclbitc::UNABBREV_RECORD if not applicable.
GetAbbreviationIndex()287   unsigned GetAbbreviationIndex() const {
288     return UsedAnAbbreviation()
289                ? GetEntryID()
290                : static_cast<unsigned>(naclbitc::UNABBREV_RECORD);
291   }
292 
293   /// Destructively change the abbreviation ID to the given value.
SetAbbreviationIndex(unsigned Index)294   void SetAbbreviationIndex(unsigned Index) { Entry.ID = Index; }
295 
296 protected:
297   // The block associated with the record.
298   const NaClBitcodeBlock &Block;
299   // The data of the record.
300   NaClBitcodeRecordData Data;
301   // The entry (i.e. value(s) preceding the record that define what
302   // value comes next).
303   NaClBitstreamEntry Entry;
304 
305 private:
306   // Allows class NaClBitcodeParser to read values into the
307   // record, thereby hiding the details of how to read values.
308   friend class NaClBitcodeParser;
309   friend class NaClBitcodeParserListener;
310 
311   /// Read bitstream entry. Defines what construct appears next in the
312   /// bitstream.
ReadEntry()313   void ReadEntry() {
314     SetStartBit(GetCursor().GetCurrentBitNo());
315     Entry =
316         GetCursor().advance(NaClBitstreamCursor::AF_DontAutoprocessAbbrevs, 0);
317   }
318 
319   /// Reads in a record's values, if the entry defines a record (Must
320   /// be called after ReadEntry).
ReadValues()321   void ReadValues() {
322     Data.Values.clear();
323     Data.Code = GetCursor().readRecord(Entry.ID, Data.Values);
324   }
325 
326   NaClBitcodeRecord(const NaClBitcodeRecord &Rcd) = delete;
327   void operator=(const NaClBitcodeRecord &Rcd) = delete;
328 };
329 
330 inline raw_ostream &operator<<(raw_ostream &Strm,
331                                const NaClBitcodeRecord &Record) {
332   Record.Print(Strm);
333   return Strm;
334 }
335 
336 /// Defines a listener to handle abbreviations within a bitcode file.
337 /// In particular, abbreviations and the BlockInfo block are made more
338 /// explicit, and then sent to the parser through virtuals
339 /// ProcessAbbreviation and SetBID.
340 class NaClBitcodeParserListener : public NaClAbbrevListener {
341   friend class NaClBitcodeParser;
342 
343 public:
344   // Constructs a listener for the given parser.  Note: All nested
345   // parsers automatically inherit this listener.
NaClBitcodeParserListener(NaClBitcodeParser * Parser)346   NaClBitcodeParserListener(NaClBitcodeParser *Parser)
347       : Parser(Parser), GlobalBlockID(naclbitc::BLOCKINFO_BLOCK_ID) {}
348 
~NaClBitcodeParserListener()349   virtual ~NaClBitcodeParserListener() {}
350 
351 private:
352   virtual void BeginBlockInfoBlock(unsigned NumWords);
353 
354   virtual void SetBID();
355 
356   virtual void EndBlockInfoBlock();
357 
358   virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, bool IsLocal);
359 
360   /// The block parser currently being listened to.
361   NaClBitcodeParser *Parser;
362 
363   /// The block ID to use if a global abbreviation. Note: This field is
364   /// updated by calls to method SetBID.
365   unsigned GlobalBlockID;
366 };
367 
368 /// Parses a block in the PNaCl bitcode stream.
369 class NaClBitcodeParser {
370   // Allow listener privledges, so that it can update/call the parser
371   // using a clean API.
372   friend class NaClBitcodeParserListener;
373 
374   // Implements an error handler for errors in the bitstream reader.
375   // Redirects bitstream reader errors to corresponding parrser error
376   // reporting function.
377   class ErrorHandler : public NaClBitstreamCursor::ErrorHandler {
378     NaClBitcodeParser *Parser;
379 
380   public:
ErrorHandler(NaClBitcodeParser * Parser,NaClBitstreamCursor & Cursor)381     ErrorHandler(NaClBitcodeParser *Parser, NaClBitstreamCursor &Cursor)
382         : NaClBitstreamCursor::ErrorHandler(Cursor), Parser(Parser) {}
383     LLVM_ATTRIBUTE_NORETURN
Fatal(const std::string & ErrorMessage)384     void Fatal(const std::string &ErrorMessage) const final {
385       Parser->FatalAt(getCurrentBitNo(), ErrorMessage);
386       llvm_unreachable("GCC treats noreturn virtual functions as returning");
387     }
~ErrorHandler()388     ~ErrorHandler() override {}
389   };
390 
391 public:
392   // Creates a parser to parse the the block at the given cursor in
393   // the PNaCl bitcode stream. This instance is a "dummy" instance
394   // that starts the parser.
NaClBitcodeParser(NaClBitstreamCursor & Cursor)395   explicit NaClBitcodeParser(NaClBitstreamCursor &Cursor)
396       : EnclosingParser(0), Block(ILLEGAL_BLOCK_ID, Cursor), Record(Block),
397         Listener(0), ErrStream(&errs()) {
398     std::unique_ptr<NaClBitstreamCursor::ErrorHandler> ErrHandler(
399         new ErrorHandler(this, Cursor));
400     Cursor.setErrorHandler(ErrHandler);
401   }
402 
403   virtual ~NaClBitcodeParser();
404 
405   /// Reads the (top-level) block associated with the given block
406   /// record at the stream cursor. Returns true if unable to parse.
407   /// Can be called multiple times to parse multiple blocks.
408   bool Parse();
409 
410   // Called once the bitstream reader has entered the corresponding
411   // subblock.  Argument NumWords is set to the number of words in the
412   // corresponding subblock.
EnterBlock(unsigned)413   virtual void EnterBlock(unsigned /*NumWords*/) {}
414 
415   // Called when the corresponding EndBlock of the block being parsed
416   // is found.
ExitBlock()417   virtual void ExitBlock() {}
418 
419   // Called after each record (within the block) is read (into field Record).
ProcessRecord()420   virtual void ProcessRecord() {}
421 
422   // Called if a SetBID record is encountered in the BlockInfo block,
423   // and the parser has a listener.
SetBID()424   virtual void SetBID() {}
425 
426   // Called to process an abbreviation if the parser has a listener.
ProcessAbbreviation(unsigned,NaClBitCodeAbbrev *,bool)427   virtual void ProcessAbbreviation(unsigned /*BlockID*/,
428                                    NaClBitCodeAbbrev * /*Abbrev*/,
429                                    bool /*IsLocal*/) {}
430 
431   // Creates an instance of the NaClBitcodeParser to use to parse the
432   // block with the given block ID, and then call's method
433   // ParseThisBlock() to parse the corresponding block. Note:
434   // Each derived class should define it's own version of this
435   // method, following the pattern below.
ParseBlock(unsigned BlockID)436   virtual bool ParseBlock(unsigned BlockID) {
437     // Default implementation just builds a parser that does nothing.
438     NaClBitcodeParser Parser(BlockID, this);
439     return Parser.ParseThisBlock();
440   }
441 
442   // Changes the stream to print errors to, and returns the old error stream.
443   // There are two use cases:
444   // 1) To change (from the default errs()) inside the constructor of the
445   //    derived class. In this context, it will be used for all error
446   //    messages for the derived class.
447   // 2) Temporarily modify it for a single error message.
setErrStream(raw_ostream & Stream)448   raw_ostream &setErrStream(raw_ostream &Stream) {
449     raw_ostream &OldErrStream = *ErrStream;
450     ErrStream = &Stream;
451     return OldErrStream;
452   }
453 
454   // Called when an error occurs. BitPosition is the bit position the
455   // error was found, and Message is the error to report. Always
456   // returns true (the error return value of Parse). Level is
457   // the severity of the error.
458   virtual bool ErrorAt(naclbitc::ErrorLevel Level, uint64_t BitPosition,
459                        const std::string &Message);
460 
ErrorAt(uint64_t BitPosition,const std::string & Message)461   bool ErrorAt(uint64_t BitPosition, const std::string &Message) {
462     return ErrorAt(naclbitc::Error, BitPosition, Message);
463   }
464 
465   // Called when an error occurs. Message is the error to
466   // report. Always returns true (the error return value of Parse).
Error(const std::string & Message)467   bool Error(const std::string &Message) {
468     return ErrorAt(Record.GetStartBit(), Message);
469   }
470 
471   // Called when a fatal error occurs. BitPosition is the bit position
472   // the error was found, and Message is the error to report. Does not
473   // return.
474   LLVM_ATTRIBUTE_NORETURN
FatalAt(uint64_t BitPosition,const std::string & Message)475   void FatalAt(uint64_t BitPosition, const std::string &Message) {
476     ErrorAt(naclbitc::Fatal, BitPosition, Message);
477     llvm_unreachable("Fatal errors should not return");
478   }
479 
480   // Called when a fatal error occurs. Message is the error to
481   // report. Does not return.
482   LLVM_ATTRIBUTE_NORETURN
Fatal(const std::string & Message)483   void Fatal(const std::string &Message) {
484     FatalAt(Record.GetStartBit(), Message);
485     llvm_unreachable("GCC treats noreturn virtual functions as returning");
486   }
487 
488   // Generates fatal generic error message.
489   LLVM_ATTRIBUTE_NORETURN
Fatal()490   void Fatal() { Fatal("Fatal error occurred!"); }
491 
492   // Returns the number of bits in this block, including nested blocks.
GetBlockNumBits()493   unsigned GetBlockNumBits() const { return Block.GetNumBits(); }
494 
495   // Returns the number of bits in this block, excluding nested blocks.
GetBlockLocalNumBits()496   unsigned GetBlockLocalNumBits() const { return Block.GetLocalNumBits(); }
497 
498   /// Returns the block ID associated with the Parser.
GetBlockID()499   unsigned GetBlockID() const { return Block.GetBlockID(); }
500 
GetBlock()501   NaClBitcodeBlock &GetBlock() { return Block; }
502 
503   /// Returns the enclosing parser of this block.
GetEnclosingParser()504   NaClBitcodeParser *GetEnclosingParser() const {
505     // Note: The top-level parser instance is a dummy instance
506     // and is not considered an enclosing parser.
507     return EnclosingParser->EnclosingParser ? EnclosingParser : 0;
508   }
509 
510   // Parses the block using the parser defined by
511   // ParseBlock(unsigned).  Returns true if unable to parse the
512   // block. Note: Should only be called by virtual ParseBlock(unsigned).
ParseThisBlock()513   bool ParseThisBlock() {
514     bool Results;
515     if (Listener) {
516       NaClBitcodeParser *CallingParser = Listener->Parser;
517       Listener->Parser = this;
518       Results = ParseThisBlockInternal();
519       Listener->Parser = CallingParser;
520     } else {
521       Results = ParseThisBlockInternal();
522     }
523     return Results;
524   }
525 
526   /// Skips the current block, assuming the parser is at the beginning
527   /// of the block. That is, Record.GetEntryKind() equals
528   /// NaClBitstreamEntry::SubBlock. Returns false if
529   /// successful. Otherwise returns 1.
SkipBlock()530   bool SkipBlock() {
531     if (Record.GetEntryKind() != NaClBitstreamEntry::SubBlock)
532       return Error("SkipBlock on non-block record");
533     return Record.GetCursor().SkipBlock();
534   }
535 
536 protected:
537   // The containing parser.
538   NaClBitcodeParser *EnclosingParser;
539 
540   // The block the parser is associated with.
541   NaClBitcodeBlock Block;
542 
543   // The current record (within the block) being processed.
544   NaClBitcodeRecord Record;
545 
546   // The listener (if any) to use.
547   NaClBitcodeParserListener *Listener;
548 
549   // The error stream to use if non-null (uses errs() if null).
550   raw_ostream *ErrStream;
551 
552   // Creates a block parser to parse the block associated with the bitcode entry
553   // that defines the beginning of a block. This instance actually parses the
554   // corresponding block. Inherits the bitstream cursor from the
555   // EnclosingParser.
NaClBitcodeParser(unsigned BlockID,NaClBitcodeParser * EnclosingParser)556   NaClBitcodeParser(unsigned BlockID, NaClBitcodeParser *EnclosingParser)
557       : EnclosingParser(EnclosingParser),
558         Block(BlockID, EnclosingParser->Record), Record(Block),
559         Listener(EnclosingParser->Listener),
560         ErrStream(EnclosingParser->ErrStream) {}
561 
562   // Same as above, but use the supplied bitstream cursor (instead of
563   // inheriting from the enclosing parser). This constructor allows
564   // parallel parsing of subblocks, by allowing the caller to generate
565   // a different Cursor for each block to be parsed in parallel.
NaClBitcodeParser(unsigned BlockID,NaClBitcodeParser * EnclosingParser,NaClBitstreamCursor & Cursor)566   NaClBitcodeParser(unsigned BlockID, NaClBitcodeParser *EnclosingParser,
567                     NaClBitstreamCursor &Cursor)
568       : EnclosingParser(EnclosingParser), Block(BlockID, Cursor), Record(Block),
569         Listener(EnclosingParser->Listener),
570         ErrStream(EnclosingParser->ErrStream) {}
571 
572   /// Defines the listener for this block, and all enclosing blocks,
573   /// to be the given listener. Should be set in the constructor.
SetListener(NaClBitcodeParserListener * UseListener)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.
ParseThisBlockInternal()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   void operator=(const NaClBitcodeParser &Parser) = delete;
604   NaClBitcodeParser(const NaClBitcodeParser &Parser) = delete;
605 };
606 
607 } // namespace llvm
608 
609 #endif
610