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