//===- subzero/src/PNaClTranslator.cpp - ICE from bitcode -----------------===//
//
//                        The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Implements the interface for translation from PNaCl bitcode files to
/// ICE to machine code.
///
//===----------------------------------------------------------------------===//

#include "PNaClTranslator.h"

#include "IceCfg.h"
#include "IceCfgNode.h"
#include "IceClFlags.h"
#include "IceDefs.h"
#include "IceGlobalInits.h"
#include "IceInst.h"
#include "IceOperand.h"

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#endif // __clang__

#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h"
#include "llvm/Bitcode/NaCl/NaClBitcodeDefs.h"
#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"

#ifdef __clang__
#pragma clang diagnostic pop
#endif // __clang__

#include <unordered_set>

// Define a hash function for SmallString's, so that it can be used in hash
// tables.
namespace std {
template <unsigned InternalLen> struct hash<llvm::SmallString<InternalLen>> {
  size_t operator()(const llvm::SmallString<InternalLen> &Key) const {
    return llvm::hash_combine_range(Key.begin(), Key.end());
  }
};
} // end of namespace std

namespace {
using namespace llvm;

// Models elements in the list of types defined in the types block. These
// elements can be undefined, a (simple) type, or a function type signature.
// Note that an extended type is undefined on construction. Use methods
// setAsSimpleType and setAsFuncSigType to define the extended type.
class ExtendedType {
  ExtendedType &operator=(const ExtendedType &Ty) = delete;

public:
  /// Discriminator for LLVM-style RTTI.
  enum TypeKind { Undefined, Simple, FuncSig };

  ExtendedType() = default;
  ExtendedType(const ExtendedType &Ty) = default;

  virtual ~ExtendedType() = default;

  ExtendedType::TypeKind getKind() const { return Kind; }
  void dump(Ice::Ostream &Stream) const;

  /// Changes the extended type to a simple type with the given / value.
  void setAsSimpleType(Ice::Type Ty) {
    assert(Kind == Undefined);
    Kind = Simple;
    Signature.setReturnType(Ty);
  }

  /// Changes the extended type to an (empty) function signature type.
  void setAsFunctionType() {
    assert(Kind == Undefined);
    Kind = FuncSig;
  }

protected:
  // Note: For simple types, the return type of the signature will be used to
  // hold the simple type.
  Ice::FuncSigType Signature;

private:
  ExtendedType::TypeKind Kind = Undefined;
};

Ice::Ostream &operator<<(Ice::Ostream &Stream, const ExtendedType &Ty) {
  if (!Ice::BuildDefs::dump())
    return Stream;
  Ty.dump(Stream);
  return Stream;
}

Ice::Ostream &operator<<(Ice::Ostream &Stream, ExtendedType::TypeKind Kind) {
  if (!Ice::BuildDefs::dump())
    return Stream;
  Stream << "ExtendedType::";
  switch (Kind) {
  case ExtendedType::Undefined:
    Stream << "Undefined";
    break;
  case ExtendedType::Simple:
    Stream << "Simple";
    break;
  case ExtendedType::FuncSig:
    Stream << "FuncSig";
    break;
  }
  return Stream;
}

// Models an ICE type as an extended type.
class SimpleExtendedType : public ExtendedType {
  SimpleExtendedType() = delete;
  SimpleExtendedType(const SimpleExtendedType &) = delete;
  SimpleExtendedType &operator=(const SimpleExtendedType &) = delete;

public:
  Ice::Type getType() const { return Signature.getReturnType(); }

  static bool classof(const ExtendedType *Ty) {
    return Ty->getKind() == Simple;
  }
};

// Models a function signature as an extended type.
class FuncSigExtendedType : public ExtendedType {
  FuncSigExtendedType() = delete;
  FuncSigExtendedType(const FuncSigExtendedType &) = delete;
  FuncSigExtendedType &operator=(const FuncSigExtendedType &) = delete;

public:
  const Ice::FuncSigType &getSignature() const { return Signature; }
  void setReturnType(Ice::Type ReturnType) {
    Signature.setReturnType(ReturnType);
  }
  void appendArgType(Ice::Type ArgType) { Signature.appendArgType(ArgType); }
  static bool classof(const ExtendedType *Ty) {
    return Ty->getKind() == FuncSig;
  }
};

void ExtendedType::dump(Ice::Ostream &Stream) const {
  if (!Ice::BuildDefs::dump())
    return;
  Stream << Kind;
  switch (Kind) {
  case Simple: {
    Stream << " " << Signature.getReturnType();
    break;
  }
  case FuncSig: {
    Stream << " " << Signature;
  }
  default:
    break;
  }
}

// Models integer literals as a sequence of bits. Used to read integer values
// from bitcode files. Based on llvm::APInt.
class BitcodeInt {
  BitcodeInt() = delete;
  BitcodeInt(const BitcodeInt &) = delete;
  BitcodeInt &operator=(const BitcodeInt &) = delete;

public:
  BitcodeInt(Ice::SizeT Bits, uint64_t Val) : BitWidth(Bits), Val(Val) {
    assert(Bits && "bitwidth too small");
    assert(Bits <= BITS_PER_WORD && "bitwidth too big");
    clearUnusedBits();
  }

  int64_t getSExtValue() const {
    return static_cast<int64_t>(Val << (BITS_PER_WORD - BitWidth)) >>
           (BITS_PER_WORD - BitWidth);
  }

  template <typename IntType, typename FpType>
  inline FpType convertToFp() const {
    static_assert(sizeof(IntType) == sizeof(FpType),
                  "IntType and FpType should be the same width");
    assert(BitWidth == sizeof(IntType) * CHAR_BIT);
    auto V = static_cast<IntType>(Val);
    return Ice::Utils::bitCopy<FpType>(V);
  }

private:
  /// Bits in the (internal) value.
  static const Ice::SizeT BITS_PER_WORD = sizeof(uint64_t) * CHAR_BIT;

  uint32_t BitWidth; /// The number of bits in the floating point number.
  uint64_t Val;      /// The (64-bit) equivalent integer value.

  /// Clear unused high order bits.
  void clearUnusedBits() {
    // If all bits are used, we want to leave the value alone.
    if (BitWidth == BITS_PER_WORD)
      return;

    // Mask out the high bits.
    Val &= ~static_cast<uint64_t>(0) >> (BITS_PER_WORD - BitWidth);
  }
};

class BlockParserBaseClass;

// Top-level class to read PNaCl bitcode files, and translate to ICE.
class TopLevelParser : public NaClBitcodeParser {
  TopLevelParser() = delete;
  TopLevelParser(const TopLevelParser &) = delete;
  TopLevelParser &operator=(const TopLevelParser &) = delete;

public:
  TopLevelParser(Ice::Translator &Translator, NaClBitstreamCursor &Cursor,
                 Ice::ErrorCode &ErrorStatus)
      : NaClBitcodeParser(Cursor), Translator(Translator),
        ErrorStatus(ErrorStatus),
        VariableDeclarations(new Ice::VariableDeclarationList()) {}

  ~TopLevelParser() override = default;

  Ice::Translator &getTranslator() const { return Translator; }

  void setBlockParser(BlockParserBaseClass *NewBlockParser) {
    BlockParser = NewBlockParser;
  }

  /// Generates error with given Message, occurring at BitPosition within the
  /// bitcode file. Always returns true.
  bool ErrorAt(naclbitc::ErrorLevel Level, uint64_t BitPosition,
               const std::string &Message) final;

  /// Generates error message with respect to the current block parser.
  bool blockError(const std::string &Message);

  /// Returns the number of errors found while parsing the bitcode file.
  unsigned getNumErrors() const { return NumErrors; }

  /// Changes the size of the type list to the given size.
  void resizeTypeIDValues(size_t NewSize) { TypeIDValues.resize(NewSize); }

  size_t getNumTypeIDValues() const { return TypeIDValues.size(); }

  /// Returns the undefined type associated with type ID. Note: Returns extended
  /// type ready to be defined.
  ExtendedType *getTypeByIDForDefining(NaClBcIndexSize_t ID) {
    // Get corresponding element, verifying the value is still undefined (and
    // hence allowed to be defined).
    ExtendedType *Ty = getTypeByIDAsKind(ID, ExtendedType::Undefined);
    if (Ty)
      return Ty;
    if (ID >= TypeIDValues.size()) {
      if (ID >= NaClBcIndexSize_t_Max) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Can't define more than " << NaClBcIndexSize_t_Max
               << " types\n";
        blockError(StrBuf.str());
        // Recover by using existing type slot.
        return &TypeIDValues[0];
      }
      TypeIDValues.resize(ID + 1);
    }
    return &TypeIDValues[ID];
  }

  /// Returns the type associated with the given index.
  Ice::Type getSimpleTypeByID(NaClBcIndexSize_t ID) {
    const ExtendedType *Ty = getTypeByIDAsKind(ID, ExtendedType::Simple);
    if (Ty == nullptr)
      // Return error recovery value.
      return Ice::IceType_void;
    return cast<SimpleExtendedType>(Ty)->getType();
  }

  /// Returns the type signature associated with the given index.
  const Ice::FuncSigType &getFuncSigTypeByID(NaClBcIndexSize_t ID) {
    const ExtendedType *Ty = getTypeByIDAsKind(ID, ExtendedType::FuncSig);
    if (Ty == nullptr)
      // Return error recovery value.
      return UndefinedFuncSigType;
    return cast<FuncSigExtendedType>(Ty)->getSignature();
  }

  /// Sets the next function ID to the given LLVM function.
  void setNextFunctionID(Ice::FunctionDeclaration *Fcn) {
    FunctionDeclarations.push_back(Fcn);
  }

  /// Returns the value id that should be associated with the the current
  /// function block. Increments internal counters during call so that it will
  /// be in correct position for next function block.
  NaClBcIndexSize_t getNextFunctionBlockValueID() {
    size_t NumDeclaredFunctions = FunctionDeclarations.size();
    while (NextDefiningFunctionID < NumDeclaredFunctions &&
           FunctionDeclarations[NextDefiningFunctionID]->isProto())
      ++NextDefiningFunctionID;
    if (NextDefiningFunctionID >= NumDeclaredFunctions)
      Fatal("More function blocks than defined function addresses");
    return NextDefiningFunctionID++;
  }

  /// Returns the function associated with ID.
  Ice::FunctionDeclaration *getFunctionByID(NaClBcIndexSize_t ID) {
    if (ID < FunctionDeclarations.size())
      return FunctionDeclarations[ID];
    return reportGetFunctionByIDError(ID);
  }

  /// Returns the constant associated with the given global value ID.
  Ice::Constant *getGlobalConstantByID(NaClBcIndexSize_t ID) {
    assert(ID < ValueIDConstants.size());
    return ValueIDConstants[ID];
  }

  /// Install names for all global values without names. Called after the global
  /// value symbol table is processed, but before any function blocks are
  /// processed.
  void installGlobalNames() {
    assert(VariableDeclarations);
    installGlobalVarNames();
    installFunctionNames();
  }

  void verifyFunctionTypeSignatures();

  void createValueIDs() {
    assert(VariableDeclarations);
    ValueIDConstants.reserve(VariableDeclarations->size() +
                             FunctionDeclarations.size());
    createValueIDsForFunctions();
    createValueIDsForGlobalVars();
  }

  /// Returns the number of function declarations in the bitcode file.
  size_t getNumFunctionIDs() const { return FunctionDeclarations.size(); }

  /// Returns the number of global declarations (i.e. IDs) defined in the
  /// bitcode file.
  size_t getNumGlobalIDs() const {
    if (VariableDeclarations) {
      return FunctionDeclarations.size() + VariableDeclarations->size();
    } else {
      return ValueIDConstants.size();
    }
  }

  /// Adds the given global declaration to the end of the list of global
  /// declarations.
  void addGlobalDeclaration(Ice::VariableDeclaration *Decl) {
    assert(VariableDeclarations);
    VariableDeclarations->push_back(Decl);
  }

  /// Returns the global variable declaration with the given index.
  Ice::VariableDeclaration *getGlobalVariableByID(NaClBcIndexSize_t Index) {
    assert(VariableDeclarations);
    if (Index < VariableDeclarations->size())
      return VariableDeclarations->at(Index);
    return reportGetGlobalVariableByIDError(Index);
  }

  /// Returns the global declaration (variable or function) with the given
  /// Index.
  Ice::GlobalDeclaration *getGlobalDeclarationByID(NaClBcIndexSize_t Index) {
    size_t NumFunctionIds = FunctionDeclarations.size();
    if (Index < NumFunctionIds)
      return getFunctionByID(Index);
    else
      return getGlobalVariableByID(Index - NumFunctionIds);
  }

  /// Returns true if a module block has been parsed.
  bool parsedModuleBlock() const { return ParsedModuleBlock; }

  /// Returns the list of parsed global variable declarations. Releases
  /// ownership of the current list of global variables. Note: only returns
  /// non-null pointer on first call. All successive calls return a null
  /// pointer.
  std::unique_ptr<Ice::VariableDeclarationList> getGlobalVariables() {
    // Before returning, check that ValidIDConstants has already been built.
    assert(!VariableDeclarations ||
           VariableDeclarations->size() <= ValueIDConstants.size());
    return std::move(VariableDeclarations);
  }

  // Upper limit of alignment power allowed by LLVM
  static constexpr uint32_t AlignPowerLimit = 29;

  // Extracts the corresponding Alignment to use, given the AlignPower (i.e.
  // 2**(AlignPower-1), or 0 if AlignPower == 0). Parser defines the block
  // context the alignment check appears in, and Prefix defines the context the
  // alignment appears in.
  uint32_t extractAlignment(NaClBitcodeParser *Parser, const char *Prefix,
                            uint32_t AlignPower) {
    if (AlignPower <= AlignPowerLimit + 1)
      return (1 << AlignPower) >> 1;
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << Prefix << " alignment greater than 2**" << AlignPowerLimit
           << ". Found: 2**" << (AlignPower - 1);
    Parser->Error(StrBuf.str());
    // Error recover with value that is always acceptable.
    return 1;
  }

private:
  // The translator associated with the parser.
  Ice::Translator &Translator;
  // The exit status that should be set to true if an error occurs.
  Ice::ErrorCode &ErrorStatus;
  // The number of errors reported.
  unsigned NumErrors = 0;
  // The types associated with each type ID.
  std::vector<ExtendedType> TypeIDValues;
  // The set of functions (prototype and defined).
  Ice::FunctionDeclarationList FunctionDeclarations;
  // The ID of the next possible defined function ID in FunctionDeclarations.
  // FunctionDeclarations is filled first. It's the set of functions (either
  // defined or isproto). Then function definitions are encountered/parsed and
  // NextDefiningFunctionID is incremented to track the next actually-defined
  // function.
  size_t NextDefiningFunctionID = 0;
  // The set of global variables.
  std::unique_ptr<Ice::VariableDeclarationList> VariableDeclarations;
  // Relocatable constants associated with global declarations.
  Ice::ConstantList ValueIDConstants;
  // Error recovery value to use when getFuncSigTypeByID fails.
  Ice::FuncSigType UndefinedFuncSigType;
  // The block parser currently being applied. Used for error reporting.
  BlockParserBaseClass *BlockParser = nullptr;
  // Defines if a module block has already been parsed.
  bool ParsedModuleBlock = false;

  bool ParseBlock(unsigned BlockID) override;

  // Gets extended type associated with the given index, assuming the extended
  // type is of the WantedKind. Generates error message if corresponding
  // extended type of WantedKind can't be found, and returns nullptr.
  ExtendedType *getTypeByIDAsKind(NaClBcIndexSize_t ID,
                                  ExtendedType::TypeKind WantedKind) {
    ExtendedType *Ty = nullptr;
    if (ID < TypeIDValues.size()) {
      Ty = &TypeIDValues[ID];
      if (Ty->getKind() == WantedKind)
        return Ty;
    }
    // Generate an error message and set ErrorStatus.
    this->reportBadTypeIDAs(ID, Ty, WantedKind);
    return nullptr;
  }

  // Gives Decl a name if it doesn't already have one. Prefix and NameIndex are
  // used to generate the name. NameIndex is automatically incremented if a new
  // name is created. DeclType is literal text describing the type of name
  // being created. Also generates warning if created names may conflict with
  // named declarations.
  void installDeclarationName(Ice::GlobalDeclaration *Decl,
                              const Ice::IceString &Prefix,
                              const char *DeclType,
                              NaClBcIndexSize_t &NameIndex) {
    if (Decl->hasName()) {
      Translator.checkIfUnnamedNameSafe(Decl->getName(), DeclType, Prefix);
    } else {
      Decl->setName(Translator.createUnnamedName(Prefix, NameIndex));
      ++NameIndex;
    }
  }

  // Installs names for global variables without names.
  void installGlobalVarNames() {
    assert(VariableDeclarations);
    const Ice::IceString &GlobalPrefix =
        getTranslator().getFlags().getDefaultGlobalPrefix();
    if (!GlobalPrefix.empty()) {
      NaClBcIndexSize_t NameIndex = 0;
      for (Ice::VariableDeclaration *Var : *VariableDeclarations) {
        installDeclarationName(Var, GlobalPrefix, "global", NameIndex);
      }
    }
  }

  // Installs names for functions without names.
  void installFunctionNames() {
    const Ice::IceString &FunctionPrefix =
        getTranslator().getFlags().getDefaultFunctionPrefix();
    if (!FunctionPrefix.empty()) {
      NaClBcIndexSize_t NameIndex = 0;
      for (Ice::FunctionDeclaration *Func : FunctionDeclarations) {
        installDeclarationName(Func, FunctionPrefix, "function", NameIndex);
      }
    }
  }

  // Builds a constant symbol named Name.  IsExternal is true iff the symbol is
  // external.
  Ice::Constant *getConstantSym(const Ice::IceString &Name,
                                bool IsExternal) const {
    if (IsExternal) {
      return getTranslator().getContext()->getConstantExternSym(Name);
    } else {
      const Ice::RelocOffsetT Offset = 0;
      return getTranslator().getContext()->getConstantSym(Offset, Name);
    }
  }

  void reportLinkageError(const char *Kind,
                          const Ice::GlobalDeclaration &Decl) {
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << Kind << " " << Decl.getName()
           << " has incorrect linkage: " << Decl.getLinkageName();
    if (Decl.isExternal())
      StrBuf << "\n  Use flag -allow-externally-defined-symbols to override";
    Error(StrBuf.str());
  }

  // Converts function declarations into constant value IDs.
  void createValueIDsForFunctions() {
    Ice::GlobalContext *Ctx = getTranslator().getContext();
    for (const Ice::FunctionDeclaration *Func : FunctionDeclarations) {
      if (!Func->verifyLinkageCorrect(Ctx))
        reportLinkageError("Function", *Func);
      Ice::Constant *C = getConstantSym(Func->getName(), Func->isProto());
      ValueIDConstants.push_back(C);
    }
  }

  // Converts global variable declarations into constant value IDs.
  void createValueIDsForGlobalVars() {
    Ice::GlobalContext *Ctx = getTranslator().getContext();
    for (const Ice::VariableDeclaration *Decl : *VariableDeclarations) {
      if (!Decl->verifyLinkageCorrect(Ctx))
        reportLinkageError("Global", *Decl);
      Ice::Constant *C =
          getConstantSym(Decl->getName(), !Decl->hasInitializer());
      ValueIDConstants.push_back(C);
    }
  }

  // Reports that type ID is undefined, or not of the WantedType.
  void reportBadTypeIDAs(NaClBcIndexSize_t ID, const ExtendedType *Ty,
                         ExtendedType::TypeKind WantedType);

  // Reports that there is no function declaration for ID. Returns an error
  // recovery value to use.
  Ice::FunctionDeclaration *reportGetFunctionByIDError(NaClBcIndexSize_t ID);

  // Reports that there is not global variable declaration for ID. Returns an
  // error recovery value to use.
  Ice::VariableDeclaration *
  reportGetGlobalVariableByIDError(NaClBcIndexSize_t Index);

  // Reports that there is no corresponding ICE type for LLVMTy, and returns
  // Ice::IceType_void.
  Ice::Type convertToIceTypeError(Type *LLVMTy);
};

bool TopLevelParser::ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit,
                             const std::string &Message) {
  ErrorStatus.assign(Ice::EC_Bitcode);
  ++NumErrors;
  Ice::GlobalContext *Context = Translator.getContext();
  { // Lock while printing out error message.
    Ice::OstreamLocker L(Context);
    raw_ostream &OldErrStream = setErrStream(Context->getStrError());
    NaClBitcodeParser::ErrorAt(Level, Bit, Message);
    setErrStream(OldErrStream);
  }
  if (Level >= naclbitc::Error &&
      !Translator.getFlags().getAllowErrorRecovery())
    Fatal();
  return true;
}

void TopLevelParser::reportBadTypeIDAs(NaClBcIndexSize_t ID,
                                       const ExtendedType *Ty,
                                       ExtendedType::TypeKind WantedType) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  if (Ty == nullptr) {
    StrBuf << "Can't find extended type for type id: " << ID;
  } else {
    StrBuf << "Type id " << ID << " not " << WantedType << ". Found: " << *Ty;
  }
  blockError(StrBuf.str());
}

Ice::FunctionDeclaration *
TopLevelParser::reportGetFunctionByIDError(NaClBcIndexSize_t ID) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << "Function index " << ID
         << " not allowed. Out of range. Must be less than "
         << FunctionDeclarations.size();
  blockError(StrBuf.str());
  if (!FunctionDeclarations.empty())
    return FunctionDeclarations[0];
  Fatal();
}

Ice::VariableDeclaration *
TopLevelParser::reportGetGlobalVariableByIDError(NaClBcIndexSize_t Index) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << "Global index " << Index
         << " not allowed. Out of range. Must be less than "
         << VariableDeclarations->size();
  blockError(StrBuf.str());
  if (!VariableDeclarations->empty())
    return VariableDeclarations->at(0);
  Fatal();
}

Ice::Type TopLevelParser::convertToIceTypeError(Type *LLVMTy) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << "Invalid LLVM type: " << *LLVMTy;
  Error(StrBuf.str());
  return Ice::IceType_void;
}

void TopLevelParser::verifyFunctionTypeSignatures() {
  const Ice::GlobalContext *Ctx = getTranslator().getContext();
  for (Ice::FunctionDeclaration *FuncDecl : FunctionDeclarations) {
    if (!FuncDecl->validateTypeSignature(Ctx))
      Error(FuncDecl->getTypeSignatureError(Ctx));
  }
}

// Base class for parsing blocks within the bitcode file. Note: Because this is
// the base class of block parsers, we generate error messages if ParseBlock or
// ParseRecord is not overridden in derived classes.
class BlockParserBaseClass : public NaClBitcodeParser {
  BlockParserBaseClass() = delete;
  BlockParserBaseClass(const BlockParserBaseClass &) = delete;
  BlockParserBaseClass &operator=(const BlockParserBaseClass &) = delete;

public:
  // Constructor for the top-level module block parser.
  BlockParserBaseClass(unsigned BlockID, TopLevelParser *Context)
      : NaClBitcodeParser(BlockID, Context), Context(Context) {
    Context->setBlockParser(this);
  }

  ~BlockParserBaseClass() override { Context->setBlockParser(nullptr); }

  // Returns the printable name of the type of block being parsed.
  virtual const char *getBlockName() const {
    // If this class is used, it is parsing an unknown block.
    return "unknown";
  }

  // Generates an error Message with the Bit address prefixed to it.
  bool ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit,
               const std::string &Message) final;

protected:
  // The context parser that contains the decoded state.
  TopLevelParser *Context;

  // Constructor for nested block parsers.
  BlockParserBaseClass(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
      : NaClBitcodeParser(BlockID, EnclosingParser),
        Context(EnclosingParser->Context) {}

  // Gets the translator associated with the bitcode parser.
  Ice::Translator &getTranslator() const { return Context->getTranslator(); }

  const Ice::ClFlags &getFlags() const { return getTranslator().getFlags(); }

  // Default implementation. Reports that block is unknown and skips its
  // contents.
  bool ParseBlock(unsigned BlockID) override;

  // Default implementation. Reports that the record is not understood.
  void ProcessRecord() override;

  // Checks if the size of the record is Size. Return true if valid. Otherwise
  // generates an error and returns false.
  bool isValidRecordSize(size_t Size, const char *RecordName) {
    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
    if (Values.size() == Size)
      return true;
    reportRecordSizeError(Size, RecordName, nullptr);
    return false;
  }

  // Checks if the size of the record is at least as large as the LowerLimit.
  // Returns true if valid. Otherwise generates an error and returns false.
  bool isValidRecordSizeAtLeast(size_t LowerLimit, const char *RecordName) {
    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
    if (Values.size() >= LowerLimit)
      return true;
    reportRecordSizeError(LowerLimit, RecordName, "at least");
    return false;
  }

  // Checks if the size of the record is no larger than the
  // UpperLimit.  Returns true if valid. Otherwise generates an error and
  // returns false.
  bool isValidRecordSizeAtMost(size_t UpperLimit, const char *RecordName) {
    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
    if (Values.size() <= UpperLimit)
      return true;
    reportRecordSizeError(UpperLimit, RecordName, "no more than");
    return false;
  }

  // Checks if the size of the record is at least as large as the LowerLimit,
  // and no larger than the UpperLimit. Returns true if valid. Otherwise
  // generates an error and returns false.
  bool isValidRecordSizeInRange(size_t LowerLimit, size_t UpperLimit,
                                const char *RecordName) {
    return isValidRecordSizeAtLeast(LowerLimit, RecordName) ||
           isValidRecordSizeAtMost(UpperLimit, RecordName);
  }

private:
  /// Generates a record size error. ExpectedSize is the number of elements
  /// expected. RecordName is the name of the kind of record that has incorrect
  /// size. ContextMessage (if not nullptr) is appended to "record expects" to
  /// describe how ExpectedSize should be interpreted.
  void reportRecordSizeError(size_t ExpectedSize, const char *RecordName,
                             const char *ContextMessage);
};

bool TopLevelParser::blockError(const std::string &Message) {
  if (BlockParser)
    return BlockParser->Error(Message);
  else
    return Error(Message);
}

// Generates an error Message with the bit address prefixed to it.
bool BlockParserBaseClass::ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit,
                                   const std::string &Message) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  // Note: If dump routines have been turned off, the error messages will not
  // be readable. Hence, replace with simple error. We also use the simple form
  // for unit tests.
  if (getFlags().getGenerateUnitTestMessages()) {
    StrBuf << "Invalid " << getBlockName() << " record: <" << Record.GetCode();
    for (const uint64_t Val : Record.GetValues()) {
      StrBuf << " " << Val;
    }
    StrBuf << ">";
  } else {
    StrBuf << Message;
  }
  return Context->ErrorAt(Level, Bit, StrBuf.str());
}

void BlockParserBaseClass::reportRecordSizeError(size_t ExpectedSize,
                                                 const char *RecordName,
                                                 const char *ContextMessage) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  const char *BlockName = getBlockName();
  const char FirstChar = toupper(*BlockName);
  StrBuf << FirstChar << (BlockName + 1) << " " << RecordName
         << " record expects";
  if (ContextMessage)
    StrBuf << " " << ContextMessage;
  StrBuf << " " << ExpectedSize << " argument";
  if (ExpectedSize > 1)
    StrBuf << "s";
  StrBuf << ". Found: " << Record.GetValues().size();
  Error(StrBuf.str());
}

bool BlockParserBaseClass::ParseBlock(unsigned BlockID) {
  // If called, derived class doesn't know how to handle block. Report error
  // and skip.
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << "Don't know how to parse block id: " << BlockID;
  Error(StrBuf.str());
  SkipBlock();
  return false;
}

void BlockParserBaseClass::ProcessRecord() {
  // If called, derived class doesn't know how to handle.
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << "Don't know how to process " << getBlockName()
         << " record:" << Record;
  Error(StrBuf.str());
}

// Class to parse a types block.
class TypesParser : public BlockParserBaseClass {
  TypesParser() = delete;
  TypesParser(const TypesParser &) = delete;
  TypesParser &operator=(const TypesParser &) = delete;

public:
  TypesParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
      : BlockParserBaseClass(BlockID, EnclosingParser),
        Timer(Ice::TimerStack::TT_parseTypes, getTranslator().getContext()) {}

  ~TypesParser() override {
    if (ExpectedNumTypes != Context->getNumTypeIDValues()) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Types block expected " << ExpectedNumTypes
             << " types but found: " << NextTypeId;
      Error(StrBuf.str());
    }
  }

private:
  Ice::TimerMarker Timer;
  // The type ID that will be associated with the next type defining record in
  // the types block.
  NaClBcIndexSize_t NextTypeId = 0;

  // The expected number of types, based on record TYPE_CODE_NUMENTRY.
  NaClBcIndexSize_t ExpectedNumTypes = 0;

  void ProcessRecord() override;

  const char *getBlockName() const override { return "type"; }

  void setNextTypeIDAsSimpleType(Ice::Type Ty) {
    Context->getTypeByIDForDefining(NextTypeId++)->setAsSimpleType(Ty);
  }
};

void TypesParser::ProcessRecord() {
  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
  switch (Record.GetCode()) {
  case naclbitc::TYPE_CODE_NUMENTRY: {
    // NUMENTRY: [numentries]
    if (!isValidRecordSize(1, "count"))
      return;
    uint64_t Size = Values[0];
    if (Size > NaClBcIndexSize_t_Max) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Size to big for count record: " << Size;
      Error(StrBuf.str());
      ExpectedNumTypes = NaClBcIndexSize_t_Max;
    }
    // The code double checks that Expected size and the actual size at the end
    // of the block. To reduce allocations we preallocate the space.
    //
    // However, if the number is large, we suspect that the number is
    // (possibly) incorrect. In that case, we preallocate a smaller space.
    constexpr uint64_t DefaultLargeResizeValue = 1000000;
    Context->resizeTypeIDValues(std::min(Size, DefaultLargeResizeValue));
    ExpectedNumTypes = Size;
    return;
  }
  case naclbitc::TYPE_CODE_VOID:
    // VOID
    if (!isValidRecordSize(0, "void"))
      return;
    setNextTypeIDAsSimpleType(Ice::IceType_void);
    return;
  case naclbitc::TYPE_CODE_FLOAT:
    // FLOAT
    if (!isValidRecordSize(0, "float"))
      return;
    setNextTypeIDAsSimpleType(Ice::IceType_f32);
    return;
  case naclbitc::TYPE_CODE_DOUBLE:
    // DOUBLE
    if (!isValidRecordSize(0, "double"))
      return;
    setNextTypeIDAsSimpleType(Ice::IceType_f64);
    return;
  case naclbitc::TYPE_CODE_INTEGER:
    // INTEGER: [width]
    if (!isValidRecordSize(1, "integer"))
      return;
    switch (Values[0]) {
    case 1:
      setNextTypeIDAsSimpleType(Ice::IceType_i1);
      return;
    case 8:
      setNextTypeIDAsSimpleType(Ice::IceType_i8);
      return;
    case 16:
      setNextTypeIDAsSimpleType(Ice::IceType_i16);
      return;
    case 32:
      setNextTypeIDAsSimpleType(Ice::IceType_i32);
      return;
    case 64:
      setNextTypeIDAsSimpleType(Ice::IceType_i64);
      return;
    default:
      break;
    }
    {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Type integer record with invalid bitsize: " << Values[0];
      Error(StrBuf.str());
    }
    return;
  case naclbitc::TYPE_CODE_VECTOR: {
    // VECTOR: [numelts, eltty]
    if (!isValidRecordSize(2, "vector"))
      return;
    Ice::Type BaseTy = Context->getSimpleTypeByID(Values[1]);
    Ice::SizeT Size = Values[0];
    switch (BaseTy) {
    case Ice::IceType_i1:
      switch (Size) {
      case 4:
        setNextTypeIDAsSimpleType(Ice::IceType_v4i1);
        return;
      case 8:
        setNextTypeIDAsSimpleType(Ice::IceType_v8i1);
        return;
      case 16:
        setNextTypeIDAsSimpleType(Ice::IceType_v16i1);
        return;
      default:
        break;
      }
      break;
    case Ice::IceType_i8:
      if (Size == 16) {
        setNextTypeIDAsSimpleType(Ice::IceType_v16i8);
        return;
      }
      break;
    case Ice::IceType_i16:
      if (Size == 8) {
        setNextTypeIDAsSimpleType(Ice::IceType_v8i16);
        return;
      }
      break;
    case Ice::IceType_i32:
      if (Size == 4) {
        setNextTypeIDAsSimpleType(Ice::IceType_v4i32);
        return;
      }
      break;
    case Ice::IceType_f32:
      if (Size == 4) {
        setNextTypeIDAsSimpleType(Ice::IceType_v4f32);
        return;
      }
      break;
    default:
      break;
    }
    {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Invalid type vector record: <" << Values[0] << " x " << BaseTy
             << ">";
      Error(StrBuf.str());
    }
    return;
  }
  case naclbitc::TYPE_CODE_FUNCTION: {
    // FUNCTION: [vararg, retty, paramty x N]
    if (!isValidRecordSizeAtLeast(2, "signature"))
      return;
    if (Values[0])
      Error("Function type can't define varargs");
    ExtendedType *Ty = Context->getTypeByIDForDefining(NextTypeId++);
    Ty->setAsFunctionType();
    auto *FuncTy = cast<FuncSigExtendedType>(Ty);
    FuncTy->setReturnType(Context->getSimpleTypeByID(Values[1]));
    for (size_t i = 2, e = Values.size(); i != e; ++i) {
      // Check that type void not used as argument type. Note: PNaCl
      // restrictions can't be checked until we know the name, because we have
      // to check for intrinsic signatures.
      Ice::Type ArgTy = Context->getSimpleTypeByID(Values[i]);
      if (ArgTy == Ice::IceType_void) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Type for parameter " << (i - 1)
               << " not valid. Found: " << ArgTy;
        ArgTy = Ice::IceType_i32;
      }
      FuncTy->appendArgType(ArgTy);
    }
    return;
  }
  default:
    BlockParserBaseClass::ProcessRecord();
    return;
  }
  llvm_unreachable("Unknown type block record not processed!");
}

/// Parses the globals block (i.e. global variable declarations and
/// corresponding initializers).
class GlobalsParser : public BlockParserBaseClass {
  GlobalsParser() = delete;
  GlobalsParser(const GlobalsParser &) = delete;
  GlobalsParser &operator=(const GlobalsParser &) = delete;

public:
  GlobalsParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
      : BlockParserBaseClass(BlockID, EnclosingParser),
        Timer(Ice::TimerStack::TT_parseGlobals, getTranslator().getContext()),
        NumFunctionIDs(Context->getNumFunctionIDs()),
        DummyGlobalVar(
            Ice::VariableDeclaration::create(getTranslator().getContext())),
        CurGlobalVar(DummyGlobalVar) {}

  ~GlobalsParser() final = default;

  const char *getBlockName() const override { return "globals"; }

private:
  using GlobalVarsMapType =
      std::unordered_map<NaClBcIndexSize_t, Ice::VariableDeclaration *>;

  Ice::TimerMarker Timer;

  // Holds global variables generated/referenced in the global variables block.
  GlobalVarsMapType GlobalVarsMap;

  // Holds the number of defined function IDs.
  NaClBcIndexSize_t NumFunctionIDs;

  // Holds the specified number of global variables by the count record in the
  // global variables block.
  NaClBcIndexSize_t SpecifiedNumberVars = 0;

  // Keeps track of how many initializers are expected for the global variable
  // declaration being built.
  NaClBcIndexSize_t InitializersNeeded = 0;

  // The index of the next global variable declaration.
  NaClBcIndexSize_t NextGlobalID = 0;

  // Dummy global variable declaration to guarantee CurGlobalVar is always
  // defined (allowing code to not need to check if CurGlobalVar is nullptr).
  Ice::VariableDeclaration *DummyGlobalVar;

  // Holds the current global variable declaration being built.
  Ice::VariableDeclaration *CurGlobalVar;

  // Returns the global variable associated with the given Index.
  Ice::VariableDeclaration *getGlobalVarByID(NaClBcIndexSize_t Index) {
    Ice::VariableDeclaration *&Decl = GlobalVarsMap[Index];
    if (Decl == nullptr)
      Decl = Ice::VariableDeclaration::create(getTranslator().getContext());
    return Decl;
  }

  // Returns the global declaration associated with the given index.
  Ice::GlobalDeclaration *getGlobalDeclByID(NaClBcIndexSize_t Index) {
    if (Index < NumFunctionIDs)
      return Context->getFunctionByID(Index);
    return getGlobalVarByID(Index - NumFunctionIDs);
  }

  // If global variables parsed correctly, install them into the top-level
  // context.
  void installGlobalVariables() {
    // Verify specified number of globals matches number found.
    size_t NumGlobals = GlobalVarsMap.size();
    if (SpecifiedNumberVars != NumGlobals ||
        SpecifiedNumberVars != NextGlobalID) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << getBlockName() << " block expects " << SpecifiedNumberVars
             << " global variables. Found: " << GlobalVarsMap.size();
      Error(StrBuf.str());
      return;
    }
    // Install global variables into top-level context.
    for (size_t I = 0; I < NumGlobals; ++I)
      Context->addGlobalDeclaration(GlobalVarsMap[I]);
  }

  void ExitBlock() override {
    verifyNoMissingInitializers();
    installGlobalVariables();
    BlockParserBaseClass::ExitBlock();
  }

  void ProcessRecord() override;

  // Checks if the number of initializers for the CurGlobalVar is the same as
  // the number found in the bitcode file. If different, and error message is
  // generated, and the internal state of the parser is fixed so this condition
  // is no longer violated.
  void verifyNoMissingInitializers() {
    size_t NumInits = CurGlobalVar->getInitializers().size();
    if (InitializersNeeded != NumInits) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Global variable @g" << NextGlobalID << " expected "
             << InitializersNeeded << " initializer";
      if (InitializersNeeded > 1)
        StrBuf << "s";
      StrBuf << ". Found: " << NumInits;
      Error(StrBuf.str());
      InitializersNeeded = NumInits;
    }
  }
};

void GlobalsParser::ProcessRecord() {
  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
  switch (Record.GetCode()) {
  case naclbitc::GLOBALVAR_COUNT:
    // COUNT: [n]
    if (!isValidRecordSize(1, "count"))
      return;
    if (SpecifiedNumberVars || NextGlobalID) {
      Error("Globals count record not first in block.");
      return;
    }
    SpecifiedNumberVars = Values[0];
    return;
  case naclbitc::GLOBALVAR_VAR: {
    // VAR: [align, isconst]
    if (!isValidRecordSize(2, "variable"))
      return;
    verifyNoMissingInitializers();
    // Always build the global variable, even if IR generation is turned off.
    // This is needed because we need a placeholder in the top-level context
    // when no IR is generated.
    uint32_t Alignment =
        Context->extractAlignment(this, "Global variable", Values[0]);
    CurGlobalVar = getGlobalVarByID(NextGlobalID);
    InitializersNeeded = 1;
    CurGlobalVar->setAlignment(Alignment);
    CurGlobalVar->setIsConstant(Values[1] != 0);
    ++NextGlobalID;
    return;
  }
  case naclbitc::GLOBALVAR_COMPOUND:
    // COMPOUND: [size]
    if (!isValidRecordSize(1, "compound"))
      return;
    if (!CurGlobalVar->getInitializers().empty()) {
      Error("Globals compound record not first initializer");
      return;
    }
    if (Values[0] < 2) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << getBlockName()
             << " compound record size invalid. Found: " << Values[0];
      Error(StrBuf.str());
      return;
    }
    InitializersNeeded = Values[0];
    return;
  case naclbitc::GLOBALVAR_ZEROFILL: {
    // ZEROFILL: [size]
    if (!isValidRecordSize(1, "zerofill"))
      return;
    CurGlobalVar->addInitializer(
        Ice::VariableDeclaration::ZeroInitializer::create(Values[0]));
    return;
  }
  case naclbitc::GLOBALVAR_DATA: {
    // DATA: [b0, b1, ...]
    if (!isValidRecordSizeAtLeast(1, "data"))
      return;
    CurGlobalVar->addInitializer(
        Ice::VariableDeclaration::DataInitializer::create(Values));
    return;
  }
  case naclbitc::GLOBALVAR_RELOC: {
    // RELOC: [val, [addend]]
    if (!isValidRecordSizeInRange(1, 2, "reloc"))
      return;
    NaClBcIndexSize_t Index = Values[0];
    NaClBcIndexSize_t IndexLimit = SpecifiedNumberVars + NumFunctionIDs;
    if (Index >= IndexLimit) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Relocation index " << Index << " to big. Expect index < "
             << IndexLimit;
      Error(StrBuf.str());
    }
    uint64_t Offset = 0;
    if (Values.size() == 2) {
      Offset = Values[1];
      if (Offset > std::numeric_limits<uint32_t>::max()) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Addend of global reloc record too big: " << Offset;
        Error(StrBuf.str());
      }
    }
    Ice::GlobalContext *Ctx = getTranslator().getContext();
    CurGlobalVar->addInitializer(
        Ice::VariableDeclaration::RelocInitializer::create(
            getGlobalDeclByID(Index), {Ice::RelocOffset::create(Ctx, Offset)}));
    return;
  }
  default:
    BlockParserBaseClass::ProcessRecord();
    return;
  }
}

/// Base class for parsing a valuesymtab block in the bitcode file.
class ValuesymtabParser : public BlockParserBaseClass {
  ValuesymtabParser() = delete;
  ValuesymtabParser(const ValuesymtabParser &) = delete;
  void operator=(const ValuesymtabParser &) = delete;

public:
  ValuesymtabParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
      : BlockParserBaseClass(BlockID, EnclosingParser) {}

  ~ValuesymtabParser() override = default;

  const char *getBlockName() const override { return "valuesymtab"; }

protected:
  using StringType = SmallString<128>;

  // Returns the name to identify the kind of symbol table this is
  // in error messages.
  virtual const char *getTableKind() const = 0;

  // Associates Name with the value defined by the given Index.
  virtual void setValueName(NaClBcIndexSize_t Index, StringType &Name) = 0;

  // Associates Name with the value defined by the given Index;
  virtual void setBbName(NaClBcIndexSize_t Index, StringType &Name) = 0;

  // Reports that the assignment of Name to the value associated with
  // index is not possible, for the given Context.
  void reportUnableToAssign(const char *Context, NaClBcIndexSize_t Index,
                            StringType &Name);

private:
  using NamesSetType = std::unordered_set<StringType>;
  NamesSetType ValueNames;
  NamesSetType BlockNames;

  void ProcessRecord() override;

  // Extracts out ConvertedName. Returns true if unique wrt to Names.
  bool convertToString(NamesSetType &Names, StringType &ConvertedName) {
    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
    for (size_t i = 1, e = Values.size(); i != e; ++i) {
      ConvertedName += static_cast<char>(Values[i]);
    }
    auto Pair = Names.insert(ConvertedName);
    return Pair.second;
  }

  void ReportDuplicateName(const char *NameCat, StringType &Name);
};

void ValuesymtabParser::reportUnableToAssign(const char *Context,
                                             NaClBcIndexSize_t Index,
                                             StringType &Name) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << getTableKind() << " " << getBlockName() << ": " << Context
         << " name '" << Name << "' can't be associated with index " << Index;
  Error(StrBuf.str());
}

void ValuesymtabParser::ReportDuplicateName(const char *NameCat,
                                            StringType &Name) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << getTableKind() << " " << getBlockName() << " defines duplicate "
         << NameCat << " name: '" << Name << "'";
  Error(StrBuf.str());
}

void ValuesymtabParser::ProcessRecord() {
  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
  StringType ConvertedName;
  switch (Record.GetCode()) {
  case naclbitc::VST_CODE_ENTRY: {
    // VST_ENTRY: [ValueId, namechar x N]
    if (!isValidRecordSizeAtLeast(2, "value entry"))
      return;
    if (convertToString(ValueNames, ConvertedName))
      setValueName(Values[0], ConvertedName);
    else
      ReportDuplicateName("value", ConvertedName);
    return;
  }
  case naclbitc::VST_CODE_BBENTRY: {
    // VST_BBENTRY: [BbId, namechar x N]
    if (!isValidRecordSizeAtLeast(2, "basic block entry"))
      return;
    if (convertToString(BlockNames, ConvertedName))
      setBbName(Values[0], ConvertedName);
    else
      ReportDuplicateName("block", ConvertedName);
    return;
  }
  default:
    break;
  }
  // If reached, don't know how to handle record.
  BlockParserBaseClass::ProcessRecord();
  return;
}

/// Parses function blocks in the bitcode file.
class FunctionParser : public BlockParserBaseClass {
  FunctionParser() = delete;
  FunctionParser(const FunctionParser &) = delete;
  FunctionParser &operator=(const FunctionParser &) = delete;

public:
  FunctionParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
      : BlockParserBaseClass(BlockID, EnclosingParser),
        Timer(Ice::TimerStack::TT_parseFunctions, getTranslator().getContext()),
        Func(nullptr), FcnId(Context->getNextFunctionBlockValueID()),
        FuncDecl(Context->getFunctionByID(FcnId)),
        CachedNumGlobalValueIDs(Context->getNumGlobalIDs()),
        NextLocalInstIndex(Context->getNumGlobalIDs()) {}

  bool convertFunction() {
    const Ice::TimerStackIdT StackID = Ice::GlobalContext::TSK_Funcs;
    Ice::TimerIdT TimerID = 0;
    const bool TimeThisFunction = getFlags().getTimeEachFunction();
    if (TimeThisFunction) {
      TimerID = getTranslator().getContext()->getTimerID(StackID,
                                                         FuncDecl->getName());
      getTranslator().getContext()->pushTimer(TimerID, StackID);
    }

    // Note: The Cfg is created, even when IR generation is disabled. This is
    // done to install a CfgLocalAllocator for various internal containers.
    Func = Ice::Cfg::create(getTranslator().getContext(),
                            getTranslator().getNextSequenceNumber());
    bool ParserResult;
    {
      Ice::CfgLocalAllocatorScope _(Func.get());

      // TODO(kschimpf) Clean up API to add a function signature to a CFG.
      const Ice::FuncSigType &Signature = FuncDecl->getSignature();

      Func->setFunctionName(FuncDecl->getName());
      Func->setReturnType(Signature.getReturnType());
      Func->setInternal(FuncDecl->getLinkage() == GlobalValue::InternalLinkage);
      CurrentNode = installNextBasicBlock();
      Func->setEntryNode(CurrentNode);
      for (Ice::Type ArgType : Signature.getArgList()) {
        Func->addArg(getNextInstVar(ArgType));
      }

      ParserResult = ParseThisBlock();

      // Temporarily end per-function timing, which will be resumed by the
      // translator function. This is because translation may be done
      // asynchronously in a separate thread.
      if (TimeThisFunction)
        getTranslator().getContext()->popTimer(TimerID, StackID);

      // Note: Once any errors have been found, we turn off all translation of
      // all remaining functions. This allows successive parsing errors to be
      // reported, without adding extra checks to the translator for such
      // parsing errors.
    }
    if (Context->getNumErrors() == 0 && Func) {
      getTranslator().translateFcn(std::move(Func));
      // The translator now has ownership of Func.
    } else {
      Func.reset();
    }

    return ParserResult;
  }

  ~FunctionParser() final = default;

  const char *getBlockName() const override { return "function"; }

  Ice::Cfg *getFunc() const { return Func.get(); }

  size_t getNumGlobalIDs() const { return CachedNumGlobalValueIDs; }

  void setNextLocalInstIndex(Ice::Operand *Op) {
    setOperand(NextLocalInstIndex++, Op);
  }

  // Set the next constant ID to the given constant C.
  void setNextConstantID(Ice::Constant *C) { setNextLocalInstIndex(C); }

  // Returns the value referenced by the given value Index.
  Ice::Operand *getOperand(NaClBcIndexSize_t Index) {
    if (Index < CachedNumGlobalValueIDs) {
      return Context->getGlobalConstantByID(Index);
    }
    NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs;
    if (LocalIndex >= LocalOperands.size())
      reportGetOperandUndefined(Index);
    Ice::Operand *Op = LocalOperands[LocalIndex];
    if (Op == nullptr)
      reportGetOperandUndefined(Index);
    return Op;
  }

private:
  Ice::TimerMarker Timer;
  // The number of words in the bitstream defining the function block.
  uint64_t NumBytesDefiningFunction = 0;
  // Maximum number of records that can appear in the function block, based on
  // the number of bytes defining the function block.
  uint64_t MaxRecordsInBlock = 0;
  // The corresponding ICE function defined by the function block.
  std::unique_ptr<Ice::Cfg> Func;
  // The index to the current basic block being built.
  NaClBcIndexSize_t CurrentBbIndex = 0;
  // The number of basic blocks declared for the function block.
  NaClBcIndexSize_t DeclaredNumberBbs = 0;
  // The basic block being built.
  Ice::CfgNode *CurrentNode = nullptr;
  // The ID for the function.
  NaClBcIndexSize_t FcnId;
  // The corresponding function declaration.
  Ice::FunctionDeclaration *FuncDecl;
  // Holds the dividing point between local and global absolute value indices.
  size_t CachedNumGlobalValueIDs;
  // Holds operands local to the function block, based on indices defined in
  // the bitcode file.
  Ice::OperandList LocalOperands;
  // Holds the index within LocalOperands corresponding to the next instruction
  // that generates a value.
  NaClBcIndexSize_t NextLocalInstIndex;
  // True if the last processed instruction was a terminating instruction.
  bool InstIsTerminating = false;

  bool ParseBlock(unsigned BlockID) override;

  void ProcessRecord() override;

  void EnterBlock(unsigned NumWords) final {
    // Note: Bitstream defines words as 32-bit values.
    NumBytesDefiningFunction = NumWords * sizeof(uint32_t);
    // We know that all records are minimally defined by a two-bit abreviation.
    MaxRecordsInBlock = NumBytesDefiningFunction * (CHAR_BIT >> 1);
  }

  void ExitBlock() override;

  // Creates and appends a new basic block to the list of basic blocks.
  Ice::CfgNode *installNextBasicBlock() {
    Ice::CfgNode *Node = Func->makeNode();
    return Node;
  }

  // Returns the Index-th basic block in the list of basic blocks.
  Ice::CfgNode *getBasicBlock(NaClBcIndexSize_t Index) {
    if (Index >= Func->getNumNodes()) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Reference to basic block " << Index
             << " not found. Must be less than " << Func->getNumNodes();
      Error(StrBuf.str());
      Index = 0;
    }
    return Func->getNodes()[Index];
  }

  // Returns the Index-th basic block in the list of basic blocks. Assumes
  // Index corresponds to a branch instruction. Hence, if the branch references
  // the entry block, it also generates a corresponding error.
  Ice::CfgNode *getBranchBasicBlock(NaClBcIndexSize_t Index) {
    if (Index == 0) {
      Error("Branch to entry block not allowed");
    }
    return getBasicBlock(Index);
  }

  // Generate an instruction variable with type Ty.
  Ice::Variable *createInstVar(Ice::Type Ty) {
    if (Ty == Ice::IceType_void) {
      Error("Can't define instruction value using type void");
      // Recover since we can't throw an exception.
      Ty = Ice::IceType_i32;
    }
    return Func->makeVariable(Ty);
  }

  // Generates the next available local variable using the given type.
  Ice::Variable *getNextInstVar(Ice::Type Ty) {
    assert(NextLocalInstIndex >= CachedNumGlobalValueIDs);
    // Before creating one, see if a forwardtyperef has already defined it.
    NaClBcIndexSize_t LocalIndex = NextLocalInstIndex - CachedNumGlobalValueIDs;
    if (LocalIndex < LocalOperands.size()) {
      Ice::Operand *Op = LocalOperands[LocalIndex];
      if (Op != nullptr) {
        if (auto *Var = dyn_cast<Ice::Variable>(Op)) {
          if (Var->getType() == Ty) {
            ++NextLocalInstIndex;
            return Var;
          }
        }
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Illegal forward referenced instruction ("
               << NextLocalInstIndex << "): " << *Op;
        Error(StrBuf.str());
        ++NextLocalInstIndex;
        return createInstVar(Ty);
      }
    }
    Ice::Variable *Var = createInstVar(Ty);
    setOperand(NextLocalInstIndex++, Var);
    return Var;
  }

  // Converts a relative index (wrt to BaseIndex) to an absolute value index.
  NaClBcIndexSize_t convertRelativeToAbsIndex(NaClRelBcIndexSize_t Id,
                                              NaClRelBcIndexSize_t BaseIndex) {
    if (BaseIndex < Id) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Invalid relative value id: " << Id
             << " (must be <= " << BaseIndex << ")";
      Error(StrBuf.str());
      return 0;
    }
    return BaseIndex - Id;
  }

  // Sets element Index (in the local operands list) to Op.
  void setOperand(NaClBcIndexSize_t Index, Ice::Operand *Op) {
    assert(Op);
    // Check if simple push works.
    NaClBcIndexSize_t LocalIndex = Index - CachedNumGlobalValueIDs;
    if (LocalIndex == LocalOperands.size()) {
      LocalOperands.push_back(Op);
      return;
    }

    // Must be forward reference, expand vector to accommodate.
    if (LocalIndex >= LocalOperands.size()) {
      if (LocalIndex > MaxRecordsInBlock) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Forward reference @" << Index << " too big. Have "
               << CachedNumGlobalValueIDs << " globals and function contains "
               << NumBytesDefiningFunction << " bytes";
        Fatal(StrBuf.str());
        // Recover by using index one beyond the maximal allowed.
        LocalIndex = MaxRecordsInBlock;
      }
      LocalOperands.resize(LocalIndex + 1);
    }

    // If element not defined, set it.
    Ice::Operand *OldOp = LocalOperands[LocalIndex];
    if (OldOp == nullptr) {
      LocalOperands[LocalIndex] = Op;
      return;
    }

    // See if forward reference matches.
    if (OldOp == Op)
      return;

    // Error has occurred.
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << "Multiple definitions for index " << Index << ": " << *Op
           << " and " << *OldOp;
    Error(StrBuf.str());
    LocalOperands[LocalIndex] = Op;
  }

  // Returns the relative operand (wrt to BaseIndex) referenced by the given
  // value Index.
  Ice::Operand *getRelativeOperand(NaClBcIndexSize_t Index,
                                   NaClBcIndexSize_t BaseIndex) {
    return getOperand(convertRelativeToAbsIndex(Index, BaseIndex));
  }

  // Returns the absolute index of the next value generating instruction.
  NaClBcIndexSize_t getNextInstIndex() const { return NextLocalInstIndex; }

  // Generates type error message for binary operator Op operating on Type
  // OpTy.
  void reportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy);

  // Validates if integer logical Op, for type OpTy, is valid. Returns true if
  // valid. Otherwise generates error message and returns false.
  bool isValidIntegerLogicalOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy) {
    if (Ice::isIntegerType(OpTy))
      return true;
    reportInvalidBinaryOp(Op, OpTy);
    return false;
  }

  // Validates if integer (or vector of integers) arithmetic Op, for type OpTy,
  // is valid. Returns true if valid. Otherwise generates error message and
  // returns false.
  bool isValidIntegerArithOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy) {
    if (Ice::isIntegerArithmeticType(OpTy))
      return true;
    reportInvalidBinaryOp(Op, OpTy);
    return false;
  }

  // Checks if floating arithmetic Op, for type OpTy, is valid. Returns true if
  // valid. Otherwise generates an error message and returns false;
  bool isValidFloatingArithOp(Ice::InstArithmetic::OpKind Op, Ice::Type OpTy) {
    if (Ice::isFloatingType(OpTy))
      return true;
    reportInvalidBinaryOp(Op, OpTy);
    return false;
  }

  // Checks if the type of operand Op is the valid pointer type, for the given
  // InstructionName. Returns true if valid. Otherwise generates an error
  // message and returns false.
  bool isValidPointerType(Ice::Operand *Op, const char *InstructionName) {
    Ice::Type PtrType = Ice::getPointerType();
    if (Op->getType() == PtrType)
      return true;
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << InstructionName << " address not " << PtrType
           << ". Found: " << Op->getType();
    Error(StrBuf.str());
    return false;
  }

  // Checks if loading/storing a value of type Ty is allowed. Returns true if
  // Valid. Otherwise generates an error message and returns false.
  bool isValidLoadStoreType(Ice::Type Ty, const char *InstructionName) {
    if (isLoadStoreType(Ty))
      return true;
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << InstructionName << " type not allowed: " << Ty << "*";
    Error(StrBuf.str());
    return false;
  }

  // Checks if loading/storing a value of type Ty is allowed for the given
  // Alignment. Otherwise generates an error message and returns false.
  bool isValidLoadStoreAlignment(size_t Alignment, Ice::Type Ty,
                                 const char *InstructionName) {
    if (!isValidLoadStoreType(Ty, InstructionName))
      return false;
    if (isAllowedAlignment(Alignment, Ty))
      return true;
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << InstructionName << " " << Ty << "*: not allowed for alignment "
           << Alignment;
    Error(StrBuf.str());
    return false;
  }

  // Defines if the given alignment is valid for the given type. Simplified
  // version of PNaClABIProps::isAllowedAlignment, based on API's offered for
  // Ice::Type.
  bool isAllowedAlignment(size_t Alignment, Ice::Type Ty) const {
    return Alignment == typeAlignInBytes(Ty) ||
           (Alignment == 1 && !isVectorType(Ty));
  }

  // Types of errors that can occur for insertelement and extractelement
  // instructions.
  enum VectorIndexCheckValue {
    VectorIndexNotVector,
    VectorIndexNotConstant,
    VectorIndexNotInRange,
    VectorIndexNotI32,
    VectorIndexValid
  };

  void dumpVectorIndexCheckValue(raw_ostream &Stream,
                                 VectorIndexCheckValue Value) const {
    if (!Ice::BuildDefs::dump())
      return;
    switch (Value) {
    case VectorIndexNotVector:
      Stream << "Vector index on non vector";
      break;
    case VectorIndexNotConstant:
      Stream << "Vector index not integer constant";
      break;
    case VectorIndexNotInRange:
      Stream << "Vector index not in range of vector";
      break;
    case VectorIndexNotI32:
      Stream << "Vector index not of type " << Ice::IceType_i32;
      break;
    case VectorIndexValid:
      Stream << "Valid vector index";
      break;
    }
  }

  // Returns whether the given vector index (for insertelement and
  // extractelement instructions) is valid.
  VectorIndexCheckValue validateVectorIndex(const Ice::Operand *Vec,
                                            const Ice::Operand *Index) const {
    Ice::Type VecType = Vec->getType();
    if (!Ice::isVectorType(VecType))
      return VectorIndexNotVector;
    const auto *C = dyn_cast<Ice::ConstantInteger32>(Index);
    if (C == nullptr)
      return VectorIndexNotConstant;
    if (static_cast<size_t>(C->getValue()) >= typeNumElements(VecType))
      return VectorIndexNotInRange;
    if (Index->getType() != Ice::IceType_i32)
      return VectorIndexNotI32;
    return VectorIndexValid;
  }

  // Takes the PNaCl bitcode binary operator Opcode, and the opcode type Ty,
  // and sets Op to the corresponding ICE binary opcode. Returns true if able
  // to convert, false otherwise.
  bool convertBinopOpcode(unsigned Opcode, Ice::Type Ty,
                          Ice::InstArithmetic::OpKind &Op) {
    switch (Opcode) {
    default: {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Binary opcode " << Opcode << "not understood for type " << Ty;
      Error(StrBuf.str());
      Op = Ice::InstArithmetic::Add;
      return false;
    }
    case naclbitc::BINOP_ADD:
      if (Ice::isIntegerType(Ty)) {
        Op = Ice::InstArithmetic::Add;
        return isValidIntegerArithOp(Op, Ty);
      } else {
        Op = Ice::InstArithmetic::Fadd;
        return isValidFloatingArithOp(Op, Ty);
      }
    case naclbitc::BINOP_SUB:
      if (Ice::isIntegerType(Ty)) {
        Op = Ice::InstArithmetic::Sub;
        return isValidIntegerArithOp(Op, Ty);
      } else {
        Op = Ice::InstArithmetic::Fsub;
        return isValidFloatingArithOp(Op, Ty);
      }
    case naclbitc::BINOP_MUL:
      if (Ice::isIntegerType(Ty)) {
        Op = Ice::InstArithmetic::Mul;
        return isValidIntegerArithOp(Op, Ty);
      } else {
        Op = Ice::InstArithmetic::Fmul;
        return isValidFloatingArithOp(Op, Ty);
      }
    case naclbitc::BINOP_UDIV:
      Op = Ice::InstArithmetic::Udiv;
      return isValidIntegerArithOp(Op, Ty);
    case naclbitc::BINOP_SDIV:
      if (Ice::isIntegerType(Ty)) {
        Op = Ice::InstArithmetic::Sdiv;
        return isValidIntegerArithOp(Op, Ty);
      } else {
        Op = Ice::InstArithmetic::Fdiv;
        return isValidFloatingArithOp(Op, Ty);
      }
    case naclbitc::BINOP_UREM:
      Op = Ice::InstArithmetic::Urem;
      return isValidIntegerArithOp(Op, Ty);
    case naclbitc::BINOP_SREM:
      if (Ice::isIntegerType(Ty)) {
        Op = Ice::InstArithmetic::Srem;
        return isValidIntegerArithOp(Op, Ty);
      } else {
        Op = Ice::InstArithmetic::Frem;
        return isValidFloatingArithOp(Op, Ty);
      }
    case naclbitc::BINOP_SHL:
      Op = Ice::InstArithmetic::Shl;
      return isValidIntegerArithOp(Op, Ty);
    case naclbitc::BINOP_LSHR:
      Op = Ice::InstArithmetic::Lshr;
      return isValidIntegerArithOp(Op, Ty);
    case naclbitc::BINOP_ASHR:
      Op = Ice::InstArithmetic::Ashr;
      return isValidIntegerArithOp(Op, Ty);
    case naclbitc::BINOP_AND:
      Op = Ice::InstArithmetic::And;
      return isValidIntegerLogicalOp(Op, Ty);
    case naclbitc::BINOP_OR:
      Op = Ice::InstArithmetic::Or;
      return isValidIntegerLogicalOp(Op, Ty);
    case naclbitc::BINOP_XOR:
      Op = Ice::InstArithmetic::Xor;
      return isValidIntegerLogicalOp(Op, Ty);
    }
  }

  /// Simplifies out vector types from Type1 and Type2, if both are vectors of
  /// the same size. Returns true iff both are vectors of the same size, or are
  /// both scalar types.
  static bool simplifyOutCommonVectorType(Ice::Type &Type1, Ice::Type &Type2) {
    bool IsType1Vector = isVectorType(Type1);
    bool IsType2Vector = isVectorType(Type2);
    if (IsType1Vector != IsType2Vector)
      return false;
    if (!IsType1Vector)
      return true;
    if (typeNumElements(Type1) != typeNumElements(Type2))
      return false;
    Type1 = typeElementType(Type1);
    Type2 = typeElementType(Type2);
    return true;
  }

  /// Returns true iff an integer truncation from SourceType to TargetType is
  /// valid.
  static bool isIntTruncCastValid(Ice::Type SourceType, Ice::Type TargetType) {
    return Ice::isIntegerType(SourceType) && Ice::isIntegerType(TargetType) &&
           simplifyOutCommonVectorType(SourceType, TargetType) &&
           getScalarIntBitWidth(SourceType) > getScalarIntBitWidth(TargetType);
  }

  /// Returns true iff a floating type truncation from SourceType to TargetType
  /// is valid.
  static bool isFloatTruncCastValid(Ice::Type SourceType,
                                    Ice::Type TargetType) {
    return simplifyOutCommonVectorType(SourceType, TargetType) &&
           SourceType == Ice::IceType_f64 && TargetType == Ice::IceType_f32;
  }

  /// Returns true iff an integer extension from SourceType to TargetType is
  /// valid.
  static bool isIntExtCastValid(Ice::Type SourceType, Ice::Type TargetType) {
    return isIntTruncCastValid(TargetType, SourceType);
  }

  /// Returns true iff a floating type extension from SourceType to TargetType
  /// is valid.
  static bool isFloatExtCastValid(Ice::Type SourceType, Ice::Type TargetType) {
    return isFloatTruncCastValid(TargetType, SourceType);
  }

  /// Returns true iff a cast from floating type SourceType to integer type
  /// TargetType is valid.
  static bool isFloatToIntCastValid(Ice::Type SourceType,
                                    Ice::Type TargetType) {
    if (!(Ice::isFloatingType(SourceType) && Ice::isIntegerType(TargetType)))
      return false;
    bool IsSourceVector = isVectorType(SourceType);
    bool IsTargetVector = isVectorType(TargetType);
    if (IsSourceVector != IsTargetVector)
      return false;
    if (IsSourceVector) {
      return typeNumElements(SourceType) == typeNumElements(TargetType);
    }
    return true;
  }

  /// Returns true iff a cast from integer type SourceType to floating type
  /// TargetType is valid.
  static bool isIntToFloatCastValid(Ice::Type SourceType,
                                    Ice::Type TargetType) {
    return isFloatToIntCastValid(TargetType, SourceType);
  }

  /// Returns the number of bits used to model type Ty when defining the bitcast
  /// instruction.
  static Ice::SizeT bitcastSizeInBits(Ice::Type Ty) {
    if (Ice::isVectorType(Ty))
      return Ice::typeNumElements(Ty) *
             bitcastSizeInBits(Ice::typeElementType(Ty));
    if (Ty == Ice::IceType_i1)
      return 1;
    return Ice::typeWidthInBytes(Ty) * CHAR_BIT;
  }

  /// Returns true iff a bitcast from SourceType to TargetType is allowed.
  static bool isBitcastValid(Ice::Type SourceType, Ice::Type TargetType) {
    return bitcastSizeInBits(SourceType) == bitcastSizeInBits(TargetType);
  }

  /// Returns true iff the NaCl bitcode Opcode is a valid cast opcode for
  /// converting SourceType to TargetType. Updates CastKind to the corresponding
  /// instruction cast opcode. Also generates an error message when this
  /// function returns false.
  bool convertCastOpToIceOp(uint64_t Opcode, Ice::Type SourceType,
                            Ice::Type TargetType,
                            Ice::InstCast::OpKind &CastKind) {
    bool Result;
    switch (Opcode) {
    default: {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Cast opcode " << Opcode << " not understood.\n";
      Error(StrBuf.str());
      CastKind = Ice::InstCast::Bitcast;
      return false;
    }
    case naclbitc::CAST_TRUNC:
      CastKind = Ice::InstCast::Trunc;
      Result = isIntTruncCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_ZEXT:
      CastKind = Ice::InstCast::Zext;
      Result = isIntExtCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_SEXT:
      CastKind = Ice::InstCast::Sext;
      Result = isIntExtCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_FPTOUI:
      CastKind = Ice::InstCast::Fptoui;
      Result = isFloatToIntCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_FPTOSI:
      CastKind = Ice::InstCast::Fptosi;
      Result = isFloatToIntCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_UITOFP:
      CastKind = Ice::InstCast::Uitofp;
      Result = isIntToFloatCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_SITOFP:
      CastKind = Ice::InstCast::Sitofp;
      Result = isIntToFloatCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_FPTRUNC:
      CastKind = Ice::InstCast::Fptrunc;
      Result = isFloatTruncCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_FPEXT:
      CastKind = Ice::InstCast::Fpext;
      Result = isFloatExtCastValid(SourceType, TargetType);
      break;
    case naclbitc::CAST_BITCAST:
      CastKind = Ice::InstCast::Bitcast;
      Result = isBitcastValid(SourceType, TargetType);
      break;
    }
    if (!Result) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Illegal cast: " << Ice::InstCast::getCastName(CastKind) << " "
             << SourceType << " to " << TargetType;
      Error(StrBuf.str());
    }
    return Result;
  }

  // Converts PNaCl bitcode Icmp operator to corresponding ICE op. Returns true
  // if able to convert, false otherwise.
  bool convertNaClBitcICmpOpToIce(uint64_t Op,
                                  Ice::InstIcmp::ICond &Cond) const {
    switch (Op) {
    case naclbitc::ICMP_EQ:
      Cond = Ice::InstIcmp::Eq;
      return true;
    case naclbitc::ICMP_NE:
      Cond = Ice::InstIcmp::Ne;
      return true;
    case naclbitc::ICMP_UGT:
      Cond = Ice::InstIcmp::Ugt;
      return true;
    case naclbitc::ICMP_UGE:
      Cond = Ice::InstIcmp::Uge;
      return true;
    case naclbitc::ICMP_ULT:
      Cond = Ice::InstIcmp::Ult;
      return true;
    case naclbitc::ICMP_ULE:
      Cond = Ice::InstIcmp::Ule;
      return true;
    case naclbitc::ICMP_SGT:
      Cond = Ice::InstIcmp::Sgt;
      return true;
    case naclbitc::ICMP_SGE:
      Cond = Ice::InstIcmp::Sge;
      return true;
    case naclbitc::ICMP_SLT:
      Cond = Ice::InstIcmp::Slt;
      return true;
    case naclbitc::ICMP_SLE:
      Cond = Ice::InstIcmp::Sle;
      return true;
    default:
      // Make sure Cond is always initialized.
      Cond = static_cast<Ice::InstIcmp::ICond>(0);
      return false;
    }
  }

  // Converts PNaCl bitcode Fcmp operator to corresponding ICE op. Returns true
  // if able to convert, false otherwise.
  bool convertNaClBitcFCompOpToIce(uint64_t Op,
                                   Ice::InstFcmp::FCond &Cond) const {
    switch (Op) {
    case naclbitc::FCMP_FALSE:
      Cond = Ice::InstFcmp::False;
      return true;
    case naclbitc::FCMP_OEQ:
      Cond = Ice::InstFcmp::Oeq;
      return true;
    case naclbitc::FCMP_OGT:
      Cond = Ice::InstFcmp::Ogt;
      return true;
    case naclbitc::FCMP_OGE:
      Cond = Ice::InstFcmp::Oge;
      return true;
    case naclbitc::FCMP_OLT:
      Cond = Ice::InstFcmp::Olt;
      return true;
    case naclbitc::FCMP_OLE:
      Cond = Ice::InstFcmp::Ole;
      return true;
    case naclbitc::FCMP_ONE:
      Cond = Ice::InstFcmp::One;
      return true;
    case naclbitc::FCMP_ORD:
      Cond = Ice::InstFcmp::Ord;
      return true;
    case naclbitc::FCMP_UNO:
      Cond = Ice::InstFcmp::Uno;
      return true;
    case naclbitc::FCMP_UEQ:
      Cond = Ice::InstFcmp::Ueq;
      return true;
    case naclbitc::FCMP_UGT:
      Cond = Ice::InstFcmp::Ugt;
      return true;
    case naclbitc::FCMP_UGE:
      Cond = Ice::InstFcmp::Uge;
      return true;
    case naclbitc::FCMP_ULT:
      Cond = Ice::InstFcmp::Ult;
      return true;
    case naclbitc::FCMP_ULE:
      Cond = Ice::InstFcmp::Ule;
      return true;
    case naclbitc::FCMP_UNE:
      Cond = Ice::InstFcmp::Une;
      return true;
    case naclbitc::FCMP_TRUE:
      Cond = Ice::InstFcmp::True;
      return true;
    default:
      // Make sure Cond is always initialized.
      Cond = static_cast<Ice::InstFcmp::FCond>(0);
      return false;
    }
  }

  // Creates an error instruction, generating a value of type Ty, and adds a
  // placeholder so that instruction indices line up. Some instructions, such
  // as a call, will not generate a value if the return type is void. In such
  // cases, a placeholder value for the badly formed instruction is not needed.
  // Hence, if Ty is void, an error instruction is not appended.
  void appendErrorInstruction(Ice::Type Ty) {
    // Note: we don't worry about downstream translation errors because the
    // function will not be translated if any errors occur.
    if (Ty == Ice::IceType_void)
      return;
    Ice::Variable *Var = getNextInstVar(Ty);
    CurrentNode->appendInst(Ice::InstAssign::create(Func.get(), Var, Var));
  }

  Ice::Operand *reportGetOperandUndefined(NaClBcIndexSize_t Index) {
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << "Value index " << Index << " not defined!";
    Error(StrBuf.str());
    // Recover and return some value.
    if (!LocalOperands.empty())
      return LocalOperands.front();
    return Context->getGlobalConstantByID(0);
  }

  void verifyCallArgTypeMatches(Ice::FunctionDeclaration *Fcn, Ice::SizeT Index,
                                Ice::Type ArgType, Ice::Type ParamType) {
    if (ArgType != ParamType) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Argument " << (Index + 1) << " of " << printName(Fcn)
             << " expects " << ParamType << ". Found: " << ArgType;
      Error(StrBuf.str());
    }
  }

  const Ice::IceString printName(Ice::FunctionDeclaration *Fcn) {
    if (Fcn)
      return Fcn->getName();
    return "function";
  }
};

void FunctionParser::ExitBlock() {
  // Check if the last instruction in the function was terminating.
  if (!InstIsTerminating) {
    Error("Last instruction in function not terminator");
    // Recover by inserting an unreachable instruction.
    CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get()));
  }
  ++CurrentBbIndex;
  if (CurrentBbIndex != DeclaredNumberBbs) {
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << "Function declared " << DeclaredNumberBbs
           << " basic blocks, but defined " << CurrentBbIndex << ".";
    Error(StrBuf.str());
  }
  // Before translating, check for blocks without instructions, and insert
  // unreachable. This shouldn't happen, but be safe.
  size_t Index = 0;
  for (Ice::CfgNode *Node : Func->getNodes()) {
    if (Node->getInsts().empty()) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Basic block " << Index << " contains no instructions";
      Error(StrBuf.str());
      Node->appendInst(Ice::InstUnreachable::create(Func.get()));
    }
    ++Index;
  }
  Func->computeInOutEdges();
}

void FunctionParser::reportInvalidBinaryOp(Ice::InstArithmetic::OpKind Op,
                                           Ice::Type OpTy) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << "Invalid operator type for " << Ice::InstArithmetic::getOpName(Op)
         << ". Found " << OpTy;
  Error(StrBuf.str());
}

void FunctionParser::ProcessRecord() {
  // Note: To better separate parse/IR generation times, when IR generation is
  // disabled we do the following:
  // 1) Delay exiting until after we extract operands.
  // 2) return before we access operands, since all operands will be a nullptr.
  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
  if (InstIsTerminating) {
    InstIsTerminating = false;
    ++CurrentBbIndex;
    CurrentNode = getBasicBlock(CurrentBbIndex);
  }
  // The base index for relative indexing.
  NaClBcIndexSize_t BaseIndex = getNextInstIndex();
  switch (Record.GetCode()) {
  case naclbitc::FUNC_CODE_DECLAREBLOCKS: {
    // DECLAREBLOCKS: [n]
    if (!isValidRecordSize(1, "count"))
      return;
    if (DeclaredNumberBbs > 0) {
      Error("Duplicate function block count record");
      return;
    }

    // Check for bad large sizes, since they can make ridiculous memory
    // requests and hang the user for large amounts of time.
    uint64_t NumBbs = Values[0];
    if (NumBbs > MaxRecordsInBlock) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Function defines " << NumBbs
             << " basic blocks, which is too big for a function containing "
             << NumBytesDefiningFunction << " bytes";
      Error(StrBuf.str());
      NumBbs = MaxRecordsInBlock;
    }

    if (NumBbs == 0) {
      Error("Functions must contain at least one basic block.");
      NumBbs = 1;
    }

    DeclaredNumberBbs = NumBbs;
    // Install the basic blocks, skipping bb0 which was created in the
    // constructor.
    for (size_t i = 1; i < NumBbs; ++i)
      installNextBasicBlock();
    return;
  }
  case naclbitc::FUNC_CODE_INST_BINOP: {
    // BINOP: [opval, opval, opcode]
    if (!isValidRecordSize(3, "binop"))
      return;
    Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex);
    Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex);
    Ice::Type Type1 = Op1->getType();
    Ice::Type Type2 = Op2->getType();
    if (Type1 != Type2) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Binop argument types differ: " << Type1 << " and " << Type2;
      Error(StrBuf.str());
      appendErrorInstruction(Type1);
      return;
    }

    Ice::InstArithmetic::OpKind Opcode;
    if (!convertBinopOpcode(Values[2], Type1, Opcode)) {
      appendErrorInstruction(Type1);
      return;
    }
    CurrentNode->appendInst(Ice::InstArithmetic::create(
        Func.get(), Opcode, getNextInstVar(Type1), Op1, Op2));
    return;
  }
  case naclbitc::FUNC_CODE_INST_CAST: {
    // CAST: [opval, destty, castopc]
    if (!isValidRecordSize(3, "cast"))
      return;
    Ice::Operand *Src = getRelativeOperand(Values[0], BaseIndex);
    Ice::Type CastType = Context->getSimpleTypeByID(Values[1]);
    Ice::InstCast::OpKind CastKind;
    if (!convertCastOpToIceOp(Values[2], Src->getType(), CastType, CastKind)) {
      appendErrorInstruction(CastType);
      return;
    }
    CurrentNode->appendInst(Ice::InstCast::create(
        Func.get(), CastKind, getNextInstVar(CastType), Src));
    return;
  }
  case naclbitc::FUNC_CODE_INST_VSELECT: {
    // VSELECT: [opval, opval, pred]
    if (!isValidRecordSize(3, "select"))
      return;
    Ice::Operand *ThenVal = getRelativeOperand(Values[0], BaseIndex);
    Ice::Operand *ElseVal = getRelativeOperand(Values[1], BaseIndex);
    Ice::Operand *CondVal = getRelativeOperand(Values[2], BaseIndex);
    Ice::Type ThenType = ThenVal->getType();
    Ice::Type ElseType = ElseVal->getType();
    if (ThenType != ElseType) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Select operands not same type. Found " << ThenType << " and "
             << ElseType;
      Error(StrBuf.str());
      appendErrorInstruction(ThenType);
      return;
    }
    Ice::Type CondType = CondVal->getType();
    if (isVectorType(CondType)) {
      if (!isVectorType(ThenType) ||
          typeElementType(CondType) != Ice::IceType_i1 ||
          typeNumElements(ThenType) != typeNumElements(CondType)) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Select condition type " << CondType
               << " not allowed for values of type " << ThenType;
        Error(StrBuf.str());
        appendErrorInstruction(ThenType);
        return;
      }
    } else if (CondVal->getType() != Ice::IceType_i1) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Select condition " << CondVal
             << " not type i1. Found: " << CondVal->getType();
      Error(StrBuf.str());
      appendErrorInstruction(ThenType);
      return;
    }
    CurrentNode->appendInst(Ice::InstSelect::create(
        Func.get(), getNextInstVar(ThenType), CondVal, ThenVal, ElseVal));
    return;
  }
  case naclbitc::FUNC_CODE_INST_EXTRACTELT: {
    // EXTRACTELT: [opval, opval]
    if (!isValidRecordSize(2, "extract element"))
      return;
    Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex);
    Ice::Operand *Index = getRelativeOperand(Values[1], BaseIndex);
    Ice::Type VecType = Vec->getType();
    VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index);
    if (IndexCheckValue != VectorIndexValid) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      dumpVectorIndexCheckValue(StrBuf, IndexCheckValue);
      StrBuf << ": extractelement " << VecType << " " << *Vec << ", "
             << Index->getType() << " " << *Index;
      Error(StrBuf.str());
      appendErrorInstruction(VecType);
      return;
    }
    CurrentNode->appendInst(Ice::InstExtractElement::create(
        Func.get(), getNextInstVar(typeElementType(VecType)), Vec, Index));
    return;
  }
  case naclbitc::FUNC_CODE_INST_INSERTELT: {
    // INSERTELT: [opval, opval, opval]
    if (!isValidRecordSize(3, "insert element"))
      return;
    Ice::Operand *Vec = getRelativeOperand(Values[0], BaseIndex);
    Ice::Operand *Elt = getRelativeOperand(Values[1], BaseIndex);
    Ice::Operand *Index = getRelativeOperand(Values[2], BaseIndex);
    Ice::Type VecType = Vec->getType();
    VectorIndexCheckValue IndexCheckValue = validateVectorIndex(Vec, Index);
    if (IndexCheckValue != VectorIndexValid) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      dumpVectorIndexCheckValue(StrBuf, IndexCheckValue);
      StrBuf << ": insertelement " << VecType << " " << *Vec << ", "
             << Elt->getType() << " " << *Elt << ", " << Index->getType() << " "
             << *Index;
      Error(StrBuf.str());
      appendErrorInstruction(Elt->getType());
      return;
    }
    if (Ice::typeElementType(VecType) != Elt->getType()) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Insertelement: Element type "
             << Ice::typeString(Elt->getType()) << " doesn't match vector type "
             << Ice::typeString(VecType);
      Error(StrBuf.str());
      appendErrorInstruction(Elt->getType());
      return;
    }
    CurrentNode->appendInst(Ice::InstInsertElement::create(
        Func.get(), getNextInstVar(VecType), Vec, Elt, Index));
    return;
  }
  case naclbitc::FUNC_CODE_INST_CMP2: {
    // CMP2: [opval, opval, pred]
    if (!isValidRecordSize(3, "compare"))
      return;
    Ice::Operand *Op1 = getRelativeOperand(Values[0], BaseIndex);
    Ice::Operand *Op2 = getRelativeOperand(Values[1], BaseIndex);
    Ice::Type Op1Type = Op1->getType();
    Ice::Type Op2Type = Op2->getType();
    Ice::Type DestType = getCompareResultType(Op1Type);
    if (Op1Type != Op2Type) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Compare argument types differ: " << Op1Type << " and "
             << Op2Type;
      Error(StrBuf.str());
      appendErrorInstruction(DestType);
      Op2 = Op1;
    }
    if (DestType == Ice::IceType_void) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Compare not defined for type " << Op1Type;
      Error(StrBuf.str());
      return;
    }
    Ice::Variable *Dest = getNextInstVar(DestType);
    if (isIntegerType(Op1Type)) {
      Ice::InstIcmp::ICond Cond;
      if (!convertNaClBitcICmpOpToIce(Values[2], Cond)) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Compare record contains unknown integer predicate index: "
               << Values[2];
        Error(StrBuf.str());
        appendErrorInstruction(DestType);
      }
      CurrentNode->appendInst(
          Ice::InstIcmp::create(Func.get(), Cond, Dest, Op1, Op2));
    } else if (isFloatingType(Op1Type)) {
      Ice::InstFcmp::FCond Cond;
      if (!convertNaClBitcFCompOpToIce(Values[2], Cond)) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Compare record contains unknown float predicate index: "
               << Values[2];
        Error(StrBuf.str());
        appendErrorInstruction(DestType);
      }
      CurrentNode->appendInst(
          Ice::InstFcmp::create(Func.get(), Cond, Dest, Op1, Op2));
    } else {
      // Not sure this can happen, but be safe.
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Compare on type not understood: " << Op1Type;
      Error(StrBuf.str());
      appendErrorInstruction(DestType);
      return;
    }
    return;
  }
  case naclbitc::FUNC_CODE_INST_RET: {
    // RET: [opval?]
    InstIsTerminating = true;
    if (!isValidRecordSizeInRange(0, 1, "return"))
      return;
    if (Values.empty()) {
      CurrentNode->appendInst(Ice::InstRet::create(Func.get()));
    } else {
      Ice::Operand *RetVal = getRelativeOperand(Values[0], BaseIndex);
      CurrentNode->appendInst(Ice::InstRet::create(Func.get(), RetVal));
    }
    return;
  }
  case naclbitc::FUNC_CODE_INST_BR: {
    InstIsTerminating = true;
    if (Values.size() == 1) {
      // BR: [bb#]
      Ice::CfgNode *Block = getBranchBasicBlock(Values[0]);
      if (Block == nullptr)
        return;
      CurrentNode->appendInst(Ice::InstBr::create(Func.get(), Block));
    } else {
      // BR: [bb#, bb#, opval]
      if (!isValidRecordSize(3, "branch"))
        return;
      Ice::Operand *Cond = getRelativeOperand(Values[2], BaseIndex);
      if (Cond->getType() != Ice::IceType_i1) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Branch condition " << *Cond
               << " not i1. Found: " << Cond->getType();
        Error(StrBuf.str());
        return;
      }
      Ice::CfgNode *ThenBlock = getBranchBasicBlock(Values[0]);
      Ice::CfgNode *ElseBlock = getBranchBasicBlock(Values[1]);
      if (ThenBlock == nullptr || ElseBlock == nullptr)
        return;
      CurrentNode->appendInst(
          Ice::InstBr::create(Func.get(), Cond, ThenBlock, ElseBlock));
    }
    return;
  }
  case naclbitc::FUNC_CODE_INST_SWITCH: {
    // SWITCH: [Condty, Cond, BbIndex, NumCases Case ...]
    // where Case = [1, 1, Value, BbIndex].
    //
    // Note: Unlike most instructions, we don't infer the type of Cond, but
    // provide it as a separate field. There are also unnecessary data fields
    // (i.e. constants 1). These were not cleaned up in PNaCl bitcode because
    // the bitcode format was already frozen when the problem was noticed.
    InstIsTerminating = true;
    if (!isValidRecordSizeAtLeast(4, "switch"))
      return;

    Ice::Type CondTy = Context->getSimpleTypeByID(Values[0]);
    if (!Ice::isScalarIntegerType(CondTy)) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Case condition must be non-wide integer. Found: " << CondTy;
      Error(StrBuf.str());
      return;
    }
    Ice::SizeT BitWidth = Ice::getScalarIntBitWidth(CondTy);
    Ice::Operand *Cond = getRelativeOperand(Values[1], BaseIndex);

    if (CondTy != Cond->getType()) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Case condition expects type " << CondTy
             << ". Found: " << Cond->getType();
      Error(StrBuf.str());
      return;
    }
    Ice::CfgNode *DefaultLabel = getBranchBasicBlock(Values[2]);
    if (DefaultLabel == nullptr)
      return;
    uint64_t NumCasesRaw = Values[3];
    if (NumCasesRaw > std::numeric_limits<uint32_t>::max()) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Too many cases specified in switch: " << NumCasesRaw;
      Error(StrBuf.str());
      NumCasesRaw = std::numeric_limits<uint32_t>::max();
    }
    uint32_t NumCases = NumCasesRaw;

    // Now recognize each of the cases.
    if (!isValidRecordSize(4 + NumCases * 4, "switch"))
      return;
    std::unique_ptr<Ice::InstSwitch> Switch(
        Ice::InstSwitch::create(Func.get(), NumCases, Cond, DefaultLabel));
    unsigned ValCaseIndex = 4; // index to beginning of case entry.
    for (uint32_t CaseIndex = 0; CaseIndex < NumCases;
         ++CaseIndex, ValCaseIndex += 4) {
      if (Values[ValCaseIndex] != 1 || Values[ValCaseIndex + 1] != 1) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Sequence [1, 1, value, label] expected for case entry "
               << "in switch record. (at index" << ValCaseIndex << ")";
        Error(StrBuf.str());
        return;
      }
      BitcodeInt Value(BitWidth,
                       NaClDecodeSignRotatedValue(Values[ValCaseIndex + 2]));
      Ice::CfgNode *Label = getBranchBasicBlock(Values[ValCaseIndex + 3]);
      if (Label == nullptr)
        return;
      Switch->addBranch(CaseIndex, Value.getSExtValue(), Label);
    }
    CurrentNode->appendInst(Switch.release());
    return;
  }
  case naclbitc::FUNC_CODE_INST_UNREACHABLE: {
    // UNREACHABLE: []
    InstIsTerminating = true;
    if (!isValidRecordSize(0, "unreachable"))
      return;
    CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get()));
    return;
  }
  case naclbitc::FUNC_CODE_INST_PHI: {
    // PHI: [ty, val1, bb1, ..., valN, bbN] for n >= 2.
    if (!isValidRecordSizeAtLeast(3, "phi"))
      return;
    Ice::Type Ty = Context->getSimpleTypeByID(Values[0]);
    if ((Values.size() & 0x1) == 0) {
      // Not an odd number of values.
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "function block phi record size not valid: " << Values.size();
      Error(StrBuf.str());
      appendErrorInstruction(Ty);
      return;
    }
    if (Ty == Ice::IceType_void) {
      Error("Phi record using type void not allowed");
      return;
    }
    Ice::Variable *Dest = getNextInstVar(Ty);
    Ice::InstPhi *Phi =
        Ice::InstPhi::create(Func.get(), Values.size() >> 1, Dest);
    for (size_t i = 1; i < Values.size(); i += 2) {
      Ice::Operand *Op =
          getRelativeOperand(NaClDecodeSignRotatedValue(Values[i]), BaseIndex);
      if (Op->getType() != Ty) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Value " << *Op << " not type " << Ty
               << " in phi instruction. Found: " << Op->getType();
        Error(StrBuf.str());
        appendErrorInstruction(Ty);
        return;
      }
      Phi->addArgument(Op, getBasicBlock(Values[i + 1]));
    }
    CurrentNode->appendInst(Phi);
    return;
  }
  case naclbitc::FUNC_CODE_INST_ALLOCA: {
    // ALLOCA: [Size, align]
    if (!isValidRecordSize(2, "alloca"))
      return;
    Ice::Operand *ByteCount = getRelativeOperand(Values[0], BaseIndex);
    uint32_t Alignment = Context->extractAlignment(this, "Alloca", Values[1]);
    Ice::Type PtrTy = Ice::getPointerType();
    if (ByteCount->getType() != Ice::IceType_i32) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Alloca on non-i32 value. Found: " << *ByteCount;
      Error(StrBuf.str());
      appendErrorInstruction(PtrTy);
      return;
    }
    CurrentNode->appendInst(Ice::InstAlloca::create(
        Func.get(), getNextInstVar(PtrTy), ByteCount, Alignment));
    return;
  }
  case naclbitc::FUNC_CODE_INST_LOAD: {
    // LOAD: [address, align, ty]
    if (!isValidRecordSize(3, "load"))
      return;
    Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex);
    Ice::Type Ty = Context->getSimpleTypeByID(Values[2]);
    uint32_t Alignment = Context->extractAlignment(this, "Load", Values[1]);
    if (!isValidPointerType(Address, "Load")) {
      appendErrorInstruction(Ty);
      return;
    }
    if (!isValidLoadStoreAlignment(Alignment, Ty, "Load")) {
      appendErrorInstruction(Ty);
      return;
    }
    CurrentNode->appendInst(Ice::InstLoad::create(
        Func.get(), getNextInstVar(Ty), Address, Alignment));
    return;
  }
  case naclbitc::FUNC_CODE_INST_STORE: {
    // STORE: [address, value, align]
    if (!isValidRecordSize(3, "store"))
      return;
    Ice::Operand *Address = getRelativeOperand(Values[0], BaseIndex);
    Ice::Operand *Value = getRelativeOperand(Values[1], BaseIndex);
    uint32_t Alignment = Context->extractAlignment(this, "Store", Values[2]);
    if (!isValidPointerType(Address, "Store"))
      return;
    if (!isValidLoadStoreAlignment(Alignment, Value->getType(), "Store"))
      return;
    CurrentNode->appendInst(
        Ice::InstStore::create(Func.get(), Value, Address, Alignment));
    return;
  }
  case naclbitc::FUNC_CODE_INST_CALL:
  case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: {
    // CALL: [cc, fnid, arg0, arg1...]
    // CALL_INDIRECT: [cc, fn, returnty, args...]
    //
    // Note: The difference between CALL and CALL_INDIRECT is that CALL has a
    // reference to an explicit function declaration, while the CALL_INDIRECT
    // is just an address. For CALL, we can infer the return type by looking up
    // the type signature associated with the function declaration. For
    // CALL_INDIRECT we can only infer the type signature via argument types,
    // and the corresponding return type stored in CALL_INDIRECT record.
    Ice::SizeT ParamsStartIndex = 2;
    if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) {
      if (!isValidRecordSizeAtLeast(2, "call"))
        return;
    } else {
      if (!isValidRecordSizeAtLeast(3, "call indirect"))
        return;
      ParamsStartIndex = 3;
    }

    uint32_t CalleeIndex = convertRelativeToAbsIndex(Values[1], BaseIndex);
    Ice::Operand *Callee = getOperand(CalleeIndex);

    // Pull out signature/return type of call (if possible).
    Ice::FunctionDeclaration *Fcn = nullptr;
    const Ice::FuncSigType *Signature = nullptr;
    Ice::Type ReturnType = Ice::IceType_void;
    const Ice::Intrinsics::FullIntrinsicInfo *IntrinsicInfo = nullptr;
    if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) {
      Fcn = Context->getFunctionByID(CalleeIndex);
      Signature = &Fcn->getSignature();
      ReturnType = Signature->getReturnType();
      Ice::SizeT NumParams = Values.size() - ParamsStartIndex;
      if (NumParams != Signature->getNumArgs()) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Call to " << printName(Fcn) << " has " << NumParams
               << " parameters. Signature expects: " << Signature->getNumArgs();
        Error(StrBuf.str());
        if (ReturnType != Ice::IceType_void)
          setNextLocalInstIndex(nullptr);
        return;
      }

      // Check if this direct call is to an Intrinsic (starts with "llvm.")
      IntrinsicInfo = Fcn->getIntrinsicInfo(getTranslator().getContext());
      if (IntrinsicInfo && IntrinsicInfo->getNumArgs() != NumParams) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Call to " << printName(Fcn) << " has " << NumParams
               << " parameters. Intrinsic expects: " << Signature->getNumArgs();
        Error(StrBuf.str());
        if (ReturnType != Ice::IceType_void)
          setNextLocalInstIndex(nullptr);
        return;
      }
    } else { // Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL_INDIRECT
      // There is no signature. Assume defined by parameter types.
      ReturnType = Context->getSimpleTypeByID(Values[2]);
      if (Callee != nullptr)
        isValidPointerType(Callee, "Call indirect");
    }

    if (Callee == nullptr)
      return;

    // Extract out the the call parameters.
    SmallVector<Ice::Operand *, 8> Params;
    for (Ice::SizeT Index = ParamsStartIndex; Index < Values.size(); ++Index) {
      Ice::Operand *Op = getRelativeOperand(Values[Index], BaseIndex);
      if (Op == nullptr) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Parameter " << (Index - ParamsStartIndex + 1) << " of "
               << printName(Fcn) << " is not defined";
        Error(StrBuf.str());
        if (ReturnType != Ice::IceType_void)
          setNextLocalInstIndex(nullptr);
        return;
      }
      Params.push_back(Op);
    }

    // Check return type.
    if (IntrinsicInfo == nullptr && !isCallReturnType(ReturnType)) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Return type of " << printName(Fcn)
             << " is invalid: " << ReturnType;
      Error(StrBuf.str());
      ReturnType = Ice::IceType_i32;
    }

    // Type check call parameters.
    for (Ice::SizeT Index = 0; Index < Params.size(); ++Index) {
      Ice::Operand *Op = Params[Index];
      Ice::Type OpType = Op->getType();
      if (Signature)
        verifyCallArgTypeMatches(Fcn, Index, OpType,
                                 Signature->getArgType(Index));
      else if (!isCallParameterType(OpType)) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Argument " << *Op << " of " << printName(Fcn)
               << " has invalid type: " << Op->getType();
        Error(StrBuf.str());
        appendErrorInstruction(ReturnType);
        return;
      }
    }

    // Extract call information.
    uint64_t CCInfo = Values[0];
    CallingConv::ID CallingConv;
    if (!naclbitc::DecodeCallingConv(CCInfo >> 1, CallingConv)) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Function call calling convention value " << (CCInfo >> 1)
             << " not understood.";
      Error(StrBuf.str());
      appendErrorInstruction(ReturnType);
      return;
    }
    const bool IsTailCall = (CCInfo & 1);

    // Create the call instruction.
    Ice::Variable *Dest = (ReturnType == Ice::IceType_void)
                              ? nullptr
                              : getNextInstVar(ReturnType);
    std::unique_ptr<Ice::InstCall> Instr;
    if (IntrinsicInfo) {
      Instr.reset(Ice::InstIntrinsicCall::create(
          Func.get(), Params.size(), Dest, Callee, IntrinsicInfo->Info));
    } else {
      Instr.reset(Ice::InstCall::create(Func.get(), Params.size(), Dest, Callee,
                                        IsTailCall));
    }
    for (Ice::Operand *Param : Params)
      Instr->addArg(Param);
    CurrentNode->appendInst(Instr.release());
    return;
  }
  case naclbitc::FUNC_CODE_INST_FORWARDTYPEREF: {
    // FORWARDTYPEREF: [opval, ty]
    if (!isValidRecordSize(2, "forward type ref"))
      return;
    Ice::Type OpType = Context->getSimpleTypeByID(Values[1]);
    setOperand(Values[0], createInstVar(OpType));
    return;
  }
  default:
    // Generate error message!
    BlockParserBaseClass::ProcessRecord();
    return;
  }
}

/// Parses constants within a function block.
class ConstantsParser : public BlockParserBaseClass {
  ConstantsParser() = delete;
  ConstantsParser(const ConstantsParser &) = delete;
  ConstantsParser &operator=(const ConstantsParser &) = delete;

public:
  ConstantsParser(unsigned BlockID, FunctionParser *FuncParser)
      : BlockParserBaseClass(BlockID, FuncParser),
        Timer(Ice::TimerStack::TT_parseConstants, getTranslator().getContext()),
        FuncParser(FuncParser) {}

  ~ConstantsParser() override = default;

  const char *getBlockName() const override { return "constants"; }

private:
  Ice::TimerMarker Timer;
  // The parser of the function block this constants block appears in.
  FunctionParser *FuncParser;
  // The type to use for succeeding constants.
  Ice::Type NextConstantType = Ice::IceType_void;

  void ProcessRecord() override;

  Ice::GlobalContext *getContext() { return getTranslator().getContext(); }

  // Returns true if the type to use for succeeding constants is defined. If
  // false, also generates an error message.
  bool isValidNextConstantType() {
    if (NextConstantType != Ice::IceType_void)
      return true;
    Error("Constant record not preceded by set type record");
    return false;
  }
};

void ConstantsParser::ProcessRecord() {
  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
  switch (Record.GetCode()) {
  case naclbitc::CST_CODE_SETTYPE: {
    // SETTYPE: [typeid]
    if (!isValidRecordSize(1, "set type"))
      return;
    NextConstantType = Context->getSimpleTypeByID(Values[0]);
    if (NextConstantType == Ice::IceType_void)
      Error("constants block set type not allowed for void type");
    return;
  }
  case naclbitc::CST_CODE_UNDEF: {
    // UNDEF
    if (!isValidRecordSize(0, "undef"))
      return;
    if (!isValidNextConstantType())
      return;
    FuncParser->setNextConstantID(
        getContext()->getConstantUndef(NextConstantType));
    return;
  }
  case naclbitc::CST_CODE_INTEGER: {
    // INTEGER: [intval]
    if (!isValidRecordSize(1, "integer"))
      return;
    if (!isValidNextConstantType())
      return;
    if (Ice::isScalarIntegerType(NextConstantType)) {
      BitcodeInt Value(Ice::getScalarIntBitWidth(NextConstantType),
                       NaClDecodeSignRotatedValue(Values[0]));
      if (Ice::Constant *C = getContext()->getConstantInt(
              NextConstantType, Value.getSExtValue())) {
        FuncParser->setNextConstantID(C);
        return;
      }
    }
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << "constant block integer record for non-integer type "
           << NextConstantType;
    Error(StrBuf.str());
    return;
  }
  case naclbitc::CST_CODE_FLOAT: {
    // FLOAT: [fpval]
    if (!isValidRecordSize(1, "float"))
      return;
    if (!isValidNextConstantType())
      return;
    switch (NextConstantType) {
    case Ice::IceType_f32: {
      const BitcodeInt Value(32, static_cast<uint32_t>(Values[0]));
      float FpValue = Value.convertToFp<int32_t, float>();
      FuncParser->setNextConstantID(getContext()->getConstantFloat(FpValue));
      return;
    }
    case Ice::IceType_f64: {
      const BitcodeInt Value(64, Values[0]);
      double FpValue = Value.convertToFp<uint64_t, double>();
      FuncParser->setNextConstantID(getContext()->getConstantDouble(FpValue));
      return;
    }
    default: {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "constant block float record for non-floating type "
             << NextConstantType;
      Error(StrBuf.str());
      return;
    }
    }
  }
  default:
    // Generate error message!
    BlockParserBaseClass::ProcessRecord();
    return;
  }
}

// Parses valuesymtab blocks appearing in a function block.
class FunctionValuesymtabParser : public ValuesymtabParser {
  FunctionValuesymtabParser() = delete;
  FunctionValuesymtabParser(const FunctionValuesymtabParser &) = delete;
  void operator=(const FunctionValuesymtabParser &) = delete;

public:
  FunctionValuesymtabParser(unsigned BlockID, FunctionParser *EnclosingParser)
      : ValuesymtabParser(BlockID, EnclosingParser),
        Timer(Ice::TimerStack::TT_parseFunctionValuesymtabs,
              getTranslator().getContext()) {}

private:
  Ice::TimerMarker Timer;
  // Returns the enclosing function parser.
  FunctionParser *getFunctionParser() const {
    return reinterpret_cast<FunctionParser *>(GetEnclosingParser());
  }

  const char *getTableKind() const final { return "Function"; }

  void setValueName(NaClBcIndexSize_t Index, StringType &Name) final;
  void setBbName(NaClBcIndexSize_t Index, StringType &Name) final;

  // Reports that the assignment of Name to the value associated with index is
  // not possible, for the given Context.
  void reportUnableToAssign(const char *Context, NaClBcIndexSize_t Index,
                            StringType &Name) {
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << "Function-local " << Context << " name '" << Name
           << "' can't be associated with index " << Index;
    Error(StrBuf.str());
  }
};

void FunctionValuesymtabParser::setValueName(NaClBcIndexSize_t Index,
                                             StringType &Name) {
  // Note: We check when Index is too small, so that we can error recover
  // (FP->getOperand will create fatal error).
  if (Index < getFunctionParser()->getNumGlobalIDs()) {
    reportUnableToAssign("Global value", Index, Name);
    return;
  }
  Ice::Operand *Op = getFunctionParser()->getOperand(Index);
  if (auto *V = dyn_cast<Ice::Variable>(Op)) {
    if (Ice::BuildDefs::dump()) {
      std::string Nm(Name.data(), Name.size());
      V->setName(getFunctionParser()->getFunc(), Nm);
    }
  } else {
    reportUnableToAssign("Local value", Index, Name);
  }
}

void FunctionValuesymtabParser::setBbName(NaClBcIndexSize_t Index,
                                          StringType &Name) {
  if (!Ice::BuildDefs::dump())
    return;
  if (Index >= getFunctionParser()->getFunc()->getNumNodes()) {
    reportUnableToAssign("Basic block", Index, Name);
    return;
  }
  std::string Nm(Name.data(), Name.size());
  if (Ice::BuildDefs::dump())
    getFunctionParser()->getFunc()->getNodes()[Index]->setName(Nm);
}

bool FunctionParser::ParseBlock(unsigned BlockID) {
  switch (BlockID) {
  case naclbitc::CONSTANTS_BLOCK_ID: {
    ConstantsParser Parser(BlockID, this);
    return Parser.ParseThisBlock();
  }
  case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
    if (PNaClAllowLocalSymbolTables) {
      FunctionValuesymtabParser Parser(BlockID, this);
      return Parser.ParseThisBlock();
    }
    break;
  }
  default:
    break;
  }
  return BlockParserBaseClass::ParseBlock(BlockID);
}

/// Parses the module block in the bitcode file.
class ModuleParser : public BlockParserBaseClass {
  ModuleParser() = delete;
  ModuleParser(const ModuleParser &) = delete;
  ModuleParser &operator=(const ModuleParser &) = delete;

public:
  ModuleParser(unsigned BlockID, TopLevelParser *Context)
      : BlockParserBaseClass(BlockID, Context),
        Timer(Ice::TimerStack::TT_parseModule,
              Context->getTranslator().getContext()) {}

  ~ModuleParser() override = default;

  const char *getBlockName() const override { return "module"; }

private:
  Ice::TimerMarker Timer;
  // True if we have already installed names for unnamed global declarations,
  // and have generated global constant initializers.
  bool GlobalDeclarationNamesAndInitializersInstalled = false;
  // True if we have already processed the symbol table for the module.
  bool FoundValuesymtab = false;

  // Generates names for unnamed global addresses (i.e. functions and global
  // variables). Then lowers global variable declaration initializers to the
  // target. May be called multiple times. Only the first call will do the
  // installation.
  void installGlobalNamesAndGlobalVarInitializers() {
    if (!GlobalDeclarationNamesAndInitializersInstalled) {
      Context->installGlobalNames();
      Context->createValueIDs();
      Context->verifyFunctionTypeSignatures();
      std::unique_ptr<Ice::VariableDeclarationList> Globals =
          Context->getGlobalVariables();
      if (Globals)
        getTranslator().lowerGlobals(std::move(Globals));
      GlobalDeclarationNamesAndInitializersInstalled = true;
    }
  }
  bool ParseBlock(unsigned BlockID) override;

  void ExitBlock() override { installGlobalNamesAndGlobalVarInitializers(); }

  void ProcessRecord() override;
};

class ModuleValuesymtabParser : public ValuesymtabParser {
  ModuleValuesymtabParser() = delete;
  ModuleValuesymtabParser(const ModuleValuesymtabParser &) = delete;
  void operator=(const ModuleValuesymtabParser &) = delete;

public:
  ModuleValuesymtabParser(unsigned BlockID, ModuleParser *MP)
      : ValuesymtabParser(BlockID, MP),
        Timer(Ice::TimerStack::TT_parseModuleValuesymtabs,
              getTranslator().getContext()) {}

  ~ModuleValuesymtabParser() override = default;

private:
  Ice::TimerMarker Timer;
  const char *getTableKind() const final { return "Module"; }
  void setValueName(NaClBcIndexSize_t Index, StringType &Name) final;
  void setBbName(NaClBcIndexSize_t Index, StringType &Name) final;
};

void ModuleValuesymtabParser::setValueName(NaClBcIndexSize_t Index,
                                           StringType &Name) {
  Context->getGlobalDeclarationByID(Index)
      ->setName(StringRef(Name.data(), Name.size()));
}

void ModuleValuesymtabParser::setBbName(NaClBcIndexSize_t Index,
                                        StringType &Name) {
  reportUnableToAssign("Basic block", Index, Name);
}

bool ModuleParser::ParseBlock(unsigned BlockID) {
  switch (BlockID) {
  case naclbitc::BLOCKINFO_BLOCK_ID:
    return NaClBitcodeParser::ParseBlock(BlockID);
  case naclbitc::TYPE_BLOCK_ID_NEW: {
    TypesParser Parser(BlockID, this);
    return Parser.ParseThisBlock();
  }
  case naclbitc::GLOBALVAR_BLOCK_ID: {
    GlobalsParser Parser(BlockID, this);
    return Parser.ParseThisBlock();
  }
  case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
    if (FoundValuesymtab)
      Fatal("Duplicate valuesymtab in module");

    // If we have already processed a function block (i.e. we have already
    // installed global names and variable initializers) we can no longer accept
    // the value symbol table. Names have already been generated.
    if (GlobalDeclarationNamesAndInitializersInstalled)
      Fatal("Module valuesymtab not allowed after function blocks");

    FoundValuesymtab = true;
    ModuleValuesymtabParser Parser(BlockID, this);
    return Parser.ParseThisBlock();
  }
  case naclbitc::FUNCTION_BLOCK_ID: {
    installGlobalNamesAndGlobalVarInitializers();
    FunctionParser Parser(BlockID, this);
    return Parser.convertFunction();
  }
  default:
    return BlockParserBaseClass::ParseBlock(BlockID);
  }
}

void ModuleParser::ProcessRecord() {
  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
  switch (Record.GetCode()) {
  case naclbitc::MODULE_CODE_VERSION: {
    // VERSION: [version#]
    if (!isValidRecordSize(1, "version"))
      return;
    uint64_t Version = Values[0];
    if (Version != 1) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Unknown bitstream version: " << Version;
      Error(StrBuf.str());
    }
    return;
  }
  case naclbitc::MODULE_CODE_FUNCTION: {
    // FUNCTION:  [type, callingconv, isproto, linkage]
    if (!isValidRecordSize(4, "address"))
      return;
    const Ice::FuncSigType &Signature = Context->getFuncSigTypeByID(Values[0]);
    CallingConv::ID CallingConv;
    if (!naclbitc::DecodeCallingConv(Values[1], CallingConv)) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Function address has unknown calling convention: "
             << Values[1];
      Error(StrBuf.str());
      return;
    }
    GlobalValue::LinkageTypes Linkage;
    if (!naclbitc::DecodeLinkage(Values[3], Linkage)) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Function address has unknown linkage. Found " << Values[3];
      Error(StrBuf.str());
      return;
    }
    bool IsProto = Values[2] == 1;
    auto *Func = Ice::FunctionDeclaration::create(
        Context->getTranslator().getContext(), Signature, CallingConv, Linkage,
        IsProto);
    Context->setNextFunctionID(Func);
    return;
  }
  default:
    BlockParserBaseClass::ProcessRecord();
    return;
  }
}

bool TopLevelParser::ParseBlock(unsigned BlockID) {
  if (BlockID == naclbitc::MODULE_BLOCK_ID) {
    if (ParsedModuleBlock)
      Fatal("Input can't contain more than one module");
    ModuleParser Parser(BlockID, this);
    bool ParseFailed = Parser.ParseThisBlock();
    ParsedModuleBlock = true;
    return ParseFailed;
  }
  // Generate error message by using default block implementation.
  BlockParserBaseClass Parser(BlockID, this);
  return Parser.ParseThisBlock();
}

} // end of anonymous namespace

namespace Ice {

void PNaClTranslator::translateBuffer(const std::string &IRFilename,
                                      MemoryBuffer *MemBuf) {
  std::unique_ptr<MemoryObject> MemObj(getNonStreamedMemoryObject(
      reinterpret_cast<const unsigned char *>(MemBuf->getBufferStart()),
      reinterpret_cast<const unsigned char *>(MemBuf->getBufferEnd())));
  translate(IRFilename, std::move(MemObj));
}

void PNaClTranslator::translate(const std::string &IRFilename,
                                std::unique_ptr<MemoryObject> &&MemObj) {
  // On error, we report_fatal_error to avoid destroying the MemObj. That may
  // still be in use by IceBrowserCompileServer. Otherwise, we need to change
  // the MemObj to be ref-counted, or have a wrapper, or simply leak. We also
  // need a hook to tell the IceBrowserCompileServer to unblock its
  // QueueStreamer.
  // https://code.google.com/p/nativeclient/issues/detail?id=4163
  // Read header and verify it is good.
  NaClBitcodeHeader Header;
  if (Header.Read(MemObj.get())) {
    llvm::report_fatal_error("Invalid PNaCl bitcode header");
  }
  if (!Header.IsSupported()) {
    getContext()->getStrError() << Header.Unsupported();
    if (!Header.IsReadable()) {
      llvm::report_fatal_error("Invalid PNaCl bitcode header");
    }
  }

  // Create a bitstream reader to read the bitcode file.
  NaClBitstreamReader InputStreamFile(MemObj.release(), Header);
  NaClBitstreamCursor InputStream(InputStreamFile);

  TopLevelParser Parser(*this, InputStream, ErrorStatus);
  while (!InputStream.AtEndOfStream()) {
    if (Parser.Parse()) {
      ErrorStatus.assign(EC_Bitcode);
      return;
    }
  }

  if (!Parser.parsedModuleBlock()) {
    std::string Buffer;
    raw_string_ostream StrBuf(Buffer);
    StrBuf << IRFilename << ": Does not contain a module!";
    llvm::report_fatal_error(StrBuf.str());
  }
  if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) {
    llvm::report_fatal_error("Bitcode stream should be a multiple of 4 bytes");
  }
}

} // end of namespace Ice
