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