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

#include "llvm/ADT/SmallString.h"
#include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.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 "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"
#include "PNaClTranslator.h"

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() : Kind(Undefined) {}
  ExtendedType(const ExtendedType &Ty) = default;

  virtual ~ExtendedType() {}

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

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

Ice::Ostream &operator<<(Ice::Ostream &Stream, ExtendedType::TypeKind Kind) {
  if (!ALLOW_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 (!ALLOW_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:
  typedef std::vector<Ice::FunctionDeclaration *> FunctionDeclarationListType;

  TopLevelParser(Ice::Translator &Translator, NaClBitstreamCursor &Cursor,
                 Ice::ErrorCode &ErrorStatus)
      : NaClBitcodeParser(Cursor), Translator(Translator),
        ErrorStatus(ErrorStatus), NumErrors(0), NextDefiningFunctionID(0),
        VariableDeclarations(new Ice::VariableDeclarationList()),
        BlockParser(nullptr), StubbedConstCallValue(nullptr) {}

  ~TopLevelParser() override {}

  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(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(unsigned NewSize) { TypeIDValues.resize(NewSize); }

  /// 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(unsigned 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())
      TypeIDValues.resize(ID + 1);
    return &TypeIDValues[ID];
  }

  /// Returns the type associated with the given index.
  Ice::Type getSimpleTypeByID(unsigned 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(unsigned 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) {
    FunctionDeclarationList.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.
  size_t getNextFunctionBlockValueID() {
    size_t NumDeclaredFunctions = FunctionDeclarationList.size();
    while (NextDefiningFunctionID < NumDeclaredFunctions &&
           FunctionDeclarationList[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(unsigned ID) {
    if (ID < FunctionDeclarationList.size())
      return FunctionDeclarationList[ID];
    return reportGetFunctionByIDError(ID);
  }

  /// Returns the constant associated with the given global value ID.
  Ice::Constant *getGlobalConstantByID(unsigned 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() +
                             FunctionDeclarationList.size());
    createValueIDsForFunctions();
    createValueIDsForGlobalVars();
  }

  /// Returns a defined function reference to be used in place of
  /// called constant addresses. Returns the corresponding operand
  /// to replace the calling address with. Reports an error if
  /// a stub could not be found, returning the CallValue.
  Ice::Operand *getStubbedConstCallValue(Ice::Operand *CallValue) {
    if (StubbedConstCallValue)
      return StubbedConstCallValue;
    for (unsigned i = 0; i < getNumFunctionIDs(); ++i) {
      Ice::FunctionDeclaration *Func = getFunctionByID(i);
      if (!Func->isProto()) {
        StubbedConstCallValue = getGlobalConstantByID(i);
        return StubbedConstCallValue;
      }
    }
    Error("Unable to find function definition to stub constant calls with");
    return CallValue;
  }

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

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

  /// Creates Count global variable declarations.
  void CreateGlobalVariables(size_t Count) {
    assert(VariableDeclarations);
    assert(VariableDeclarations->empty());
    for (size_t i = 0; i < Count; ++i) {
      VariableDeclarations->push_back(Ice::VariableDeclaration::create());
    }
  }

  /// Returns the number of global variable declarations in the
  /// bitcode file.
  Ice::SizeT getNumGlobalVariables() const {
    if (VariableDeclarations) {
      return VariableDeclarations->size();
    } else {
      return ValueIDConstants.size() - FunctionDeclarationList.size();
    }
  }

  /// Returns the global variable declaration with the given index.
  Ice::VariableDeclaration *getGlobalVariableByID(unsigned 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(size_t Index) {
    size_t NumFunctionIds = FunctionDeclarationList.size();
    if (Index < NumFunctionIds)
      return getFunctionByID(Index);
    else
      return getGlobalVariableByID(Index - NumFunctionIds);
  }

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

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;
  // The types associated with each type ID.
  std::vector<ExtendedType> TypeIDValues;
  // The set of functions (prototype and defined).
  FunctionDeclarationListType FunctionDeclarationList;
  // The ID of the next possible defined function ID in
  // FunctionDeclarationList.  FunctionDeclarationList 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;
  // The set of global variables.
  std::unique_ptr<Ice::VariableDeclarationList> VariableDeclarations;
  // Relocatable constants associated with global declarations.
  std::vector<Ice::Constant *> ValueIDConstants;
  // Error recovery value to use when getFuncSigTypeByID fails.
  Ice::FuncSigType UndefinedFuncSigType;
  // The block parser currently being applied. Used for error
  // reporting.
  BlockParserBaseClass *BlockParser;
  // Value to use to stub constant calls.
  Ice::Operand *StubbedConstCallValue;

  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(unsigned 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, uint32_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()) {
      uint32_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()) {
      uint32_t NameIndex = 0;
      for (Ice::FunctionDeclaration *Func : FunctionDeclarationList) {
        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);
    }
  }

  // Converts function declarations into constant value IDs.
  void createValueIDsForFunctions() {
    for (const Ice::FunctionDeclaration *Func : FunctionDeclarationList) {
      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() {
    for (const Ice::VariableDeclaration *Decl : *VariableDeclarations) {
      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(unsigned 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(unsigned ID);

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

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

bool TopLevelParser::ErrorAt(uint64_t Bit, const std::string &Message) {
  ErrorStatus.assign(Ice::EC_Bitcode);
  ++NumErrors;
  Ice::GlobalContext *Context = Translator.getContext();
  Ice::OstreamLocker L(Context);
  raw_ostream &OldErrStream = setErrStream(Context->getStrDump());
  NaClBitcodeParser::ErrorAt(Bit, Message);
  setErrStream(OldErrStream);
  if (!Translator.getFlags().getAllowErrorRecovery())
    Fatal();
  return true;
}

void TopLevelParser::reportBadTypeIDAs(unsigned 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(unsigned ID) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << "Function index " << ID
         << " not allowed. Out of range. Must be less than "
         << FunctionDeclarationList.size();
  BlockError(StrBuf.str());
  // TODO(kschimpf) Remove error recovery once implementation complete.
  if (!FunctionDeclarationList.empty())
    return FunctionDeclarationList[0];
  Fatal();
}

Ice::VariableDeclaration *
TopLevelParser::reportGetGlobalVariableByIDError(unsigned 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());
  // TODO(kschimpf) Remove error recovery once implementation complete.
  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(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(unsigned 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(unsigned 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(unsigned 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(unsigned LowerLimit, unsigned 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(unsigned 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(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(Bit, StrBuf.str());
}

void BlockParserBaseClass::ReportRecordSizeError(unsigned 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());
  // TODO(kschimpf) Remove error recovery once implementation complete.
  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()),
        NextTypeId(0) {}

  ~TypesParser() override {}

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

  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;
    Context->resizeTypeIDValues(Values[0]);
    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 (unsigned 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;
        // TODO(kschimpf) Remove error recovery once implementation complete.
        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()),
        InitializersNeeded(0), NextGlobalID(0),
        DummyGlobalVar(Ice::VariableDeclaration::create()),
        CurGlobalVar(DummyGlobalVar) {}

  ~GlobalsParser() final {}

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

private:
  Ice::TimerMarker Timer;
  // Keeps track of how many initializers are expected for the global variable
  // declaration being built.
  unsigned InitializersNeeded;

  // The index of the next global variable declaration.
  unsigned NextGlobalID;

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

  void ExitBlock() override {
    verifyNoMissingInitializers();
    unsigned NumIDs = Context->getNumGlobalVariables();
    if (NextGlobalID < NumIDs) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << getBlockName() << " block expects " << NumIDs
             << " global variable declarations. Found: " << NextGlobalID;
      Error(StrBuf.str());
    }
    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 (NextGlobalID != Context->getNumGlobalVariables()) {
      Error("Globals count record not first in block.");
      return;
    }
    Context->CreateGlobalVariables(Values[0]);
    return;
  case naclbitc::GLOBALVAR_VAR: {
    // VAR: [align, isconst]
    if (!isValidRecordSize(2, "variable"))
      return;
    verifyNoMissingInitializers();
    if (!isIRGenerationDisabled()) {
      InitializersNeeded = 1;
      CurGlobalVar = Context->getGlobalVariableByID(NextGlobalID);
      CurGlobalVar->setAlignment((1 << Values[0]) >> 1);
      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(
        new Ice::VariableDeclaration::ZeroInitializer(Values[0]));
    return;
  }
  case naclbitc::GLOBALVAR_DATA: {
    // DATA: [b0, b1, ...]
    if (!isValidRecordSizeAtLeast(1, "data"))
      return;
    if (isIRGenerationDisabled())
      return;
    CurGlobalVar->addInitializer(
        new Ice::VariableDeclaration::DataInitializer(Values));
    return;
  }
  case naclbitc::GLOBALVAR_RELOC: {
    // RELOC: [val, [addend]]
    if (!isValidRecordSizeInRange(1, 2, "reloc"))
      return;
    if (isIRGenerationDisabled())
      return;
    unsigned Index = Values[0];
    Ice::SizeT Offset = 0;
    if (Values.size() == 2)
      Offset = Values[1];
    CurGlobalVar->addInitializer(new Ice::VariableDeclaration::RelocInitializer(
        Context->getGlobalDeclarationByID(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 {}

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

protected:
  typedef SmallString<128> StringType;

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

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

private:
  void ProcessRecord() override;

  void ConvertToString(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]);
    }
  }
};

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;
    ConvertToString(ConvertedName);
    setValueName(Values[0], ConvertedName);
    return;
  }
  case naclbitc::VST_CODE_BBENTRY: {
    // VST_BBENTRY: [BbId, namechar x N]
    if (!isValidRecordSizeAtLeast(2, "basic block entry"))
      return;
    ConvertToString(ConvertedName);
    setBbName(Values[0], 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), CurrentBbIndex(0),
        FcnId(Context->getNextFunctionBlockValueID()),
        FuncDecl(Context->getFunctionByID(FcnId)),
        CachedNumGlobalValueIDs(Context->getNumGlobalIDs()),
        NextLocalInstIndex(Context->getNumGlobalIDs()),
        InstIsTerminating(false) {}

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

    if (!isIRGenerationDisabled())
      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 {}

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

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

  uint32_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(uint32_t Index) {
    if (Index < CachedNumGlobalValueIDs) {
      return Context->getGlobalConstantByID(Index);
    }
    uint32_t LocalIndex = Index - CachedNumGlobalValueIDs;
    if (LocalIndex >= LocalOperands.size()) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Value index " << Index << " not defined!";
      Fatal(StrBuf.str());
    }
    Ice::Operand *Op = LocalOperands[LocalIndex];
    if (Op == nullptr) {
      if (isIRGenerationDisabled())
        return nullptr;
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Value index " << Index << " not defined!";
      Fatal(StrBuf.str());
    }
    return Op;
  }

private:
  Ice::TimerMarker Timer;
  // The corresponding ICE function defined by the function block.
  std::unique_ptr<Ice::Cfg> Func;
  // The index to the current basic block being built.
  uint32_t CurrentBbIndex;
  // The basic block being built.
  Ice::CfgNode *CurrentNode;
  // The ID for the function.
  unsigned FcnId;
  // The corresponding function declaration.
  Ice::FunctionDeclaration *FuncDecl;
  // Holds the dividing point between local and global absolute value indices.
  uint32_t CachedNumGlobalValueIDs;
  // Holds operands local to the function block, based on indices
  // defined in the bitcode file.
  std::vector<Ice::Operand *> LocalOperands;
  // Holds the index within LocalOperands corresponding to the next
  // instruction that generates a value.
  uint32_t NextLocalInstIndex;
  // True if the last processed instruction was a terminating
  // instruction.
  bool InstIsTerminating;
  // Upper limit of alignment power allowed by LLVM
  static const uint32_t AlignPowerLimit = 29;

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

  bool ParseBlock(unsigned BlockID) override;

  void ProcessRecord() override;

  void ExitBlock() override;

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

  // Returns the Index-th basic block in the list of basic blocks.
  Ice::CfgNode *getBasicBlock(uint32_t Index) {
    assert(!isIRGenerationDisabled());
    const Ice::NodeList &Nodes = Func->getNodes();
    if (Index >= Nodes.size()) {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      StrBuf << "Reference to basic block " << Index
             << " not found. Must be less than " << Nodes.size();
      Error(StrBuf.str());
      // TODO(kschimpf) Remove error recovery once implementation complete.
      Index = 0;
    }
    return Nodes[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(uint32_t Index) {
    assert(!isIRGenerationDisabled());
    if (Index == 0) {
      Error("Branch to entry block not allowed");
      // TODO(kschimpf) Remove error recovery once implementation complete.
    }
    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.
    uint32_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());
        // TODO(kschimpf) Remove error recovery once implementation complete.
        ++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.
  uint32_t convertRelativeToAbsIndex(int32_t Id, int32_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());
      // TODO(kschimpf) Remove error recovery once implementation complete.
      return 0;
    }
    return BaseIndex - Id;
  }

  // Sets element Index (in the local operands list) to Op.
  void setOperand(uint32_t Index, Ice::Operand *Op) {
    assert(Op || isIRGenerationDisabled());
    // Check if simple push works.
    uint32_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())
      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());
    // TODO(kschimpf) Remove error recovery once implementation complete.
    LocalOperands[LocalIndex] = Op;
  }

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

  // Returns the absolute index of the next value generating instruction.
  uint32_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;
    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 (!ALLOW_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());
      // TODO(kschimpf) Remove error recovery once implementation complete.
      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());
      // TODO(kschimpf) Remove error recovery once implementation complete.
      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.
  // TODO(kschimpf) Remove error recovery once implementation complete.
  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));
  }
};

void FunctionParser::ExitBlock() {
  if (isIRGenerationDisabled()) {
    return;
  }
  // Before translating, check for blocks without instructions, and
  // insert unreachable. This shouldn't happen, but be safe.
  unsigned 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());
      // TODO(kschimpf) Remove error recovery once implementation complete.
      Node->appendInst(Ice::InstUnreachable::create(Func.get()));
    }
    ++Index;
  }
  Func->computePredecessors();
}

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;
    if (!isIRGenerationDisabled())
      CurrentNode = getBasicBlock(++CurrentBbIndex);
  }
  // The base index for relative indexing.
  int32_t BaseIndex = getNextInstIndex();
  switch (Record.GetCode()) {
  case naclbitc::FUNC_CODE_DECLAREBLOCKS: {
    // DECLAREBLOCKS: [n]
    if (!isValidRecordSize(1, "count"))
      return;
    uint32_t NumBbs = Values[0];
    if (NumBbs == 0) {
      Error("Functions must contain at least one basic block.");
      // TODO(kschimpf) Remove error recovery once implementation complete.
      NumBbs = 1;
    }
    if (isIRGenerationDisabled())
      return;
    if (Func->getNodes().size() != 1) {
      Error("Duplicate function block count record");
      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;
    }
    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?]
    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));
    }
    InstIsTerminating = true;
    return;
  }
  case naclbitc::FUNC_CODE_INST_BR: {
    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));
    }
    InstIsTerminating = true;
    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
    // unnecesary 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.
    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]);
    unsigned NumCases = Values[3];

    // Now recognize each of the cases.
    if (!isValidRecordSize(4 + NumCases * 4, "switch"))
      return;
    Ice::InstSwitch *Switch =
        isIRGenDisabled
            ? nullptr
            : Ice::InstSwitch::create(Func.get(), NumCases, Cond, DefaultLabel);
    unsigned ValCaseIndex = 4; // index to beginning of case entry.
    for (unsigned 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]);
      Switch->addBranch(CaseIndex, Value.getSExtValue(), Label);
    }
    if (isIRGenDisabled)
      return;
    CurrentNode->appendInst(Switch);
    InstIsTerminating = true;
    return;
  }
  case naclbitc::FUNC_CODE_INST_UNREACHABLE: {
    // UNREACHABLE: []
    if (!isValidRecordSize(0, "unreachable"))
      return;
    if (isIRGenerationDisabled())
      return;
    CurrentNode->appendInst(Ice::InstUnreachable::create(Func.get()));
    InstIsTerminating = true;
    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 (unsigned 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;
    extractAlignment("Alloca", Values[1], Alignment);
    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;
    extractAlignment("Load", Values[1], Alignment);
    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;
    extractAlignment("Store", Values[2], Alignment);
    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;
    }

    // Extract out the called function and its return type.
    uint32_t CalleeIndex = convertRelativeToAbsIndex(Values[1], BaseIndex);
    Ice::Operand *Callee = getOperand(CalleeIndex);
    Ice::Type ReturnType = Ice::IceType_void;
    const Ice::Intrinsics::FullIntrinsicInfo *IntrinsicInfo = nullptr;
    if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) {
      Ice::FunctionDeclaration *Fcn = Context->getFunctionByID(CalleeIndex);
      const Ice::FuncSigType &Signature = Fcn->getSignature();
      ReturnType = Signature.getReturnType();

      // Check if this direct call is to an Intrinsic (starts with "llvm.")
      bool BadIntrinsic;
      const Ice::IceString &Name = Fcn->getName();
      IntrinsicInfo = getTranslator().getContext()->getIntrinsicsInfo().find(
          Name, BadIntrinsic);
      if (BadIntrinsic) {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Invalid PNaCl intrinsic call to " << Name;
        Error(StrBuf.str());
        appendErrorInstruction(ReturnType);
        return;
      }
    } else {
      if (getFlags().getStubConstantCalls() &&
          llvm::isa<Ice::ConstantInteger32>(Callee)) {
        Callee = Context->getStubbedConstCallValue(Callee);
      }
      ReturnType = Context->getSimpleTypeByID(Values[2]);
    }

    // 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);
    Ice::SizeT NumParams = Values.size() - ParamsStartIndex;

    if (isIRGenerationDisabled()) {
      assert(Callee == nullptr);
      // Check that parameters are defined.
      for (Ice::SizeT ParamIndex = 0; ParamIndex < NumParams; ++ParamIndex) {
        assert(getRelativeOperand(Values[ParamsStartIndex + ParamIndex],
                                  BaseIndex) == nullptr);
      }
      // Define value slot only if value returned.
      if (ReturnType != Ice::IceType_void)
        setNextLocalInstIndex(nullptr);
      return;
    }

    // Create the call instruction.
    Ice::Variable *Dest = (ReturnType == Ice::IceType_void)
                              ? nullptr
                              : getNextInstVar(ReturnType);
    Ice::InstCall *Inst = nullptr;
    if (IntrinsicInfo) {
      Inst = Ice::InstIntrinsicCall::create(Func.get(), NumParams, Dest, Callee,
                                            IntrinsicInfo->Info);
    } else {
      Inst = Ice::InstCall::create(Func.get(), NumParams, Dest, Callee,
                                   IsTailCall);
    }

    // Add parameters.
    for (Ice::SizeT ParamIndex = 0; ParamIndex < NumParams; ++ParamIndex) {
      Inst->addArg(
          getRelativeOperand(Values[ParamsStartIndex + ParamIndex], BaseIndex));
    }

    // If intrinsic call, validate call signature.
    if (IntrinsicInfo) {
      Ice::SizeT ArgIndex = 0;
      switch (IntrinsicInfo->validateCall(Inst, ArgIndex)) {
      case Ice::Intrinsics::IsValidCall:
        break;
      case Ice::Intrinsics::BadReturnType: {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Intrinsic call expects return type "
               << IntrinsicInfo->getReturnType()
               << ". Found: " << Inst->getReturnType();
        Error(StrBuf.str());
        // TODO(kschimpf) Remove error recovery once implementation complete.
        break;
      }
      case Ice::Intrinsics::WrongNumOfArgs: {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Intrinsic call expects " << IntrinsicInfo->getNumArgs()
               << ". Found: " << Inst->getNumArgs();
        Error(StrBuf.str());
        // TODO(kschimpf) Remove error recovery once implementation complete.
        break;
      }
      case Ice::Intrinsics::WrongCallArgType: {
        std::string Buffer;
        raw_string_ostream StrBuf(Buffer);
        StrBuf << "Intrinsic call argument " << ArgIndex << " expects type "
               << IntrinsicInfo->getArgType(ArgIndex)
               << ". Found: " << Inst->getArg(ArgIndex)->getType();
        Error(StrBuf.str());
        // TODO(kschimpf) Remove error recovery once implementation complete.
        break;
      }
      }
    }

    CurrentNode->appendInst(Inst);
    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), NextConstantType(Ice::IceType_void) {}

  ~ConstantsParser() override {}

  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;

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

  void setValueName(uint64_t Index, StringType &Name) override;
  void setBbName(uint64_t Index, StringType &Name) override;

  // Reports that the assignment of Name to the value associated with
  // index is not possible, for the given Context.
  void reportUnableToAssign(const char *Context, uint64_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(uint64_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("instruction", Index, Name);
    // TODO(kschimpf) Remove error recovery once implementation complete.
    return;
  }
  if (isIRGenerationDisabled())
    return;
  Ice::Operand *Op = getFunctionParser()->getOperand(Index);
  if (Ice::Variable *V = dyn_cast<Ice::Variable>(Op)) {
    if (ALLOW_DUMP) {
      std::string Nm(Name.data(), Name.size());
      V->setName(getFunctionParser()->getFunc(), Nm);
    }
  } else {
    reportUnableToAssign("variable", Index, Name);
  }
}

void FunctionValuesymtabParser::setBbName(uint64_t Index, StringType &Name) {
  if (isIRGenerationDisabled())
    return;
  if (Index >= getFunctionParser()->getFunc()->getNumNodes()) {
    reportUnableToAssign("block", Index, Name);
    return;
  }
  std::string Nm(Name.data(), Name.size());
  if (ALLOW_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()),
        GlobalDeclarationNamesAndInitializersInstalled(false) {}

  ~ModuleParser() override {}

  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;

  // 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();
      getTranslator().lowerGlobals(Context->getGlobalVariables());
      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 {}

private:
  Ice::TimerMarker Timer;
  void setValueName(uint64_t Index, StringType &Name) override;
  void setBbName(uint64_t Index, StringType &Name) override;
};

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

void ModuleValuesymtabParser::setBbName(uint64_t Index, StringType &Name) {
  std::string Buffer;
  raw_string_ostream StrBuf(Buffer);
  StrBuf << "Can't define basic block name at global level: '" << Name
         << "' -> " << Index;
  Error(StrBuf.str());
}

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: {
    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;
    unsigned 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(
        Signature, CallingConv, Linkage, IsProto);
    Context->setNextFunctionID(Func);
    return;
  }
  default:
    BlockParserBaseClass::ProcessRecord();
    return;
  }
}

bool TopLevelParser::ParseBlock(unsigned BlockID) {
  if (BlockID == naclbitc::MODULE_BLOCK_ID) {
    ModuleParser Parser(BlockID, this);
    return Parser.ParseThisBlock();
  }
  // 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) {

  // Read header and verify it is good.
  NaClBitcodeHeader Header;
  if (Header.Read(MemObj.get()) || !Header.IsSupported()) {
    errs() << "Invalid PNaCl bitcode header.\n";
    ErrorStatus.assign(EC_Bitcode);
    return;
  }

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

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

  if (TopLevelBlocks != 1) {
    errs() << IRFilename
           << ": Contains more than one module. Found: " << TopLevelBlocks
           << "\n";
    ErrorStatus.assign(EC_Bitcode);
  }
  if (InputStreamFile.getBitcodeBytes().getExtent() % 4 != 0) {
    errs() << IRFilename
           << ": Bitcode stream should be a multiple of 4 bytes in length.\n";
    ErrorStatus.assign(EC_Bitcode);
    return;
  }
}

} // end of namespace Ice
