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