Home | History | Annotate | Download | only in pnacl-llvm
      1 //===- NaClBitcodeParser.cpp ----------------------------------------------===//
      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 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
     12 
     13 using namespace llvm;
     14 
     15 void NaClBitcodeRecordData::Print(raw_ostream &os) const {
     16   os << "[" << Code;
     17   for (NaClRecordVector::const_iterator
     18            Iter = Values.begin(), IterEnd = Values.end();
     19        Iter != IterEnd; ++Iter) {
     20     os << ", " << *Iter;
     21   }
     22   os << "]";
     23 }
     24 
     25 void NaClBitcodeRecord::Print(raw_ostream& os) const {
     26   Block.Print(os);
     27   os << ", Code " << Data.Code << ", EntryID " << Entry.ID << ", <";
     28   for (unsigned i = 0, e = Data.Values.size(); i != e; ++i) {
     29     if (i > 0) os << " ";
     30     os << Data.Values[i];
     31   }
     32   os << ">";
     33 }
     34 
     35 NaClBitcodeBlock::NaClBitcodeBlock(unsigned BlockID,
     36                                    const NaClBitcodeRecord &Record)
     37     : NaClBitcodeData(Record),
     38       BlockID(BlockID),
     39       EnclosingBlock(&Record.GetBlock()),
     40       LocalStartBit(Record.GetStartBit())
     41 {}
     42 
     43 void NaClBitcodeBlock::Print(raw_ostream &os) const {
     44   os << "Block " << BlockID;
     45 }
     46 
     47 void NaClBitcodeParserListener::BeginBlockInfoBlock(unsigned NumWords) {
     48   Parser->EnterBlock(NumWords);
     49 }
     50 
     51 void NaClBitcodeParserListener::SetBID() {
     52   Parser->Record.SetStartBit(StartBit);
     53   Parser->Record.Entry.Kind = NaClBitstreamEntry::Record;
     54   Parser->Record.Entry.ID = naclbitc::UNABBREV_RECORD;
     55   Parser->Record.Data.Code = naclbitc::BLOCKINFO_CODE_SETBID;
     56   Parser->Record.Data.Values = Values;
     57   GlobalBlockID = Values[0];
     58   Parser->SetBID();
     59   Values.clear();
     60 }
     61 
     62 void NaClBitcodeParserListener::EndBlockInfoBlock() {
     63   Parser->Record.SetStartBit(StartBit);
     64   Parser->Record.Entry.Kind = NaClBitstreamEntry::EndBlock;
     65   Parser->Record.Entry.ID = naclbitc::END_BLOCK;
     66   Parser->Record.Data.Code = naclbitc::END_BLOCK;
     67   Parser->Record.Data.Values.clear();
     68   GlobalBlockID = naclbitc::BLOCKINFO_BLOCK_ID;
     69   Parser->ExitBlock();
     70 }
     71 
     72 void NaClBitcodeParserListener::
     73 ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, bool IsLocal) {
     74   Parser->Record.SetStartBit(StartBit);
     75   Parser->Record.Entry.Kind = NaClBitstreamEntry::Record;
     76   Parser->Record.Entry.ID = naclbitc::DEFINE_ABBREV;
     77   Parser->Record.Data.Code = naclbitc::BLK_CODE_DEFINE_ABBREV;
     78   Parser->Record.Data.Values = Values;
     79   Parser->ProcessAbbreviation(IsLocal ? Parser->GetBlockID() : GlobalBlockID,
     80                               Abbrev, IsLocal);
     81 }
     82 
     83 NaClBitcodeParser::~NaClBitcodeParser() {
     84   if (EnclosingParser) {
     85     EnclosingParser->Block.LocalStartBit += Block.GetNumBits();
     86   }
     87 }
     88 
     89 bool NaClBitcodeParser::ErrorAt(
     90     naclbitc::ErrorLevel Level, uint64_t BitPosition,
     91     const std::string &Message) {
     92   naclbitc::ErrorAt(*ErrStream, Level, BitPosition) << Message << "\n";
     93   if (Level == naclbitc::Fatal)
     94     report_fatal_error("Unable to continue");
     95   return true;
     96 }
     97 
     98 bool NaClBitcodeParser::Parse() {
     99   Record.ReadEntry();
    100 
    101   if (Record.GetEntryKind() != NaClBitstreamEntry::SubBlock)
    102     return Error("Expected block, but not found");
    103 
    104   return ParseBlock(Record.GetEntryID());
    105 }
    106 
    107 bool NaClBitcodeParser::ParseBlockInfoInternal() {
    108   // BLOCKINFO is a special part of the stream. Let the bitstream
    109   // reader process this block.
    110   bool Result = Record.GetCursor().ReadBlockInfoBlock(Listener);
    111   if (Result) return Error("Malformed BlockInfoBlock");
    112   return Result;
    113 }
    114 
    115 bool NaClBitcodeParser::ParseBlockInternal() {
    116   // Regular block. Enter subblock.
    117   unsigned NumWords;
    118   if (Record.GetCursor().EnterSubBlock(GetBlockID(), &NumWords)) {
    119     return Error("Malformed block record");
    120   }
    121 
    122   EnterBlock(NumWords);
    123 
    124   // Process records.
    125   while (1) {
    126     if (Record.GetCursor().AtEndOfStream())
    127       return Error("Premature end of bitstream");
    128 
    129     // Read entry defining type of entry.
    130     Record.ReadEntry();
    131 
    132     switch (Record.GetEntryKind()) {
    133     case NaClBitstreamEntry::Error:
    134       return Error("malformed bitcode file");
    135     case NaClBitstreamEntry::EndBlock: {
    136       return false;
    137     }
    138     case NaClBitstreamEntry::SubBlock: {
    139       if (ParseBlock(Record.GetEntryID())) return true;
    140       break;
    141     }
    142     case NaClBitstreamEntry::Record:
    143       // The interesting case.
    144       if (Record.GetEntryID() == naclbitc::DEFINE_ABBREV) {
    145         // Since this abbreviation is local, the listener doesn't
    146         // have the start bit set (it is only set when processing
    147         // the BlockInfo block). Fix this by setting it here.
    148         if (Listener) Listener->StartBit = Record.GetStartBit();
    149         Record.GetCursor().ReadAbbrevRecord(true, Listener);
    150       } else {
    151         // Read in a record.
    152         Record.ReadValues();
    153         ProcessRecord();
    154       }
    155       break;
    156     }
    157   }
    158   return false;
    159 }
    160