|  | //===- NaClBitcodeParser.cpp ----------------------------------------------===// | 
|  | //     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. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | void NaClBitcodeRecordData::Print(raw_ostream &os) const { | 
|  | os << "[" << Code; | 
|  | for (NaClRecordVector::const_iterator | 
|  | Iter = Values.begin(), IterEnd = Values.end(); | 
|  | Iter != IterEnd; ++Iter) { | 
|  | os << ", " << *Iter; | 
|  | } | 
|  | os << "]"; | 
|  | } | 
|  |  | 
|  | void NaClBitcodeRecord::Print(raw_ostream& os) const { | 
|  | Block.Print(os); | 
|  | os << ", Code " << Data.Code << ", EntryID " << Entry.ID << ", <"; | 
|  | for (unsigned i = 0, e = Data.Values.size(); i != e; ++i) { | 
|  | if (i > 0) os << " "; | 
|  | os << Data.Values[i]; | 
|  | } | 
|  | os << ">"; | 
|  | } | 
|  |  | 
|  | NaClBitcodeBlock::NaClBitcodeBlock(unsigned BlockID, | 
|  | const NaClBitcodeRecord &Record) | 
|  | : NaClBitcodeData(Record), | 
|  | BlockID(BlockID), | 
|  | EnclosingBlock(&Record.GetBlock()), | 
|  | LocalStartBit(Record.GetStartBit()) | 
|  | {} | 
|  |  | 
|  | void NaClBitcodeBlock::Print(raw_ostream &os) const { | 
|  | os << "Block " << BlockID; | 
|  | } | 
|  |  | 
|  | void NaClBitcodeParserListener::BeginBlockInfoBlock(unsigned NumWords) { | 
|  | Parser->EnterBlock(NumWords); | 
|  | } | 
|  |  | 
|  | void NaClBitcodeParserListener::SetBID() { | 
|  | Parser->Record.SetStartBit(StartBit); | 
|  | Parser->Record.Entry.Kind = NaClBitstreamEntry::Record; | 
|  | Parser->Record.Entry.ID = naclbitc::UNABBREV_RECORD; | 
|  | Parser->Record.Data.Code = naclbitc::BLOCKINFO_CODE_SETBID; | 
|  | Parser->Record.Data.Values = Values; | 
|  | GlobalBlockID = Values[0]; | 
|  | Parser->SetBID(); | 
|  | Values.clear(); | 
|  | } | 
|  |  | 
|  | void NaClBitcodeParserListener::EndBlockInfoBlock() { | 
|  | Parser->Record.SetStartBit(StartBit); | 
|  | Parser->Record.Entry.Kind = NaClBitstreamEntry::EndBlock; | 
|  | Parser->Record.Entry.ID = naclbitc::END_BLOCK; | 
|  | Parser->Record.Data.Code = naclbitc::END_BLOCK; | 
|  | Parser->Record.Data.Values.clear(); | 
|  | GlobalBlockID = naclbitc::BLOCKINFO_BLOCK_ID; | 
|  | Parser->ExitBlock(); | 
|  | } | 
|  |  | 
|  | void NaClBitcodeParserListener:: | 
|  | ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev, bool IsLocal) { | 
|  | Parser->Record.SetStartBit(StartBit); | 
|  | Parser->Record.Entry.Kind = NaClBitstreamEntry::Record; | 
|  | Parser->Record.Entry.ID = naclbitc::DEFINE_ABBREV; | 
|  | Parser->Record.Data.Code = naclbitc::BLK_CODE_DEFINE_ABBREV; | 
|  | Parser->Record.Data.Values = Values; | 
|  | Parser->ProcessAbbreviation(IsLocal ? Parser->GetBlockID() : GlobalBlockID, | 
|  | Abbrev, IsLocal); | 
|  | } | 
|  |  | 
|  | NaClBitcodeParser::~NaClBitcodeParser() { | 
|  | if (EnclosingParser) { | 
|  | EnclosingParser->Block.LocalStartBit += Block.GetNumBits(); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool NaClBitcodeParser::ErrorAt( | 
|  | naclbitc::ErrorLevel Level, uint64_t BitPosition, | 
|  | const std::string &Message) { | 
|  | naclbitc::ErrorAt(*ErrStream, Level, BitPosition) << Message << "\n"; | 
|  | if (Level == naclbitc::Fatal) | 
|  | report_fatal_error("Unable to continue"); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool NaClBitcodeParser::Parse() { | 
|  | Record.ReadEntry(); | 
|  |  | 
|  | if (Record.GetEntryKind() != NaClBitstreamEntry::SubBlock) | 
|  | return Error("Expected block, but not found"); | 
|  |  | 
|  | return ParseBlock(Record.GetEntryID()); | 
|  | } | 
|  |  | 
|  | bool NaClBitcodeParser::ParseBlockInfoInternal() { | 
|  | // BLOCKINFO is a special part of the stream. Let the bitstream | 
|  | // reader process this block. | 
|  | bool Result = Record.GetCursor().ReadBlockInfoBlock(Listener); | 
|  | if (Result) return Error("Malformed BlockInfoBlock"); | 
|  | return Result; | 
|  | } | 
|  |  | 
|  | bool NaClBitcodeParser::ParseBlockInternal() { | 
|  | // Regular block. Enter subblock. | 
|  | unsigned NumWords; | 
|  | if (Record.GetCursor().EnterSubBlock(GetBlockID(), &NumWords)) { | 
|  | return Error("Malformed block record"); | 
|  | } | 
|  |  | 
|  | EnterBlock(NumWords); | 
|  |  | 
|  | // Process records. | 
|  | while (1) { | 
|  | if (Record.GetCursor().AtEndOfStream()) | 
|  | return Error("Premature end of bitstream"); | 
|  |  | 
|  | // Read entry defining type of entry. | 
|  | Record.ReadEntry(); | 
|  |  | 
|  | switch (Record.GetEntryKind()) { | 
|  | case NaClBitstreamEntry::Error: | 
|  | return Error("malformed bitcode file"); | 
|  | case NaClBitstreamEntry::EndBlock: { | 
|  | return false; | 
|  | } | 
|  | case NaClBitstreamEntry::SubBlock: { | 
|  | if (ParseBlock(Record.GetEntryID())) return true; | 
|  | break; | 
|  | } | 
|  | case NaClBitstreamEntry::Record: | 
|  | // The interesting case. | 
|  | if (Record.GetEntryID() == naclbitc::DEFINE_ABBREV) { | 
|  | // Since this abbreviation is local, the listener doesn't | 
|  | // have the start bit set (it is only set when processing | 
|  | // the BlockInfo block). Fix this by setting it here. | 
|  | if (Listener) Listener->StartBit = Record.GetStartBit(); | 
|  | Record.GetCursor().ReadAbbrevRecord(true, Listener); | 
|  | } else { | 
|  | // Read in a record. | 
|  | Record.ReadValues(); | 
|  | ProcessRecord(); | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } |