Index: pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeParser.h |
diff --git a/pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeParser.h b/pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeParser.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e48aebd5e0123de3b734643f948ae43a4b032a25 |
--- /dev/null |
+++ b/pnacl-llvm/include/llvm/Bitcode/NaCl/NaClBitcodeParser.h |
@@ -0,0 +1,663 @@ |
+//===- NaClBitcodeParser.h -----------------------------------*- C++ -*-===// |
+// Low-level bitcode driver to parse PNaCl bitcode files. |
+// |
+// The LLVM Compiler Infrastructure |
+// |
+// This file is distributed under the University of Illinois Open Source |
+// License. See LICENSE.TXT for details. |
+// |
+//===----------------------------------------------------------------------===// |
+// |
+// Parses and processes low-level PNaCl bitcode files. Defines class |
+// NaClBitcodeParser. |
+// |
+// The concepts of PNaCl bitcode files are basically the same as for |
+// LLVM bitcode files (see http://llvm.org/docs/BitCodeFormat.html for |
+// details). |
+// |
+// The bitstream format is an abstract encoding of structured data, |
+// very similar to XML in some ways. Like XML, bitstream files contain |
+// tags, and nested structures, and you can parse the file without |
+// having to understand the tags. Unlike XML, the bitstream format is |
+// a binary encoding, and provides a mechanism for the file to |
+// self-describe "abbreviations". Abbreviations are effectively size |
+// optimizations for the content. |
+// |
+// The bitcode file is conceptually a sequence of "blocks", defining |
+// the content. Blocks contain a sequence of records and |
+// blocks. Nested content is defined using nested blocks. A (data) |
+// "record" is a tag, and a vector of (unsigned integer) values. |
+// |
+// Blocks are identified using Block IDs. Each kind of block has a |
+// unique block "ID". Records have two elements: |
+// |
+// a) A "code" identifying what type of record it is. |
+// b) A vector of "values" defining the contents of the record. |
+// |
+// The bitstream "reader" (defined in NaClBitstreamReader.h) defines |
+// the implementation that converts the low-level bit file into |
+// records and blocks. The bit stream is processed by moving a |
+// "cursor" over the sequence of bits. |
+// |
+// The bitstream reader assumes that each block/record is read in by |
+// first reading the "entry". The entry defines whether it corresponds |
+// to one of the following: |
+// |
+// a) At the beginning of a (possibly nested) block |
+// b) At the end of the current block. |
+// c) The input defines an abberviation. |
+// d) The input defines a record. |
+// |
+// An entry contains two values, a "kind" and an "ID". The kind |
+// defines which of the four cases above occurs. The ID provides |
+// identifying information on how to further process the input. For |
+// case (a), the ID is the identifier associated with the the block |
+// being processed. For case (b) and (c) the ID is ignored. For case |
+// (d) the ID identifies the abbreviation that should be used to parse |
+// the values. |
+// |
+// The class NaClBitcodeParser defines a bitcode parser that extracts |
+// the blocks and records, which are then processed using virtual |
+// callbacks. In general, you will want to implement derived classes |
+// for each type of block, so that the corresponding data is processed |
+// appropriately. |
+// |
+// The class NaClBitcodeParser parses a bitcode block, and defines a |
+// set of callbacks for that block, including: |
+// |
+// a) EnterBlock: What to do once we have entered the block. |
+// b) ProcessRecord: What to do with each parsed record. |
+// c) ParseBlock: Parse the (nested) block with the given ID. |
+// d) ExitBlock: What to do once we have finished processing the block. |
+// |
+// Note that a separate instance of NaClBitcodeParser (or a |
+// corresponding derived class) is created for each nested block. Each |
+// instance is responsible for only parsing a single block. Method |
+// ParseBlock creates new instances to parse nested blocks. Method |
+// GetEnclosingParser() can be used to refer to the parser associated |
+// with the enclosing block. |
+// |
+// Currently, the default processing of abbreviations is handled by |
+// the PNaCl bitstream reader, rather than by the parser. |
+// |
+// If you need to process abbreviations processed by the PNaCl |
+// bitstream reader, you must explicitly define a |
+// NaClBitcodeParserListener to listen (within the bitstream reader), |
+// and make appropriate call backs to the NaClBitcodeParser. |
+// The listener is glued to parsers using method SetListener. |
+// |
+// TODO(kschimpf): Define an intermediate derived class of |
+// NaClBitcodeParser that defines callbacks based on the actual |
+// structure of PNaCl bitcode files. That is, it has callbacks for |
+// each of the types of blocks (i.e. module, types, global variables, |
+// function, symbol tables etc). This derivied class can then be used |
+// as the base class for the bitcode reader. |
+// ===----------------------------------------------------------------------===// |
+ |
+#ifndef LLVM_BITCODE_NACL_NACLBITCODEPARSER_H |
+#define LLVM_BITCODE_NACL_NACLBITCODEPARSER_H |
+ |
+#include "llvm/Bitcode/NaCl/NaClBitstreamReader.h" |
+#include "llvm/Bitcode/NaCl/NaClBitcodeDefs.h" |
+#include "llvm/Support/raw_ostream.h" |
+#include <vector> |
+ |
+namespace llvm { |
+ |
+class NaClBitcodeRecord; |
+class NaClBitcodeParser; |
+class NaClBitcodeParserListener; |
+ |
+// Defines the base class for data extracted from the input bitstream |
+// (i.e blocks and records). |
+class NaClBitcodeData { |
+ void operator=(const NaClBitcodeData&) = delete; |
+ |
+public: |
+ /// Create data element to be read from input cursor. |
+ explicit NaClBitcodeData(NaClBitstreamCursor &Cursor) |
+ : Cursor(Cursor), StartBit(Cursor.GetCurrentBitNo()) |
+ {} |
+ |
+ /// Create copy of the given data element. |
+ explicit NaClBitcodeData(const NaClBitcodeData &Data) |
+ : Cursor(Data.Cursor), StartBit(Data.StartBit) |
+ {} |
+ |
+ /// Returns the bitstream reader being used. |
+ NaClBitstreamReader &GetReader() const { |
+ return *Cursor.getBitStreamReader(); |
+ } |
+ |
+ /// Returns the cursor position within the bitstream. |
+ NaClBitstreamCursor &GetCursor() const { |
+ return Cursor; |
+ } |
+ |
+ /// Returns the number of bits defined by the data. |
+ uint64_t GetNumBits() const { |
+ return GetCursor().GetCurrentBitNo() - StartBit; |
+ } |
+ |
+ /// Returns the first bit of the stream data. |
+ uint64_t GetStartBit() const { |
+ return StartBit; |
+ } |
+ |
+protected: |
+ /// Change the start bit for the data to the new value. |
+ void SetStartBit(uint64_t NewValue) { |
+ StartBit = NewValue; |
+ } |
+ |
+private: |
+ // The bitstream cursor defining location within the bitcode file. |
+ NaClBitstreamCursor &Cursor; |
+ |
+ // Start bit for the record. |
+ uint64_t StartBit; |
+}; |
+ |
+/// Models the block defined by a (begin) block record, through the |
+/// (end) block record. |
+class NaClBitcodeBlock : public NaClBitcodeData { |
+ NaClBitcodeBlock(const NaClBitcodeBlock &) = delete; |
+ void operator=(const NaClBitcodeBlock &) = delete; |
+ |
+public: |
+ /// Given the found (begin) block record for block BlockID, create |
+ /// the corresponding data associated with that block. |
+ NaClBitcodeBlock(unsigned BlockID, const NaClBitcodeRecord &Record); |
+ |
+ /// Create block data for block BlockID, using the input cursor. |
+ NaClBitcodeBlock(unsigned BlockID, NaClBitstreamCursor &Cursor) |
+ : NaClBitcodeData(Cursor), |
+ BlockID(BlockID), |
+ EnclosingBlock(0) |
+ { |
+ LocalStartBit = GetStartBit(); |
+ } |
+ |
+ /// Print the contents out to the given stream. |
+ void Print(raw_ostream& os) const; |
+ |
+ /// Returns pointer to the enclosing block. |
+ const NaClBitcodeBlock *GetEnclosingBlock() const { |
+ return EnclosingBlock; |
+ } |
+ |
+ /// Returns the block ID of the block. |
+ unsigned GetBlockID() const { |
+ return BlockID; |
+ } |
+ |
+ /// Returns the number of bits in the block associated with the |
+ /// bitcode parser parsing this block, excluding nested blocks. |
+ unsigned GetLocalNumBits() const { |
+ return GetCursor().GetCurrentBitNo() - LocalStartBit; |
+ } |
+ |
+protected: |
+ // The block ID associated with this record. |
+ unsigned BlockID; |
+ // The enclosing block, if defined. |
+ const NaClBitcodeBlock *EnclosingBlock; |
+ // Start bit for the block, updated to skip nested blocks. |
+ uint64_t LocalStartBit; |
+ |
+ // Note: We friend class NaClBitcodeParser, so that it can |
+ // update field LocalStartBit. |
+ friend class NaClBitcodeParser; |
+}; |
+ |
+typedef NaClBitcodeRecordVector NaClRecordVector; |
+ |
+class NaClBitcodeRecordData { |
+ NaClBitcodeRecordData &operator=(const NaClBitcodeRecordData &) = delete; |
+public: |
+ NaClBitcodeRecordData(unsigned Code, const NaClRecordVector &Values) |
+ : Code(Code), Values(Values) {} |
+ explicit NaClBitcodeRecordData(const NaClBitcodeRecordData &Record) |
+ : Code(Record.Code), Values(Record.Values) {} |
+ NaClBitcodeRecordData() : Code(0) {} |
+ // The selector code associated with the record. |
+ unsigned Code; |
+ // The sequence of values defining the parsed record. |
+ NaClRecordVector Values; |
+ |
+ void Print(raw_ostream &strm) const; |
+}; |
+ |
+inline raw_ostream &operator<<(raw_ostream &Strm, |
+ const NaClBitcodeRecordData &Data) { |
+ Data.Print(Strm); |
+ return Strm; |
+} |
+ |
+/// Simple container class to convert the values of the corresponding |
+/// read record to a simpler form, only containing values. |
+struct NaClBitcodeValues { |
+public: |
+ NaClBitcodeValues(const NaClBitcodeRecordData &Record) |
+ : Record(Record) {} |
+ |
+ size_t size() const { |
+ return Record.Values.size()+1; |
+ } |
+ |
+ uint64_t operator[](size_t index) const { |
+ return index == 0 ? Record.Code : Record.Values[index-1]; |
+ } |
+ |
+private: |
+ const NaClBitcodeRecordData &Record; |
+}; |
+ |
+/// Defines the data associated with reading a block record in the |
+/// PNaCl bitcode stream. |
+class NaClBitcodeRecord : public NaClBitcodeData { |
+public: |
+ /// Type for vector of values representing a record. |
+ typedef NaClRecordVector RecordVector; |
+ |
+ /// Creates a bitcode record, starting at the position defined |
+ /// by cursor. |
+ explicit NaClBitcodeRecord(const NaClBitcodeBlock &Block) |
+ : NaClBitcodeData(Block.GetCursor()), |
+ Block(Block) |
+ {} |
+ |
+ /// Print the contents out to the given stream. |
+ void Print(raw_ostream& os) const; |
+ |
+ /// The block the record appears in. |
+ const NaClBitcodeBlock &GetBlock() const { |
+ return Block; |
+ } |
+ |
+ /// Returns the block ID associated with the record. |
+ unsigned GetBlockID() const { |
+ return Block.GetBlockID(); |
+ } |
+ |
+ /// Returns the kind of entry read from the input stream. |
+ unsigned GetEntryKind() const { |
+ return Entry.Kind; |
+ } |
+ |
+ /// Returns the code value (i.e. selector) associated with the |
+ /// record. |
+ unsigned GetCode() const { |
+ return Data.Code; |
+ } |
+ |
+ /// Returns the EntryID (e.g. abbreviation if != |
+ /// naclbitc::UNABBREV_RECORD) associated with the record. Note: |
+ /// for block-enter, block-exit, and define-abbreviation, EntryID is |
+ /// not the corresponding abbreviation. |
+ unsigned GetEntryID() const { |
+ return Entry.ID; |
+ } |
+ |
+ /// Returns the (value) record associated with the read record. |
+ const RecordVector &GetValues() const { |
+ return Data.Values; |
+ } |
+ |
+ /// Allows lower level access to data representing record. |
+ const NaClBitcodeRecordData &GetRecordData() const { |
+ return Data; |
+ } |
+ |
+ /// Returns true if the record was read using an abbreviation. |
+ bool UsedAnAbbreviation() const { |
+ return GetEntryKind() == NaClBitstreamEntry::Record && |
+ GetEntryID() != naclbitc::UNABBREV_RECORD; |
+ } |
+ |
+ /// Returns the abbrevation index used to read the record. |
+ /// Returns naclbitc::UNABBREV_RECORD if not applicable. |
+ unsigned GetAbbreviationIndex() const { |
+ return UsedAnAbbreviation() |
+ ? GetEntryID() : static_cast<unsigned>(naclbitc::UNABBREV_RECORD); |
+ } |
+ |
+ /// Destructively change the abbreviation ID to the given value. |
+ void SetAbbreviationIndex(unsigned Index) { |
+ Entry.ID = Index; |
+ } |
+ |
+protected: |
+ // The block associated with the record. |
+ const NaClBitcodeBlock &Block; |
+ // The data of the record. |
+ NaClBitcodeRecordData Data; |
+ // The entry (i.e. value(s) preceding the record that define what |
+ // value comes next). |
+ NaClBitstreamEntry Entry; |
+ |
+private: |
+ // Allows class NaClBitcodeParser to read values into the |
+ // record, thereby hiding the details of how to read values. |
+ friend class NaClBitcodeParser; |
+ friend class NaClBitcodeParserListener; |
+ |
+ /// Read bitstream entry. Defines what construct appears next in the |
+ /// bitstream. |
+ void ReadEntry() { |
+ SetStartBit(GetCursor().GetCurrentBitNo()); |
+ Entry = GetCursor(). |
+ advance(NaClBitstreamCursor::AF_DontAutoprocessAbbrevs, 0); |
+ } |
+ |
+ /// Reads in a record's values, if the entry defines a record (Must |
+ /// be called after ReadEntry). |
+ void ReadValues() { |
+ Data.Values.clear(); |
+ Data.Code = GetCursor().readRecord(Entry.ID, Data.Values); |
+ } |
+ |
+ NaClBitcodeRecord(const NaClBitcodeRecord &Rcd) = delete; |
+ void operator=(const NaClBitcodeRecord &Rcd) = delete; |
+}; |
+ |
+inline raw_ostream &operator<<(raw_ostream &Strm, |
+ const NaClBitcodeRecord &Record) { |
+ Record.Print(Strm); |
+ return Strm; |
+} |
+ |
+/// Defines a listener to handle abbreviations within a bitcode file. |
+/// In particular, abbreviations and the BlockInfo block are made more |
+/// explicit, and then sent to the parser through virtuals |
+/// ProcessAbbreviation and SetBID. |
+class NaClBitcodeParserListener : public NaClAbbrevListener { |
+ friend class NaClBitcodeParser; |
+public: |
+ // Constructs a listener for the given parser. Note: All nested |
+ // parsers automatically inherit this listener. |
+ NaClBitcodeParserListener(NaClBitcodeParser *Parser) |
+ : Parser(Parser), GlobalBlockID(naclbitc::BLOCKINFO_BLOCK_ID) { |
+ } |
+ |
+ virtual ~NaClBitcodeParserListener() {} |
+ |
+private: |
+ virtual void BeginBlockInfoBlock(unsigned NumWords); |
+ |
+ virtual void SetBID(); |
+ |
+ virtual void EndBlockInfoBlock(); |
+ |
+ virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, |
+ bool IsLocal); |
+ |
+ /// The block parser currently being listened to. |
+ NaClBitcodeParser *Parser; |
+ |
+ /// The block ID to use if a global abbreviation. Note: This field is |
+ /// updated by calls to method SetBID. |
+ unsigned GlobalBlockID; |
+}; |
+ |
+/// Parses a block in the PNaCl bitcode stream. |
+class NaClBitcodeParser { |
+ // Allow listener privledges, so that it can update/call the parser |
+ // using a clean API. |
+ friend class NaClBitcodeParserListener; |
+ |
+ // Implements an error handler for errors in the bitstream reader. |
+ // Redirects bitstream reader errors to corresponding parrser error |
+ // reporting function. |
+ class ErrorHandler : public NaClBitstreamCursor::ErrorHandler { |
+ NaClBitcodeParser *Parser; |
+ public: |
+ ErrorHandler(NaClBitcodeParser *Parser, |
+ NaClBitstreamCursor &Cursor): |
+ NaClBitstreamCursor::ErrorHandler(Cursor), Parser(Parser) {} |
+ LLVM_ATTRIBUTE_NORETURN |
+ void Fatal(const std::string &ErrorMessage) const final { |
+ Parser->FatalAt(getCurrentBitNo(), ErrorMessage); |
+ llvm_unreachable("GCC treats noreturn virtual functions as returning"); |
+ } |
+ ~ErrorHandler() override {} |
+ }; |
+ |
+public: |
+ // Creates a parser to parse the the block at the given cursor in |
+ // the PNaCl bitcode stream. This instance is a "dummy" instance |
+ // that starts the parser. |
+ explicit NaClBitcodeParser(NaClBitstreamCursor &Cursor) |
+ : EnclosingParser(0), |
+ Block(ILLEGAL_BLOCK_ID, Cursor), |
+ Record(Block), |
+ Listener(0), |
+ ErrStream(&errs()) { |
+ std::unique_ptr<NaClBitstreamCursor::ErrorHandler> |
+ ErrHandler(new ErrorHandler(this, Cursor)); |
+ Cursor.setErrorHandler(ErrHandler); |
+ } |
+ |
+ virtual ~NaClBitcodeParser(); |
+ |
+ /// Reads the (top-level) block associated with the given block |
+ /// record at the stream cursor. Returns true if unable to parse. |
+ /// Can be called multiple times to parse multiple blocks. |
+ bool Parse(); |
+ |
+ // Called once the bitstream reader has entered the corresponding |
+ // subblock. Argument NumWords is set to the number of words in the |
+ // corresponding subblock. |
+ virtual void EnterBlock(unsigned /*NumWords*/) {} |
+ |
+ // Called when the corresponding EndBlock of the block being parsed |
+ // is found. |
+ virtual void ExitBlock() {} |
+ |
+ // Called after each record (within the block) is read (into field Record). |
+ virtual void ProcessRecord() {} |
+ |
+ // Called if a SetBID record is encountered in the BlockInfo block, |
+ // and the parser has a listener. |
+ virtual void SetBID() {} |
+ |
+ // Called to process an abbreviation if the parser has a listener. |
+ virtual void ProcessAbbreviation(unsigned /*BlockID*/, |
+ NaClBitCodeAbbrev * /*Abbrev*/, |
+ bool /*IsLocal*/) {} |
+ |
+ // Creates an instance of the NaClBitcodeParser to use to parse the |
+ // block with the given block ID, and then call's method |
+ // ParseThisBlock() to parse the corresponding block. Note: |
+ // Each derived class should define it's own version of this |
+ // method, following the pattern below. |
+ virtual bool ParseBlock(unsigned BlockID) { |
+ // Default implementation just builds a parser that does nothing. |
+ NaClBitcodeParser Parser(BlockID, this); |
+ return Parser.ParseThisBlock(); |
+ } |
+ |
+ // Changes the stream to print errors to, and returns the old error stream. |
+ // There are two use cases: |
+ // 1) To change (from the default errs()) inside the constructor of the |
+ // derived class. In this context, it will be used for all error |
+ // messages for the derived class. |
+ // 2) Temporarily modify it for a single error message. |
+ raw_ostream &setErrStream(raw_ostream &Stream) { |
+ raw_ostream &OldErrStream = *ErrStream; |
+ ErrStream = &Stream; |
+ return OldErrStream; |
+ } |
+ |
+ // Called when an error occurs. BitPosition is the bit position the |
+ // error was found, and Message is the error to report. Always |
+ // returns true (the error return value of Parse). Level is |
+ // the severity of the error. |
+ virtual bool ErrorAt(naclbitc::ErrorLevel Level, uint64_t BitPosition, |
+ const std::string &Message); |
+ |
+ bool ErrorAt(uint64_t BitPosition, const std::string &Message) { |
+ return ErrorAt(naclbitc::Error, BitPosition, Message); |
+ } |
+ |
+ // Called when an error occurs. Message is the error to |
+ // report. Always returns true (the error return value of Parse). |
+ bool Error(const std::string &Message) { |
+ return ErrorAt(Record.GetStartBit(), Message); |
+ } |
+ |
+ // Called when a fatal error occurs. BitPosition is the bit position |
+ // the error was found, and Message is the error to report. Does not |
+ // return. |
+ LLVM_ATTRIBUTE_NORETURN |
+ void FatalAt(uint64_t BitPosition, const std::string &Message) { |
+ ErrorAt(naclbitc::Fatal, BitPosition, Message); |
+ llvm_unreachable("Fatal errors should not return"); |
+ } |
+ |
+ // Called when a fatal error occurs. Message is the error to |
+ // report. Does not return. |
+ LLVM_ATTRIBUTE_NORETURN |
+ void Fatal(const std::string &Message) { |
+ FatalAt(Record.GetStartBit(), Message); |
+ llvm_unreachable("GCC treats noreturn virtual functions as returning"); |
+ } |
+ |
+ // Generates fatal generic error message. |
+ LLVM_ATTRIBUTE_NORETURN |
+ void Fatal() { |
+ Fatal("Fatal error occurred!"); |
+ } |
+ |
+ // Returns the number of bits in this block, including nested blocks. |
+ unsigned GetBlockNumBits() const { |
+ return Block.GetNumBits(); |
+ } |
+ |
+ // Returns the number of bits in this block, excluding nested blocks. |
+ unsigned GetBlockLocalNumBits() const { |
+ return Block.GetLocalNumBits(); |
+ } |
+ |
+ /// Returns the block ID associated with the Parser. |
+ unsigned GetBlockID() const { |
+ return Block.GetBlockID(); |
+ } |
+ |
+ NaClBitcodeBlock &GetBlock() { |
+ return Block; |
+ } |
+ |
+ /// Returns the enclosing parser of this block. |
+ NaClBitcodeParser *GetEnclosingParser() const { |
+ // Note: The top-level parser instance is a dummy instance |
+ // and is not considered an enclosing parser. |
+ return EnclosingParser->EnclosingParser ? EnclosingParser : 0; |
+ } |
+ |
+ // Parses the block using the parser defined by |
+ // ParseBlock(unsigned). Returns true if unable to parse the |
+ // block. Note: Should only be called by virtual ParseBlock(unsigned). |
+ bool ParseThisBlock() { |
+ bool Results; |
+ if (Listener) { |
+ NaClBitcodeParser *CallingParser = Listener->Parser; |
+ Listener->Parser = this; |
+ Results = ParseThisBlockInternal(); |
+ Listener->Parser = CallingParser; |
+ } else { |
+ Results = ParseThisBlockInternal(); |
+ } |
+ return Results; |
+ } |
+ |
+ /// Skips the current block, assuming the parser is at the beginning |
+ /// of the block. That is, Record.GetEntryKind() equals |
+ /// NaClBitstreamEntry::SubBlock. Returns false if |
+ /// successful. Otherwise returns 1. |
+ bool SkipBlock() { |
+ if (Record.GetEntryKind() != NaClBitstreamEntry::SubBlock) |
+ return Error("SkipBlock on non-block record"); |
+ return Record.GetCursor().SkipBlock(); |
+ } |
+ |
+protected: |
+ // The containing parser. |
+ NaClBitcodeParser *EnclosingParser; |
+ |
+ // The block the parser is associated with. |
+ NaClBitcodeBlock Block; |
+ |
+ // The current record (within the block) being processed. |
+ NaClBitcodeRecord Record; |
+ |
+ // The listener (if any) to use. |
+ NaClBitcodeParserListener *Listener; |
+ |
+ // The error stream to use if non-null (uses errs() if null). |
+ raw_ostream *ErrStream; |
+ |
+ // Creates a block parser to parse the block associated with the bitcode entry |
+ // that defines the beginning of a block. This instance actually parses the |
+ // corresponding block. Inherits the bitstream cursor from the |
+ // EnclosingParser. |
+ NaClBitcodeParser(unsigned BlockID, NaClBitcodeParser *EnclosingParser) |
+ : EnclosingParser(EnclosingParser), |
+ Block(BlockID, EnclosingParser->Record), |
+ Record(Block), |
+ Listener(EnclosingParser->Listener), |
+ ErrStream(EnclosingParser->ErrStream) |
+ {} |
+ |
+ // Same as above, but use the supplied bitstream cursor (instead of |
+ // inheriting from the enclosing parser). This constructor allows |
+ // parallel parsing of subblocks, by allowing the caller to generate |
+ // a different Cursor for each block to be parsed in parallel. |
+ NaClBitcodeParser(unsigned BlockID, NaClBitcodeParser *EnclosingParser, |
+ NaClBitstreamCursor &Cursor) |
+ : EnclosingParser(EnclosingParser), |
+ Block(BlockID, Cursor), |
+ Record(Block), |
+ Listener(EnclosingParser->Listener), |
+ ErrStream(EnclosingParser->ErrStream) |
+ {} |
+ |
+ /// Defines the listener for this block, and all enclosing blocks, |
+ /// to be the given listener. Should be set in the constructor. |
+ void SetListener(NaClBitcodeParserListener* UseListener) { |
+ Listener = UseListener; |
+ } |
+ |
+private: |
+ // Special constant identifying the top-level instance. |
+ static const unsigned ILLEGAL_BLOCK_ID = UINT_MAX; |
+ |
+ // Parses the block. Returns true if unable to parse the |
+ // block. Note: Should only be called by virtual ParseThisBlock. |
+ bool ParseThisBlockInternal() { |
+ bool Results; |
+ if (GetBlockID() == naclbitc::BLOCKINFO_BLOCK_ID) { |
+ Results = ParseBlockInfoInternal(); |
+ } else { |
+ Results = ParseBlockInternal(); |
+ ExitBlock(); |
+ } |
+ return Results; |
+ } |
+ |
+ // Parses a BlockInfo block, where processing is handled through |
+ // a listener in the bitstream reader. |
+ bool ParseBlockInfoInternal(); |
+ |
+ // Parses the non-BlockInfo block. Returns true if unable to parse the |
+ // block. |
+ bool ParseBlockInternal(); |
+ |
+ void operator=(const NaClBitcodeParser &Parser) = delete; |
+ NaClBitcodeParser(const NaClBitcodeParser &Parser) = delete; |
+ |
+}; |
+ |
+} // namespace llvm |
+ |
+#endif |