xref: /aosp_15_r20/external/swiftshader/third_party/subzero/pnacl-llvm/NaClBitcodeParser.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- NaClBitcodeParser.cpp ----------------------------------------------===//
2*03ce13f7SAndroid Build Coastguard Worker //     Low-level bitcode driver to parse PNaCl bitcode files.
3*03ce13f7SAndroid Build Coastguard Worker //
4*03ce13f7SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
5*03ce13f7SAndroid Build Coastguard Worker //
6*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
7*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
10*03ce13f7SAndroid Build Coastguard Worker 
11*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
12*03ce13f7SAndroid Build Coastguard Worker 
13*03ce13f7SAndroid Build Coastguard Worker using namespace llvm;
14*03ce13f7SAndroid Build Coastguard Worker 
Print(raw_ostream & os) const15*03ce13f7SAndroid Build Coastguard Worker void NaClBitcodeRecordData::Print(raw_ostream &os) const {
16*03ce13f7SAndroid Build Coastguard Worker   os << "[" << Code;
17*03ce13f7SAndroid Build Coastguard Worker   for (NaClRecordVector::const_iterator Iter = Values.begin(),
18*03ce13f7SAndroid Build Coastguard Worker                                         IterEnd = Values.end();
19*03ce13f7SAndroid Build Coastguard Worker        Iter != IterEnd; ++Iter) {
20*03ce13f7SAndroid Build Coastguard Worker     os << ", " << *Iter;
21*03ce13f7SAndroid Build Coastguard Worker   }
22*03ce13f7SAndroid Build Coastguard Worker   os << "]";
23*03ce13f7SAndroid Build Coastguard Worker }
24*03ce13f7SAndroid Build Coastguard Worker 
Print(raw_ostream & os) const25*03ce13f7SAndroid Build Coastguard Worker void NaClBitcodeRecord::Print(raw_ostream &os) const {
26*03ce13f7SAndroid Build Coastguard Worker   Block.Print(os);
27*03ce13f7SAndroid Build Coastguard Worker   os << ", Code " << Data.Code << ", EntryID " << Entry.ID << ", <";
28*03ce13f7SAndroid Build Coastguard Worker   for (unsigned i = 0, e = Data.Values.size(); i != e; ++i) {
29*03ce13f7SAndroid Build Coastguard Worker     if (i > 0)
30*03ce13f7SAndroid Build Coastguard Worker       os << " ";
31*03ce13f7SAndroid Build Coastguard Worker     os << Data.Values[i];
32*03ce13f7SAndroid Build Coastguard Worker   }
33*03ce13f7SAndroid Build Coastguard Worker   os << ">";
34*03ce13f7SAndroid Build Coastguard Worker }
35*03ce13f7SAndroid Build Coastguard Worker 
NaClBitcodeBlock(unsigned BlockID,const NaClBitcodeRecord & Record)36*03ce13f7SAndroid Build Coastguard Worker NaClBitcodeBlock::NaClBitcodeBlock(unsigned BlockID,
37*03ce13f7SAndroid Build Coastguard Worker                                    const NaClBitcodeRecord &Record)
38*03ce13f7SAndroid Build Coastguard Worker     : NaClBitcodeData(Record), BlockID(BlockID),
39*03ce13f7SAndroid Build Coastguard Worker       EnclosingBlock(&Record.GetBlock()), LocalStartBit(Record.GetStartBit()) {}
40*03ce13f7SAndroid Build Coastguard Worker 
Print(raw_ostream & os) const41*03ce13f7SAndroid Build Coastguard Worker void NaClBitcodeBlock::Print(raw_ostream &os) const {
42*03ce13f7SAndroid Build Coastguard Worker   os << "Block " << BlockID;
43*03ce13f7SAndroid Build Coastguard Worker }
44*03ce13f7SAndroid Build Coastguard Worker 
BeginBlockInfoBlock(unsigned NumWords)45*03ce13f7SAndroid Build Coastguard Worker void NaClBitcodeParserListener::BeginBlockInfoBlock(unsigned NumWords) {
46*03ce13f7SAndroid Build Coastguard Worker   Parser->EnterBlock(NumWords);
47*03ce13f7SAndroid Build Coastguard Worker }
48*03ce13f7SAndroid Build Coastguard Worker 
SetBID()49*03ce13f7SAndroid Build Coastguard Worker void NaClBitcodeParserListener::SetBID() {
50*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.SetStartBit(StartBit);
51*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Entry.Kind = NaClBitstreamEntry::Record;
52*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Entry.ID = naclbitc::UNABBREV_RECORD;
53*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Data.Code = naclbitc::BLOCKINFO_CODE_SETBID;
54*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Data.Values = Values;
55*03ce13f7SAndroid Build Coastguard Worker   GlobalBlockID = Values[0];
56*03ce13f7SAndroid Build Coastguard Worker   Parser->SetBID();
57*03ce13f7SAndroid Build Coastguard Worker   Values.clear();
58*03ce13f7SAndroid Build Coastguard Worker }
59*03ce13f7SAndroid Build Coastguard Worker 
EndBlockInfoBlock()60*03ce13f7SAndroid Build Coastguard Worker void NaClBitcodeParserListener::EndBlockInfoBlock() {
61*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.SetStartBit(StartBit);
62*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Entry.Kind = NaClBitstreamEntry::EndBlock;
63*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Entry.ID = naclbitc::END_BLOCK;
64*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Data.Code = naclbitc::END_BLOCK;
65*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Data.Values.clear();
66*03ce13f7SAndroid Build Coastguard Worker   GlobalBlockID = naclbitc::BLOCKINFO_BLOCK_ID;
67*03ce13f7SAndroid Build Coastguard Worker   Parser->ExitBlock();
68*03ce13f7SAndroid Build Coastguard Worker }
69*03ce13f7SAndroid Build Coastguard Worker 
ProcessAbbreviation(NaClBitCodeAbbrev * Abbrev,bool IsLocal)70*03ce13f7SAndroid Build Coastguard Worker void NaClBitcodeParserListener::ProcessAbbreviation(NaClBitCodeAbbrev *Abbrev,
71*03ce13f7SAndroid Build Coastguard Worker                                                     bool IsLocal) {
72*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.SetStartBit(StartBit);
73*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Entry.Kind = NaClBitstreamEntry::Record;
74*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Entry.ID = naclbitc::DEFINE_ABBREV;
75*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Data.Code = naclbitc::BLK_CODE_DEFINE_ABBREV;
76*03ce13f7SAndroid Build Coastguard Worker   Parser->Record.Data.Values = Values;
77*03ce13f7SAndroid Build Coastguard Worker   Parser->ProcessAbbreviation(IsLocal ? Parser->GetBlockID() : GlobalBlockID,
78*03ce13f7SAndroid Build Coastguard Worker                               Abbrev, IsLocal);
79*03ce13f7SAndroid Build Coastguard Worker }
80*03ce13f7SAndroid Build Coastguard Worker 
~NaClBitcodeParser()81*03ce13f7SAndroid Build Coastguard Worker NaClBitcodeParser::~NaClBitcodeParser() {
82*03ce13f7SAndroid Build Coastguard Worker   if (EnclosingParser) {
83*03ce13f7SAndroid Build Coastguard Worker     EnclosingParser->Block.LocalStartBit += Block.GetNumBits();
84*03ce13f7SAndroid Build Coastguard Worker   }
85*03ce13f7SAndroid Build Coastguard Worker }
86*03ce13f7SAndroid Build Coastguard Worker 
ErrorAt(naclbitc::ErrorLevel Level,uint64_t BitPosition,const std::string & Message)87*03ce13f7SAndroid Build Coastguard Worker bool NaClBitcodeParser::ErrorAt(naclbitc::ErrorLevel Level,
88*03ce13f7SAndroid Build Coastguard Worker                                 uint64_t BitPosition,
89*03ce13f7SAndroid Build Coastguard Worker                                 const std::string &Message) {
90*03ce13f7SAndroid Build Coastguard Worker   naclbitc::ErrorAt(*ErrStream, Level, BitPosition) << Message << "\n";
91*03ce13f7SAndroid Build Coastguard Worker   if (Level == naclbitc::Fatal)
92*03ce13f7SAndroid Build Coastguard Worker     report_fatal_error("Unable to continue");
93*03ce13f7SAndroid Build Coastguard Worker   return true;
94*03ce13f7SAndroid Build Coastguard Worker }
95*03ce13f7SAndroid Build Coastguard Worker 
Parse()96*03ce13f7SAndroid Build Coastguard Worker bool NaClBitcodeParser::Parse() {
97*03ce13f7SAndroid Build Coastguard Worker   Record.ReadEntry();
98*03ce13f7SAndroid Build Coastguard Worker 
99*03ce13f7SAndroid Build Coastguard Worker   if (Record.GetEntryKind() != NaClBitstreamEntry::SubBlock)
100*03ce13f7SAndroid Build Coastguard Worker     return Error("Expected block, but not found");
101*03ce13f7SAndroid Build Coastguard Worker 
102*03ce13f7SAndroid Build Coastguard Worker   return ParseBlock(Record.GetEntryID());
103*03ce13f7SAndroid Build Coastguard Worker }
104*03ce13f7SAndroid Build Coastguard Worker 
ParseBlockInfoInternal()105*03ce13f7SAndroid Build Coastguard Worker bool NaClBitcodeParser::ParseBlockInfoInternal() {
106*03ce13f7SAndroid Build Coastguard Worker   // BLOCKINFO is a special part of the stream. Let the bitstream
107*03ce13f7SAndroid Build Coastguard Worker   // reader process this block.
108*03ce13f7SAndroid Build Coastguard Worker   bool Result = Record.GetCursor().ReadBlockInfoBlock(Listener);
109*03ce13f7SAndroid Build Coastguard Worker   if (Result)
110*03ce13f7SAndroid Build Coastguard Worker     return Error("Malformed BlockInfoBlock");
111*03ce13f7SAndroid Build Coastguard Worker   return Result;
112*03ce13f7SAndroid Build Coastguard Worker }
113*03ce13f7SAndroid Build Coastguard Worker 
ParseBlockInternal()114*03ce13f7SAndroid Build Coastguard Worker bool NaClBitcodeParser::ParseBlockInternal() {
115*03ce13f7SAndroid Build Coastguard Worker   // Regular block. Enter subblock.
116*03ce13f7SAndroid Build Coastguard Worker   unsigned NumWords;
117*03ce13f7SAndroid Build Coastguard Worker   if (Record.GetCursor().EnterSubBlock(GetBlockID(), &NumWords)) {
118*03ce13f7SAndroid Build Coastguard Worker     return Error("Malformed block record");
119*03ce13f7SAndroid Build Coastguard Worker   }
120*03ce13f7SAndroid Build Coastguard Worker 
121*03ce13f7SAndroid Build Coastguard Worker   EnterBlock(NumWords);
122*03ce13f7SAndroid Build Coastguard Worker 
123*03ce13f7SAndroid Build Coastguard Worker   // Process records.
124*03ce13f7SAndroid Build Coastguard Worker   while (1) {
125*03ce13f7SAndroid Build Coastguard Worker     if (Record.GetCursor().AtEndOfStream())
126*03ce13f7SAndroid Build Coastguard Worker       return Error("Premature end of bitstream");
127*03ce13f7SAndroid Build Coastguard Worker 
128*03ce13f7SAndroid Build Coastguard Worker     // Read entry defining type of entry.
129*03ce13f7SAndroid Build Coastguard Worker     Record.ReadEntry();
130*03ce13f7SAndroid Build Coastguard Worker 
131*03ce13f7SAndroid Build Coastguard Worker     switch (Record.GetEntryKind()) {
132*03ce13f7SAndroid Build Coastguard Worker     case NaClBitstreamEntry::Error:
133*03ce13f7SAndroid Build Coastguard Worker       return Error("malformed bitcode file");
134*03ce13f7SAndroid Build Coastguard Worker     case NaClBitstreamEntry::EndBlock: {
135*03ce13f7SAndroid Build Coastguard Worker       return false;
136*03ce13f7SAndroid Build Coastguard Worker     }
137*03ce13f7SAndroid Build Coastguard Worker     case NaClBitstreamEntry::SubBlock: {
138*03ce13f7SAndroid Build Coastguard Worker       if (ParseBlock(Record.GetEntryID()))
139*03ce13f7SAndroid Build Coastguard Worker         return true;
140*03ce13f7SAndroid Build Coastguard Worker       break;
141*03ce13f7SAndroid Build Coastguard Worker     }
142*03ce13f7SAndroid Build Coastguard Worker     case NaClBitstreamEntry::Record:
143*03ce13f7SAndroid Build Coastguard Worker       // The interesting case.
144*03ce13f7SAndroid Build Coastguard Worker       if (Record.GetEntryID() == naclbitc::DEFINE_ABBREV) {
145*03ce13f7SAndroid Build Coastguard Worker         // Since this abbreviation is local, the listener doesn't
146*03ce13f7SAndroid Build Coastguard Worker         // have the start bit set (it is only set when processing
147*03ce13f7SAndroid Build Coastguard Worker         // the BlockInfo block). Fix this by setting it here.
148*03ce13f7SAndroid Build Coastguard Worker         if (Listener)
149*03ce13f7SAndroid Build Coastguard Worker           Listener->StartBit = Record.GetStartBit();
150*03ce13f7SAndroid Build Coastguard Worker         Record.GetCursor().ReadAbbrevRecord(true, Listener);
151*03ce13f7SAndroid Build Coastguard Worker       } else {
152*03ce13f7SAndroid Build Coastguard Worker         // Read in a record.
153*03ce13f7SAndroid Build Coastguard Worker         Record.ReadValues();
154*03ce13f7SAndroid Build Coastguard Worker         ProcessRecord();
155*03ce13f7SAndroid Build Coastguard Worker       }
156*03ce13f7SAndroid Build Coastguard Worker       break;
157*03ce13f7SAndroid Build Coastguard Worker     }
158*03ce13f7SAndroid Build Coastguard Worker   }
159*03ce13f7SAndroid Build Coastguard Worker   return false;
160*03ce13f7SAndroid Build Coastguard Worker }
161