//===- 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; }