Index: pnacl-llvm/NaClBitcodeParser.cpp |
diff --git a/pnacl-llvm/NaClBitcodeParser.cpp b/pnacl-llvm/NaClBitcodeParser.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..30744ec4982dc7c91806712286652040203206f5 |
--- /dev/null |
+++ b/pnacl-llvm/NaClBitcodeParser.cpp |
@@ -0,0 +1,159 @@ |
+//===- 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; |
+} |