xref: /aosp_15_r20/external/swiftshader/third_party/subzero/pnacl-llvm/NaClBitstreamReader.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- NaClBitstreamReader.cpp --------------------------------------------===//
2*03ce13f7SAndroid Build Coastguard Worker //     NaClBitstreamReader implementation
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/NaClBitstreamReader.h"
12*03ce13f7SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
13*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/Format.h"
14*03ce13f7SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
15*03ce13f7SAndroid Build Coastguard Worker 
16*03ce13f7SAndroid Build Coastguard Worker using namespace llvm;
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker namespace {
19*03ce13f7SAndroid Build Coastguard Worker 
20*03ce13f7SAndroid Build Coastguard Worker static const char *ErrorLevelName[] = {"Warning", "Error", "Fatal"};
21*03ce13f7SAndroid Build Coastguard Worker 
22*03ce13f7SAndroid Build Coastguard Worker } // End of anonymous namespace.
23*03ce13f7SAndroid Build Coastguard Worker 
getBitAddress(uint64_t Bit)24*03ce13f7SAndroid Build Coastguard Worker std::string llvm::naclbitc::getBitAddress(uint64_t Bit) {
25*03ce13f7SAndroid Build Coastguard Worker   std::string Buffer;
26*03ce13f7SAndroid Build Coastguard Worker   raw_string_ostream Stream(Buffer);
27*03ce13f7SAndroid Build Coastguard Worker   Stream << (Bit / 8) << ":" << (Bit % 8);
28*03ce13f7SAndroid Build Coastguard Worker   return Stream.str();
29*03ce13f7SAndroid Build Coastguard Worker }
30*03ce13f7SAndroid Build Coastguard Worker 
ErrorAt(raw_ostream & Out,ErrorLevel Level,uint64_t BitPosition)31*03ce13f7SAndroid Build Coastguard Worker raw_ostream &llvm::naclbitc::ErrorAt(raw_ostream &Out, ErrorLevel Level,
32*03ce13f7SAndroid Build Coastguard Worker                                      uint64_t BitPosition) {
33*03ce13f7SAndroid Build Coastguard Worker   assert(Level < array_lengthof(::ErrorLevelName));
34*03ce13f7SAndroid Build Coastguard Worker   return Out << ErrorLevelName[Level] << "("
35*03ce13f7SAndroid Build Coastguard Worker              << naclbitc::getBitAddress(BitPosition) << "): ";
36*03ce13f7SAndroid Build Coastguard Worker }
37*03ce13f7SAndroid Build Coastguard Worker 
38*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
39*03ce13f7SAndroid Build Coastguard Worker //  NaClBitstreamCursor implementation
40*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
41*03ce13f7SAndroid Build Coastguard Worker 
Fatal(const std::string & ErrorMessage) const42*03ce13f7SAndroid Build Coastguard Worker void NaClBitstreamCursor::ErrorHandler::Fatal(
43*03ce13f7SAndroid Build Coastguard Worker     const std::string &ErrorMessage) const {
44*03ce13f7SAndroid Build Coastguard Worker   // Default implementation is simply print message, and the bit where
45*03ce13f7SAndroid Build Coastguard Worker   // the error occurred.
46*03ce13f7SAndroid Build Coastguard Worker   std::string Buffer;
47*03ce13f7SAndroid Build Coastguard Worker   raw_string_ostream StrBuf(Buffer);
48*03ce13f7SAndroid Build Coastguard Worker   naclbitc::ErrorAt(StrBuf, naclbitc::Fatal,
49*03ce13f7SAndroid Build Coastguard Worker                     Cursor.getErrorBitNo(getCurrentBitNo()))
50*03ce13f7SAndroid Build Coastguard Worker       << ErrorMessage;
51*03ce13f7SAndroid Build Coastguard Worker   report_fatal_error(StrBuf.str());
52*03ce13f7SAndroid Build Coastguard Worker }
53*03ce13f7SAndroid Build Coastguard Worker 
reportInvalidAbbrevNumber(unsigned AbbrevNo) const54*03ce13f7SAndroid Build Coastguard Worker void NaClBitstreamCursor::reportInvalidAbbrevNumber(unsigned AbbrevNo) const {
55*03ce13f7SAndroid Build Coastguard Worker   std::string Buffer;
56*03ce13f7SAndroid Build Coastguard Worker   raw_string_ostream StrBuf(Buffer);
57*03ce13f7SAndroid Build Coastguard Worker   StrBuf << "Invalid abbreviation # " << AbbrevNo << " defined for record";
58*03ce13f7SAndroid Build Coastguard Worker   ErrHandler->Fatal(StrBuf.str());
59*03ce13f7SAndroid Build Coastguard Worker }
60*03ce13f7SAndroid Build Coastguard Worker 
reportInvalidJumpToBit(uint64_t BitNo) const61*03ce13f7SAndroid Build Coastguard Worker void NaClBitstreamCursor::reportInvalidJumpToBit(uint64_t BitNo) const {
62*03ce13f7SAndroid Build Coastguard Worker   std::string Buffer;
63*03ce13f7SAndroid Build Coastguard Worker   raw_string_ostream StrBuf(Buffer);
64*03ce13f7SAndroid Build Coastguard Worker   StrBuf << "Invalid jump to bit " << BitNo;
65*03ce13f7SAndroid Build Coastguard Worker   ErrHandler->Fatal(StrBuf.str());
66*03ce13f7SAndroid Build Coastguard Worker }
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, enter
69*03ce13f7SAndroid Build Coastguard Worker /// the block, and return true if the block has an error.
EnterSubBlock(unsigned BlockID,unsigned * NumWordsP)70*03ce13f7SAndroid Build Coastguard Worker bool NaClBitstreamCursor::EnterSubBlock(unsigned BlockID, unsigned *NumWordsP) {
71*03ce13f7SAndroid Build Coastguard Worker   const bool IsFixed = true;
72*03ce13f7SAndroid Build Coastguard Worker   NaClBitcodeSelectorAbbrev CodeAbbrev(IsFixed,
73*03ce13f7SAndroid Build Coastguard Worker                                        ReadVBR(naclbitc::CodeLenWidth));
74*03ce13f7SAndroid Build Coastguard Worker   BlockScope.push_back(Block(BitStream->getBlockInfo(BlockID), CodeAbbrev));
75*03ce13f7SAndroid Build Coastguard Worker   SkipToFourByteBoundary();
76*03ce13f7SAndroid Build Coastguard Worker   unsigned NumWords = Read(naclbitc::BlockSizeWidth);
77*03ce13f7SAndroid Build Coastguard Worker   if (NumWordsP)
78*03ce13f7SAndroid Build Coastguard Worker     *NumWordsP = NumWords;
79*03ce13f7SAndroid Build Coastguard Worker 
80*03ce13f7SAndroid Build Coastguard Worker   // Validate that this block is sane.
81*03ce13f7SAndroid Build Coastguard Worker   if (BlockScope.back().getCodeAbbrev().NumBits == 0 || AtEndOfStream())
82*03ce13f7SAndroid Build Coastguard Worker     return true;
83*03ce13f7SAndroid Build Coastguard Worker 
84*03ce13f7SAndroid Build Coastguard Worker   return false;
85*03ce13f7SAndroid Build Coastguard Worker }
86*03ce13f7SAndroid Build Coastguard Worker 
skipAbbreviatedField(const NaClBitCodeAbbrevOp & Op)87*03ce13f7SAndroid Build Coastguard Worker void NaClBitstreamCursor::skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op) {
88*03ce13f7SAndroid Build Coastguard Worker   // Decode the value as we are commanded.
89*03ce13f7SAndroid Build Coastguard Worker   switch (Op.getEncoding()) {
90*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Literal:
91*03ce13f7SAndroid Build Coastguard Worker     // No read necessary for literal.
92*03ce13f7SAndroid Build Coastguard Worker     break;
93*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Fixed:
94*03ce13f7SAndroid Build Coastguard Worker     (void)Read((unsigned)Op.getValue());
95*03ce13f7SAndroid Build Coastguard Worker     break;
96*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::VBR:
97*03ce13f7SAndroid Build Coastguard Worker     (void)ReadVBR64((unsigned)Op.getValue());
98*03ce13f7SAndroid Build Coastguard Worker     break;
99*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Array:
100*03ce13f7SAndroid Build Coastguard Worker     // This can't happen because the abbreviation must be valid.
101*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable("Bad array abbreviation encoding!");
102*03ce13f7SAndroid Build Coastguard Worker     break;
103*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Char6:
104*03ce13f7SAndroid Build Coastguard Worker     (void)Read(6);
105*03ce13f7SAndroid Build Coastguard Worker     break;
106*03ce13f7SAndroid Build Coastguard Worker   }
107*03ce13f7SAndroid Build Coastguard Worker }
108*03ce13f7SAndroid Build Coastguard Worker 
109*03ce13f7SAndroid Build Coastguard Worker /// skipRecord - Read the current record and discard it.
skipRecord(unsigned AbbrevID)110*03ce13f7SAndroid Build Coastguard Worker void NaClBitstreamCursor::skipRecord(unsigned AbbrevID) {
111*03ce13f7SAndroid Build Coastguard Worker   // Skip unabbreviated records by reading past their entries.
112*03ce13f7SAndroid Build Coastguard Worker   if (AbbrevID == naclbitc::UNABBREV_RECORD) {
113*03ce13f7SAndroid Build Coastguard Worker     unsigned Code = ReadVBR(6);
114*03ce13f7SAndroid Build Coastguard Worker     (void)Code;
115*03ce13f7SAndroid Build Coastguard Worker     unsigned NumElts = ReadVBR(6);
116*03ce13f7SAndroid Build Coastguard Worker     for (unsigned i = 0; i != NumElts; ++i)
117*03ce13f7SAndroid Build Coastguard Worker       (void)ReadVBR64(6);
118*03ce13f7SAndroid Build Coastguard Worker     SkipToByteBoundaryIfAligned();
119*03ce13f7SAndroid Build Coastguard Worker     return;
120*03ce13f7SAndroid Build Coastguard Worker   }
121*03ce13f7SAndroid Build Coastguard Worker 
122*03ce13f7SAndroid Build Coastguard Worker   const NaClBitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
123*03ce13f7SAndroid Build Coastguard Worker 
124*03ce13f7SAndroid Build Coastguard Worker   for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) {
125*03ce13f7SAndroid Build Coastguard Worker     const NaClBitCodeAbbrevOp &Op = Abbv->getOperandInfo(i);
126*03ce13f7SAndroid Build Coastguard Worker     switch (Op.getEncoding()) {
127*03ce13f7SAndroid Build Coastguard Worker     default:
128*03ce13f7SAndroid Build Coastguard Worker       skipAbbreviatedField(Op);
129*03ce13f7SAndroid Build Coastguard Worker       break;
130*03ce13f7SAndroid Build Coastguard Worker     case NaClBitCodeAbbrevOp::Literal:
131*03ce13f7SAndroid Build Coastguard Worker       break;
132*03ce13f7SAndroid Build Coastguard Worker     case NaClBitCodeAbbrevOp::Array: {
133*03ce13f7SAndroid Build Coastguard Worker       // Array case.  Read the number of elements as a vbr6.
134*03ce13f7SAndroid Build Coastguard Worker       unsigned NumElts = ReadVBR(6);
135*03ce13f7SAndroid Build Coastguard Worker 
136*03ce13f7SAndroid Build Coastguard Worker       // Get the element encoding.
137*03ce13f7SAndroid Build Coastguard Worker       const NaClBitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i);
138*03ce13f7SAndroid Build Coastguard Worker 
139*03ce13f7SAndroid Build Coastguard Worker       // Read all the elements.
140*03ce13f7SAndroid Build Coastguard Worker       for (; NumElts; --NumElts)
141*03ce13f7SAndroid Build Coastguard Worker         skipAbbreviatedField(EltEnc);
142*03ce13f7SAndroid Build Coastguard Worker       break;
143*03ce13f7SAndroid Build Coastguard Worker     }
144*03ce13f7SAndroid Build Coastguard Worker     }
145*03ce13f7SAndroid Build Coastguard Worker   }
146*03ce13f7SAndroid Build Coastguard Worker   SkipToByteBoundaryIfAligned();
147*03ce13f7SAndroid Build Coastguard Worker }
148*03ce13f7SAndroid Build Coastguard Worker 
readRecordAbbrevField(const NaClBitCodeAbbrevOp & Op,uint64_t & Value)149*03ce13f7SAndroid Build Coastguard Worker bool NaClBitstreamCursor::readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op,
150*03ce13f7SAndroid Build Coastguard Worker                                                 uint64_t &Value) {
151*03ce13f7SAndroid Build Coastguard Worker   switch (Op.getEncoding()) {
152*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Literal:
153*03ce13f7SAndroid Build Coastguard Worker     Value = Op.getValue();
154*03ce13f7SAndroid Build Coastguard Worker     break;
155*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Array:
156*03ce13f7SAndroid Build Coastguard Worker     // Returns number of elements in the array.
157*03ce13f7SAndroid Build Coastguard Worker     Value = ReadVBR(6);
158*03ce13f7SAndroid Build Coastguard Worker     return true;
159*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Fixed:
160*03ce13f7SAndroid Build Coastguard Worker     Value = Read((unsigned)Op.getValue());
161*03ce13f7SAndroid Build Coastguard Worker     break;
162*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::VBR:
163*03ce13f7SAndroid Build Coastguard Worker     Value = ReadVBR64((unsigned)Op.getValue());
164*03ce13f7SAndroid Build Coastguard Worker     break;
165*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Char6:
166*03ce13f7SAndroid Build Coastguard Worker     Value = NaClBitCodeAbbrevOp::DecodeChar6(Read(6));
167*03ce13f7SAndroid Build Coastguard Worker     break;
168*03ce13f7SAndroid Build Coastguard Worker   }
169*03ce13f7SAndroid Build Coastguard Worker   return false;
170*03ce13f7SAndroid Build Coastguard Worker }
171*03ce13f7SAndroid Build Coastguard Worker 
172*03ce13f7SAndroid Build Coastguard Worker uint64_t
readArrayAbbreviatedField(const NaClBitCodeAbbrevOp & Op)173*03ce13f7SAndroid Build Coastguard Worker NaClBitstreamCursor::readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op) {
174*03ce13f7SAndroid Build Coastguard Worker   // Decode the value as we are commanded.
175*03ce13f7SAndroid Build Coastguard Worker   switch (Op.getEncoding()) {
176*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Literal:
177*03ce13f7SAndroid Build Coastguard Worker     return Op.getValue();
178*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Fixed:
179*03ce13f7SAndroid Build Coastguard Worker     return Read((unsigned)Op.getValue());
180*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::VBR:
181*03ce13f7SAndroid Build Coastguard Worker     return ReadVBR64((unsigned)Op.getValue());
182*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Array:
183*03ce13f7SAndroid Build Coastguard Worker     // This can't happen because the abbreviation must be valid.
184*03ce13f7SAndroid Build Coastguard Worker     llvm_unreachable("Bad array abbreviation encoding!");
185*03ce13f7SAndroid Build Coastguard Worker     break;
186*03ce13f7SAndroid Build Coastguard Worker   case NaClBitCodeAbbrevOp::Char6:
187*03ce13f7SAndroid Build Coastguard Worker     return NaClBitCodeAbbrevOp::DecodeChar6(Read(6));
188*03ce13f7SAndroid Build Coastguard Worker   }
189*03ce13f7SAndroid Build Coastguard Worker   llvm_unreachable("Illegal abbreviation encoding for field!");
190*03ce13f7SAndroid Build Coastguard Worker }
191*03ce13f7SAndroid Build Coastguard Worker 
readArrayAbbrev(const NaClBitCodeAbbrevOp & Op,unsigned NumArrayElements,SmallVectorImpl<uint64_t> & Vals)192*03ce13f7SAndroid Build Coastguard Worker void NaClBitstreamCursor::readArrayAbbrev(const NaClBitCodeAbbrevOp &Op,
193*03ce13f7SAndroid Build Coastguard Worker                                           unsigned NumArrayElements,
194*03ce13f7SAndroid Build Coastguard Worker                                           SmallVectorImpl<uint64_t> &Vals) {
195*03ce13f7SAndroid Build Coastguard Worker   for (; NumArrayElements; --NumArrayElements) {
196*03ce13f7SAndroid Build Coastguard Worker     Vals.push_back(readArrayAbbreviatedField(Op));
197*03ce13f7SAndroid Build Coastguard Worker   }
198*03ce13f7SAndroid Build Coastguard Worker }
199*03ce13f7SAndroid Build Coastguard Worker 
readRecord(unsigned AbbrevID,SmallVectorImpl<uint64_t> & Vals)200*03ce13f7SAndroid Build Coastguard Worker unsigned NaClBitstreamCursor::readRecord(unsigned AbbrevID,
201*03ce13f7SAndroid Build Coastguard Worker                                          SmallVectorImpl<uint64_t> &Vals) {
202*03ce13f7SAndroid Build Coastguard Worker   if (AbbrevID == naclbitc::UNABBREV_RECORD) {
203*03ce13f7SAndroid Build Coastguard Worker     unsigned Code = ReadVBR(6);
204*03ce13f7SAndroid Build Coastguard Worker     unsigned NumElts = ReadVBR(6);
205*03ce13f7SAndroid Build Coastguard Worker     for (unsigned i = 0; i != NumElts; ++i)
206*03ce13f7SAndroid Build Coastguard Worker       Vals.push_back(ReadVBR64(6));
207*03ce13f7SAndroid Build Coastguard Worker     SkipToByteBoundaryIfAligned();
208*03ce13f7SAndroid Build Coastguard Worker     return Code;
209*03ce13f7SAndroid Build Coastguard Worker   }
210*03ce13f7SAndroid Build Coastguard Worker 
211*03ce13f7SAndroid Build Coastguard Worker   // Read code.
212*03ce13f7SAndroid Build Coastguard Worker   const NaClBitCodeAbbrev *Abbv = getAbbrev(AbbrevID);
213*03ce13f7SAndroid Build Coastguard Worker   uint64_t Value;
214*03ce13f7SAndroid Build Coastguard Worker   unsigned Code;
215*03ce13f7SAndroid Build Coastguard Worker   if (readRecordAbbrevField(Abbv->getOperandInfo(0), Value)) {
216*03ce13f7SAndroid Build Coastguard Worker     // Array found, use to read all elements.
217*03ce13f7SAndroid Build Coastguard Worker     if (Value == 0)
218*03ce13f7SAndroid Build Coastguard Worker       ErrHandler->Fatal("No code found for record!");
219*03ce13f7SAndroid Build Coastguard Worker     const NaClBitCodeAbbrevOp &Op = Abbv->getOperandInfo(1);
220*03ce13f7SAndroid Build Coastguard Worker     Code = readArrayAbbreviatedField(Op);
221*03ce13f7SAndroid Build Coastguard Worker     readArrayAbbrev(Op, Value - 1, Vals);
222*03ce13f7SAndroid Build Coastguard Worker     SkipToByteBoundaryIfAligned();
223*03ce13f7SAndroid Build Coastguard Worker     return Code;
224*03ce13f7SAndroid Build Coastguard Worker   }
225*03ce13f7SAndroid Build Coastguard Worker   Code = Value;
226*03ce13f7SAndroid Build Coastguard Worker 
227*03ce13f7SAndroid Build Coastguard Worker   // Read arguments.
228*03ce13f7SAndroid Build Coastguard Worker   unsigned NumOperands = Abbv->getNumOperandInfos();
229*03ce13f7SAndroid Build Coastguard Worker   for (unsigned i = 1; i != NumOperands; ++i) {
230*03ce13f7SAndroid Build Coastguard Worker     if (readRecordAbbrevField(Abbv->getOperandInfo(i), Value)) {
231*03ce13f7SAndroid Build Coastguard Worker       ++i;
232*03ce13f7SAndroid Build Coastguard Worker       readArrayAbbrev(Abbv->getOperandInfo(i), Value, Vals);
233*03ce13f7SAndroid Build Coastguard Worker       SkipToByteBoundaryIfAligned();
234*03ce13f7SAndroid Build Coastguard Worker       return Code;
235*03ce13f7SAndroid Build Coastguard Worker     }
236*03ce13f7SAndroid Build Coastguard Worker     Vals.push_back(Value);
237*03ce13f7SAndroid Build Coastguard Worker   }
238*03ce13f7SAndroid Build Coastguard Worker   SkipToByteBoundaryIfAligned();
239*03ce13f7SAndroid Build Coastguard Worker   return Code;
240*03ce13f7SAndroid Build Coastguard Worker }
241*03ce13f7SAndroid Build Coastguard Worker 
getEncoding(uint64_t Value)242*03ce13f7SAndroid Build Coastguard Worker NaClBitCodeAbbrevOp::Encoding NaClBitstreamCursor::getEncoding(uint64_t Value) {
243*03ce13f7SAndroid Build Coastguard Worker   if (!NaClBitCodeAbbrevOp::isValidEncoding(Value)) {
244*03ce13f7SAndroid Build Coastguard Worker     std::string Buffer;
245*03ce13f7SAndroid Build Coastguard Worker     raw_string_ostream StrBuf(Buffer);
246*03ce13f7SAndroid Build Coastguard Worker     StrBuf << "Invalid abbreviation encoding specified in bitcode file: "
247*03ce13f7SAndroid Build Coastguard Worker            << Value;
248*03ce13f7SAndroid Build Coastguard Worker     ErrHandler->Fatal(StrBuf.str());
249*03ce13f7SAndroid Build Coastguard Worker   }
250*03ce13f7SAndroid Build Coastguard Worker   return NaClBitCodeAbbrevOp::Encoding(Value);
251*03ce13f7SAndroid Build Coastguard Worker }
252*03ce13f7SAndroid Build Coastguard Worker 
ReadAbbrevRecord(bool IsLocal,NaClAbbrevListener * Listener)253*03ce13f7SAndroid Build Coastguard Worker void NaClBitstreamCursor::ReadAbbrevRecord(bool IsLocal,
254*03ce13f7SAndroid Build Coastguard Worker                                            NaClAbbrevListener *Listener) {
255*03ce13f7SAndroid Build Coastguard Worker   NaClBitCodeAbbrev *Abbv = BlockScope.back().appendLocalCreate();
256*03ce13f7SAndroid Build Coastguard Worker   unsigned NumOpInfo = ReadVBR(5);
257*03ce13f7SAndroid Build Coastguard Worker   if (Listener)
258*03ce13f7SAndroid Build Coastguard Worker     Listener->Values.push_back(NumOpInfo);
259*03ce13f7SAndroid Build Coastguard Worker   for (unsigned i = 0; i != NumOpInfo; ++i) {
260*03ce13f7SAndroid Build Coastguard Worker     bool IsLiteral = Read(1) ? true : false;
261*03ce13f7SAndroid Build Coastguard Worker     if (Listener)
262*03ce13f7SAndroid Build Coastguard Worker       Listener->Values.push_back(IsLiteral);
263*03ce13f7SAndroid Build Coastguard Worker     if (IsLiteral) {
264*03ce13f7SAndroid Build Coastguard Worker       uint64_t Value = ReadVBR64(8);
265*03ce13f7SAndroid Build Coastguard Worker       if (Listener)
266*03ce13f7SAndroid Build Coastguard Worker         Listener->Values.push_back(Value);
267*03ce13f7SAndroid Build Coastguard Worker       Abbv->Add(NaClBitCodeAbbrevOp(Value));
268*03ce13f7SAndroid Build Coastguard Worker       continue;
269*03ce13f7SAndroid Build Coastguard Worker     }
270*03ce13f7SAndroid Build Coastguard Worker     NaClBitCodeAbbrevOp::Encoding E = getEncoding(Read(3));
271*03ce13f7SAndroid Build Coastguard Worker     if (Listener)
272*03ce13f7SAndroid Build Coastguard Worker       Listener->Values.push_back(E);
273*03ce13f7SAndroid Build Coastguard Worker     if (NaClBitCodeAbbrevOp::hasValue(E)) {
274*03ce13f7SAndroid Build Coastguard Worker       unsigned Data = ReadVBR64(5);
275*03ce13f7SAndroid Build Coastguard Worker       if (Listener)
276*03ce13f7SAndroid Build Coastguard Worker         Listener->Values.push_back(Data);
277*03ce13f7SAndroid Build Coastguard Worker 
278*03ce13f7SAndroid Build Coastguard Worker       // As a special case, handle fixed(0) (i.e., a fixed field with zero bits)
279*03ce13f7SAndroid Build Coastguard Worker       // and vbr(0) as a literal zero.  This is decoded the same way, and avoids
280*03ce13f7SAndroid Build Coastguard Worker       // a slow path in Read() to have to handle reading zero bits.
281*03ce13f7SAndroid Build Coastguard Worker       if ((E == NaClBitCodeAbbrevOp::Fixed || E == NaClBitCodeAbbrevOp::VBR) &&
282*03ce13f7SAndroid Build Coastguard Worker           Data == 0) {
283*03ce13f7SAndroid Build Coastguard Worker         if (Listener)
284*03ce13f7SAndroid Build Coastguard Worker           Listener->Values.push_back(0);
285*03ce13f7SAndroid Build Coastguard Worker         Abbv->Add(NaClBitCodeAbbrevOp(0));
286*03ce13f7SAndroid Build Coastguard Worker         continue;
287*03ce13f7SAndroid Build Coastguard Worker       }
288*03ce13f7SAndroid Build Coastguard Worker       if (!NaClBitCodeAbbrevOp::isValid(E, Data)) {
289*03ce13f7SAndroid Build Coastguard Worker         std::string Buffer;
290*03ce13f7SAndroid Build Coastguard Worker         raw_string_ostream StrBuf(Buffer);
291*03ce13f7SAndroid Build Coastguard Worker         StrBuf << "Invalid abbreviation encoding ("
292*03ce13f7SAndroid Build Coastguard Worker                << NaClBitCodeAbbrevOp::getEncodingName(E) << ", " << Data
293*03ce13f7SAndroid Build Coastguard Worker                << ")";
294*03ce13f7SAndroid Build Coastguard Worker         ErrHandler->Fatal(StrBuf.str());
295*03ce13f7SAndroid Build Coastguard Worker       }
296*03ce13f7SAndroid Build Coastguard Worker       Abbv->Add(NaClBitCodeAbbrevOp(E, Data));
297*03ce13f7SAndroid Build Coastguard Worker     } else {
298*03ce13f7SAndroid Build Coastguard Worker       if (!NaClBitCodeAbbrevOp::isValid(E)) {
299*03ce13f7SAndroid Build Coastguard Worker         std::string Buffer;
300*03ce13f7SAndroid Build Coastguard Worker         raw_string_ostream StrBuf(Buffer);
301*03ce13f7SAndroid Build Coastguard Worker         StrBuf << "Invalid abbreviation encoding ("
302*03ce13f7SAndroid Build Coastguard Worker                << NaClBitCodeAbbrevOp::getEncodingName(E) << ")";
303*03ce13f7SAndroid Build Coastguard Worker         ErrHandler->Fatal(StrBuf.str());
304*03ce13f7SAndroid Build Coastguard Worker       }
305*03ce13f7SAndroid Build Coastguard Worker       Abbv->Add(NaClBitCodeAbbrevOp(E));
306*03ce13f7SAndroid Build Coastguard Worker     }
307*03ce13f7SAndroid Build Coastguard Worker   }
308*03ce13f7SAndroid Build Coastguard Worker   SkipToByteBoundaryIfAligned();
309*03ce13f7SAndroid Build Coastguard Worker   if (!Abbv->isValid())
310*03ce13f7SAndroid Build Coastguard Worker     ErrHandler->Fatal("Invalid abbreviation specified in bitcode file");
311*03ce13f7SAndroid Build Coastguard Worker   if (Listener) {
312*03ce13f7SAndroid Build Coastguard Worker     Listener->ProcessAbbreviation(Abbv, IsLocal);
313*03ce13f7SAndroid Build Coastguard Worker     // Reset record information of the listener.
314*03ce13f7SAndroid Build Coastguard Worker     Listener->Values.clear();
315*03ce13f7SAndroid Build Coastguard Worker     Listener->StartBit = GetCurrentBitNo();
316*03ce13f7SAndroid Build Coastguard Worker   }
317*03ce13f7SAndroid Build Coastguard Worker }
318*03ce13f7SAndroid Build Coastguard Worker 
SkipAbbrevRecord()319*03ce13f7SAndroid Build Coastguard Worker void NaClBitstreamCursor::SkipAbbrevRecord() {
320*03ce13f7SAndroid Build Coastguard Worker   unsigned NumOpInfo = ReadVBR(5);
321*03ce13f7SAndroid Build Coastguard Worker   for (unsigned i = 0; i != NumOpInfo; ++i) {
322*03ce13f7SAndroid Build Coastguard Worker     bool IsLiteral = Read(1) ? true : false;
323*03ce13f7SAndroid Build Coastguard Worker     if (IsLiteral) {
324*03ce13f7SAndroid Build Coastguard Worker       ReadVBR64(8);
325*03ce13f7SAndroid Build Coastguard Worker       continue;
326*03ce13f7SAndroid Build Coastguard Worker     }
327*03ce13f7SAndroid Build Coastguard Worker     NaClBitCodeAbbrevOp::Encoding E = getEncoding(Read(3));
328*03ce13f7SAndroid Build Coastguard Worker     if (NaClBitCodeAbbrevOp::hasValue(E)) {
329*03ce13f7SAndroid Build Coastguard Worker       ReadVBR64(5);
330*03ce13f7SAndroid Build Coastguard Worker     }
331*03ce13f7SAndroid Build Coastguard Worker   }
332*03ce13f7SAndroid Build Coastguard Worker   SkipToByteBoundaryIfAligned();
333*03ce13f7SAndroid Build Coastguard Worker }
334*03ce13f7SAndroid Build Coastguard Worker 
335*03ce13f7SAndroid Build Coastguard Worker namespace {
336*03ce13f7SAndroid Build Coastguard Worker 
337*03ce13f7SAndroid Build Coastguard Worker unsigned ValidBlockIDs[] = {
338*03ce13f7SAndroid Build Coastguard Worker     naclbitc::BLOCKINFO_BLOCK_ID, naclbitc::CONSTANTS_BLOCK_ID,
339*03ce13f7SAndroid Build Coastguard Worker     naclbitc::FUNCTION_BLOCK_ID,  naclbitc::GLOBALVAR_BLOCK_ID,
340*03ce13f7SAndroid Build Coastguard Worker     naclbitc::MODULE_BLOCK_ID,    naclbitc::TOP_LEVEL_BLOCKID,
341*03ce13f7SAndroid Build Coastguard Worker     naclbitc::TYPE_BLOCK_ID_NEW,  naclbitc::VALUE_SYMTAB_BLOCK_ID};
342*03ce13f7SAndroid Build Coastguard Worker 
343*03ce13f7SAndroid Build Coastguard Worker } // end of anonymous namespace
344*03ce13f7SAndroid Build Coastguard Worker 
BlockInfoRecordsMap()345*03ce13f7SAndroid Build Coastguard Worker NaClBitstreamReader::BlockInfoRecordsMap::BlockInfoRecordsMap()
346*03ce13f7SAndroid Build Coastguard Worker     : IsFrozen(false) {
347*03ce13f7SAndroid Build Coastguard Worker   for (size_t BlockID : ValidBlockIDs) {
348*03ce13f7SAndroid Build Coastguard Worker     std::unique_ptr<BlockInfo> Info(new BlockInfo(BlockID));
349*03ce13f7SAndroid Build Coastguard Worker     KnownInfos.emplace(BlockID, std::move(Info));
350*03ce13f7SAndroid Build Coastguard Worker   }
351*03ce13f7SAndroid Build Coastguard Worker }
352*03ce13f7SAndroid Build Coastguard Worker 
353*03ce13f7SAndroid Build Coastguard Worker NaClBitstreamReader::BlockInfo *
getOrCreateUnknownBlockInfo(unsigned BlockID)354*03ce13f7SAndroid Build Coastguard Worker NaClBitstreamReader::BlockInfoRecordsMap::getOrCreateUnknownBlockInfo(
355*03ce13f7SAndroid Build Coastguard Worker     unsigned BlockID) {
356*03ce13f7SAndroid Build Coastguard Worker   std::unique_lock<std::mutex> Lock(UnknownBlockInfoLock);
357*03ce13f7SAndroid Build Coastguard Worker   while (true) {
358*03ce13f7SAndroid Build Coastguard Worker     auto Pos = UnknownInfos.find(BlockID);
359*03ce13f7SAndroid Build Coastguard Worker     if (Pos != UnknownInfos.end())
360*03ce13f7SAndroid Build Coastguard Worker       return Pos->second.get();
361*03ce13f7SAndroid Build Coastguard Worker     // Install, then let next iteration find.
362*03ce13f7SAndroid Build Coastguard Worker     std::unique_ptr<BlockInfo> Info(new BlockInfo(BlockID));
363*03ce13f7SAndroid Build Coastguard Worker     UnknownInfos.emplace(BlockID, std::move(Info));
364*03ce13f7SAndroid Build Coastguard Worker   }
365*03ce13f7SAndroid Build Coastguard Worker }
366*03ce13f7SAndroid Build Coastguard Worker 
UpdateLock(BlockInfoRecordsMap & BlockInfoRecords)367*03ce13f7SAndroid Build Coastguard Worker NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock::UpdateLock(
368*03ce13f7SAndroid Build Coastguard Worker     BlockInfoRecordsMap &BlockInfoRecords)
369*03ce13f7SAndroid Build Coastguard Worker     : BlockInfoRecords(BlockInfoRecords),
370*03ce13f7SAndroid Build Coastguard Worker       Lock(BlockInfoRecords.UpdateRecordsLock) {}
371*03ce13f7SAndroid Build Coastguard Worker 
~UpdateLock()372*03ce13f7SAndroid Build Coastguard Worker NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock::~UpdateLock() {
373*03ce13f7SAndroid Build Coastguard Worker   if (BlockInfoRecords.freeze())
374*03ce13f7SAndroid Build Coastguard Worker     report_fatal_error("Global abbreviations block frozen while building.");
375*03ce13f7SAndroid Build Coastguard Worker }
376*03ce13f7SAndroid Build Coastguard Worker 
ReadBlockInfoBlock(NaClAbbrevListener * Listener)377*03ce13f7SAndroid Build Coastguard Worker bool NaClBitstreamCursor::ReadBlockInfoBlock(NaClAbbrevListener *Listener) {
378*03ce13f7SAndroid Build Coastguard Worker   // If this is the second read of the block info block, skip it.
379*03ce13f7SAndroid Build Coastguard Worker   if (BitStream->BlockInfoRecords->isFrozen())
380*03ce13f7SAndroid Build Coastguard Worker     return SkipBlock();
381*03ce13f7SAndroid Build Coastguard Worker 
382*03ce13f7SAndroid Build Coastguard Worker   NaClBitstreamReader::BlockInfoRecordsMap::UpdateLock Lock(
383*03ce13f7SAndroid Build Coastguard Worker       *BitStream->BlockInfoRecords);
384*03ce13f7SAndroid Build Coastguard Worker   unsigned NumWords;
385*03ce13f7SAndroid Build Coastguard Worker   if (EnterSubBlock(naclbitc::BLOCKINFO_BLOCK_ID, &NumWords))
386*03ce13f7SAndroid Build Coastguard Worker     return true;
387*03ce13f7SAndroid Build Coastguard Worker 
388*03ce13f7SAndroid Build Coastguard Worker   if (Listener)
389*03ce13f7SAndroid Build Coastguard Worker     Listener->BeginBlockInfoBlock(NumWords);
390*03ce13f7SAndroid Build Coastguard Worker 
391*03ce13f7SAndroid Build Coastguard Worker   NaClBitcodeRecordVector Record;
392*03ce13f7SAndroid Build Coastguard Worker   Block &CurBlock = BlockScope.back();
393*03ce13f7SAndroid Build Coastguard Worker   NaClBitstreamReader::AbbrevList *UpdateAbbrevs =
394*03ce13f7SAndroid Build Coastguard Worker       &CurBlock.GlobalAbbrevs->getAbbrevs();
395*03ce13f7SAndroid Build Coastguard Worker   bool FoundSetBID = false;
396*03ce13f7SAndroid Build Coastguard Worker 
397*03ce13f7SAndroid Build Coastguard Worker   // Read records of the BlockInfo block.
398*03ce13f7SAndroid Build Coastguard Worker   while (1) {
399*03ce13f7SAndroid Build Coastguard Worker     if (Listener)
400*03ce13f7SAndroid Build Coastguard Worker       Listener->StartBit = GetCurrentBitNo();
401*03ce13f7SAndroid Build Coastguard Worker     NaClBitstreamEntry Entry = advance(AF_DontAutoprocessAbbrevs, Listener);
402*03ce13f7SAndroid Build Coastguard Worker 
403*03ce13f7SAndroid Build Coastguard Worker     switch (Entry.Kind) {
404*03ce13f7SAndroid Build Coastguard Worker     case llvm::NaClBitstreamEntry::SubBlock: // PNaCl doesn't allow!
405*03ce13f7SAndroid Build Coastguard Worker     case llvm::NaClBitstreamEntry::Error:
406*03ce13f7SAndroid Build Coastguard Worker       return true;
407*03ce13f7SAndroid Build Coastguard Worker     case llvm::NaClBitstreamEntry::EndBlock:
408*03ce13f7SAndroid Build Coastguard Worker       if (Listener)
409*03ce13f7SAndroid Build Coastguard Worker         Listener->EndBlockInfoBlock();
410*03ce13f7SAndroid Build Coastguard Worker       return false;
411*03ce13f7SAndroid Build Coastguard Worker     case llvm::NaClBitstreamEntry::Record:
412*03ce13f7SAndroid Build Coastguard Worker       // The interesting case.
413*03ce13f7SAndroid Build Coastguard Worker       break;
414*03ce13f7SAndroid Build Coastguard Worker     }
415*03ce13f7SAndroid Build Coastguard Worker 
416*03ce13f7SAndroid Build Coastguard Worker     // Read abbrev records, associate them with CurBID.
417*03ce13f7SAndroid Build Coastguard Worker     if (Entry.ID == naclbitc::DEFINE_ABBREV) {
418*03ce13f7SAndroid Build Coastguard Worker       ReadAbbrevRecord(false, Listener);
419*03ce13f7SAndroid Build Coastguard Worker 
420*03ce13f7SAndroid Build Coastguard Worker       // ReadAbbrevRecord installs a local abbreviation.  Move it to the
421*03ce13f7SAndroid Build Coastguard Worker       // appropriate BlockInfo if the corresponding SetBID record has been
422*03ce13f7SAndroid Build Coastguard Worker       // found.
423*03ce13f7SAndroid Build Coastguard Worker       if (FoundSetBID)
424*03ce13f7SAndroid Build Coastguard Worker         CurBlock.moveLocalAbbrevToAbbrevList(UpdateAbbrevs);
425*03ce13f7SAndroid Build Coastguard Worker       continue;
426*03ce13f7SAndroid Build Coastguard Worker     }
427*03ce13f7SAndroid Build Coastguard Worker 
428*03ce13f7SAndroid Build Coastguard Worker     // Read a record.
429*03ce13f7SAndroid Build Coastguard Worker     Record.clear();
430*03ce13f7SAndroid Build Coastguard Worker     switch (readRecord(Entry.ID, Record)) {
431*03ce13f7SAndroid Build Coastguard Worker     default:
432*03ce13f7SAndroid Build Coastguard Worker       // No other records should be found!
433*03ce13f7SAndroid Build Coastguard Worker       return true;
434*03ce13f7SAndroid Build Coastguard Worker     case naclbitc::BLOCKINFO_CODE_SETBID:
435*03ce13f7SAndroid Build Coastguard Worker       if (Record.size() < 1)
436*03ce13f7SAndroid Build Coastguard Worker         return true;
437*03ce13f7SAndroid Build Coastguard Worker       FoundSetBID = true;
438*03ce13f7SAndroid Build Coastguard Worker       UpdateAbbrevs =
439*03ce13f7SAndroid Build Coastguard Worker           &BitStream->getBlockInfo((unsigned)Record[0])->getAbbrevs();
440*03ce13f7SAndroid Build Coastguard Worker       if (Listener) {
441*03ce13f7SAndroid Build Coastguard Worker         Listener->Values = Record;
442*03ce13f7SAndroid Build Coastguard Worker         Listener->SetBID();
443*03ce13f7SAndroid Build Coastguard Worker       }
444*03ce13f7SAndroid Build Coastguard Worker       break;
445*03ce13f7SAndroid Build Coastguard Worker     }
446*03ce13f7SAndroid Build Coastguard Worker   }
447*03ce13f7SAndroid Build Coastguard Worker }
448