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
Print(raw_ostream & os) const15 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
Print(raw_ostream & os) const25 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
NaClBitcodeBlock(unsigned BlockID,const NaClBitcodeRecord & Record)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
Print(raw_ostream & os) const43 void NaClBitcodeBlock::Print(raw_ostream &os) const {
44 os << "Block " << BlockID;
45 }
46
BeginBlockInfoBlock(unsigned NumWords)47 void NaClBitcodeParserListener::BeginBlockInfoBlock(unsigned NumWords) {
48 Parser->EnterBlock(NumWords);
49 }
50
SetBID()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
EndBlockInfoBlock()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::
ProcessAbbreviation(NaClBitCodeAbbrev * Abbrev,bool IsLocal)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
~NaClBitcodeParser()83 NaClBitcodeParser::~NaClBitcodeParser() {
84 if (EnclosingParser) {
85 EnclosingParser->Block.LocalStartBit += Block.GetNumBits();
86 }
87 }
88
ErrorAt(naclbitc::ErrorLevel Level,uint64_t BitPosition,const std::string & Message)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
Parse()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
ParseBlockInfoInternal()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
ParseBlockInternal()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