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 Iter = Values.begin(),
18 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)
30 os << " ";
31 os << Data.Values[i];
32 }
33 os << ">";
34 }
35
NaClBitcodeBlock(unsigned BlockID,const NaClBitcodeRecord & Record)36 NaClBitcodeBlock::NaClBitcodeBlock(unsigned BlockID,
37 const NaClBitcodeRecord &Record)
38 : NaClBitcodeData(Record), BlockID(BlockID),
39 EnclosingBlock(&Record.GetBlock()), LocalStartBit(Record.GetStartBit()) {}
40
Print(raw_ostream & os) const41 void NaClBitcodeBlock::Print(raw_ostream &os) const {
42 os << "Block " << BlockID;
43 }
44
BeginBlockInfoBlock(unsigned NumWords)45 void NaClBitcodeParserListener::BeginBlockInfoBlock(unsigned NumWords) {
46 Parser->EnterBlock(NumWords);
47 }
48
SetBID()49 void NaClBitcodeParserListener::SetBID() {
50 Parser->Record.SetStartBit(StartBit);
51 Parser->Record.Entry.Kind = NaClBitstreamEntry::Record;
52 Parser->Record.Entry.ID = naclbitc::UNABBREV_RECORD;
53 Parser->Record.Data.Code = naclbitc::BLOCKINFO_CODE_SETBID;
54 Parser->Record.Data.Values = Values;
55 GlobalBlockID = Values[0];
56 Parser->SetBID();
57 Values.clear();
58 }
59
EndBlockInfoBlock()60 void NaClBitcodeParserListener::EndBlockInfoBlock() {
61 Parser->Record.SetStartBit(StartBit);
62 Parser->Record.Entry.Kind = NaClBitstreamEntry::EndBlock;
63 Parser->Record.Entry.ID = naclbitc::END_BLOCK;
64 Parser->Record.Data.Code = naclbitc::END_BLOCK;
65 Parser->Record.Data.Values.clear();
66 GlobalBlockID = naclbitc::BLOCKINFO_BLOCK_ID;
67 Parser->ExitBlock();
68 }
69
ProcessAbbreviation(NaClBitCodeAbbrev * Abbrev,bool IsLocal)70 void NaClBitcodeParserListener::ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev,
71 bool IsLocal) {
72 Parser->Record.SetStartBit(StartBit);
73 Parser->Record.Entry.Kind = NaClBitstreamEntry::Record;
74 Parser->Record.Entry.ID = naclbitc::DEFINE_ABBREV;
75 Parser->Record.Data.Code = naclbitc::BLK_CODE_DEFINE_ABBREV;
76 Parser->Record.Data.Values = Values;
77 Parser->ProcessAbbreviation(IsLocal ? Parser->GetBlockID() : GlobalBlockID,
78 Abbrev, IsLocal);
79 }
80
~NaClBitcodeParser()81 NaClBitcodeParser::~NaClBitcodeParser() {
82 if (EnclosingParser) {
83 EnclosingParser->Block.LocalStartBit += Block.GetNumBits();
84 }
85 }
86
ErrorAt(naclbitc::ErrorLevel Level,uint64_t BitPosition,const std::string & Message)87 bool NaClBitcodeParser::ErrorAt(naclbitc::ErrorLevel Level,
88 uint64_t BitPosition,
89 const std::string &Message) {
90 naclbitc::ErrorAt(*ErrStream, Level, BitPosition) << Message << "\n";
91 if (Level == naclbitc::Fatal)
92 report_fatal_error("Unable to continue");
93 return true;
94 }
95
Parse()96 bool NaClBitcodeParser::Parse() {
97 Record.ReadEntry();
98
99 if (Record.GetEntryKind() != NaClBitstreamEntry::SubBlock)
100 return Error("Expected block, but not found");
101
102 return ParseBlock(Record.GetEntryID());
103 }
104
ParseBlockInfoInternal()105 bool NaClBitcodeParser::ParseBlockInfoInternal() {
106 // BLOCKINFO is a special part of the stream. Let the bitstream
107 // reader process this block.
108 bool Result = Record.GetCursor().ReadBlockInfoBlock(Listener);
109 if (Result)
110 return Error("Malformed BlockInfoBlock");
111 return Result;
112 }
113
ParseBlockInternal()114 bool NaClBitcodeParser::ParseBlockInternal() {
115 // Regular block. Enter subblock.
116 unsigned NumWords;
117 if (Record.GetCursor().EnterSubBlock(GetBlockID(), &NumWords)) {
118 return Error("Malformed block record");
119 }
120
121 EnterBlock(NumWords);
122
123 // Process records.
124 while (1) {
125 if (Record.GetCursor().AtEndOfStream())
126 return Error("Premature end of bitstream");
127
128 // Read entry defining type of entry.
129 Record.ReadEntry();
130
131 switch (Record.GetEntryKind()) {
132 case NaClBitstreamEntry::Error:
133 return Error("malformed bitcode file");
134 case NaClBitstreamEntry::EndBlock: {
135 return false;
136 }
137 case NaClBitstreamEntry::SubBlock: {
138 if (ParseBlock(Record.GetEntryID()))
139 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)
149 Listener->StartBit = Record.GetStartBit();
150 Record.GetCursor().ReadAbbrevRecord(true, Listener);
151 } else {
152 // Read in a record.
153 Record.ReadValues();
154 ProcessRecord();
155 }
156 break;
157 }
158 }
159 return false;
160 }
161