//===- NaClBitstreamReader.h -----------------------------------*- C++ -*-===//
//     Low-level bitstream reader interface
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This header defines the BitstreamReader class.  This class can be used to
// read an arbitrary bitstream, regardless of its contents.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H
#define LLVM_BITCODE_NACL_NACLBITSTREAMREADER_H

#include "llvm/ADT/SmallVector.h"
#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
#include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/StreamingMemoryObject.h"
#include <atomic>
#include <climits>
#include <mutex>
#include <unordered_map>
#include <vector>

namespace llvm {

class Deserializer;
class NaClBitstreamCursor;

namespace naclbitc {

/// Returns the Bit as a Byte:BitInByte string.
std::string getBitAddress(uint64_t Bit);

/// Severity levels for reporting errors.
enum ErrorLevel {
  Warning,
  Error,
  Fatal
};

// Basic printing routine to generate the beginning of an error
// message. BitPosition is the bit position the error was found.
// Level is the severity of the error.
raw_ostream &ErrorAt(raw_ostream &Out, ErrorLevel Level,
                     uint64_t BitPosition);

} // End namespace naclbitc.

/// This class is used to read from a NaCl bitcode wire format stream,
/// maintaining information that is global to decoding the entire file.
/// While a file is being read, multiple cursors can be independently
/// advanced or skipped around within the file.  These are represented by
/// the NaClBitstreamCursor class.
class NaClBitstreamReader {
public:
  // Models a raw list of abbreviations.
  static const size_t DefaultAbbrevListSize = 12;
  using AbbrevListVector = SmallVector<NaClBitCodeAbbrev *,
                                       DefaultAbbrevListSize>;

  // Models and maintains a list of abbreviations. In particular, it maintains
  // updating reference counts of abbreviation operators within the abbreviation
  // list.
  class AbbrevList {
  public:
    AbbrevList() = default;
    explicit AbbrevList(const AbbrevList &NewAbbrevs) {
      appendList(NewAbbrevs);
    }
    AbbrevList &operator=(const AbbrevList &Rhs) {
      clear();
      appendList(Rhs);
      return *this;
    }
    // Creates a new (empty) abbreviation, appends it to this, and then returns
    // the new abbreviation.
    NaClBitCodeAbbrev *appendCreate() {
      NaClBitCodeAbbrev *Abbv = new NaClBitCodeAbbrev();
      Abbrevs.push_back(Abbv);
      return Abbv;
    }
    // Appends the given abbreviation to this.
    void append(NaClBitCodeAbbrev *Abbrv) {
      Abbrv->addRef();
      Abbrevs.push_back(Abbrv);
    }
    // Appends the contents of NewAbbrevs to this.
    void appendList(const AbbrevList &NewAbbrevs) {
      for (NaClBitCodeAbbrev *Abbrv : NewAbbrevs.Abbrevs)
        append(Abbrv);
    }
    // Returns last abbreviation on list.
    NaClBitCodeAbbrev *last() { return Abbrevs.back(); }
    // Removes the last element of the list.
    void popLast() {
      Abbrevs.back()->dropRef();
      Abbrevs.pop_back();
    }
    // Empties abbreviation list.
    void clear() {
      while(!Abbrevs.empty())
        popLast();
    }
    // Allow read access to vector defining list.
    const AbbrevListVector &getVector() const { return Abbrevs; }
    ~AbbrevList() { clear(); }
  private:
    AbbrevListVector Abbrevs;
  };

  /// This contains information about abbreviations in blocks defined in the
  /// BLOCKINFO_BLOCK block.  These describe global abbreviations that apply to
  /// all succeeding blocks of the specified ID.
  class BlockInfo {
    BlockInfo &operator=(const BlockInfo&) = delete;
  public:
    BlockInfo() = default;
    explicit BlockInfo(unsigned BlockID)
        : BlockID(BlockID), Abbrevs() {}
    BlockInfo(const BlockInfo&) = default;
    unsigned getBlockID() const { return BlockID; }
    void setBlockID(unsigned ID) { BlockID = ID; }
    AbbrevList &getAbbrevs() { return Abbrevs; }
    ~BlockInfo() {}
  private:
    unsigned BlockID;
    AbbrevList Abbrevs;
  };

  class BlockInfoRecordsMap;
  using SharedBlockInfoMap = std::shared_ptr<BlockInfoRecordsMap>;

  // Holds the global abbreviations in the BlockInfo block of the bitcode file.
  // Sharing is used to allow parallel parses. Share by using std::share_ptr's
  // and std::shared_from_this().
  //
  // Note: The BlockInfo block must be parsed before sharing of the
  // BlockInfoRecordsMap.  Therefore, before changing to a parallel parse, the
  // BlockInfoRecordsMap must be frozen.  Failure to do so, can lead to
  // unexpected behaviour.
  //
  // In practice, this means that only function blocks can be parsed in
  // parallel.
  class BlockInfoRecordsMap :
      public std::enable_shared_from_this<BlockInfoRecordsMap> {
    friend class NaClBitstreamReader;
    BlockInfoRecordsMap(const BlockInfoRecordsMap&) = delete;
    BlockInfoRecordsMap &operator=(const BlockInfoRecordsMap&) = delete;
  public:
    using InfosMap = std::unordered_map<unsigned, std::unique_ptr<BlockInfo>>;

    static SharedBlockInfoMap create() {
      return SharedBlockInfoMap(new BlockInfoRecordsMap());
    }
    ~BlockInfoRecordsMap() = default;

    bool isFrozen() const {
      return IsFrozen.load();
    }

    // Returns true if already frozen.
    bool freeze() {
      return IsFrozen.exchange(true);
    }

    BlockInfo *getBlockInfo(unsigned BlockID) {
      auto Pos = KnownInfos.find(BlockID);
      if (Pos != KnownInfos.end())
        return Pos->second.get();
      return getOrCreateUnknownBlockInfo(BlockID);
    }

    // Locks the BlockInfoRecordsMap for the lifetime of the UpdateLock.  Used
    // to allow the parsing of a BlockInfo block, and install global
    // abbreviations.
    //
    // Verifies that the BlockInfoRecordsMap didn't get frozen during the
    // instance's lifetime as a safety precaution. That is, it checks that no
    // bitstream reader was created to share the global abbreviations before the
    // global abbreviations are defined.
    class UpdateLock {
      UpdateLock() = delete;
      UpdateLock(const UpdateLock&) = delete;
      UpdateLock &operator=(const UpdateLock&) = delete;
    public:
      explicit UpdateLock(BlockInfoRecordsMap &BlockInfoRecords);
      ~UpdateLock();
    private:
      // The BlockInfoRecordsMap to update.
      BlockInfoRecordsMap &BlockInfoRecords;
      // The locked mutex from BlockInfoRecordsMap;
      std::unique_lock<std::mutex> Lock;
    };

  private:
    // The set of known BlockInfo's. This map is prepopulated so that fast
    // lookup can be performed thread safe (i.e. without using a lock).
    InfosMap KnownInfos;
    // The set of unknown BlockInfo's. This map is to handle unknown (and hence,
    // invalid) PNaCl bitcode files. This map is updated incrementally, and uses
    // UnknownBlockInfoLock to make it thread safe.
    InfosMap UnknownInfos;
    // True if the known BlockInfo blocks are frozen (i.e. the bitstream reader
    // will ignore the BlockInfo block).
    std::atomic_bool IsFrozen;
    // Lock to use to update this data structure.
    std::mutex UpdateRecordsLock;
    // Lock to get/create an unknonw block info.
    std::mutex UnknownBlockInfoLock;

    BlockInfoRecordsMap();

    BlockInfo *getOrCreateUnknownBlockInfo(unsigned BlockID);
  };

private:
  friend class NaClBitstreamCursor;

  std::unique_ptr<MemoryObject> BitcodeBytes;

  SharedBlockInfoMap BlockInfoRecords;

  /// \brief Holds the offset of the first byte after the header.
  size_t InitialAddress;

  // Holds the number of bytes to add to the bitcode position, when reporting
  // errors. Useful when using parallel parses of function blocks.
  size_t ErrorOffset = 0;

  // True if filler should be added to byte align records.
  bool AlignBitcodeRecords = false;
  NaClBitstreamReader(const NaClBitstreamReader&) = delete;
  void operator=(const NaClBitstreamReader&) = delete;


  void initFromHeader(NaClBitcodeHeader &Header) {
    InitialAddress = Header.getHeaderSize();
    AlignBitcodeRecords = Header.getAlignBitcodeRecords();
  }

public:
  /// Read stream from sequence of bytes [Start .. End) after parsing
  /// the given bitcode header.
  NaClBitstreamReader(const unsigned char *Start, const unsigned char *End,
                      NaClBitcodeHeader &Header)
      : BitcodeBytes(getNonStreamedMemoryObject(Start, End)),
        BlockInfoRecords(BlockInfoRecordsMap::create()) {
    initFromHeader(Header);
  }

  /// Read stream from Bytes, after parsing the given bitcode header.
  NaClBitstreamReader(MemoryObject *Bytes, NaClBitcodeHeader &Header)
      : BitcodeBytes(Bytes), BlockInfoRecords(BlockInfoRecordsMap::create())
  { initFromHeader(Header); }

  /// Read stream from bytes, starting at the given initial address.
  /// Provides simple API for unit testing.
  NaClBitstreamReader(MemoryObject *Bytes, size_t InitialAddress)
      : BitcodeBytes(Bytes), BlockInfoRecords(BlockInfoRecordsMap::create()),
        InitialAddress(InitialAddress) {}

  /// Read stream from sequence of bytes [Start .. End), using the global
  /// abbreviations of the given bitstream reader. Assumes that [Start .. End)
  /// is copied from Reader's memory object.
  NaClBitstreamReader(size_t StartAddress, const unsigned char *Start,
                      const unsigned char *End, NaClBitstreamReader *Reader)
      : BitcodeBytes(getNonStreamedMemoryObject(Start, End)),
        BlockInfoRecords(Reader->BlockInfoRecords), InitialAddress(0),
        ErrorOffset(StartAddress) { BlockInfoRecords->freeze(); }

  // Returns the memory object that is being read.
  MemoryObject &getBitcodeBytes() { return *BitcodeBytes; }

  ~NaClBitstreamReader() {}

  /// \brief Returns the initial address (after the header) of the input stream.
  size_t getInitialAddress() const {
    return InitialAddress;
  }

  /// Returns the byte address of the first byte in the bitstream. Used
  /// for error reporting.
  size_t getErrorOffset() const { return ErrorOffset; }

  //===--------------------------------------------------------------------===//
  // Block Manipulation
  //===--------------------------------------------------------------------===//

  BlockInfo *getBlockInfo(unsigned BlockID) {
    return BlockInfoRecords->getBlockInfo(BlockID);
  }
};

/// When advancing through a bitstream cursor, each advance can discover a few
/// different kinds of entries:
struct NaClBitstreamEntry {
  enum {
    Error,    // Malformed bitcode was found.
    EndBlock, // We've reached the end of the current block, (or the end of the
              // file, which is treated like a series of EndBlock records.
    SubBlock, // This is the start of a new subblock of a specific ID.
    Record    // This is a record with a specific AbbrevID.
  } Kind;

  unsigned ID;

  static NaClBitstreamEntry getError() {
    NaClBitstreamEntry E; E.Kind = Error; return E;
  }
  static NaClBitstreamEntry getEndBlock() {
    NaClBitstreamEntry E; E.Kind = EndBlock; return E;
  }
  static NaClBitstreamEntry getSubBlock(unsigned ID) {
    NaClBitstreamEntry E; E.Kind = SubBlock; E.ID = ID; return E;
  }
  static NaClBitstreamEntry getRecord(unsigned AbbrevID) {
    NaClBitstreamEntry E; E.Kind = Record; E.ID = AbbrevID; return E;
  }
};

/// Models default view of a bitcode record.
typedef SmallVector<uint64_t, 8> NaClBitcodeRecordVector;

/// Class NaClAbbrevListener is used to allow instances of class
/// NaClBitcodeParser to listen to record details when processing
/// abbreviations. The major reason for using a listener is that the
/// NaCl bitcode reader would require a major rewrite (including the
/// introduction of more overhead) if we were to lift abbreviations up
/// to the bitcode reader. That is, not only would we have to lift the
/// block processing up into the readers (i.e. many blocks in
/// NaClBitcodeReader and NaClBitcodeParser), but add many new API's
/// to allow the readers to update internals of the bit stream reader
/// appropriately.
class NaClAbbrevListener {
  NaClAbbrevListener(const NaClAbbrevListener&) = delete;
  void operator=(const NaClAbbrevListener&) = delete;
public:
  NaClAbbrevListener() {}
  virtual ~NaClAbbrevListener() {}

  /// Called to process the read abbreviation.
  virtual void ProcessAbbreviation(NaClBitCodeAbbrev *Abbrv,
                                   bool IsLocal) = 0;

  /// Called after entering block. NumWords is the number of words
  /// in the block.
  virtual void BeginBlockInfoBlock(unsigned NumWords) = 0;

  /// Called if a naclbitc::BLOCKINFO_CODE_SETBID record is found in
  /// NaClBitstreamCursor::ReadBlockInfoBlock.
  virtual void SetBID() = 0;

  /// Called just before an EndBlock record is processed by
  /// NaClBitstreamCursor::ReadBlockInfoBlock
  virtual void EndBlockInfoBlock() = 0;

  /// The values of the bitcode record associated with the called
  /// virtual function.
  NaClBitcodeRecordVector Values;

  /// Start bit for current record being processed in
  /// NaClBitstreamCursor::ReadBlockInfoBlock.
  uint64_t StartBit;
};

/// This represents a position within a bitcode file. There may be multiple
/// independent cursors reading within one bitstream, each maintaining their
/// own local state.
///
/// Unlike iterators, NaClBitstreamCursors are heavy-weight objects
/// that should not be passed by value.
class NaClBitstreamCursor {
public:
  /// This class handles errors in the bitstream reader. Redirects
  /// fatal error messages to virtual method Fatal.
  class ErrorHandler {
    ErrorHandler(const ErrorHandler &) = delete;
    ErrorHandler &operator=(const ErrorHandler &) = delete;
  public:
    explicit ErrorHandler(NaClBitstreamCursor &Cursor) : Cursor(Cursor) {}
    LLVM_ATTRIBUTE_NORETURN
    virtual void Fatal(const std::string &ErrorMessage) const;
    virtual ~ErrorHandler() {}
    uint64_t getCurrentBitNo() const {
      return Cursor.GetCurrentBitNo();
    }
  private:
    NaClBitstreamCursor &Cursor;
  };

private:
  friend class Deserializer;
  NaClBitstreamReader *BitStream;
  size_t NextChar;
  // The current error handler for the bitstream reader.
  std::unique_ptr<ErrorHandler> ErrHandler;

  // The size of the bitcode. 0 if we don't know it yet.
  size_t Size;

  /// This is the current data we have pulled from the stream but have not
  /// returned to the client. This is specifically and intentionally defined to
  /// follow the word size of the host machine for efficiency. We use word_t in
  /// places that are aware of this to make it perfectly explicit what is going
  /// on.
  typedef size_t word_t;
  word_t CurWord;

  /// This is the number of bits in CurWord that are valid. This
  /// is always from [0...bits_of(word_t)-1] inclusive.
  unsigned BitsInCurWord;

  // Data specific to a block being scanned.
  class Block {
  public:
    Block() = delete;
    Block &operator=(const Block &Rhs) {
      GlobalAbbrevs = Rhs.GlobalAbbrevs;
      NumGlobalAbbrevs = Rhs.NumGlobalAbbrevs;
      LocalAbbrevs = Rhs.LocalAbbrevs;
      CodeAbbrev = Rhs.CodeAbbrev;
      return *this;
    }
    Block(NaClBitstreamReader::BlockInfo *GlobalAbbrevs,
          NaClBitcodeSelectorAbbrev& CodeAbbrev)
        : GlobalAbbrevs(GlobalAbbrevs),
          NumGlobalAbbrevs(GlobalAbbrevs->getAbbrevs().getVector().size()),
          LocalAbbrevs(), CodeAbbrev(CodeAbbrev) {}
    Block(NaClBitstreamReader::BlockInfo *GlobalAbbrevs)
        : GlobalAbbrevs(GlobalAbbrevs),
          NumGlobalAbbrevs(GlobalAbbrevs->getAbbrevs().getVector().size()),
          LocalAbbrevs(), CodeAbbrev() {}
    ~Block() = default;
    const NaClBitstreamReader::AbbrevList &getGlobalAbbrevs() const {
      return GlobalAbbrevs->getAbbrevs();
    }
    unsigned getNumGlobalAbbrevs() const { return NumGlobalAbbrevs; }
    const NaClBitstreamReader::AbbrevList &getLocalAbbrevs() const {
      return LocalAbbrevs;
    }
    const NaClBitcodeSelectorAbbrev &getCodeAbbrev() const {
      return CodeAbbrev;
    }
    void setCodeAbbrev(NaClBitcodeSelectorAbbrev &Abbrev) {
      CodeAbbrev = Abbrev;
    }
    NaClBitCodeAbbrev *appendLocalCreate() {
      return LocalAbbrevs.appendCreate();
    }
    void moveLocalAbbrevToAbbrevList(NaClBitstreamReader::AbbrevList *List) {
      if (List != &LocalAbbrevs) {
        NaClBitCodeAbbrev *Abbv = LocalAbbrevs.last();
        List->append(Abbv);
        LocalAbbrevs.popLast();
      }
    }
  private:
    friend class NaClBitstreamCursor;
    // The global abbreviations associated with this scope.
    NaClBitstreamReader::BlockInfo *GlobalAbbrevs;
    // Number of abbreviations when block was entered. Used to limit scope of
    // CurBlockInfo, since any abbreviation added inside a BlockInfo block
    // (within this block) must not effect global abbreviations.
    unsigned NumGlobalAbbrevs;
    NaClBitstreamReader::AbbrevList LocalAbbrevs;
    // This is the declared size of code values used for the current block, in
    // bits.
    NaClBitcodeSelectorAbbrev CodeAbbrev;
  };

  /// This tracks the Block-specific information for each nested block.
  SmallVector<Block, 8> BlockScope;

  NaClBitstreamCursor(const NaClBitstreamCursor &) = delete;
  NaClBitstreamCursor &operator=(const NaClBitstreamCursor &) = delete;

public:
  NaClBitstreamCursor() : ErrHandler(new ErrorHandler(*this)) {
    init(nullptr);
  }

  explicit NaClBitstreamCursor(NaClBitstreamReader &R)
      : ErrHandler(new ErrorHandler(*this)) { init(&R); }

  void init(NaClBitstreamReader *R) {
    freeState();
    BitStream = R;
    NextChar = (BitStream == nullptr) ? 0 : BitStream->getInitialAddress();
    Size = 0;
    BitsInCurWord = 0;
    if (BitStream) {
      BlockScope.push_back(
          Block(BitStream->getBlockInfo(naclbitc::TOP_LEVEL_BLOCKID)));
    }
  }

  ~NaClBitstreamCursor() {
    freeState();
  }

  void freeState() {
    while (!BlockScope.empty())
      BlockScope.pop_back();
  }

  // Replaces the current bitstream error handler with the new
  // handler. Takes ownership of the new handler and deletes it when
  // it is no longer needed.
  void setErrorHandler(std::unique_ptr<ErrorHandler> &NewHandler) {
    ErrHandler = std::move(NewHandler);
  }

  bool canSkipToPos(size_t pos) const {
    // pos can be skipped to if it is a valid address or one byte past the end.
    return pos == 0 || BitStream->getBitcodeBytes().isValidAddress(
        static_cast<uint64_t>(pos - 1));
  }

  bool AtEndOfStream() {
    if (BitsInCurWord != 0)
      return false;
    if (Size != 0)
      return Size == NextChar;
    fillCurWord();
    return BitsInCurWord == 0;
  }

  /// Return the number of bits used to encode an abbrev #.
  unsigned getAbbrevIDWidth() const {
    return BlockScope.back().getCodeAbbrev().NumBits;
  }

  /// Return the bit # of the bit we are reading.
  uint64_t GetCurrentBitNo() const {
    return NextChar*CHAR_BIT - BitsInCurWord;
  }

  /// Converts the given position into the corresponding Error position.
  uint64_t getErrorBitNo(uint64_t Position) const {
    return BitStream->getErrorOffset() * CHAR_BIT + Position;
  }

  /// Returns the current bit address for reporting errors.
  uint64_t getErrorBitNo() const {
    return getErrorBitNo(GetCurrentBitNo());
  }

  NaClBitstreamReader *getBitStreamReader() {
    return BitStream;
  }
  const NaClBitstreamReader *getBitStreamReader() const {
    return BitStream;
  }

  /// Returns the current bit address (string) of the bit cursor.
  std::string getCurrentBitAddress() const {
    return naclbitc::getBitAddress(GetCurrentBitNo());
  }

  /// Flags that modify the behavior of advance().
  enum {
    /// If this flag is used, the advance() method does not automatically pop
    /// the block scope when the end of a block is reached.
    AF_DontPopBlockAtEnd = 1,

    /// If this flag is used, abbrev entries are returned just like normal
    /// records.
    AF_DontAutoprocessAbbrevs = 2
  };

  /// Advance the current bitstream, returning the next entry in the stream.
  /// Use the given abbreviation listener (if provided).
  NaClBitstreamEntry advance(unsigned Flags, NaClAbbrevListener *Listener) {
    while (1) {
      unsigned Code = ReadCode();
      if (Code == naclbitc::END_BLOCK) {
        // Pop the end of the block unless Flags tells us not to.
        if (!(Flags & AF_DontPopBlockAtEnd) && ReadBlockEnd())
          return NaClBitstreamEntry::getError();
        return NaClBitstreamEntry::getEndBlock();
      }

      if (Code == naclbitc::ENTER_SUBBLOCK)
        return NaClBitstreamEntry::getSubBlock(ReadSubBlockID());

      if (Code == naclbitc::DEFINE_ABBREV &&
          !(Flags & AF_DontAutoprocessAbbrevs)) {
        // We read and accumulate abbrev's, the client can't do anything with
        // them anyway.
        ReadAbbrevRecord(true, Listener);
        continue;
      }

      return NaClBitstreamEntry::getRecord(Code);
    }
  }

  /// This is a convenience function for clients that don't expect any
  /// subblocks. This just skips over them automatically.
  NaClBitstreamEntry advanceSkippingSubblocks(unsigned Flags = 0) {
    while (1) {
      // If we found a normal entry, return it.
      NaClBitstreamEntry Entry = advance(Flags, 0);
      if (Entry.Kind != NaClBitstreamEntry::SubBlock)
        return Entry;

      // If we found a sub-block, just skip over it and check the next entry.
      if (SkipBlock())
        return NaClBitstreamEntry::getError();
    }
  }

  /// Returns the starting byte of the word containing BitNo.
  uintptr_t getStartWordByteForBit(uint64_t BitNo) const {
    return uintptr_t(BitNo/CHAR_BIT) & ~(sizeof(word_t)-1);
  }

  /// Returns the index of BitNo within the word it appears in.
  unsigned getWordBitNo(uint64_t BitNo) const {
    return unsigned(BitNo & (sizeof(word_t)*CHAR_BIT-1));
  }

  /// Returns the ending byte of the word containing BitNo.
  uintptr_t getEndWordByteForBit(uint64_t BitNo) const {
    return getStartWordByteForBit(BitNo) +
        (getWordBitNo(BitNo)
         ? sizeof(word_t)
         : 0);
  }

  /// Fills Buffer[Size] using bytes at Address (in the memory object being
  /// read). Returns number of bytes filled (less than Size if at end of memory
  /// object).
  uint64_t fillBuffer(uint8_t *Buffer, size_t Size, size_t Address) const {
    return BitStream->getBitcodeBytes().readBytes(Buffer, Size, Address);
  }

  /// Reset the stream to the specified bit number.
  void JumpToBit(uint64_t BitNo) {
    const uintptr_t ByteNo = getStartWordByteForBit(BitNo);
    const unsigned WordBitNo = getWordBitNo(BitNo);
    if (!canSkipToPos(ByteNo))
      reportInvalidJumpToBit(BitNo);

    // Move the cursor to the right word.
    NextChar = ByteNo;
    BitsInCurWord = 0;

    // Skip over any bits that are already consumed.
    if (WordBitNo)
      Read(WordBitNo);
  }

  void fillCurWord() {
    assert(Size == 0 || NextChar < (unsigned)Size);

    // Read the next word from the stream.
    uint8_t Array[sizeof(word_t)] = {0};

    uint64_t BytesRead = fillBuffer(Array, sizeof(Array), NextChar);

    // If we run out of data, stop at the end of the stream.
    if (BytesRead == 0) {
      Size = NextChar;
      return;
    }

    CurWord =
        support::endian::read<word_t, support::little, support::unaligned>(
            Array);
    NextChar += BytesRead;
    BitsInCurWord = BytesRead * CHAR_BIT;
  }

  word_t Read(unsigned NumBits) {
    static const unsigned BitsInWord = sizeof(word_t) * CHAR_BIT;

    assert(NumBits && NumBits <= BitsInWord &&
           "Cannot return zero or more than BitsInWord bits!");

    static const unsigned Mask = sizeof(word_t) > 4 ? 0x3f : 0x1f;

    // If the field is fully contained by CurWord, return it quickly.
    if (BitsInCurWord >= NumBits) {
      word_t R = CurWord & (~word_t(0) >> (BitsInWord - NumBits));

      // Use a mask to avoid undefined behavior.
      CurWord >>= (NumBits & Mask);

      BitsInCurWord -= NumBits;
      return R;
    }

    word_t R = BitsInCurWord ? CurWord : 0;
    unsigned BitsLeft = NumBits - BitsInCurWord;

    fillCurWord();

    // If we run out of data, stop at the end of the stream.
    if (BitsLeft > BitsInCurWord)
      return 0;

    word_t R2 = CurWord & (~word_t(0) >> (BitsInWord - BitsLeft));

    // Use a mask to avoid undefined behavior.
    CurWord >>= (BitsLeft & Mask);

    BitsInCurWord -= BitsLeft;

    R |= R2 << (NumBits - BitsLeft);

    return R;
  }

  uint32_t ReadVBR(unsigned NumBits) {
    uint32_t Piece = Read(NumBits);
    if ((Piece & (1U << (NumBits-1))) == 0)
      return Piece;

    uint32_t Result = 0;
    unsigned NextBit = 0;
    while (1) {
      Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit;

      if ((Piece & (1U << (NumBits-1))) == 0)
        return Result;

      NextBit += NumBits-1;
      Piece = Read(NumBits);
    }
  }

  // Read a VBR that may have a value up to 64-bits in size. The chunk size of
  // the VBR must still be <= 32 bits though.
  uint64_t ReadVBR64(unsigned NumBits) {
    uint32_t Piece = Read(NumBits);
    if ((Piece & (1U << (NumBits-1))) == 0)
      return uint64_t(Piece);

    uint64_t Result = 0;
    unsigned NextBit = 0;
    while (1) {
      Result |= uint64_t(Piece & ((1U << (NumBits-1))-1)) << NextBit;

      if ((Piece & (1U << (NumBits-1))) == 0)
        return Result;

      NextBit += NumBits-1;
      Piece = Read(NumBits);
    }
  }

private:
  void SkipToByteBoundary() {
    unsigned BitsToSkip = BitsInCurWord % CHAR_BIT;
    if (BitsToSkip) {
      CurWord >>= BitsToSkip;
      BitsInCurWord -= BitsToSkip;
    }
  }

  void SkipToByteBoundaryIfAligned() {
    if (BitStream->AlignBitcodeRecords)
      SkipToByteBoundary();
  }

  void SkipToFourByteBoundary() {
    // If word_t is 64-bits and if we've read less than 32 bits, just dump
    // the bits we have up to the next 32-bit boundary.
    if (sizeof(word_t) > 4 &&
        BitsInCurWord >= 32) {
      CurWord >>= BitsInCurWord-32;
      BitsInCurWord = 32;
      return;
    }

    BitsInCurWord = 0;
  }
public:

  unsigned ReadCode() {
    const NaClBitcodeSelectorAbbrev &CodeAbbrev =
        BlockScope.back().getCodeAbbrev();
    return CodeAbbrev.IsFixed
        ? Read(CodeAbbrev.NumBits)
        : ReadVBR(CodeAbbrev.NumBits);
  }

  // Block header:
  //    [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen]

  /// Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
  unsigned ReadSubBlockID() {
    return ReadVBR(naclbitc::BlockIDWidth);
  }

  /// Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body
  /// of this block. If the block record is malformed, return true.
  bool SkipBlock() {
    // Read and ignore the codelen value.  Since we are skipping this block, we
    // don't care what code widths are used inside of it.
    ReadVBR(naclbitc::CodeLenWidth);
    SkipToFourByteBoundary();
    unsigned NumFourBytes = Read(naclbitc::BlockSizeWidth);

    // Check that the block wasn't partially defined, and that the offset isn't
    // bogus.
    size_t SkipTo = GetCurrentBitNo() + NumFourBytes*4*CHAR_BIT;
    if (AtEndOfStream() || !canSkipToPos(SkipTo/CHAR_BIT))
      return true;

    JumpToBit(SkipTo);
    return false;
  }

  /// Having read the ENTER_SUBBLOCK abbrevid, enter the block, and return true
  /// if the block has an error.
  bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = nullptr);

  bool ReadBlockEnd() {
    if (BlockScope.empty()) return true;

    // Block tail:
    //    [END_BLOCK, <align4bytes>]
    SkipToFourByteBoundary();

    BlockScope.pop_back();
    return false;
  }

private:

  //===--------------------------------------------------------------------===//
  // Record Processing
  //===--------------------------------------------------------------------===//

private:
  // Returns abbreviation encoding associated with Value.
  NaClBitCodeAbbrevOp::Encoding getEncoding(uint64_t Value);

  void skipAbbreviatedField(const NaClBitCodeAbbrevOp &Op);

  // Reads the next Value using the abbreviation Op. Returns true only
  // if Op is an array (and sets Value to the number of elements in the
  // array).
  inline bool readRecordAbbrevField(const NaClBitCodeAbbrevOp &Op,
                                    uint64_t &Value);

  // Reads and returns the next value using the abbreviation Op,
  // assuming Op appears after an array abbreviation.
  inline uint64_t readArrayAbbreviatedField(const NaClBitCodeAbbrevOp &Op);

  // Reads the array abbreviation Op, NumArrayElements times, putting
  // the read values in Vals.
  inline void readArrayAbbrev(const NaClBitCodeAbbrevOp &Op,
                              unsigned NumArrayElements,
                              SmallVectorImpl<uint64_t> &Vals);

  // Reports that that abbreviation Index is not valid.
  void reportInvalidAbbrevNumber(unsigned Index) const;

  // Reports that jumping to Bit is not valid.
  void reportInvalidJumpToBit(uint64_t Bit) const;

public:

  /// Return the abbreviation for the specified AbbrevId.
  const NaClBitCodeAbbrev *getAbbrev(unsigned AbbrevID) const {
    unsigned AbbrevNo = AbbrevID-naclbitc::FIRST_APPLICATION_ABBREV;
    const Block &CurBlock = BlockScope.back();
    const unsigned NumGlobalAbbrevs = CurBlock.getNumGlobalAbbrevs();
    if (AbbrevNo < NumGlobalAbbrevs)
      return CurBlock.getGlobalAbbrevs().getVector()[AbbrevNo];
    unsigned LocalAbbrevNo = AbbrevNo - NumGlobalAbbrevs;
    NaClBitstreamReader::AbbrevListVector
        LocalAbbrevs = CurBlock.getLocalAbbrevs().getVector();
    if (LocalAbbrevNo >= LocalAbbrevs.size())
      reportInvalidAbbrevNumber(AbbrevID);
    return LocalAbbrevs[LocalAbbrevNo];
  }

  /// Read the current record and discard it.
  void skipRecord(unsigned AbbrevID);
  
  unsigned readRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals);

  //===--------------------------------------------------------------------===//
  // Abbrev Processing
  //===--------------------------------------------------------------------===//
  // IsLocal indicates where the abbreviation occurs. If it is in the
  // BlockInfo block, IsLocal is false. In all other cases, IsLocal is
  // true.
  void ReadAbbrevRecord(bool IsLocal,
                        NaClAbbrevListener *Listener);

  // Skips over an abbreviation record. Duplicates code of ReadAbbrevRecord,
  // except that no abbreviation is built.
  void SkipAbbrevRecord();
  
  bool ReadBlockInfoBlock(NaClAbbrevListener *Listener);
};

} // End llvm namespace

#endif
