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