//===- 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
/// This file implements the PNaCl bitcode file to Ice, to machine code
/// translator.
///
//===----------------------------------------------------------------------===//

#include "PNaClTranslator.h"

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

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#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"
#include <unordered_set>
#pragma clang diagnostic pop

// 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;
  }
}

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 true if generation of Subzero IR is disabled.
  bool isIRGenerationDisabled() const {
    return Translator.getFlags().getDisableIRGeneration();
  }

  /// 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 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, suppressing name mangling if
  // SuppressMangling. IsExternal is true iff the symbol is external.
  Ice::Constant *getConstantSym(const Ice::IceString &Name,
                                bool SuppressMangling, bool IsExternal) const {
    if (IsExternal) {
      return getTranslator().getContext()->getConstantExternSym(Name);
    } else {
      const Ice::RelocOffsetT Offset = 0;
      return getTranslator().getContext()->getConstantSym(Offset, Name,
                                                          SuppressMangling);
    }
  }

  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 = nullptr;
      if (!isIRGenerationDisabled()) {
        C = getConstantSym(Func->getName(), Func->getSuppressMangling(),
                           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 = nullptr;
      if (!isIRGenerationDisabled()) {
        C = getConstantSym(Decl->getName(), Decl->getSuppressMangling(),
                           !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;
}

// 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(); }

  bool isIRGenerationDisabled() const {
    return getTranslator().getFlags().getDisableIRGeneration();
  }

  // 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();
    FuncSigExtendedType *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);
    if (!isIRGenerationDisabled()) {
      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;
    }
    if (isIRGenerationDisabled())
      return;
    InitializersNeeded = Values[0];
    return;
  case naclbitc::GLOBALVAR_ZEROFILL: {
    // ZEROFILL: [size]
    if (!isValidRecordSize(1, "zerofill"))
      return;
    if (isIRGenerationDisabled())
      return;
    CurGlobalVar->addInitializer(
        Ice::VariableDeclaration::ZeroInitializer::create(Values[0]));
    return;
  }
  case naclbitc::GLOBALVAR_DATA: {
    // DATA: [b0, b1, ...]
    if (!isValidRecordSizeAtLeast(1, "data"))
      return;
    if (isIRGenerationDisabled())
      return;
    CurGlobalVar->addInitializer(
        Ice::VariableDeclaration::DataInitializer::create(Values));
    return;
  }
  case naclbitc::GLOBALVAR_RELOC: {
    // RELOC: [val, [addend]]
    if (!isValidRecordSizeInRange(1, 2, "reloc"))
      return;
    if (isIRGenerationDisabled())
      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());
      }
    }
    CurGlobalVar->addInitializer(
        Ice::VariableDeclaration::RelocInitializer::create(
            getGlobalDeclByID(Index), 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());
    Ice::Cfg::setCurrentCfg(Func.get());

    // TODO(kschimpf) Clean up API to add a function signature to a CFG.
    const Ice::FuncSigType &Signature = FuncDecl->getSignature();
    if (isIRGenerationDisabled()) {
      CurrentNode = nullptr;
      for (Ice::Type ArgType : Signature.getArgList()) {
        (void)ArgType;
        setNextLocalInstIndex(nullptr);
      }
    } else {
      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));
      }
    }
    bool 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);

    Ice::Cfg::setCurrentCfg(nullptr);
    // 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);
    }
    if (isIRGenerationDisabled())
      return nullptr;
    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() {
    assert(!isIRGenerationDisabled());
    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) {
    assert(!isIRGenerationDisabled());
    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) {
    assert(!isIRGenerationDisabled());
    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) {
    assert(!isIRGenerationDisabled());
    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(!isIRGenerationDisabled());
    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 (Ice::Variable *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 || isIRGenerationDisabled());
    // 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");
    if (isIRGenerationDisabled())
      return;
    // 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());
  }
  if (isIRGenerationDisabled())
    return;
  // 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;
    if (!isIRGenerationDisabled())
      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;
    if (isIRGenerationDisabled())
      return;
    // 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);
    if (isIRGenerationDisabled()) {
      assert(Op1 == nullptr && Op2 == nullptr);
      setNextLocalInstIndex(nullptr);
      return;
    }
    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 (isIRGenerationDisabled()) {
      assert(Src == nullptr);
      setNextLocalInstIndex(nullptr);
      return;
    }
    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);
    if (isIRGenerationDisabled()) {
      assert(ThenVal == nullptr && ElseVal == nullptr && CondVal == nullptr);
      setNextLocalInstIndex(nullptr);
      return;
    }
    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);
    if (isIRGenerationDisabled()) {
      assert(Vec == nullptr && Index == nullptr);
      setNextLocalInstIndex(nullptr);
      return;
    }
    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);
    if (isIRGenerationDisabled()) {
      assert(Vec == nullptr && Elt == nullptr && Index == nullptr);
      setNextLocalInstIndex(nullptr);
      return;
    }
    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);
    if (isIRGenerationDisabled()) {
      assert(Op1 == nullptr && Op2 == nullptr);
      setNextLocalInstIndex(nullptr);
      return;
    }
    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()) {
      if (isIRGenerationDisabled())
        return;
      CurrentNode->appendInst(Ice::InstRet::create(Func.get()));
    } else {
      Ice::Operand *RetVal = getRelativeOperand(Values[0], BaseIndex);
      if (isIRGenerationDisabled()) {
        assert(RetVal == nullptr);
        return;
      }
      CurrentNode->appendInst(Ice::InstRet::create(Func.get(), RetVal));
    }
    return;
  }
  case naclbitc::FUNC_CODE_INST_BR: {
    InstIsTerminating = true;
    if (Values.size() == 1) {
      // BR: [bb#]
      if (isIRGenerationDisabled())
        return;
      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 (isIRGenerationDisabled()) {
        assert(Cond == nullptr);
        return;
      }
      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);

    const bool isIRGenDisabled = isIRGenerationDisabled();
    if (isIRGenDisabled) {
      assert(Cond == nullptr);
    } else 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 =
        isIRGenDisabled ? nullptr : 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(
        isIRGenDisabled ? nullptr
                        : 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;
      }
      Ice::APInt Value(BitWidth,
                       NaClDecodeSignRotatedValue(Values[ValCaseIndex + 2]));
      if (isIRGenDisabled)
        continue;
      Ice::CfgNode *Label = getBranchBasicBlock(Values[ValCaseIndex + 3]);
      if (Label == nullptr)
        return;
      Switch->addBranch(CaseIndex, Value.getSExtValue(), Label);
    }
    if (isIRGenDisabled)
      return;
    CurrentNode->appendInst(Switch.release());
    return;
  }
  case naclbitc::FUNC_CODE_INST_UNREACHABLE: {
    // UNREACHABLE: []
    InstIsTerminating = true;
    if (!isValidRecordSize(0, "unreachable"))
      return;
    if (isIRGenerationDisabled())
      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;
    }
    if (isIRGenerationDisabled()) {
      // Verify arguments are defined before quitting.
      for (unsigned i = 1; i < Values.size(); i += 2) {
        assert(getRelativeOperand(NaClDecodeSignRotatedValue(Values[i]),
                                  BaseIndex) == nullptr);
      }
      setNextLocalInstIndex(nullptr);
      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]);
    if (isIRGenerationDisabled()) {
      assert(ByteCount == nullptr);
      setNextLocalInstIndex(nullptr);
      return;
    }
    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(), ByteCount, Alignment, getNextInstVar(PtrTy)));
    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 (isIRGenerationDisabled()) {
      assert(Address == nullptr);
      setNextLocalInstIndex(nullptr);
      return;
    }
    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 (isIRGenerationDisabled()) {
      assert(Address == nullptr && Value == nullptr);
      return;
    }
    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.")
      bool BadIntrinsic;
      IntrinsicInfo = getTranslator().getContext()->getIntrinsicsInfo().find(
          Fcn->getName(), BadIntrinsic);
      if (BadIntrinsic) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Invalid PNaCl intrinsic call to " << Fcn->getName();
        Error(StrBuf.str());
        IntrinsicInfo = nullptr;
      }
      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 (!isIRGenerationDisabled() && Callee != nullptr)
        isValidPointerType(Callee, "Call indirect");
    }

    if (Callee == nullptr && !isIRGenerationDisabled())
      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 (isIRGenerationDisabled())
        continue;
      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;
    }

    if (isIRGenerationDisabled()) {
      if (ReturnType != Ice::IceType_void)
        setNextLocalInstIndex(nullptr);
      return;
    }

    // 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));
      if (IntrinsicInfo) {
        verifyCallArgTypeMatches(Fcn, Index, OpType,
                                 IntrinsicInfo->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);
      }
    }

    // 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;
    }
    bool IsTailCall = static_cast<bool>(CCInfo & 1);

    // Create the call instruction.
    Ice::Variable *Dest = (ReturnType == Ice::IceType_void)
                              ? nullptr
                              : getNextInstVar(ReturnType);
    std::unique_ptr<Ice::InstCall> Inst;
    if (IntrinsicInfo) {
      Inst.reset(Ice::InstIntrinsicCall::create(Func.get(), Params.size(), Dest,
                                                Callee, IntrinsicInfo->Info));
    } else {
      Inst.reset(Ice::InstCall::create(Func.get(), Params.size(), Dest, Callee,
                                       IsTailCall));
    }
    for (Ice::Operand *Param : Params)
      Inst->addArg(Param);
    CurrentNode->appendInst(Inst.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],
               isIRGenerationDisabled() ? nullptr : 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;
    if (isIRGenerationDisabled()) {
      FuncParser->setNextConstantID(nullptr);
      return;
    }
    FuncParser->setNextConstantID(
        getContext()->getConstantUndef(NextConstantType));
    return;
  }
  case naclbitc::CST_CODE_INTEGER: {
    // INTEGER: [intval]
    if (!isValidRecordSize(1, "integer"))
      return;
    if (!isValidNextConstantType())
      return;
    if (isIRGenerationDisabled()) {
      FuncParser->setNextConstantID(nullptr);
      return;
    }
    if (Ice::isScalarIntegerType(NextConstantType)) {
      Ice::APInt 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;
    if (isIRGenerationDisabled()) {
      FuncParser->setNextConstantID(nullptr);
      return;
    }
    switch (NextConstantType) {
    case Ice::IceType_f32: {
      const Ice::APInt IntValue(32, static_cast<uint32_t>(Values[0]));
      float FpValue = Ice::convertAPIntToFp<int32_t, float>(IntValue);
      FuncParser->setNextConstantID(getContext()->getConstantFloat(FpValue));
      return;
    }
    case Ice::IceType_f64: {
      const Ice::APInt IntValue(64, Values[0]);
      double FpValue = Ice::convertAPIntToFp<uint64_t, double>(IntValue);
      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;
  }
  if (isIRGenerationDisabled())
    return;
  Ice::Operand *Op = getFunctionParser()->getOperand(Index);
  if (Ice::Variable *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 (isIRGenerationDisabled())
    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();
      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;
    Ice::FunctionDeclaration *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
