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