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