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. NaClBitcodeData(NaClBitstreamCursor & Cursor)118 explicit NaClBitcodeData(NaClBitstreamCursor &Cursor) 119 : Cursor(Cursor), StartBit(Cursor.GetCurrentBitNo()) 120 {} 121 122 /// Create copy of the given data element. NaClBitcodeData(const NaClBitcodeData & Data)123 explicit NaClBitcodeData(const NaClBitcodeData &Data) 124 : Cursor(Data.Cursor), StartBit(Data.StartBit) 125 {} 126 127 /// Returns the bitstream reader being used. GetReader()128 NaClBitstreamReader &GetReader() const { 129 return *Cursor.getBitStreamReader(); 130 } 131 132 /// Returns the cursor position within the bitstream. GetCursor()133 NaClBitstreamCursor &GetCursor() const { 134 return Cursor; 135 } 136 137 /// Returns the number of bits defined by the data. GetNumBits()138 uint64_t GetNumBits() const { 139 return GetCursor().GetCurrentBitNo() - StartBit; 140 } 141 142 /// Returns the first bit of the stream data. GetStartBit()143 uint64_t GetStartBit() const { 144 return StartBit; 145 } 146 147 protected: 148 /// Change the start bit for the data to the new value. SetStartBit(uint64_t NewValue)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. NaClBitcodeBlock(unsigned BlockID,NaClBitstreamCursor & 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. GetEnclosingBlock()185 const NaClBitcodeBlock *GetEnclosingBlock() const { 186 return EnclosingBlock; 187 } 188 189 /// Returns the block ID of the block. GetBlockID()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. GetLocalNumBits()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: NaClBitcodeRecordData(unsigned Code,const NaClRecordVector & Values)218 NaClBitcodeRecordData(unsigned Code, const NaClRecordVector &Values) 219 : Code(Code), Values(Values) {} NaClBitcodeRecordData(const NaClBitcodeRecordData & Record)220 explicit NaClBitcodeRecordData(const NaClBitcodeRecordData &Record) 221 : Code(Record.Code), Values(Record.Values) {} NaClBitcodeRecordData()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: NaClBitcodeValuesNaClBitcodeValues241 NaClBitcodeValues(const NaClBitcodeRecordData &Record) 242 : Record(Record) {} 243 sizeNaClBitcodeValues244 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. NaClBitcodeRecord(const NaClBitcodeBlock & Block)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. GetBlock()274 const NaClBitcodeBlock &GetBlock() const { 275 return Block; 276 } 277 278 /// Returns the block ID associated with the record. GetBlockID()279 unsigned GetBlockID() const { 280 return Block.GetBlockID(); 281 } 282 283 /// Returns the kind of entry read from the input stream. GetEntryKind()284 unsigned GetEntryKind() const { 285 return Entry.Kind; 286 } 287 288 /// Returns the code value (i.e. selector) associated with the 289 /// record. GetCode()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. GetEntryID()298 unsigned GetEntryID() const { 299 return Entry.ID; 300 } 301 302 /// Returns the (value) record associated with the read record. GetValues()303 const RecordVector &GetValues() const { 304 return Data.Values; 305 } 306 307 /// Allows lower level access to data representing record. GetRecordData()308 const NaClBitcodeRecordData &GetRecordData() const { 309 return Data; 310 } 311 312 /// Returns true if the record was read using an abbreviation. UsedAnAbbreviation()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. GetAbbreviationIndex()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. SetAbbreviationIndex(unsigned Index)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. ReadEntry()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). ReadValues()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. NaClBitcodeParserListener(NaClBitcodeParser * Parser)379 NaClBitcodeParserListener(NaClBitcodeParser *Parser) 380 : Parser(Parser), GlobalBlockID(naclbitc::BLOCKINFO_BLOCK_ID) { 381 } 382 ~NaClBitcodeParserListener()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: ErrorHandler(NaClBitcodeParser * Parser,NaClBitstreamCursor & Cursor)415 ErrorHandler(NaClBitcodeParser *Parser, 416 NaClBitstreamCursor &Cursor): 417 NaClBitstreamCursor::ErrorHandler(Cursor), Parser(Parser) {} 418 LLVM_ATTRIBUTE_NORETURN Fatal(const std::string & ErrorMessage)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 } ~ErrorHandler()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. NaClBitcodeParser(NaClBitstreamCursor & Cursor)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. EnterBlock(unsigned)451 virtual void EnterBlock(unsigned /*NumWords*/) {} 452 453 // Called when the corresponding EndBlock of the block being parsed 454 // is found. ExitBlock()455 virtual void ExitBlock() {} 456 457 // Called after each record (within the block) is read (into field Record). ProcessRecord()458 virtual void ProcessRecord() {} 459 460 // Called if a SetBID record is encountered in the BlockInfo block, 461 // and the parser has a listener. SetBID()462 virtual void SetBID() {} 463 464 // Called to process an abbreviation if the parser has a listener. ProcessAbbreviation(unsigned,NaClBitCodeAbbrev *,bool)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. ParseBlock(unsigned BlockID)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. setErrStream(raw_ostream & Stream)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 ErrorAt(uint64_t BitPosition,const std::string & Message)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). Error(const std::string & Message)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 FatalAt(uint64_t BitPosition,const std::string & Message)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 Fatal(const std::string & Message)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 Fatal()528 void Fatal() { 529 Fatal("Fatal error occurred!"); 530 } 531 532 // Returns the number of bits in this block, including nested blocks. GetBlockNumBits()533 unsigned GetBlockNumBits() const { 534 return Block.GetNumBits(); 535 } 536 537 // Returns the number of bits in this block, excluding nested blocks. GetBlockLocalNumBits()538 unsigned GetBlockLocalNumBits() const { 539 return Block.GetLocalNumBits(); 540 } 541 542 /// Returns the block ID associated with the Parser. GetBlockID()543 unsigned GetBlockID() const { 544 return Block.GetBlockID(); 545 } 546 GetBlock()547 NaClBitcodeBlock &GetBlock() { 548 return Block; 549 } 550 551 /// Returns the enclosing parser of this block. GetEnclosingParser()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). ParseThisBlock()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. SkipBlock()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. NaClBitcodeParser(unsigned BlockID,NaClBitcodeParser * 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. NaClBitcodeParser(unsigned BlockID,NaClBitcodeParser * EnclosingParser,NaClBitstreamCursor & Cursor)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. SetListener(NaClBitcodeParserListener * UseListener)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. ParseThisBlockInternal()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