• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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