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 13using namespace llvm; 14 15void 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 25void 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 35NaClBitcodeBlock::NaClBitcodeBlock(unsigned BlockID, 36 const NaClBitcodeRecord &Record) 37 : NaClBitcodeData(Record), 38 BlockID(BlockID), 39 EnclosingBlock(&Record.GetBlock()), 40 LocalStartBit(Record.GetStartBit()) 41{} 42 43void NaClBitcodeBlock::Print(raw_ostream &os) const { 44 os << "Block " << BlockID; 45} 46 47void NaClBitcodeParserListener::BeginBlockInfoBlock(unsigned NumWords) { 48 Parser->EnterBlock(NumWords); 49} 50 51void 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 62void 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 72void NaClBitcodeParserListener:: 73ProcessAbbreviation(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 83NaClBitcodeParser::~NaClBitcodeParser() { 84 if (EnclosingParser) { 85 EnclosingParser->Block.LocalStartBit += Block.GetNumBits(); 86 } 87} 88 89bool 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 98bool 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 107bool 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 115bool 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