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