text: //===-- NaClObjDump.cpp - Dump PNaCl bitcode contents ---------------------===//
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  
  #include "llvm/ADT/STLExtras.h"
  #include "llvm/Analysis/NaCl/PNaClABIProps.h"
  #include "llvm/Analysis/NaCl/PNaClABITypeChecker.h"
  #include "llvm/Analysis/NaCl/PNaClAllowedIntrinsics.h"
  #include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h"
  #include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
  #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
  #include "llvm/Bitcode/NaCl/NaClBitCodes.h"
  #include "llvm/Bitcode/NaCl/NaClObjDumpStream.h"
  #include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
  #include "llvm/IR/Constants.h"
  #include "llvm/IR/DataLayout.h"
  #include "llvm/IR/InstrTypes.h"
  #include "llvm/IR/LLVMContext.h"
  #include "llvm/IR/Module.h"
  #include "llvm/Support/CommandLine.h"
  #include "llvm/Support/MemoryBuffer.h"
  #include "llvm/Support/Format.h"
  #include "llvm/Support/raw_ostream.h"
  
  #include <map>
  
  namespace {
  
  using namespace llvm;
  
  static cl::opt<bool>
  ReportWarningsAsErrors(
      "Werror",
      cl::desc("Report warnings as errors."),
      cl::init(false));
  
  static cl::opt<bool>
  IgnorePNaClABIChecks(
      "ignore-pnaclabi-checks",
      cl::desc("Ignore checking bitcode for PNaCl ABI violations"),
      cl::init(false));
  
  /// Class to handle sign rotations in a human readable form. That is,
  /// the sign is in the low bit. The two special cases are:
  /// 1) -1 is true for i1.
  /// 2) The representation allows -0 (which is different than 0).
  class SignRotatedInt {
  public:
    SignRotatedInt(uint64_t Value, Type* ValueType)
        : SignedValue(Value >> 1),
          IsNegated((Value & 0x1)
                    && !(ValueType->isIntegerTy()
                         && ValueType->getIntegerBitWidth() == 1)) {
    }
  
    SignRotatedInt()
        : SignedValue(0), IsNegated(false) {}
  
    explicit SignRotatedInt(const SignRotatedInt &V)
        : SignedValue(V.SignedValue), IsNegated(V.IsNegated) {}
  
    void operator=(const SignRotatedInt &V) {
      SignedValue = V.SignedValue;
      IsNegated = V.IsNegated;
    }
  
    void Print(raw_ostream &Strm) const {
      if (IsNegated) Strm << "-";
      Strm << SignedValue;
    }
  
  private:
    int64_t SignedValue;
    bool IsNegated;
  };
  
  inline raw_ostream &operator<<(raw_ostream &Strm, const SignRotatedInt &V) {
    V.Print(Strm);
    return Strm;
  }
  
  /// Convenience class to be able to print value ids to raw_ostream's.
  /// Kinds of bitcode Ids:
  ///    a : For abbreviations.
  ///    b : For basic blocks.
  ///    c : For local constants.
  ///    f : For function addresses.
  ///    g : For global variable addresses.
  ///    p : For parameter arguments.
  ///    t : For type values.
  ///    v : For values generated by instructions.
  class BitcodeId {
  public:
    BitcodeId(char Kind, uint32_t Index)
        : Kind(Kind), Index(Index), IsGlobal(IsGlobalKind(Kind)) {
    }
  
    BitcodeId(const BitcodeId &Id)
        : Kind(Id.Kind), Index(Id.Index), IsGlobal(Id.IsGlobal) {}
  
    BitcodeId(char Kind, uint32_t Index, bool IsGlobal)
        : Kind(Kind), Index(Index), IsGlobal(IsGlobal) {}
  
    void operator=(const BitcodeId &Id) {
      Kind = Id.Kind;
      Index = Id.Index;
      IsGlobal = Id.IsGlobal;
    }
  
    raw_ostream &Print(raw_ostream &Stream) const {
      return Stream << Prefix() << Kind << Index;
    }
  
    char GetKind() const {
      return Kind;
    }
  
    std::string GetName() const {
      std::string Buffer;
      raw_string_ostream StrBuf(Buffer);
      Print(StrBuf);
      return StrBuf.str();
    }
  
  private:
    char Kind;
    uint32_t Index;
    bool IsGlobal;
  
    // Returns true if (default) assumption for kind implies global.
    static bool IsGlobalKind(char Kind);
  
    // Returns the bitcode prefix character that communicates if the
    // bitcode Id is lcoal or global.
    char Prefix() const { return IsGlobal ? '@' : '%'; }
  };
  
  bool BitcodeId::IsGlobalKind(char Kind) {
    switch (Kind) {
    case 'f':
    case 'g':
    case 't':
      return true;
    case 'b':
    case 'c':
    case 'p':
    case 'v':
      return false;
    default:
      errs() << "Bad bitcode id, can't determine (statically) if global: "
             << Kind << "\n";
      report_fatal_error("Unable to continue");
    }
  }
  
  raw_ostream &operator<<(raw_ostream &Stream, const BitcodeId &Id) {
    return Id.Print(Stream);
  }
  
  class NaClDisBlockParser;
  
  /// The text formatter for PNaClAsm instructions.
  class AssemblyTextFormatter : public naclbitc::TextFormatter {
  public:
    // Special directive to tokenize type expressions. Used to convert
    // type signatures into a sequence of tokens.
    class TypeDirective : public naclbitc::TextFormatter::Directive {
    public:
      TypeDirective(TextFormatter *Formatter)
          : naclbitc::TextFormatter::Directive(Formatter),
            Typ(0),
            FcnId(0),
            AddParams(false) {}
  
      ~TypeDirective() override {}
  
    private:
      /// Calls the corresponding method in AssemblyTextFormatter, with
      /// the locally stored arguments.
      void MyApply(bool Replay) const override;
  
      void MaybeSaveForReplay() const override {}
  
      // The type to tokenize.
      Type *Typ;
      // Pointer to function id, if not NULL.
      BitcodeId *FcnId;
      // true if parameter id's should be added to function signature.
      bool AddParams;
  
      friend class AssemblyTextFormatter;
  
      // Internal routine to allow AssemblyTextFormatter::AllocateTypeDirective
      // to initialize a type directive.
      void Init(Type *NewTyp, BitcodeId *NewFcnId, bool NewAddParams) {
        Typ = NewTyp;
        FcnId = NewFcnId;
        AddParams = NewAddParams;
      }
    };
  
    // Special directive to tokenize an abbreviation. Used to convert
    // an abbreviation (pointer) into a sequence of tokens.
    class AbbreviationDirective : public naclbitc::TextFormatter::Directive {
    public:
      AbbreviationDirective(TextFormatter *Formatter)
          : naclbitc::TextFormatter::Directive(Formatter),
            Abbrev(0) {}
  
      ~AbbreviationDirective() override {}
  
    private:
      void MyApply(bool Replay) const override;
  
      void MaybeSaveForReplay() const override {}
  
      // The abbreviation to tokenize.
      NaClBitCodeAbbrev *Abbrev;
  
      friend class AssemblyTextFormatter;
    };
  
    // Special directive to tokenize an abbreviation index, if the corresponding
    // record in the block parser used a user-defined abbreviation.
    class AbbrevIndexDirective : public naclbitc::TextFormatter::Directive {
    public:
      AbbrevIndexDirective(TextFormatter *Formatter)
          : naclbitc::TextFormatter::Directive(Formatter),
            Record(0), NumGlobalAbbreviations(0) {}
  
      ~AbbrevIndexDirective() override {}
  
    private:
      void MyApply(bool Replay) const override;
  
      void MaybeSaveForReplay() const override {}
  
      // The record containing the associated abbreviation.
      NaClBitcodeRecord *Record;
  
      // The number of global abbreviations defined for the block the
      // record appears in.
      unsigned NumGlobalAbbreviations;
  
      friend class AssemblyTextFormatter;
    };
  
  public:
  
    /// Creates an assembly text formatter for the given dump stream.
    AssemblyTextFormatter(naclbitc::ObjDumpStream &ObjDump)
        : TextFormatter(ObjDump.Assembly(),
                        std::max(20U, GetAssemblyWidth(ObjDump)),
                        "  "),
          Comma(this, ","),
          Semicolon(this, ";"),
          Colon(this, ":"),
          Space(this),
          OpenParen(this, "("),
          CloseParen(this, ")"),
          OpenAngle(this, "<"),
          CloseAngle(this, ">"),
          OpenCurly(this, "{"),
          CloseCurly(this, "}"),
          OpenSquare(this, "["),
          CloseSquare(this, "]"),
          Endline(this),
          StartCluster(this),
          FinishCluster(this)
    {
      ContinuationIndent = GetIndent(2);
    }
  
    ~AssemblyTextFormatter() override {}
  
    naclbitc::TokenTextDirective Comma;
    naclbitc::TokenTextDirective Semicolon;
    naclbitc::TokenTextDirective Colon;
    naclbitc::SpaceTextDirective Space;
    naclbitc::OpenTextDirective OpenParen;
    naclbitc::CloseTextDirective CloseParen;
    naclbitc::OpenTextDirective OpenAngle;
    naclbitc::CloseTextDirective CloseAngle;
    naclbitc::OpenTextDirective OpenCurly;
    naclbitc::CloseTextDirective CloseCurly;
    naclbitc::OpenTextDirective OpenSquare;
    naclbitc::CloseTextDirective CloseSquare;
    naclbitc::EndlineTextDirective Endline;
    naclbitc::StartClusteringDirective StartCluster;
    naclbitc::FinishClusteringDirective FinishCluster;
  
    /// Prints the given type as a sequence of tokens.
    TypeDirective &TokenizeType(Type *Typ) {
      return AllocateTypeDirective(Typ, 0, false);
    }
  
    /// Prints the named function type as a sequence of tokens.
    /// Typ is the type signature of the function, and FunctionName
    /// points to the name of the function.
    TypeDirective &TokenizeFunctionType(FunctionType *Typ,
                                        BitcodeId *FunctionName) {
      return AllocateTypeDirective(Typ, FunctionName, false);
    }
  
    /// Prints the function signature of the function type. Typ is
    /// the type signature of the function. FunctionName points to the
    /// name of the function. Note: Unlike TokenizeFunctionType, this
    /// method also adds the parameter names to paramter argumements.
    TypeDirective &TokenizeFunctionSignature(FunctionType *Typ,
                                             BitcodeId *FunctionName) {
      return AllocateTypeDirective(Typ, FunctionName, true);
    }
  
    /// Prints out the abbreviation defined by Abbrev.
    AbbreviationDirective &TokenizeAbbreviation(NaClBitCodeAbbrev *Abbrev) {
      AbbreviationDirective *Dir = AbbrevDirMemoryPool.Allocate(this);
      Dir->Abbrev = Abbrev;
      return *Dir;
    }
  
    /// If the record was read using a user-defined abbreviation,
    /// generates assembly tokens describing the abbreviation index
    /// used. Otherwise, no tokens are generated. NumGlobalAbbreviations
    /// is used to determine if the user-defined abbreviation is local
    /// or global.
    AbbrevIndexDirective &TokenizeAbbrevIndex(NaClBitcodeRecord &Record,
                                              unsigned NumGlobalAbbreviations) {
      AbbrevIndexDirective *Dir = AbbrevIndexDirMemoryPool.Allocate(this);
      Dir->Record = &Record;
      Dir->NumGlobalAbbreviations = NumGlobalAbbreviations;
      return *Dir;
    }
  
  private:
    // Converts the given type to tokens, based on the values passed in
    // by TokenizeType, TokenizeFunctionType, or TokenizeFunctionSignature.
    void TokenizeTypeInternal(Type *Typ, BitcodeId* FcnName, bool AddParams);
  
    // The free list of type directives.
    naclbitc::DirectiveMemoryPool<TypeDirective> TypeDirMemoryPool;
  
    // Allocates an instance of TypeDirective with the following fields.
    TypeDirective &AllocateTypeDirective(Type *Typ, BitcodeId *FcnId,
                                         bool AddParams);
  
    // Converts the given abbreviation to tokens.
    void TokenizeAbbreviationInternal(const NaClBitCodeAbbrev *Abbrev);
  
    // Helper function that prints out the abbreviation expression
    // located at Index in the given abbreviation. Updates Index to
    // next expression in the abbreviation.
    void TokenizeAbbrevExpression(const NaClBitCodeAbbrev *Abbrev,
                                  unsigned &Index);
  
    // Prints out the given abbreviation operator.
    void TokenizeAbbrevOp(const NaClBitCodeAbbrevOp &Op);
  
    // The free list for abbreviation directives.
    naclbitc::DirectiveMemoryPool<AbbreviationDirective> AbbrevDirMemoryPool;
  
    // The free list for abbreviation index directives.
    naclbitc::DirectiveMemoryPool<AbbrevIndexDirective> AbbrevIndexDirMemoryPool;
  
    // Computes how wide the assembly portion of the dump file should be.
    static unsigned GetAssemblyWidth(naclbitc::ObjDumpStream &ObjDump) {
      int Diff = 80 - (ObjDump.GetRecordWidth()+1);
      // Make sure there is enough room to print out assembly.
      return Diff < 20 ? 20 : Diff;
    }
  };
  
  void AssemblyTextFormatter::TypeDirective::MyApply(bool Replay) const {
    assert(!Replay && "Shouldn't have been saved for replay");
    AssemblyTextFormatter *AssemblyFormatter =
        reinterpret_cast<AssemblyTextFormatter*>(Formatter);
    AssemblyFormatter->TokenizeTypeInternal(Typ, FcnId, AddParams);
    AssemblyFormatter->TypeDirMemoryPool.Free(const_cast<TypeDirective*>(this));
  }
  
  void AssemblyTextFormatter::AbbreviationDirective::MyApply(bool Replay) const {
    assert(!Replay && "Shouldn't have been saved for replay");
    AssemblyTextFormatter *AssemblyFormatter =
        reinterpret_cast<AssemblyTextFormatter*>(Formatter);
    AssemblyFormatter->TokenizeAbbreviationInternal(Abbrev);
    AssemblyFormatter->AbbrevDirMemoryPool.Free(
        const_cast<AbbreviationDirective*>(this));
  }
  
  AssemblyTextFormatter::TypeDirective &AssemblyTextFormatter::
  AllocateTypeDirective(Type *Typ, BitcodeId *FcnId, bool AddParams) {
    TypeDirective *Element = TypeDirMemoryPool.Allocate(this);
    Element->Init(Typ, FcnId, AddParams);
    return *Element;
  }
  
  void AssemblyTextFormatter::TokenizeTypeInternal(
      Type *Typ, BitcodeId* FcnName, bool AddParams) {
    switch (Typ->getTypeID()) {
    case Type::VoidTyID:
      TextStream << "void";
      break;
    case Type::FloatTyID:
      TextStream << "float";
      break;
    case Type::DoubleTyID:
      TextStream << "double";
      break;
    case Type::IntegerTyID:
      TextStream << "i" << Typ->getIntegerBitWidth();
      break;
    case Type::VectorTyID: {
      VectorType *VecType = cast<VectorType>(Typ);
      TextStream << StartCluster << OpenAngle << VecType->getNumElements()
                 << Space << "x" << Space
                 << TokenizeType(VecType->getElementType())
                 << CloseAngle << FinishCluster;
      break;
    }
    case Type::FunctionTyID: {
      FunctionType *FcnType = cast<FunctionType>(Typ);
      unsigned NumParams = FcnType->getFunctionNumParams();
      TextStream << StartCluster
                 << TokenizeType(FcnType->getReturnType())
                 << Space
                 << StartCluster;
      if (NumParams > 0) TextStream << StartCluster;
      if (FcnName) TextStream << *FcnName;
      TextStream << OpenParen << FinishCluster;
      bool HasParamStartCluster = false;
      for (unsigned i = 0, NumParams = FcnType->getFunctionNumParams();
           i < NumParams; ++i) {
        if (i > 0) {
          TextStream << Comma << FinishCluster << Space;
          HasParamStartCluster = false;
        }
        TextStream << StartCluster
                   << TokenizeType(FcnType->getFunctionParamType(i));
        if (AddParams) TextStream << Space << BitcodeId('p', i);
        HasParamStartCluster = true;
      }
      if (FcnType->isFunctionVarArg()) {
        if (HasParamStartCluster) {
          TextStream << Comma << FinishCluster << Space;
        }
        TextStream << StartCluster << "...";
        HasParamStartCluster = true;
      }
      if (HasParamStartCluster) TextStream << FinishCluster;
      TextStream << CloseParen << FinishCluster;
      if (NumParams > 0) TextStream << FinishCluster;
      break;
    }
    default:
      report_fatal_error("Unsupported PNaCl type found");
      break;
    }
  }
  
  void AssemblyTextFormatter::TokenizeAbbrevOp(const NaClBitCodeAbbrevOp &Op) {
    // Note: Mimics NaClBitCodeAbbrevOp::Print in NaClBitCodes.cpp
    switch (Op.getEncoding()) {
    case NaClBitCodeAbbrevOp::Literal:
      Tokens() << Op.getValue();
      return;
    case NaClBitCodeAbbrevOp::Fixed:
      Tokens() << StartCluster << "fixed" << OpenParen << Op.getValue()
               << CloseParen << FinishCluster;
      return;
    case NaClBitCodeAbbrevOp::VBR:
      Tokens() << StartCluster << "vbr" << OpenParen << Op.getValue()
               << CloseParen << FinishCluster;
      return;
    case NaClBitCodeAbbrevOp::Array:
      Tokens() << "array";
      return;
    case NaClBitCodeAbbrevOp::Char6:
      Tokens() << "char6";
      return;
    }
  }
  
  void AssemblyTextFormatter::
  TokenizeAbbrevExpression(const NaClBitCodeAbbrev *Abbrev, unsigned &Index) {
    // Note: Mimics PrintExpression in NaClBitCodes.cpp
    const NaClBitCodeAbbrevOp &Op = Abbrev->getOperandInfo(Index);
    TokenizeAbbrevOp(Op);
    if (unsigned NumArgs = Op.NumArguments()) {
      Tokens() << StartCluster << OpenParen;
      for (unsigned i = 0; i < NumArgs; ++i) {
        ++Index;
        if (i > 0) {
          Tokens() << Comma << FinishCluster << Space << StartCluster;
        }
        TokenizeAbbrevExpression(Abbrev, Index);
      }
      Tokens() << CloseParen << FinishCluster;
    }
  }
  
  void AssemblyTextFormatter::
  TokenizeAbbreviationInternal(const NaClBitCodeAbbrev *Abbrev) {
    Tokens() << StartCluster << OpenAngle;
    for (unsigned i = 0; i < Abbrev->getNumOperandInfos(); ++i) {
      if (i > 0) {
        Tokens() << Comma << FinishCluster << Space << StartCluster;
      }
      TokenizeAbbrevExpression(Abbrev, i);
    }
    Tokens() << CloseAngle << FinishCluster;
  }
  
  void AssemblyTextFormatter::AbbrevIndexDirective::MyApply(bool Replay) const {
    assert(!Replay && "Shouldn't have been saved for replay");
    if (!Record->UsedAnAbbreviation()) return;
    unsigned Index = Record->GetAbbreviationIndex();
    if (Index < naclbitc::FIRST_APPLICATION_ABBREV) return;
    Index -= naclbitc::FIRST_APPLICATION_ABBREV;
    bool IsGlobal = Index < NumGlobalAbbreviations;
    if (!IsGlobal) Index -= NumGlobalAbbreviations;
    BitcodeId AbbrevIndex('a', Index, IsGlobal);
    AssemblyTextFormatter *Fmtr =
        reinterpret_cast<AssemblyTextFormatter*>(Formatter);
    Tokens() << Fmtr->Space << Fmtr->StartCluster << Fmtr->OpenAngle
             << AbbrevIndex << Fmtr->CloseAngle << Fmtr->FinishCluster;
    Fmtr->AbbrevIndexDirMemoryPool.Free(const_cast<AbbrevIndexDirective*>(this));
  }
  
  // Holds possible alignements for loads/stores etc. Used to extract
  // expected values.
  static unsigned NaClPossibleLoadStoreAlignments[] = {
    1, 2, 4, 8
  };
  
  // Finds the expected alignments for the load/store, for type Ty.
  static void NaClGetExpectedLoadStoreAlignment(
      const DataLayout &DL, Type *Ty, std::vector<unsigned> &ValidAlignments) {
    for (size_t i = 0; i < array_lengthof(NaClPossibleLoadStoreAlignments); ++i) {
      unsigned Alignment = NaClPossibleLoadStoreAlignments[i];
      if (PNaClABIProps::isAllowedAlignment(&DL, Alignment, Ty)) {
        ValidAlignments.push_back(Alignment);
      }
    }
  }
  
  /// Top-level class to parse bitcode file and transform to
  /// corresponding disassembled code.
  class NaClDisTopLevelParser : public NaClBitcodeParser {
    NaClDisTopLevelParser(const NaClDisTopLevelParser&) = delete;
    void operator=(const NaClDisTopLevelParser&) = delete;
  
  public:
    NaClDisTopLevelParser(NaClBitcodeHeader &Header,
                          NaClBitstreamCursor &Cursor,
                          naclbitc::ObjDumpStream &ObjDump)
        : NaClBitcodeParser(Cursor),
          Mod("ObjDump", getGlobalContext()),
          ObjDump(ObjDump),
          AbbrevListener(this),
          DL(&Mod),
          AllowedIntrinsics(&Mod.getContext()),
          AssemblyFormatter(ObjDump),
          Header(Header),
          NumFunctions(0),
          NumGlobals(0),
          ExpectedNumGlobals(0),
          NumParams(0),
          NumConstants(0),
          NumValuedInsts(0),
          UnknownType(Type::getVoidTy(Mod.getContext())),
          PointerType(Type::getInt32Ty(Mod.getContext())),
          ComparisonType(Type::getInt1Ty(Mod.getContext())),
          NumDefinedFunctions(0) {
      SetListener(&AbbrevListener);
    }
  
    ~NaClDisTopLevelParser() override {
      // Be sure to flush any remaining errors.
      ObjDump.Flush();
    }
  
    // Returns the number of errors that were sent to the ObjDump.
    unsigned GetNumErrors() {
      return ObjDump.GetNumErrors();
    }
  
    /// Generates an error with the given message.
    bool ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit,
                 const std::string &Message) final {
      ObjDump.ErrorAt(Level, Bit) << Message << "\n";
      if (Level == naclbitc::Fatal)
        ObjDump.FlushThenQuit();
      return true;
    }
  
    /// Parses the top-level module block.
    bool ParseBlock(unsigned BlockID) override;
  
    /// Installs the given type to the next available type index.
    void InstallType(Type *Ty) {
      TypeIdType.push_back(Ty);
    }
  
    /// Returns the type associated with the given type index.
    Type *GetType(uint32_t Index) {
      if (Index >= TypeIdType.size()) {
        BitcodeId Id('t', Index);
        Errors() << "Can't find definition for " << Id << "\n";
        // Recover so that additional errors can be found.
        return UnknownType;
      }
      return TypeIdType[Index];
    }
  
    /// Returns the number of types (currently) defined in the bitcode
    /// file.
    uint32_t GetNumTypes() const {
      return TypeIdType.size();
    }
  
    /// Returns true if Type represents a (non-zero sized) value.
    bool isValidValueType(Type *Ty) const {
      return Ty->isIntegerTy() || Ty->isFloatTy() || Ty->isDoubleTy()
          || Ty->isVectorTy();
    }
  
    /// Installs the given type to the next available function index.
    void InstallFunctionType(FunctionType *Ty, uint64_t BitAddress) {
      assert(FunctionIdType.size() == NumFunctions);
      ++NumFunctions;
      FunctionIdType.push_back(Ty);
      FunctionIdAddress.push_back(BitAddress);
      // Let Valuesymtab change this to true if appropriate.
      FunctionIdIsIntrinsic.push_back(false);
    }
  
    /// Returns the bit address where the function record appeared in
    /// the bitcode file. Returns 0 if unknown.
    uint64_t GetFunctionIdAddress(uint32_t Index) {
      if (Index >= FunctionIdAddress.size()) return 0;
      return FunctionIdAddress[Index];
    }
  
    /// Sets the record bit address to the function ID address (if known).
    void SetRecordAddressToFunctionIdAddress(uint32_t Index) {
      uint64_t Address = GetFunctionIdAddress(Index);
      if (Address)
        ObjDump.SetRecordBitAddress(Address);
    }
  
    //// Returns the type associated with the given function index.
    FunctionType *GetFunctionType(uint32_t Index) {
      if (Index >= FunctionIdType.size()) {
        BitcodeId Id('f', Index);
        Errors() << "Can't find definition for " << Id << "\n";
        Fatal();
      }
      return FunctionIdType[Index];
    }
  
    /// Marks the function associated with the given Index as intrinsic.
    void MarkFunctionAsIntrinsic(uint32_t Index) {
      if (Index >= FunctionIdIsIntrinsic.size()) {
        BitcodeId Id('f', Index);
        Errors() << "Can't define " << Id << " as intrinsic, no definition";
      }
      FunctionIdIsIntrinsic[Index] = true;
    }
  
    /// Returns true if the given Index is for a function intrinsic.
    bool IsFunctionIntrinsic(uint32_t Index) {
      if (Index >= FunctionIdIsIntrinsic.size()) return false;
      return FunctionIdIsIntrinsic[Index];
    }
  
    /// Returns true if the function is an intrinsic function.
    bool IsIntrinsicAllowed(const std::string &FuncName,
                            const FunctionType *FuncType) {
      return AllowedIntrinsics.isAllowed(FuncName, FuncType);
    }
  
    /// Returns the type of the Name'd intrinsic, if defined as an
    /// allowed intrinsic name. Otherwise returns 0.
    FunctionType *GetIntrinsicType(const std::string &Name) {
      return AllowedIntrinsics.getIntrinsicType(Name);
    }
  
    /// Returns the number of functions (currently) defined/declared in
    /// the bitcode file.
    uint32_t GetNumFunctions() const {
      return NumFunctions;
    }
  
    /// Installs that the given function index as having a function body
    /// (i.e. the function address uses the "define" keyword instead of
    /// the "declare" keyword).
    void InstallDefinedFunction(uint32_t Index) {
      DefinedFunctions.push_back(Index);
    }
  
    /// Returns true if there is an Index defined function block.
    bool HasDefinedFunctionIndex(uint32_t Index) const {
      return Index < DefinedFunctions.size();
    }
  
    /// Returns the function index associated with the Index defined
    /// function block.
    uint32_t GetDefinedFunctionIndex(uint32_t Index) const {
      assert(Index < DefinedFunctions.size());
      return DefinedFunctions[NumDefinedFunctions];
    }
  
    /// Returns true if there is a next defined function index.
    bool HasNextDefinedFunctionIndex() const {
      return HasDefinedFunctionIndex(NumDefinedFunctions);
    }
  
    /// Returns the function index associated with the next defined function.
    uint32_t GetNextDefinedFunctionIndex() const {
      return GetDefinedFunctionIndex(NumDefinedFunctions);
    }
  
    /// Returns true if the given value ID corresponds to a declared (rather
    /// than defined) function.
    bool IsDeclaredFunction(uint32_t Index) {
      if (Index >= NumFunctions) return false;
      for (size_t i = 0, e = DefinedFunctions.size(); i < e; ++i) {
        if (DefinedFunctions[i] == Index) return false;
      }
      return true;
    }
  
    /// Increments the number of (currently) defined functions in the
    /// bitcode file by one.
    void IncNumDefinedFunctions() {
      ++NumDefinedFunctions;
    }
  
    void IncNumGlobals() {
      NumGlobals++;
    }
  
    /// Returns the number of globals (currently) defined in the bitcode
    /// file.
    uint32_t GetNumGlobals() const {
      return NumGlobals;
    }
  
    /// Returns the expected number of globals (as defined by the count
    /// record of the globals block).
    uint32_t GetExpectedNumGlobals() const {
      return ExpectedNumGlobals;
    }
  
    /// Sets field ExpectedNumGlobals to the given value.
    void SetExpectedNumGlobals(uint32_t NewValue) {
      ExpectedNumGlobals = NewValue;
    }
  
    /// Installs the given type to the next available parameter index.
    void InstallParamType(Type *Ty) {
      while (ParamIdType.size() <= NumParams) {
        ParamIdType.push_back(UnknownType);
      }
      ParamIdType[NumParams++] = Ty;
    }
  
    /// Returns the type associated with the given parameter index.
    Type *GetParamType(uint32_t Index) {
      if (Index >= ParamIdType.size()) {
        BitcodeId Id('p', Index);
        Errors() << "Can't find defintion for " << Id << "\n";
        Fatal();
      }
      return ParamIdType[Index];
    }
  
    /// Returns the number of parameters (currently) defined in the
    /// enclosing defined function.
    uint32_t GetNumParams() const {
      return NumParams;
    }
  
    /// Installs the given type to the next available constant index.
    void InstallConstantType(Type *Ty) {
      while (ConstantIdType.size() <= NumConstants) {
        ConstantIdType.push_back(UnknownType);
      }
      ConstantIdType[NumConstants++] = Ty;
    }
  
    /// Returns the type associated with the given constant index.
    Type *GetConstantType(uint32_t Index) {
      if (Index >= ConstantIdType.size()) {
        BitcodeId Id('c', Index);
        Errors() << "Can't find definition for " << Id << "\n";
        Fatal();
      }
      return ConstantIdType[Index];
    }
  
    /// Returns the number of constants (currently) defined in the
    /// enclosing defined function.
    uint32_t GetNumConstants() const {
      return NumConstants;
    }
  
    /// Installs the given type to the given instruction index.  Note:
    /// Instruction indices are only associated with instructions that
    /// generate values.
    void InstallInstType(Type *Ty, uint32_t Index) {
      while (InstIdType.size() <= Index) {
        InstIdType.push_back(UnknownType);
      }
      if (InstIdType[Index] != UnknownType && Ty != InstIdType[Index]) {
        Errors() << BitcodeId('v', Index) << " defined with multiple types: "
                 << *Ty << " and " << *InstIdType[Index] << "\n";
      }
      InstIdType[Index] = Ty;
    }
  
    /// Installs the given type to the next available instruction index.
    void InstallInstType(Type *Ty) {
      InstallInstType(Ty, NumValuedInsts++);
    }
  
    /// Returns the type associated with the given instruction index.
    /// Note: Instruction indices are only associated with instructions
    /// that generate values.
    Type *GetInstType(uint32_t Index) {
      if (Index >= InstIdType.size()) {
        Errors() << "Can't find type for " << BitcodeId('v', Index) << "\n";
        return UnknownType;
      }
      return InstIdType[Index];
    }
  
    /// Returns the number of instructions (in the defined function)
    /// that (currently) generate values.
    uint32_t GetNumValuedInstructions() const {
      return NumValuedInsts;
    }
  
    /// Resets index counters local to a defined function.
    void ResetLocalCounters() {
      ParamIdType.clear();
      NumParams = 0;
      NumConstants = 0;
      InstIdType.clear();
      NumValuedInsts = 0;
    }
  
    /// Returns the bitcode id associated with the absolute value index
    BitcodeId GetBitcodeId(uint32_t Index);
  
    /// Returns the type associated with the given absolute value index.
    /// If UnderlyingType is false, function indices always return a
    /// pointer type. Otherwise, function indices returns the declared
    /// type of the function index.
    Type *GetValueType(uint32_t Index, bool UnderlyingType = false);
  
    /// Returns a type to use when the type is unknown.
    Type *GetUnknownType() const {
      return UnknownType;
    }
  
    /// Returns the type used to represent a pointer.
    Type *GetPointerType() const {
      return PointerType;
    }
  
    /// Returns the type used to represent comparison results.
    Type *GetComparisonType() const {
      return ComparisonType;
    }
  
    /// Returns the void type.
    Type *GetVoidType() const {
      return Type::getVoidTy(getGlobalContext());
    }
  
    /// Returns the float (32-bit) type.
    Type *GetFloatType() const {
      return Type::getFloatTy(getGlobalContext());
    }
  
    /// Returns the double (64-bit) type.
    Type *GetDoubleType() const {
      return Type::getDoubleTy(getGlobalContext());
    }
  
    /// Returns an integer type of N bits.
    Type *GetIntegerType(unsigned N) const {
      return Type::getIntNTy(getGlobalContext(), N);
    }
  
    /// Returns the number of defined global abbreviations (currently)
    /// for the given block id.
    unsigned GetNumGlobalAbbreviations(unsigned BlockID) {
      return GlobalAbbrevsCountMap[BlockID];
    }
  
    /// Increments the current number of defined global abbreviations.
    void IncNumGlobalAbbreviations(unsigned BlockID) {
      ++GlobalAbbrevsCountMap[BlockID];
    }
  
    /// Verifies the given integer operator has the right type.  Returns
    /// the operator.
    const char *VerifyIntArithmeticOp(const char *Op, Type *OpTy) {
      if (!IgnorePNaClABIChecks &&
          !PNaClABITypeChecker::isValidIntArithmeticType(OpTy)) {
        Errors() << Op << ": Invalid integer arithmetic type: " << *OpTy;
      }
      return Op;
    }
  
    // Checks the Alignment for loading/storing a value of type Ty. If
    // invalid, generates an appropriate error message.
    void VerifyMemoryAccessAlignment(const char *Op, Type *Ty,
                                     unsigned Alignment) {
      if (IgnorePNaClABIChecks) return;
      if (!PNaClABIProps::isAllowedAlignment(&DL, Alignment, Ty)) {
        raw_ostream &Errs = Errors();
        std::vector<unsigned> Alignments;
        NaClGetExpectedLoadStoreAlignment(DL, Ty, Alignments);
        if (!Alignments.empty()) {
          Errs << Op << ": Illegal alignment for " << *Ty << ". Expects: ";
          bool isFirst = true;
          for (auto Align : Alignments) {
            if (isFirst)
              isFirst = false;
            else
              Errs << " or ";
            Errs << Align;
          }
          Errs << "\n";
        } else {
          Errs << Op << ": Not allowed for type: " << *Ty << "\n";
        }
      }
    }
  
    // ******************************************************
    // The following return the corresponding methods/fields
    // from the the assembly formatter/objdumper.
    // ******************************************************
  
    naclbitc::TokenTextDirective &Semicolon() {
      return AssemblyFormatter.Semicolon;
    }
  
    naclbitc::TokenTextDirective &Colon() {
      return AssemblyFormatter.Colon;
    }
  
    naclbitc::SpaceTextDirective &Space() {
      return AssemblyFormatter.Space;
    }
  
    naclbitc::TokenTextDirective &Comma() {
      return AssemblyFormatter.Comma;
    }
  
    naclbitc::OpenTextDirective &OpenParen() {
      return AssemblyFormatter.OpenParen;
    }
  
    naclbitc::CloseTextDirective &CloseParen() {
      return AssemblyFormatter.CloseParen;
    }
  
    naclbitc::OpenTextDirective &OpenAngle() {
      return AssemblyFormatter.OpenAngle;
    }
  
    naclbitc::CloseTextDirective &CloseAngle() {
      return AssemblyFormatter.CloseAngle;
    }
  
    naclbitc::OpenTextDirective &OpenCurly() {
      return AssemblyFormatter.OpenCurly;
    }
  
    naclbitc::CloseTextDirective &CloseCurly() {
      return AssemblyFormatter.CloseCurly;
    }
  
    naclbitc::OpenTextDirective &OpenSquare() {
      return AssemblyFormatter.OpenSquare;
    }
  
    naclbitc::CloseTextDirective &CloseSquare() {
      return AssemblyFormatter.CloseSquare;
    }
  
    naclbitc::EndlineTextDirective &Endline() {
      return AssemblyFormatter.Endline;
    }
  
    naclbitc::StartClusteringDirective &StartCluster() {
      return AssemblyFormatter.StartCluster;
    }
  
    naclbitc::FinishClusteringDirective &FinishCluster() {
      return AssemblyFormatter.FinishCluster;
    }
  
    raw_ostream &Tokens() {
      return AssemblyFormatter.Tokens();
    }
  
    raw_ostream &Errors() {
      return ObjDump.Error();
    }
  
    raw_ostream &Warnings() {
      if (ReportWarningsAsErrors) return Errors();
      return ObjDump.Warning();
    }
  
    const std::string &GetAssemblyIndent() const {
      return AssemblyFormatter.GetIndent();
    }
  
    unsigned GetAssemblyNumTabs() const {
      return AssemblyFormatter.GetNumTabs();
    }
  
    void IncAssemblyIndent() {
      AssemblyFormatter.Inc();
    }
  
    void DecAssemblyIndent() {
      AssemblyFormatter.Dec();
    }
  
    void IncRecordIndent() {
      ObjDump.IncRecordIndent();
    }
  
    void DecRecordIndent() {
      ObjDump.DecRecordIndent();
    }
  
    void ObjDumpFlush() {
      ObjDump.Flush();
    }
  
    void ObjDumpSetRecordBitAddress(uint64_t Bit) {
      ObjDump.SetRecordBitAddress(Bit);
    }
  
    void ObjDumpWrite(uint64_t Bit,
                      const NaClBitcodeRecordData &Record,
                      int32_t AbbrevIndex =
                      naclbitc::ABBREV_INDEX_NOT_SPECIFIED) {
      ObjDump.Write(Bit, Record, AbbrevIndex);
    }
  
    void ObjDumpWrite(uint64_t Bit,
                      const NaClBitcodeRecord &Record) {
      ObjDump.Write(Bit, Record.GetRecordData(), Record.GetAbbreviationIndex());
    }
  
    AssemblyTextFormatter::TypeDirective &
    TokenizeType(Type *Typ) {
      return AssemblyFormatter.TokenizeType(Typ);
    }
  
    AssemblyTextFormatter::TypeDirective &
    TokenizeFunctionType(FunctionType *Type, BitcodeId *FcnId) {
      return AssemblyFormatter.TokenizeFunctionType(Type, FcnId);
    }
  
    AssemblyTextFormatter::TypeDirective &
    TokenizeFunctionSignature(FunctionType *Typ, BitcodeId *FcnId) {
      return AssemblyFormatter.TokenizeFunctionSignature(Typ, FcnId);
    }
  
    AssemblyTextFormatter::AbbreviationDirective &
    TokenizeAbbreviation(NaClBitCodeAbbrev *Abbrev) {
      return AssemblyFormatter.TokenizeAbbreviation(Abbrev);
    }
  
    AssemblyTextFormatter::AbbrevIndexDirective &
    TokenizeAbbrevIndex(NaClBitcodeRecord &Record,
                        unsigned NumGlobalAbbreviations) {
      return AssemblyFormatter.TokenizeAbbrevIndex(Record,
                                                   NumGlobalAbbreviations);
    }
  
  private:
    // A placeholder module for associating context and data layout.
    Module Mod;
    // The output stream to generate disassembly into.
    naclbitc::ObjDumpStream &ObjDump;
    // Listener used to get abbreviations as they are read.
    NaClBitcodeParserListener AbbrevListener;
    // DataLayout to use.
    const DataLayout DL;
    // The set of allowed intrinsics.
    PNaClAllowedIntrinsics AllowedIntrinsics;
    // The formatter to use to format assembly code.
    AssemblyTextFormatter AssemblyFormatter;
    // The header appearing before the beginning of the input stream.
    NaClBitcodeHeader &Header;
    // The list of known types (index i defines the type associated with
    // type index i).
    std::vector<Type*> TypeIdType;
    // The list of known function signatures (index i defines the type
    // signature associated with function index i).
    std::vector<FunctionType*> FunctionIdType;
    // boolean flag defining if function id is an intrinsic.
    std::vector<bool> FunctionIdIsIntrinsic;
    // The list of record bit addresses associated with corresponding
    // declaration of function IDs.
    std::vector<uint64_t> FunctionIdAddress;
    // The number of function indices currently defined.
    uint32_t NumFunctions;
    // The number of global indices currently defined.
    uint32_t NumGlobals;
    // The expected number of global indices (i.e. value of count record
    // in the globals block).
    uint32_t ExpectedNumGlobals;
    // The list of known parameter types (index i defines the type
    // associated with parameter index i).
    std::vector<Type*>ParamIdType;
    // The number of parameter indices currently defined.
    uint32_t NumParams;
    std::vector<Type*>ConstantIdType;
    // The number of constant indices currently defined.
    uint32_t NumConstants;
    // The list of known instruction types (index i defines the type
    // associated with valued instruction index i).
    std::vector<Type*> InstIdType;
    // The number of valued instructions currently defined.
    uint32_t NumValuedInsts;
    // Models an unknown type.
    Type *UnknownType;
    // Models the pointer type.
    Type *PointerType;
    // Models a result of a comparison.
    Type *ComparisonType;
    // Keeps list of function indicies (in the order found in the bitcode)
    // that correspond to defined functions.
    std::vector<uint32_t> DefinedFunctions;
    // The number of function indices currently known to be defined.
    uint32_t NumDefinedFunctions;
    // Holds the number of global abbreviations defined for each block.
    std::map<unsigned, unsigned> GlobalAbbrevsCountMap;
  };
  
  BitcodeId NaClDisTopLevelParser::GetBitcodeId(uint32_t Index) {
    if (Index < NumFunctions) {
      return BitcodeId('f', Index);
    }
    Index -= NumFunctions;
    if (Index < ExpectedNumGlobals) {
      return BitcodeId('g', Index);
    }
    Index -= ExpectedNumGlobals;
    if (Index < NumParams) {
      return BitcodeId('p', Index);
    }
    Index -= NumParams;
    if (Index < NumConstants) {
      return BitcodeId('c', Index);
    }
    Index -= NumConstants;
    return BitcodeId('v', Index);
  }
  
  Type *NaClDisTopLevelParser::GetValueType(uint32_t Index, bool UnderlyingType) {
    uint32_t Idx = Index;
    if (Idx < NumFunctions)
      return UnderlyingType ? GetFunctionType(Idx) : PointerType;
    Idx -= NumFunctions;
    if (Idx < ExpectedNumGlobals)
      return PointerType;
    Idx -= ExpectedNumGlobals;
    if (Idx < NumParams)
      return GetParamType(Idx);
    Idx -= NumParams;
    if (Idx < NumConstants)
      return GetConstantType(Idx);
    Idx -= NumConstants;
    return GetInstType(Idx);
  }
  
  // Base class of all block parsers for the bitcode file. Handles
  // common actions needed by derived blocks.
  //
  // Note: This class also handles blocks with unknown block ID's.
  class NaClDisBlockParser : public NaClBitcodeParser {
  protected:
    /// Constructor for the top-level block parser.
    NaClDisBlockParser(unsigned BlockID, NaClDisTopLevelParser *Context)
        : NaClBitcodeParser(BlockID, Context),
          Context(Context){
      InitAbbreviations();
    }
  
    /// Constructor for nested block parsers.
    NaClDisBlockParser(unsigned BlockID, NaClDisBlockParser *EnclosingParser)
        : NaClBitcodeParser(BlockID, EnclosingParser),
          Context(EnclosingParser->Context) {
      InitAbbreviations();
    }
  
  public:
  
    ~NaClDisBlockParser() override {
      // Be sure to flush any remaining errors reported at end of block.
      ObjDumpFlush();
    }
  
    bool ParseBlock(unsigned BlockID) override;
  
  protected:
    void EnterBlock(unsigned NumWords) override;
  
    void ExitBlock() override;
  
    void ProcessRecord() override;
  
    void ProcessAbbreviation(unsigned BlockID, NaClBitCodeAbbrev *Abbrev,
                             bool IsLocal) override;
  
    void InitAbbreviations() {
      NumGlobalAbbreviations = Context->GetNumGlobalAbbreviations(GetBlockID());
      NumLocalAbbreviations = 0;
    }
  
    // Prints the block header instruction for the block. Called by EnterBlock.
    virtual void PrintBlockHeader();
  
    // Dumps the corresponding record for a block enter.
    void DumpEnterBlockRecord();
  
    // Returns the identifier for the next local abbreviation appearing in
    // the block.
    BitcodeId NextLocalAbbreviationId() {
      return BitcodeId('a', NumLocalAbbreviations, false);
    }
  
    AssemblyTextFormatter::AbbrevIndexDirective &TokenizeAbbrevIndex() {
      return Context->TokenizeAbbrevIndex(Record, NumGlobalAbbreviations);
    }
  
    // *****************************************************************
    // The following are dispatching methods that call the corresponding
    // method on the Context (i.e. NaClDisTopLevelParser).
    // *****************************************************************
  
    /// Returns a directive to tokenize the given type.
    AssemblyTextFormatter::TypeDirective &TokenizeType(Type *Type) {
      return Context->TokenizeType(Type);
    }
  
    /// Returns a directive to tokenize the given function type,
    /// using the given function id.
    AssemblyTextFormatter::TypeDirective
    &TokenizeFunctionType(FunctionType *Type, BitcodeId *FcnId) {
      return Context->TokenizeFunctionType(Type, FcnId);
    }
  
    /// Returns a directive to tokenize the function signature, given the
    /// type of the function signature, and the given function id.
    AssemblyTextFormatter::TypeDirective
    &TokenizeFunctionSignature(FunctionType *Typ, BitcodeId *FcnId) {
      return Context->TokenizeFunctionSignature(Typ, FcnId);
    }
  
    AssemblyTextFormatter::AbbreviationDirective &TokenizeAbbreviation(
        NaClBitCodeAbbrev *Abbrev) {
      return Context->TokenizeAbbreviation(Abbrev);
    }
  
    naclbitc::TokenTextDirective &Semicolon() {
      return Context->Semicolon();
    }
  
    naclbitc::TokenTextDirective &Colon() {
      return Context->Colon();
    }
  
    naclbitc::SpaceTextDirective &Space() {
      return Context->Space();
    }
  
    naclbitc::TokenTextDirective &Comma() {
      return Context->Comma();
    }
  
    naclbitc::OpenTextDirective &OpenParen() {
      return Context->OpenParen();
    }
  
  
    naclbitc::CloseTextDirective &CloseParen() {
      return Context->CloseParen();
    }
  
    naclbitc::OpenTextDirective &OpenAngle() {
      return Context->OpenAngle();
    }
  
    naclbitc::CloseTextDirective &CloseAngle() {
      return Context->CloseAngle();
    }
  
    naclbitc::OpenTextDirective &OpenCurly() {
      return Context->OpenCurly();
    }
  
    naclbitc::CloseTextDirective &CloseCurly() {
      return Context->CloseCurly();
    }
  
    naclbitc::OpenTextDirective &OpenSquare() {
      return Context->OpenSquare();
    }
  
    naclbitc::CloseTextDirective &CloseSquare() {
      return Context->CloseSquare();
    }
  
    naclbitc::EndlineTextDirective &Endline() {
      return Context->Endline();
    }
  
    naclbitc::StartClusteringDirective &StartCluster() {
      return Context->StartCluster();
    }
  
    naclbitc::FinishClusteringDirective &FinishCluster() {
      return Context->FinishCluster();
    }
  
    raw_ostream &Tokens() {
      return Context->Tokens();
    }
  
    raw_ostream &Errors() {
      return Context->Errors();
    }
  
    raw_ostream &Warnings() {
      return Context->Warnings();
    }
  
    bool ErrorAt(naclbitc::ErrorLevel Level, uint64_t Bit,
                 const std::string &Message) final {
      return Context->ErrorAt(Level, Bit, Message);
    }
  
    const std::string &GetAssemblyIndent() const {
      return Context->GetAssemblyIndent();
    }
  
    unsigned GetAssemblyNumTabs() const {
      return Context->GetAssemblyNumTabs();
    }
  
    void IncAssemblyIndent() {
      Context->IncAssemblyIndent();
    }
  
    void DecAssemblyIndent() {
      Context->DecAssemblyIndent();
    }
  
    void IncRecordIndent() {
      Context->IncRecordIndent();
    }
  
    void DecRecordIndent() {
      Context->DecRecordIndent();
    }
  
    void ObjDumpFlush() {
      Context->ObjDumpFlush();
    }
  
    void ObjDumpWrite(uint64_t Bit,
                      const NaClBitcodeRecordData &Record,
                      int32_t AbbrevIndex =
                      naclbitc::ABBREV_INDEX_NOT_SPECIFIED) {
      Context->ObjDumpWrite(Bit, Record, AbbrevIndex);
    }
  
    void ObjDumpWrite(uint64_t Bit,
                      const NaClBitcodeRecord &Record) {
      Context->ObjDumpWrite(Bit, Record);
    }
  
    void ObjDumpSetRecordBitAddress(uint64_t Bit) {
      Context->ObjDumpSetRecordBitAddress(Bit);
    }
  
    void InstallType(Type *Ty) {
      Context->InstallType(Ty);
    }
  
    Type *GetType(uint32_t Index) {
      return Context->GetType(Index);
    }
  
    uint32_t GetNumTypes() const {
      return Context->GetNumTypes();
    }
  
    bool isValidValueType(Type *Ty) const {
      return Context->isValidValueType(Ty);
    }
  
    FunctionType *GetFunctionType(uint32_t Index) {
      return Context->GetFunctionType(Index);
    }
  
    uint32_t GetNumFunctions() const {
      return Context->GetNumFunctions();
    }
  
    void IncNumGlobals() {
      Context->IncNumGlobals();
    }
  
    uint32_t GetNumGlobals() const {
      return Context->GetNumGlobals();
    }
  
    void InstallFunctionType(FunctionType *Ty) {
      return Context->InstallFunctionType(Ty, Record.GetStartBit());
    }
  
    void InstallDefinedFunction(uint32_t Index) {
      Context->InstallDefinedFunction(Index);
    }
  
    BitcodeId GetBitcodeId(uint32_t Id) {
      return Context->GetBitcodeId(Id);
    }
  
    void InstallParamType(Type *Ty) {
      Context->InstallParamType(Ty);
    }
  
    uint32_t GetNumParams() const {
      return Context->GetNumParams();
    }
    void InstallConstantType(Type *ConstantType) {
      Context->InstallConstantType(ConstantType);
    }
  
    Type *GetConstantType(uint32_t Index) {
      return Context->GetConstantType(Index);
    }
  
    uint32_t GetNumConstants() const {
      return Context->GetNumConstants();
    }
  
    void InstallInstType(Type *Ty, uint32_t Index) {
      Context->InstallInstType(Ty, Index);
    }
  
    void InstallInstType(Type *Ty) {
      Context->InstallInstType(Ty);
    }
  
    uint32_t GetNumValuedInstructions() const {
      return Context->GetNumValuedInstructions();
    }
  
    Type *GetValueType(uint32_t Id, bool UnderlyingType = false) {
      return Context->GetValueType(Id, UnderlyingType);
    }
  
    Type *GetFunctionValueType(uint32_t Id) {
      return GetValueType(Id, /* UnderlyingType = */ true);
    }
  
    Type *GetUnknownType() const {
      return Context->GetUnknownType();
    }
  
    Type *GetPointerType() const {
      return Context->GetPointerType();
    }
  
    Type *GetComparisonType() const {
      return Context->GetComparisonType();
    }
  
    Type *GetVoidType() const {
      return Context->GetVoidType();
    }
  
    Type *GetFloatType() const {
      return Context->GetFloatType();
    }
  
    Type *GetDoubleType() const {
      return Context->GetDoubleType();
    }
  
    Type *GetIntegerType(unsigned Size) const {
      return Context->GetIntegerType(Size);
    }
  
    const char *VerifyIntArithmeticOp(const char *Op, Type *OpTy) {
      return Context->VerifyIntArithmeticOp(Op, OpTy);
    }
  
  protected:
    // The context parser that contains decoding state.
    NaClDisTopLevelParser *Context;
    // The number of global abbreviations defined for this block.
    unsigned NumGlobalAbbreviations;
    // The current number of local abbreviations defined for this block.
    unsigned NumLocalAbbreviations;
  };
  
  bool NaClDisBlockParser::ParseBlock(unsigned BlockId) {
    // Only called if we don't know the details about the block.
    ObjDumpSetRecordBitAddress(GetBlock().GetStartBit());
    Errors() << "Don't know how to parse block " << BlockId
             << ", when in block " << GetBlockID() << "\n";
    NaClDisBlockParser Parser(BlockId, this);
    return Parser.ParseThisBlock();
  }
  
  void NaClDisBlockParser::PrintBlockHeader() {
    Errors() << "Unknown block id found: " << GetBlockID() << "\n";
    Tokens() << "unknown" << Space() << OpenCurly()
             << Space() << Space() << "// BlockID = "
             << GetBlockID() << Endline();
  }
  
  void NaClDisBlockParser::EnterBlock(unsigned NumWords) {
    PrintBlockHeader();
    DumpEnterBlockRecord();
    IncRecordIndent();
    IncAssemblyIndent();
  }
  
  void NaClDisBlockParser::ExitBlock() {
    DecAssemblyIndent();
    DecRecordIndent();
    Tokens() << CloseCurly() << Endline();
    NaClBitcodeRecordData Exit;
    Exit.Code = naclbitc::BLK_CODE_EXIT;
    ObjDumpWrite(Record.GetStartBit(), Exit, naclbitc::END_BLOCK);
  }
  
  void NaClDisBlockParser::DumpEnterBlockRecord() {
    // TODO(kschimpf): Better integrate this with the bitstream reader
    // (which currently doesn't build any records).
    NaClBitcodeRecordData Enter;
    Enter.Code = naclbitc::BLK_CODE_ENTER;
    Enter.Values.push_back(GetBlockID());
    Enter.Values.push_back(Record.GetCursor().getAbbrevIDWidth());
    ObjDumpWrite(GetBlock().GetStartBit(), Enter, naclbitc::ENTER_SUBBLOCK);
  }
  
  void NaClDisBlockParser::ProcessAbbreviation(unsigned BlockID,
                                               NaClBitCodeAbbrev *Abbrev,
                                               bool IsLocal) {
    Tokens() << NextLocalAbbreviationId() << Space() << "=" << Space()
             << "abbrev" << Space() << TokenizeAbbreviation(Abbrev)
             << Semicolon() << Endline();
    ++NumLocalAbbreviations;
    ObjDumpWrite(Record.GetStartBit(), Record);
  }
  
  void NaClDisBlockParser::ProcessRecord() {
    // Note: Only called if block is not understood. Hence, we
    // only report the records.
    ObjDumpWrite(Record.GetStartBit(), Record);
  }
  
  /// Parses and disassembles the blockinfo block.
  class NaClDisBlockInfoParser : public NaClDisBlockParser {
  public:
    NaClDisBlockInfoParser(unsigned BlockID,
                           NaClDisBlockParser *EnclosingParser)
        : NaClDisBlockParser(BlockID, EnclosingParser) {
    }
  
    ~NaClDisBlockInfoParser() override {}
  
  private:
    void PrintBlockHeader() override;
  
    void SetBID() override;
  
    void ProcessAbbreviation(unsigned BlockID, NaClBitCodeAbbrev *Abbrev,
                             bool IsLocal) override;
  
    /// Returns the abbreviation id for the next global abbreviation
    /// to be defined for the given block id.
    BitcodeId NextGlobalAbbreviationId(unsigned BlockID) {
      return BitcodeId('a', Context->GetNumGlobalAbbreviations(BlockID), true);
    }
  };
  
  void NaClDisBlockInfoParser::PrintBlockHeader() {
    Tokens() << "abbreviations" << Space() << OpenCurly()
             << Space() << Space() << "// BlockID = "
             << GetBlockID() << Endline();
  }
  
  void NaClDisBlockInfoParser::SetBID() {
    std::string BlockName;
    uint64_t BlockID = Record.GetValues()[0];
    switch (BlockID) {
    case naclbitc::MODULE_BLOCK_ID:
      Tokens() << "module";
      break;
    case naclbitc::CONSTANTS_BLOCK_ID:
      Tokens() << "constants";
      break;
    case naclbitc::FUNCTION_BLOCK_ID:
      Tokens() << "function";
      break;
    case naclbitc::VALUE_SYMTAB_BLOCK_ID:
      Tokens() << "valuesymtab";
      break;
    case naclbitc::TYPE_BLOCK_ID_NEW:
      Tokens() << "types";
      break;
    case naclbitc::GLOBALVAR_BLOCK_ID:
      Tokens() << "globals";
      break;
    default:
      Tokens() << "block" << OpenParen() << BlockID << CloseParen();
      Errors() << "Block id " << BlockID << " not understood.\n";
      break;
    }
    Tokens() << Colon() << Endline();
    ObjDumpWrite(Record.GetStartBit(), Record);
  }
  
  void NaClDisBlockInfoParser::ProcessAbbreviation(unsigned BlockID,
                                                   NaClBitCodeAbbrev *Abbrev,
                                                   bool IsLocal) {
    IncAssemblyIndent();
    Tokens() << NextGlobalAbbreviationId(BlockID) << Space() << "=" << Space()
             << "abbrev" << Space() << TokenizeAbbreviation(Abbrev)
             << Semicolon() << Endline();
    Context->IncNumGlobalAbbreviations(BlockID);
    DecAssemblyIndent();
    ObjDumpWrite(Record.GetStartBit(), Record);
  }
  
  /// Parses and disassembles the types block.
  class NaClDisTypesParser : public NaClDisBlockParser {
  public:
    NaClDisTypesParser(unsigned BlockID,
                       NaClDisBlockParser *EnclosingParser)
        : NaClDisBlockParser(BlockID, EnclosingParser),
          ExpectedNumTypes(0),
          IsFirstRecord(true)
    {
    }
  
    ~NaClDisTypesParser() override;
  
  private:
    void PrintBlockHeader() override;
  
    void ProcessRecord() override;
  
    /// Returns the value id for the next type to be defined.
    BitcodeId NextTypeId() {
      return BitcodeId('t', GetNumTypes());
    }
  
    // Installs unknown type as definition of next type.
    void InstallUnknownTypeForNextId();
  
  
    uint32_t ExpectedNumTypes;
    bool IsFirstRecord;
  };
  
  NaClDisTypesParser::~NaClDisTypesParser() {
    if (GetNumTypes() != ExpectedNumTypes) {
      Errors() << "Expected " << ExpectedNumTypes << " types but found: "
               << GetNumTypes() << "\n";
    }
  }
  
  void NaClDisTypesParser::PrintBlockHeader() {
    Tokens() << "types" << Space() << OpenCurly()
             << Space() << Space() << "// BlockID = " << GetBlockID()
             << Endline();
  }
  
  void NaClDisTypesParser::InstallUnknownTypeForNextId() {
    Type *UnknownType = GetUnknownType();
    Tokens() << NextTypeId() << Space() << "=" << Space()
             << TokenizeType(UnknownType) << Semicolon()
             << TokenizeAbbrevIndex() << Endline();
    InstallType(UnknownType);
  }
  
  void NaClDisTypesParser::ProcessRecord() {
    ObjDumpSetRecordBitAddress(Record.GetStartBit());
    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
    switch (Record.GetCode()) {
    case naclbitc::TYPE_CODE_NUMENTRY: {
      // NUMENTRY: [numentries]
      uint64_t Size = 0;
      if (Values.size() == 1) {
        Size = Values[0];
      } else {
        Errors() << "Count record should have 1 argument. Found: "
                 << Values.size() << "\n";
      }
      if (!IsFirstRecord) {
        Errors() << "Count record not first record of types block\n";
      }
      Tokens() << "count" << Space() << Size << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      ExpectedNumTypes = Size;
      break;
    }
    case naclbitc::TYPE_CODE_VOID: {
      // VOID
      if (!Values.empty())
        Errors() << "Void record shouldn't have arguments. Found: "
                 << Values.size() << "\n";
      Type *VoidType = GetVoidType();
      Tokens() << NextTypeId() << Space() << "=" << Space()
               << TokenizeType(VoidType) << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      InstallType(VoidType);
      break;
    }
    case naclbitc::TYPE_CODE_FLOAT: {
      // FLOAT
      if (!Values.empty())
        Errors() << "Float record shoudn't have arguments. Found: "
                 << Values.size() << "\n";
      Type *FloatType = GetFloatType();
      Tokens() << NextTypeId() << Space() << "=" << Space()
               << TokenizeType(FloatType) << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      InstallType(FloatType);
      break;
    }
    case naclbitc::TYPE_CODE_DOUBLE: {
      // DOUBLE
      if (!Values.empty())
        Errors() << "Double record shound't have arguments. Found: "
                 << Values.size() << "\n";
      Type *DoubleType = GetDoubleType();
      Tokens() << NextTypeId() << Space() << "=" << Space()
               << TokenizeType(DoubleType) << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      InstallType(DoubleType);
      break;
    }
    case naclbitc::TYPE_CODE_INTEGER: {
      // INTEGER: [width]
      uint64_t Size;
      if (Values.size() == 1) {
        Size = Values[0];
      } else {
        Errors() << "Integer record should have one argument. Found: "
                 << Values.size() << "\n";
        Size = 32;
      }
      switch (Size) {
        case 1:
        case 8:
        case 16:
        case 32:
        case 64: {
          break;
        }
        default:
          if (!IgnorePNaClABIChecks) {
            Errors() << "Integer record contains bad integer size: "
                     << Size << "\n";
            Size = 32;
          }
          break;
      }
      Type *IntType = GetIntegerType(Size);
      Tokens() << NextTypeId() << Space() << "=" << Space()
               << TokenizeType(IntType) << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      InstallType(IntType);
      break;
    }
    case naclbitc::TYPE_CODE_VECTOR: {
      // VECTOR: [numelts, eltty]
      if (Values.size() != 2) {
        Errors() << "Vector record should contain two arguments. Found: "
                 << Values.size() << "\n";
        InstallUnknownTypeForNextId();
        break;
      }
      Type *BaseType = GetType(Values[1]);
      if (!(BaseType->isIntegerTy()
            || BaseType->isFloatTy()
            || BaseType->isDoubleTy())) {
        Type *ErrorRecoveryTy = GetIntegerType(32);
        Errors() << "Vectors can only be defined on primitive types. Found "
                 << *BaseType << ". Assuming " << *ErrorRecoveryTy
                 << " instead.\n";
        BaseType = ErrorRecoveryTy;
      }
      uint64_t NumElements = Values[0];
      Type *VecType = VectorType::get(BaseType, NumElements);
      if (!IgnorePNaClABIChecks &&
          !PNaClABITypeChecker::isValidVectorType(VecType)) {
        Errors() << "Vector type " << *VecType << " not allowed.\n";
      }
      Tokens() << NextTypeId() << Space() << "=" << Space()
               << TokenizeType(VecType) << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      InstallType(VecType);
      break;
    }
    case naclbitc::TYPE_CODE_FUNCTION: {
      // FUNCTION: [vararg, retty, paramty x N]
      if (Values.size() < 2) {
        Errors()
            << "Function record should contain at least 2 arguments. Found: "
            << Values.size() << "\n";
        InstallUnknownTypeForNextId();
        break;
      }
      if (Values[0]) {
        Errors() << "Functions with variable length arguments is not supported\n";
      }
      Type *ReturnType = GetType(Values[1]);
      if (!(isValidValueType(ReturnType) || ReturnType->isVoidTy())) {
        Type *ReplaceType = GetIntegerType(32);
        Errors() << "Invalid return type. Found: " << *ReturnType
                 << ". Assuming: " << *ReplaceType << "\n";
        ReturnType = ReplaceType;
      }
      SmallVector<Type*, 8> Signature;
      for (size_t i = 2; i < Values.size(); ++i) {
        Type *Ty = GetType(Values[i]);
        if (!isValidValueType(Ty)) {
          Type *ReplaceTy = GetIntegerType(32);
          Errors() << "Invalid type for parameter " << (i - 1) << ". Found: "
                   << *Ty << ". Assuming: " << *ReplaceTy << "\n";
          Ty = ReplaceTy;
        }
        Signature.push_back(Ty);
      }
      Type *FcnType =  FunctionType::get(ReturnType, Signature, Values[0]);
      Tokens() << NextTypeId() << Space() << "=" << Space()
               << StartCluster() << TokenizeType(FcnType)
               << Semicolon() << FinishCluster() << TokenizeAbbrevIndex()
               << Endline();
      InstallType(FcnType);
      break;
    }
    default:
      Errors() << "Unknown record code in types block. Found: "
               << Record.GetCode() << "\n";
      break;
    }
    ObjDumpWrite(Record.GetStartBit(), Record);
    IsFirstRecord = false;
  }
  
  /// Parses and disassembles the globalvars block.
  class NaClDisGlobalsParser : public NaClDisBlockParser {
  public:
    NaClDisGlobalsParser(unsigned BlockID,
                         NaClDisBlockParser *EnclosingParser)
        : NaClDisBlockParser(BlockID, EnclosingParser),
          NumInitializers(0),
          InsideCompound(false),
          BaseTabs(GetAssemblyNumTabs()+1) {}
  
    ~NaClDisGlobalsParser() override {}
  
  private:
    void PrintBlockHeader() override;
  
    void ProcessRecord() override;
  
    void ExitBlock() override;
  
    // Expected number of initializers associated with last globalvars
    // record
    uint32_t NumInitializers;
    // True if last globalvars record was defined by a compound record.
    bool InsideCompound;
    // Number of tabs used to indent elements in the globals block.
    unsigned BaseTabs;
  
    // Returns the ID for the next defined global.
    BitcodeId NextGlobalId() {
      return BitcodeId('g', GetNumGlobals());
    }
  
    // Prints out the close initializer "}" if necessary, and fixes
    // the indentation to match previous indentation.
    void InsertCloseInitializer();
  
    uint32_t GetExpectedNumGlobals() const {
      return Context->GetExpectedNumGlobals();
    }
  };
  
  void NaClDisGlobalsParser::PrintBlockHeader() {
    Tokens() << "globals" << Space() << OpenCurly()
             << Space() << Space() << "// BlockID = " << GetBlockID()
             << Endline();
  }
  
  void NaClDisGlobalsParser::InsertCloseInitializer() {
    if (InsideCompound) {
      while (BaseTabs + 1 < GetAssemblyNumTabs()) DecAssemblyIndent();
      Tokens() << CloseCurly() << Endline();
    }
    while (BaseTabs < GetAssemblyNumTabs()) DecAssemblyIndent();
    ObjDumpFlush();
    NumInitializers = 0;
    InsideCompound = false;
  }
  
  void NaClDisGlobalsParser::ExitBlock() {
    if (NumInitializers > 0) {
      BitcodeId LastGlobal('g', (GetNumGlobals()-1));
      Errors() << "More initializers for " << LastGlobal << " expected: "
               << NumInitializers << "\n";
    }
    if (GetNumGlobals() != GetExpectedNumGlobals()) {
      Errors() << "Expected " << GetExpectedNumGlobals()
               << " globals but found: " << GetNumGlobals() << "\n";
    }
    NaClDisBlockParser::ExitBlock();
  }
  
  void NaClDisGlobalsParser::ProcessRecord() {
    ObjDumpSetRecordBitAddress(Record.GetStartBit());
    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
    switch (Record.GetCode()) {
    case naclbitc::GLOBALVAR_VAR: {
      // VAR: [align, isconst]
      if (Values.size() != 2) {
        Errors() << "Globalvar record expects two arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      if (GetNumGlobals() == GetExpectedNumGlobals()) {
        Errors() << "Exceeded expected number of globals: "
                 << GetExpectedNumGlobals() << "\n";
      }
      if (NumInitializers > 0) {
        Errors() << "Previous initializer list too short. Expects "
                 << NumInitializers << " more initializers\n";
        InsertCloseInitializer();
      }
      uint32_t Alignment = (1 << Values[0]) >> 1;
      Tokens() << StartCluster() << (Values[1] ? "const" : "var")
               << Space() << NextGlobalId()
               << Comma() << FinishCluster() << Space()
               << StartCluster() << "align" << Space() << Alignment
               << Comma() << FinishCluster() << TokenizeAbbrevIndex()
               << Endline();
      IncAssemblyIndent();
      IncNumGlobals();
      NumInitializers = 1;
      break;
    }
    case naclbitc::GLOBALVAR_COMPOUND:
      // COMPOUND: [size]
      if (Values.size() != 1) {
        Errors() << "Compound record expects one argument. Found: "
                 << Values.size() << "\n";
        break;
      }
      if (NumInitializers == 1) {
        if (InsideCompound) {
          Errors() << "Nested initialization records not allowed\n";
          InsertCloseInitializer();
        }
      } else {
        Errors() << "Compound record must follow globalvars record\n";
        InsertCloseInitializer();
      }
      Tokens() << StartCluster() << "initializers" << Space()
               << Values[0] << FinishCluster() << Space()
               << OpenCurly() << TokenizeAbbrevIndex() << Endline();
      IncAssemblyIndent();
      NumInitializers = Values[0];
      InsideCompound = true;
      break;
    case naclbitc::GLOBALVAR_ZEROFILL:
      // ZEROFILL: [size]
      if (Values.size() != 1) {
        Errors() << "Zerofill record expects one argument. Found: "
                 << Values.size() << "\n";
        break;
      }
      if (NumInitializers == 0) {
        Errors() << "Zerofill initializer not associated with globalvar record\n";
      }
      Tokens() << "zerofill" << Space() << Values[0] << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      --NumInitializers;
      break;
    case naclbitc::GLOBALVAR_DATA: {
      // DATA: [b0, b1, ...]
      if (Values.empty()) {
        Errors() << "Globals data record must have arguments.\n";
      }
      if (NumInitializers == 0) {
        Errors() << "Data initializer not associated with globalvar record\n";
      }
      Tokens() << StartCluster() << OpenCurly();
      for (size_t i = 0; i < Values.size(); ++i) {
        if (i > 0) Tokens() << Comma() << FinishCluster() << Space();
        uint64_t Byte = Values[i];
        if (Byte >= 256) {
          Errors() << "Invalid byte value in data record: " << Byte << "\n";
          Byte &= 0xFF;
        }
        if (i > 0) Tokens() << StartCluster();
        Tokens() << format("%3u", static_cast<unsigned>(Byte));
      }
      Tokens() << CloseCurly() << FinishCluster() << TokenizeAbbrevIndex()
               << Endline();
      --NumInitializers;
      break;
    }
    case naclbitc::GLOBALVAR_RELOC:
      // RELOC: [val, [addend]]
      if (Values.empty() || Values.size() > 2) {
        Errors() << "Invalid reloc record size: " << Values.size() << "\n";
        break;
      }
      if (NumInitializers == 0) {
        Errors() <<
            "Relocation initializer not associated with globalvar record\n";
      }
      Tokens() << "reloc" << Space() << StartCluster() << GetBitcodeId(Values[0]);
      if (Values.size() == 2) {
        int32_t Addend = static_cast<int32_t>(Values[1]);
        char Operator = '+';
        if (Addend < 0) {
          Operator = '-';
          Addend = -Addend;
        }
        Tokens() << Space()<< Operator << Space() << Addend;
      }
      Tokens() << Semicolon() << FinishCluster() << TokenizeAbbrevIndex()
               << Endline();
      --NumInitializers;
      break;
    case naclbitc::GLOBALVAR_COUNT: {
      // COUNT: [n]
      uint32_t Count = 0;
      if (Values.size() == 1) {
        Count = Values[0];
      } else {
        Errors() << "Globals count record expects one argument. Found: "
                 << Values.size() << "\n";
      }
      if (GetNumGlobals() != 0)
        Errors() << "Count record not first record in block.\n";
      Tokens() << "count" << Space() << Count << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      Context->SetExpectedNumGlobals(Count);
      break;
    }
    default:
      Errors() << "Unknown record found in globals block.\n";
    }
  
    ObjDumpWrite(Record.GetStartBit(), Record);
  
    if (GetNumGlobals() > 0 && NumInitializers == 0)
      InsertCloseInitializer();
  }
  
  /// Parsers and disassembles a valuesymtab block.
  class NaClDisValueSymtabParser : public NaClDisBlockParser {
  public:
    NaClDisValueSymtabParser(unsigned BlockID,
                             NaClDisBlockParser *EnclosingParser)
        : NaClDisBlockParser(BlockID, EnclosingParser) {
    }
  
    ~NaClDisValueSymtabParser() override {}
  
  private:
    void PrintBlockHeader() override;
  
    void ProcessRecord() override;
  
    // Displays the context of the name (in Values) for the given Id.
    void DisplayEntry(BitcodeId &Id,
                      const NaClBitcodeRecord::RecordVector &Values);
  };
  
  void NaClDisValueSymtabParser::PrintBlockHeader() {
    Tokens() << "valuesymtab" << Space() << OpenCurly()
             << Space() << Space() << "// BlockID = " << GetBlockID()
             << Endline();
  }
  
  void NaClDisValueSymtabParser::
  DisplayEntry(BitcodeId &Id,
               const NaClBitcodeRecord::RecordVector &Values) {
    if (Values.size() <= 1) {
      Errors() << "Valuesymtab entry record expects 2 arguments. Found: "
               << Values.size() << "\n";
      return;
    }
    Tokens() << Id << Space() << Colon() << Space();
    // Check if the name of the symbol is alphanumeric. If so, print
    // as a string. Otherwise, print a sequence of bytes.
    // Note: The check isChar6 is a test for aphanumeric + {'.', '_'}.
    bool IsChar6 = true;  // Until proven otherwise.
    for (size_t i = 1; i < Values.size(); ++i) {
      uint64_t Byte = Values[i];
      if (Byte >= 256) {
        Errors() << "Argument " << i << " of symbol entry not byte: "
                 << Byte << "\n";
        IsChar6 = false;
        break;
      }
      if (!NaClBitCodeAbbrevOp::isChar6(Byte))
        IsChar6 = false;
    }
    if (IsChar6) {
      Tokens() << StartCluster() << "\"";
      for (size_t i = 1; i < Values.size(); ++i) {
        Tokens() << static_cast<char>(Values[i]);
      }
      Tokens() << "\"" << Semicolon();
    } else {
      Tokens() << StartCluster() << OpenCurly();
      for (size_t i = 1; i < Values.size(); ++i) {
        if (i > 1) {
          Tokens() << Comma() << FinishCluster() << Space()
                   << StartCluster();
        }
        char ch = Values[i];
        if (NaClBitCodeAbbrevOp::isChar6(ch)) {
          Tokens() << "'" << ch << "'";
        } else {
          Tokens() << format("%3u", static_cast<unsigned>(ch));
        }
      }
      Tokens() << CloseCurly();
    }
    Tokens() << FinishCluster() << TokenizeAbbrevIndex() << Endline();
  }
  
  void NaClDisValueSymtabParser::ProcessRecord() {
    ObjDumpSetRecordBitAddress(Record.GetStartBit());
    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
    switch (Record.GetCode()) {
    case naclbitc::VST_CODE_ENTRY: {
      // VST_ENTRY: [valueid, namechar x N]
      uint32_t ValID = Values[0];
      BitcodeId ID(GetBitcodeId(ValID));
      DisplayEntry(ID, Values);
      if (ValID < GetNumFunctions()) {
        // Check if value is intrinsic name. If so, verify function signature.
        std::string Name;
        for (unsigned i = 1; i < Values.size(); ++i) {
          Name.push_back(static_cast<char>(Values[i]));
        }
        FunctionType *IntrinTy = Context->GetIntrinsicType(Name);
        if (IntrinTy == 0)
          // TODO(kschimpf): Check for _start? Complain about other names?
          break;
        Context->MarkFunctionAsIntrinsic(ValID);
        // Verify that expected intrinsic function type matches declared
        // type signature.
        FunctionType *FcnTy = GetFunctionType(ValID);
        if (FcnTy->getNumParams() != IntrinTy->getNumParams()) {
          Errors() << "Intrinsic " << Name
                   << " expects " << IntrinTy->getNumParams()
                   << " arguments. Found: " << FcnTy->getNumParams()
                   << "\n";
          break;
        }
        if (!IgnorePNaClABIChecks && !PNaClABITypeChecker::IsPointerEquivType(
                IntrinTy->getReturnType(), FcnTy->getReturnType())) {
          Errors() << "Intrinsic " << Name
                   << " expects return type " << *IntrinTy->getReturnType()
                   << ". Found: " << *FcnTy->getReturnType() << "\n";
          break;
        }
        for (size_t i = 0; i < FcnTy->getNumParams(); ++i) {
          if (!IgnorePNaClABIChecks && !PNaClABITypeChecker::IsPointerEquivType(
                  IntrinTy->getParamType(i),
                  FcnTy->getParamType(i))) {
            Errors() << "Intrinsic " << Name
                     << " expects " << *IntrinTy->getParamType(i)
                     << " for argument " << (i+1) << ". Found: "
                     << *FcnTy->getParamType(i) << "\n";
            break;
          }
        }
      }
      break;
    }
    case naclbitc::VST_CODE_BBENTRY: {
      // [bbid, namechar x N]
      BitcodeId ID('b', Values[0]);
      DisplayEntry(ID, Values);
      break;
    }
    default:
      Errors() << "Unknown record in valuesymtab block.\n";
      break;
    }
    ObjDumpWrite(Record.GetStartBit(), Record);
  }
  
  /// Parses and disassembles a constants block.
  class NaClDisConstantsParser : public NaClDisBlockParser {
  public:
    NaClDisConstantsParser(unsigned BlockID,
                           NaClDisBlockParser *EnclosingParser)
        : NaClDisBlockParser(BlockID, EnclosingParser),
          ConstantType(0),
          BlockTabs(GetAssemblyNumTabs()) {}
  
    virtual ~NaClDisConstantsParser() {
      while (BlockTabs < GetAssemblyNumTabs()) DecAssemblyIndent();
    }
  
  private:
    void PrintBlockHeader() override;
  
    void ProcessRecord() override;
  
    /// Generates the value id for the next generated constant.
    BitcodeId NextConstId() {
      return BitcodeId('c', GetNumConstants());
    }
  
    // The type associated with the constant.
    Type *ConstantType;
    // The number of tabs used to indent the globals block.
    unsigned BlockTabs;
  };
  
  void NaClDisConstantsParser::PrintBlockHeader() {
    Tokens() << "constants" << Space() << OpenCurly()
             << Space() << Space() << "// BlockID = " << GetBlockID()
             << Endline();
  }
  
  void NaClDisConstantsParser::ProcessRecord() {
    ObjDumpSetRecordBitAddress(Record.GetStartBit());
    const NaClBitcodeRecord::RecordVector Values = Record.GetValues();
    switch (Record.GetCode()) {
    case naclbitc::CST_CODE_SETTYPE:
      // SETTYPE: [typeid]
      while (BlockTabs + 1 < GetAssemblyNumTabs()) DecAssemblyIndent();
      if (Values.size() == 1) {
        ConstantType = GetType(Values[0]);
        Tokens() << TokenizeType(ConstantType) << ":"
                 << TokenizeAbbrevIndex() << Endline();
      } else {
        Errors() << "Settype record should have 1 argument. Found: "
                 << Values.size() << "\n";
        // Make up a type, so we can continue.
        ConstantType = GetIntegerType(32);
      }
      IncAssemblyIndent();
      break;
    case naclbitc::CST_CODE_UNDEF:
      // CST_CODE_UNDEF: []
      if (!Values.empty()) {
        Errors() << "Undefined record should not have arguments: Found: "
                 << Values.size() << "\n";
      }
      Tokens() << NextConstId() << Space() << "=" << Space()
               << StartCluster() << TokenizeType(ConstantType)
               << Space() << "undef"
               << Semicolon() << FinishCluster()
               << TokenizeAbbrevIndex() << Endline();
      InstallConstantType(ConstantType);
      break;
    case naclbitc::CST_CODE_INTEGER: {
      // INTEGER: [intval]
      SignRotatedInt Value;
      if (Values.size() == 1) {
        const SignRotatedInt MyValue(Values[0], ConstantType);
        Value = MyValue;
      } else {
        Errors() << "Integer record should have 1 argument. Found: "
                 << Values.size() << "\n";
      }
      Tokens() << NextConstId() << Space() << "=" << Space() << StartCluster()
               << StartCluster() << TokenizeType(ConstantType) << Space()
               << Value << Semicolon() << FinishCluster() << FinishCluster()
               << TokenizeAbbrevIndex() << Endline();
      InstallConstantType(ConstantType);
      break;
    }
    case naclbitc::CST_CODE_FLOAT: {
      // FLOAT: [fpval]
      // Define initially with default value zero, in case of errors.
      const fltSemantics &FloatRep =
          ConstantType->isFloatTy() ? APFloat::IEEEsingle : APFloat::IEEEdouble;
      APFloat Value(APFloat::getZero(FloatRep));
      if (Values.size() == 1) {
        if (ConstantType->isFloatTy()) {
          Value = APFloat(FloatRep, APInt(32, static_cast<uint32_t>(Values[0])));
        }
        else if (ConstantType->isDoubleTy()) {
          Value = APFloat(FloatRep, APInt(64, Values[0]));
        } else {
          Errors() << "Bad floating point constant argument: "
                   << Values[0] << "\n";
        }
      } else {
        Errors() << "Float record should have 1 argument. Found: "
                 << Values.size() << "\n";
      }
      Tokens() << NextConstId() << Space() << "=" << Space() << StartCluster()
               << TokenizeType(ConstantType) << Space();
      if (ConstantType->isFloatTy()) {
        Tokens() << format("%g", Value.convertToFloat());
      } else {
        Tokens() << format("%g", Value.convertToDouble());
      }
      Tokens() << Semicolon() << FinishCluster()
               << TokenizeAbbrevIndex() << Endline();
      InstallConstantType(ConstantType);
      break;
    }
    default:
      Errors() << "Unknown record in valuesymtab block.\n";
      break;
    }
    ObjDumpWrite(Record.GetStartBit(), Record);
  }
  
  /// Parses and disassembles function blocks.
  class NaClDisFunctionParser : public NaClDisBlockParser {
  public:
    NaClDisFunctionParser(unsigned BlockID,
                          NaClDisBlockParser *EnclosingParser);
  
    ~NaClDisFunctionParser() override {}
  
    void PrintBlockHeader() override;
  
    bool ParseBlock(unsigned BlockID) override;
  
    void ProcessRecord() override;
  
    /// Returns the absolute value index of the first instruction that
    /// generates a value in the defined function.
    uint32_t FirstValuedInstructionId() const {
      return GetNumFunctions() + GetNumGlobals() + GetNumParams()
          + GetNumConstants();
    }
  
    /// Converts an instruction index to the corresponding absolute value
    /// index.
    uint32_t ValuedInstToAbsId(uint32_t Id) const {
      return FirstValuedInstructionId() + Id;
    }
  
    /// Converts the (function) relative index to the corresponding
    /// absolute value index.
    uint32_t RelativeToAbsId(int32_t Id) {
      uint32_t AbsNextId = ValuedInstToAbsId(GetNumValuedInstructions());
      if (Id > 0 && AbsNextId < static_cast<uint32_t>(Id)) {
        Errors() << "Invalid relative value id: " << Id
                 << " (Must be <= " << AbsNextId << ")\n";
        AbsNextId = Id;
      }
      return AbsNextId - Id;
    }
  
    /// Converts the given absolute value index to a corresponding
    /// valued instruction index.
    uint32_t AbsToValuedInstId(uint32_t Id) const {
      return Id - FirstValuedInstructionId();
    }
  
    /// Returns the text representation of the encoded binary operator,
    /// assuming the binary operator is operating on the given type.
    /// Generates appropriate error messages if the given type is not
    // allowed for the given Opcode.
    const char *GetBinop(uint32_t Opcode, Type *Type);
  
    /// Returns the text representation of the encoded cast operator.
    /// Generates appropriate error messages if the given Opcode is
    /// not allowed for the given types.
    const char *GetCastOp(uint32_t Opcode, Type *FromType, Type *ToType);
  
    /// Returns the text representation of the encoded integer compare
    /// predicate. Generates appropriate error message if the given
    /// Opcode is not defined.
    const char *GetIcmpPredicate(uint32_t Opcode);
  
    /// Returns the text representation of the encoded floating point
    /// compare predicate. Generates appropriate error message if the
    /// given Opcode is not defined.
    const char *GetFcmpPredicate(uint32_t Opcode);
  
    /// Returns the value id for the next instruction to be defined.
    BitcodeId NextInstId() const {
      return BitcodeId('v', GetNumValuedInstructions());
    }
  
  private:
    // The function index of the function being defined.
    uint32_t FcnId;
    // The function type for the function being defined.
    FunctionType *FcnTy;
    // The current basic block being printed.
    int32_t CurrentBbIndex;
    // The expected number of basic blocks.
    uint64_t ExpectedNumBbs;
    // True if the previously printed instruction was a terminating
    // instruction. Used to figure out where to insert block labels.
    bool InstIsTerminating;
  
    /// Returns scalar type of vector type Ty, if vector type. Otherwise
    /// returns Ty.
    Type *UnderlyingType(Type *Ty) {
      return Ty->isVectorTy() ? Ty->getVectorElementType() : Ty;
    }
  
    bool isFloatingType(Type *Ty) {
      return Ty->isFloatTy() || Ty->isDoubleTy();
    }
  
    /// Verifies that OpTy is an integer, or a vector of integers, for
    /// operator Op. Generates error messages if appropriate. Returns Op.
    const char *VerifyIntegerOrVectorOp(const char *Op, Type *OpTy) {
      Type *BaseTy = OpTy;
      if (OpTy->isVectorTy()) {
        if (!IgnorePNaClABIChecks &&
            !PNaClABITypeChecker::isValidVectorType(OpTy)) {
          Errors() << Op << ": invalid vector type: " << *OpTy << "\n";
          return Op;
        }
        BaseTy = OpTy->getVectorElementType();
      }
      if (BaseTy->isIntegerTy()) {
        if (IgnorePNaClABIChecks ||
            PNaClABITypeChecker::isValidScalarType(BaseTy)) {
          return Op;
        }
        Errors() << Op << ": Invalid integer type: " << *OpTy << "\n";
      } else {
        Errors() << Op << ": Expects integer type. Found: " << *OpTy << "\n";
      }
      return Op;
    }
  
    /// Verifies that Opty is a floating point type, or a vector of a
    /// floating points, for operator Op. Generates error messages if
    /// appropriate. Returns Op.
    const char *VerifyFloatingOrVectorOp(const char *Op, Type *OpTy) {
      Type *BaseTy = OpTy;
      if (OpTy->isVectorTy()) {
        if (!IgnorePNaClABIChecks &&
            !PNaClABITypeChecker::isValidVectorType(OpTy)) {
          Errors() << Op << ": invalid vector type: " << *OpTy << "\n";
          return Op;
        }
        BaseTy = OpTy->getVectorElementType();
      }
      if (!isFloatingType(BaseTy)) {
        Errors() << Op << ": Expects floating point. Found "
                 << OpTy << "\n";
        return Op;
      }
      if (!IgnorePNaClABIChecks &&
          !PNaClABITypeChecker::isValidScalarType(BaseTy)) {
        Errors() << Op << ": type not allowed: " << OpTy << "\n";
      }
      return Op;
    }
  
    /// Op is the name of the operation that called this.  Checks if
    /// OpTy is either a (non-void) scalar, or a vector of scalars. If
    /// not, generates an appropriate error message. Always returns Op.
    const char *VerifyScalarOrVectorOp(const char *Op, Type *OpTy) {
      if (IgnorePNaClABIChecks) return Op;
      if (PNaClABITypeChecker::isValidScalarType(OpTy)) {
        if (OpTy->isVoidTy())
          Errors() << Op << ": Type void not allowed\n";
      } else if (!PNaClABITypeChecker::isValidVectorType(OpTy)) {
        Errors() << Op << ": Expects scalar/vector type. Found: "
                 << OpTy << "\n";
      }
      return Op;
    }
  
    void VerifyIndexedVector(const char *Op, uint32_t VecValue,
                             uint32_t IdxValue) {
      Type *VecType = GetValueType(VecValue);
      Type *IdxType = GetValueType(IdxValue);
      if (!IgnorePNaClABIChecks &&
          !PNaClABITypeChecker::isValidVectorType(VecType)){
        if (VecType->isVectorTy())
          Errors() << Op << ": Vector type " << *VecType << " not allowed\n";
        else
          Errors() << Op << ": Vector type expected. Found: " << *VecType << "\n";
      }
      // Note: This restriction appears to be LLVM specific.
      if (!IdxType->isIntegerTy(32)) {
        Errors() << Op << ": Index not i32. Found: " << *IdxType << "\n";
      }
      BitcodeId IdxId(GetBitcodeId(IdxValue));
      if (IdxId.GetKind() != 'c') {
        Errors() << Op << ": Vector index not constant: " << IdxId << "\n";
        // TODO(kschimpf): We should check that Idx is a constant with
        // valid access. However, we currently don't store constant
        // values, so it can't be tested.
      }
    }
  
    /// Checks if block Value is a valid branch target for the current
    /// function block. If not, generates an appropriate error message.
    void VerifyBranchRange(uint64_t Value) {
      if (0 == Value || Value >= ExpectedNumBbs) {
        Errors() << "Branch " << BitcodeId('b', Value)
                 << " out of range. Not in [1," << ExpectedNumBbs << "]\n";
      }
    }
  
    /// Convert alignment exponent (i.e. power of two (or zero)) to the
    /// corresponding alignment to use. If alignment is too large, it generates
    /// an error message and returns 0.
    unsigned getAlignmentValue(uint64_t Exponent);
  };
  
  NaClDisFunctionParser::NaClDisFunctionParser(
      unsigned BlockID,
      NaClDisBlockParser *EnclosingParser)
      : NaClDisBlockParser(BlockID, EnclosingParser),
        CurrentBbIndex(-1),
        ExpectedNumBbs(0),
        InstIsTerminating(false) {
    Context->ResetLocalCounters();
    if (Context->HasNextDefinedFunctionIndex()) {
      FcnId = Context->GetNextDefinedFunctionIndex();
      FcnTy = GetFunctionType(FcnId);
    } else {
      FcnId = 0;
      SmallVector<Type*, 8> Signature;
      FcnTy = FunctionType::get(GetVoidType(), Signature, 0);
      Errors() <<
          "No corresponding defining function address for function block.\n";
      return;
    }
    Context->IncNumDefinedFunctions();
  
    // Now install parameters.
    for (size_t Index = 0; Index < FcnTy->getFunctionNumParams(); ++Index) {
      InstallParamType(FcnTy->getFunctionParamType(Index));
    }
  }
  
  void NaClDisFunctionParser::PrintBlockHeader() {
    Tokens() << "function" << Space();
    BitcodeId FunctionId('f', FcnId);
    bool InvalidSignature = true; // until proven otherwise.
    if (Context->IsFunctionIntrinsic(FcnId))
      InvalidSignature = false;
    else if (IgnorePNaClABIChecks ||
             PNaClABITypeChecker::isValidFunctionType(FcnTy)) {
        InvalidSignature = false;
    }
    if (InvalidSignature) {
      Errors() << "Invalid type signature for "
               << BitcodeId('f', FcnId) << ": " << *FcnTy << "\n";
    }
    Tokens() << TokenizeFunctionSignature(FcnTy, &FunctionId)
             << Space() << OpenCurly()
             << Space() << Space() << "// BlockID = " << GetBlockID()
             << Endline();
  }
  
  const char *NaClDisFunctionParser::GetBinop(uint32_t Opcode, Type *Ty) {
    Instruction::BinaryOps LLVMOpcode;
    if (!naclbitc::DecodeBinaryOpcode(Opcode, Ty, LLVMOpcode)) {
      Errors() << "Binary opcode not understood: " << Opcode << "\n";
      return "???";
    }
    switch (LLVMOpcode) {
    default:
      Errors() << "Binary opcode not understood: " << Opcode << "\n";
      return "???";
    case Instruction::Add:
      return VerifyIntArithmeticOp("add", Ty);
    case Instruction::FAdd:
      return VerifyFloatingOrVectorOp("fadd", Ty);
    case Instruction::Sub:
      return VerifyIntArithmeticOp("sub", Ty);
    case Instruction::FSub:
      return VerifyFloatingOrVectorOp("fsub", Ty);
    case Instruction::Mul:
      return VerifyIntArithmeticOp("mul", Ty);
    case Instruction::FMul:
      return VerifyFloatingOrVectorOp("fmul", Ty);
    case Instruction::UDiv:
      return VerifyIntArithmeticOp("udiv", Ty);
    case Instruction::SDiv:
      return VerifyIntArithmeticOp("sdiv", Ty);
    case Instruction::FDiv:
      return VerifyFloatingOrVectorOp("fdiv", Ty);
    case Instruction::URem:
      return VerifyIntArithmeticOp("urem", Ty);
    case Instruction::SRem:
      return VerifyIntArithmeticOp("srem", Ty);
    case Instruction::FRem:
      return VerifyFloatingOrVectorOp("frem", Ty);
    case Instruction::Shl:
      return VerifyIntArithmeticOp("shl", Ty);
    case Instruction::LShr:
      return VerifyIntArithmeticOp("lshr", Ty);
    case Instruction::AShr:
      return VerifyIntArithmeticOp("ashr", Ty);
    case Instruction::And:
      return VerifyIntegerOrVectorOp("and", Ty);
    case Instruction::Or:
      return VerifyIntegerOrVectorOp("or", Ty);
    case Instruction::Xor:
      return VerifyIntegerOrVectorOp("xor", Ty);
    }
  }
  
  const char *NaClDisFunctionParser::GetCastOp(uint32_t Opcode,
                                               Type *FromType, Type *ToType) {
    Instruction::CastOps Cast;
    const char *CastName = "???";
    if (!naclbitc::DecodeCastOpcode(Opcode, Cast)) {
      Errors() << "Cast opcode not understood: " << Opcode << "\n";
      return CastName;
    }
    switch (Cast) {
    default:
      Errors() << "Cast opcode not understood: " << Opcode << "\n";
      return CastName;
    case Instruction::BitCast:
      CastName = "bitcast";
      break;
    case Instruction::Trunc:
      CastName = "trunc";
      break;
    case Instruction::ZExt:
      CastName = "zext";
      break;
    case Instruction::SExt:
      CastName = "sext";
      break;
    case Instruction::FPToUI:
      CastName = "fptoui";
      break;
    case Instruction::FPToSI:
      CastName = "fptosi";
      break;
    case Instruction::UIToFP:
      CastName = "uitofp";
      break;
    case Instruction::SIToFP:
      CastName = "sitofp";
      break;
    case Instruction::FPTrunc:
      CastName = "fptrunc";
      break;
    case Instruction::FPExt:
      CastName = "fpext";
      break;
    }
    if (!CastInst::castIsValid(Cast, FromType, ToType)) {
      Errors() << "Invalid cast '" << CastName << "'. Not defined on "
               << FromType << " to " << ToType << "\n";
    }
    return CastName;
  }
  
  const char *NaClDisFunctionParser::GetIcmpPredicate(uint32_t Opcode) {
    CmpInst::Predicate Predicate;
    if (!naclbitc::DecodeIcmpPredicate(Opcode, Predicate)) {
      Errors() << "Icmp predicate not understood: " << Opcode << "\n";
      return "???";
    }
    switch (Predicate) {
    default:
      Errors() << "Icmp predicate not understood: " << Opcode << "\n";
      return "???";
    case CmpInst::ICMP_EQ:
      return "eq";
    case CmpInst::ICMP_NE:
      return "ne";
   case CmpInst::ICMP_UGT:
      return "ugt";
    case CmpInst::ICMP_UGE:
      return "uge";
    case CmpInst::ICMP_ULT:
      return "ult";
    case CmpInst::ICMP_ULE:
      return "ule";
    case CmpInst::ICMP_SGT:
      return "sgt";
    case CmpInst::ICMP_SGE:
      return "sge";
    case CmpInst::ICMP_SLT:
      return "slt";
    case CmpInst::ICMP_SLE:
      return "sle";
    }
  }
  
  const char *NaClDisFunctionParser::GetFcmpPredicate(uint32_t Opcode) {
    CmpInst::Predicate Predicate;
    if (!naclbitc::DecodeFcmpPredicate(Opcode, Predicate)) {
      Errors() << "Fcmp predicate not understood: " << Opcode << "\n";
      return "???";
    }
    switch (Predicate) {
    default:
      Errors() << "Fcmp predicate not understood: " << Opcode << "\n";
      return "???";
    case CmpInst::FCMP_FALSE:
      return "false";
    case CmpInst::FCMP_OEQ:
      return "oeq";
    case CmpInst::FCMP_OGT:
      return "ogt";
    case CmpInst::FCMP_OGE:
      return "oge";
    case CmpInst::FCMP_OLT:
      return "olt";
    case CmpInst::FCMP_OLE:
      return "ole";
    case CmpInst::FCMP_ONE:
      return "one";
    case CmpInst::FCMP_ORD:
      return "ord";
    case CmpInst::FCMP_UNO:
      return "uno";
    case CmpInst::FCMP_UEQ:
      return "ueq";
    case CmpInst::FCMP_UGT:
      return "ugt";
    case CmpInst::FCMP_UGE:
      return "uge";
    case CmpInst::FCMP_ULT:
      return "ult";
    case CmpInst::FCMP_ULE:
      return "ule";
    case CmpInst::FCMP_UNE:
      return "une";
    case CmpInst::FCMP_TRUE:
      return "true";
    }
  }
  
  namespace {
  
  static const unsigned MaxAlignmentExponent = 29;
  static_assert(
      (1u << MaxAlignmentExponent) == Value::MaximumAlignment,
      "Inconsistency between Value.MaxAlignment and PNaCl alignment limit");
  }
  
  unsigned NaClDisFunctionParser::getAlignmentValue(uint64_t Exponent) {
    if (Exponent > MaxAlignmentExponent + 1) {
      Errors() << "Alignment can't be greater than 2**" << MaxAlignmentExponent
               << ". Found: 2**" << (Exponent - 1) << "\n";
      return 0;
    }
    return (1 << static_cast<unsigned>(Exponent)) >> 1;
  }
  
  bool NaClDisFunctionParser::ParseBlock(unsigned BlockID) {
    ObjDumpSetRecordBitAddress(GetBlock().GetStartBit());
    switch (BlockID) {
    case naclbitc::CONSTANTS_BLOCK_ID: {
      NaClDisConstantsParser Parser(BlockID, this);
      return Parser.ParseThisBlock();
    }
    case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
      if (!PNaClAllowLocalSymbolTables) break;
      NaClDisValueSymtabParser Parser(BlockID, this);
      return Parser.ParseThisBlock();
    }
    default:
      break;
    }
    return NaClDisBlockParser::ParseBlock(BlockID);
  }
  
  void NaClDisFunctionParser::ProcessRecord() {
    ObjDumpSetRecordBitAddress(Record.GetStartBit());
    const NaClBitcodeRecord::RecordVector Values = Record.GetValues();
    // Start by adding block label if previous instruction is terminating.
    if (InstIsTerminating) {
      InstIsTerminating = false;
      ++CurrentBbIndex;
      DecAssemblyIndent();
      Tokens() << BitcodeId('b', CurrentBbIndex) << ":" << Endline();
      ObjDumpFlush();
      IncAssemblyIndent();
    }
    switch (Record.GetCode()) {
    case naclbitc::FUNC_CODE_DECLAREBLOCKS:
      // DECLAREBLOCKS: [n]
      InstIsTerminating = true;  // Force block label on first instruction.
      if (Values.size() != 1) {
        Errors() << "Function blocks record expects a size argument.\n";
        break;
      }
      ExpectedNumBbs = Values[0];
      if (ExpectedNumBbs == 0) {
        Errors() << "Functions must contain at least one block.\n";
      }
      Tokens() << "blocks" << Space() << ExpectedNumBbs << Semicolon();
      break;
    case naclbitc::FUNC_CODE_INST_BINOP: {
      // BINOP: [opval, opval, opcode]
      if (Values.size() != 3) {
        Errors() << "Binop record expects 3 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      uint32_t Op1 = RelativeToAbsId(Values[0]);
      uint32_t Op2 = RelativeToAbsId(Values[1]);
      Type *Type1 = GetValueType(Op1);
      Type *Type2 = GetValueType(Op2);
      if (Type1 != Type2) {
        Errors() << "Binop argument types differ: " << *Type1 << " and "
                 << *Type2 << "\n";
      }
      const char *Binop = GetBinop(Values[2], Type1);
      Tokens() << NextInstId() << Space() << "=" << Space() << Binop << Space()
               << TokenizeType(Type1) << Space() << GetBitcodeId(Op1) << Comma()
               << Space() << GetBitcodeId(Op2) << Semicolon();
      InstallInstType(Type1);
      break;
    }
    case naclbitc::FUNC_CODE_INST_CAST: {
      // CAST: [opval, destty, castopc]
      if (Values.size() != 3) {
        Errors() << "Cast record expects 3 argments. Found: "
                 << Values.size() << "\n";
        break;
      }
      uint32_t Op = RelativeToAbsId(Values[0]);
      Type *FromType = GetValueType(Op);
      Type *ToType = GetType(Values[1]);
      const char *CastOp = GetCastOp(Values[2], FromType, ToType);
      Tokens() << NextInstId() << Space() << "=" << Space() << CastOp << Space()
               << TokenizeType(FromType) << Space() << GetBitcodeId(Op)
               << Space() << "to" << Space() << TokenizeType(ToType)
               << Semicolon();
      InstallInstType(ToType);
      break;
    }
    case naclbitc::FUNC_CODE_INST_RET: {
      // RET: [opval?]
      InstIsTerminating = true;
      Tokens() << "ret" << Space();
      switch (Values.size()) {
      default:
        Errors() << "Function return record expects an optional return argument. "
                 << "Found: " << Values.size() << " arguments\n";
        break;
      case 0:
        Tokens() << "void";
        break;
      case 1: {
        uint32_t Op = RelativeToAbsId(Values[0]);
        Tokens() << TokenizeType(GetValueType(Op)) << Space()<< GetBitcodeId(Op);
        break;
      }
      }
      Tokens() << Semicolon();
      break;
    }
    case naclbitc::FUNC_CODE_INST_BR: {
      // BR: [bb#, bb#, opval] or [bb#]
      InstIsTerminating = true;
      if (Values.size() != 1 && Values.size() != 3) {
        Errors() << "Function branch record expects 1 or 3 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      Tokens() << "br" << Space();
      if (Values.size() == 3) {
        uint32_t OpIndex = RelativeToAbsId(Values[2]);
        if (GetValueType(OpIndex) != GetComparisonType())
          Errors() << "Branch condition not i1\n";
        Tokens() << StartCluster() << "i1" << Space() << GetBitcodeId(OpIndex)
                 << Comma() << FinishCluster() << Space();
      }
      VerifyBranchRange(Values[0]);
      Tokens() << StartCluster() << "label" << Space()
               << BitcodeId('b', Values[0]);
      if (Values.size() == 3) {
        VerifyBranchRange(Values[1]);
        Tokens() << Comma() << FinishCluster() << Space()
                 << StartCluster() << "label" << Space()
                 << BitcodeId('b', Values[1]);
      }
      Tokens() << Semicolon() << FinishCluster();
      break;
    }
    case naclbitc::FUNC_CODE_INST_SWITCH: {
      // SWITCH:  [opty, op, bb#, n, (1, 1, int, bb#)*]
      InstIsTerminating = true;
      if (Values.size() < 4) {
        Errors()
            << "Function switch record expects at least 4 arguments. Found: "
            << Values.size() << "\n";
        break;
      }
      Type *OpType = GetType(Values[0]);
      uint32_t CondId = RelativeToAbsId(Values[1]);
      Type *CondType = GetValueType(CondId);
      if (OpType != CondType)
        Errors() << "Specified select type " << *OpType << " but found: "
                 << *CondType << "\n";
      if (!IgnorePNaClABIChecks &&
          !PNaClABITypeChecker::isValidSwitchConditionType(CondType)) {
        Errors() << PNaClABITypeChecker::ExpectedSwitchConditionType(CondType)
                 << "\n";
      }
      uint32_t DefaultBb = Values[2];
      unsigned NumCases = Values[3];
      VerifyBranchRange(DefaultBb);
      Tokens() << "switch" << Space() << StartCluster() << StartCluster()
               << TokenizeType(OpType) << Space() <<  GetBitcodeId(CondId)
               << FinishCluster() << Space() << "{" << FinishCluster()
               << Endline();
      IncAssemblyIndent();
      Tokens() << StartCluster() << "default" << ":" << Space()
               << FinishCluster() << StartCluster() << "br" << Space() << "label"
               << Space() << BitcodeId('b', DefaultBb) << Semicolon()
               << FinishCluster() << Endline();
      unsigned CurIdx = 4;
      for (unsigned i = 0; i < NumCases; ++i) {
        unsigned NumItems = Values[CurIdx++];
        bool IsSingleNumber = Values[CurIdx++];
        if (NumItems != 1 || !IsSingleNumber) {
          Errors() << "Case ranges are not supported in PNaCl\n";
          break;
        }
        SignRotatedInt CaseValue(Values[CurIdx++], OpType);
        // TODO(kschimpf) Check if CaseValue possible based on OpType.
        uint64_t Label = Values[CurIdx++];
        VerifyBranchRange(Label);
        Tokens() << StartCluster() << TokenizeType(OpType) << Space()
                 << CaseValue << ":" << Space() << FinishCluster()
                 << StartCluster() << "br" << Space() << "label" << Space()
                 << BitcodeId('b', Label) << Semicolon() << FinishCluster()
                 << Endline();
      }
      DecAssemblyIndent();
      Tokens() << "}";
      break;
    }
    case naclbitc::FUNC_CODE_INST_UNREACHABLE:
      // UNREACHABLE
      InstIsTerminating = true;
      if (!Values.empty()) {
        Errors() << "Function unreachable record expects no arguments. Found: "
                 << Values.size() << "\n";
      }
      Tokens() << "unreachable" << Semicolon();
      break;
    case naclbitc::FUNC_CODE_INST_PHI: {
      // PHI: [ty, (val0, bb0)*]
      if (Values.size() < 3) {
        Errors() << "Function phi record expects at least 3 arguments. Found: "
                 << Values.size() << "\n";
        break;
      } else if (Values.size() % 2 == 0) {
        Errors()
            << "Function phi records should have an odd number of arguments. "
            << "Found: " << Values.size() << "\n";
      }
      Type* OpType = GetType(Values[0]);
      Tokens() << NextInstId() << Space() << "=" << StartCluster() << Space()
               << "phi" << Space() << TokenizeType(OpType);
      for (size_t i = 1; i < Values.size(); i += 2) {
        if (i > 1) Tokens() << Comma();
        uint32_t Index = RelativeToAbsId(NaClDecodeSignRotatedValue(Values[i]));
        Tokens() << FinishCluster() << Space() << StartCluster() << OpenSquare()
                 << GetBitcodeId(Index) << Comma() << Space()
                 << BitcodeId('b', Values[i+1]) << CloseSquare();
      }
      Tokens() << Semicolon() << FinishCluster();
      InstallInstType(OpType);
      break;
    };
    case naclbitc::FUNC_CODE_INST_ALLOCA: {
      // ALLOCA:     [size, align]
      if (Values.size() != 2) {
        Errors() << "Function alloca record expects 2 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      uint32_t SizeOp = RelativeToAbsId(Values[0]);
      Type* SizeType = GetValueType(SizeOp);
      BitcodeId SizeId(GetBitcodeId(SizeOp));
      unsigned Alignment = getAlignmentValue(Values[1]);
      if (!IgnorePNaClABIChecks && !PNaClABIProps::isAllocaSizeType(SizeType))
        Errors() << PNaClABIProps::ExpectedAllocaSizeType() << "\n";
      // TODO(kschimpf) Are there any constraints on alignment?
      Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster()
               << "alloca" << Space() << "i8" << Comma() << FinishCluster()
               << Space() << StartCluster() << TokenizeType(SizeType) << Space()
               << SizeId << Comma() << FinishCluster() << Space()
               << StartCluster() <<"align" << Space() << Alignment << Semicolon()
               << FinishCluster();
      InstallInstType(GetPointerType());
      break;
    }
    case naclbitc::FUNC_CODE_INST_LOAD: {
      // LOAD: [op, align, ty]
      if (Values.size() != 3) {
        Errors() << "Function load record expects 3 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      unsigned Alignment = getAlignmentValue(Values[1]);
      Type *LoadType = GetType(Values[2]);
      VerifyScalarOrVectorOp("load", LoadType);
      Context->VerifyMemoryAccessAlignment("load", LoadType, Alignment);
      Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster()
               << "load" << Space() << TokenizeType(LoadType) << "*" << Space()
               << GetBitcodeId(RelativeToAbsId(Values[0])) << Comma()
               << FinishCluster() << Space() << StartCluster()
               << "align" << Space() << Alignment << Semicolon()
               << FinishCluster();
      InstallInstType(LoadType);
      break;
    }
    case naclbitc::FUNC_CODE_INST_STORE: {
      // STORE: [ptr, val, align]
      if (Values.size() != 3) {
        Errors() << "Function store record expects 3 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      unsigned Alignment = getAlignmentValue(Values[2]);
      uint32_t Val = RelativeToAbsId(Values[1]);
      Type *ValType = GetValueType(Val);
      VerifyScalarOrVectorOp("store", ValType);
      Context->VerifyMemoryAccessAlignment("store", ValType, Alignment);
      Tokens() << StartCluster() << "store" << Space() << TokenizeType(ValType)
               << Space() << GetBitcodeId(Val) << Comma() << FinishCluster()
               << Space() << StartCluster() << TokenizeType(ValType) << "*"
               << Space() << GetBitcodeId(RelativeToAbsId(Values[0])) << Comma()
               << FinishCluster() << Space() << StartCluster() << "align"
               << Space() << Alignment << Semicolon() << FinishCluster();
      break;
    }
    case naclbitc::FUNC_CODE_INST_CMP2: {
      // CMP2: [opval, opval, pred]
      if (Values.size() != 3) {
        Errors() << "Function compare record expects 3 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      uint32_t Arg1 = RelativeToAbsId(Values[0]);
      uint32_t Arg2 = RelativeToAbsId(Values[1]);
      Type *Arg1Type = GetValueType(Arg1);
      Type *Arg2Type = GetValueType(Arg2);
      if (Arg1Type != Arg2Type) {
        Errors() << "Arguments not of same type: " << *Arg1Type << " and "
                 << *Arg2Type << "\n";
      }
      const char *Pred = "???";
      Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster();
      Type* BaseType = UnderlyingType(Arg1Type);
      if (BaseType->isIntegerTy()) {
        Pred = GetIcmpPredicate(Values[2]);
        Tokens() << "icmp" << Space() << Pred;
      } else if (isFloatingType(BaseType)) {
        Pred = GetFcmpPredicate(Values[2]);
        Tokens() << "fcmp" << Space() << Pred;
      } else {
        Errors() << "Compare not on integer/float type. Found: "
                 << *Arg1Type << "\n";
        Tokens() << "cmp" << Space() << "???" "(" << Values[2] << ")";
      }
      Tokens() << FinishCluster() << Space() << StartCluster()
               << TokenizeType(Arg1Type) << Space () << GetBitcodeId(Arg1)
               << Comma() << FinishCluster() << Space() << StartCluster()
               << GetBitcodeId(Arg2) << Semicolon() << FinishCluster();
      Type *ResultType = GetComparisonType();
      if (Arg1Type->isVectorTy()) {
        ResultType = VectorType::get(ResultType,
                                     Arg1Type->getVectorNumElements());
      }
      InstallInstType(ResultType);
      break;
    }
    case naclbitc::FUNC_CODE_INST_VSELECT: {
      // VSELECT:    [opval, opval, pred]
      if (Values.size() != 3) {
        Errors() << "Select record expects 3 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      uint32_t CondValue = RelativeToAbsId(Values[2]);
      uint32_t ThenValue = RelativeToAbsId(Values[0]);
      uint32_t ElseValue = RelativeToAbsId(Values[1]);
      Type *CondType = GetValueType(CondValue);
      Type *ThenType = GetValueType(ThenValue);
      Type *ElseType = GetValueType(ElseValue);
      if (ThenType != ElseType) {
        Errors() << "Selected arguments not of same type: "
                 << *ThenType << " and " << *ElseType << "\n";
      }
      Type *BaseType = UnderlyingType(ThenType);
      if (!(BaseType->isIntegerTy() || isFloatingType(BaseType))) {
        Errors() << "Select arguments not integer/float. Found: " << *ThenType;
      }
      Tokens() << NextInstId() << Space() << "=" << Space() << StartCluster()
               << "select" << Space() << TokenizeType(CondType) << Space()
               << GetBitcodeId(CondValue) << Comma() << FinishCluster() << Space()
               << StartCluster() << TokenizeType(ThenType) << Space()
               << GetBitcodeId(ThenValue) << Comma() << FinishCluster() << Space()
               << StartCluster() << TokenizeType(ElseType) << Space()
               << GetBitcodeId(ElseValue) << Semicolon()
               << FinishCluster();
      InstallInstType(ThenType);
      break;
    }
    case naclbitc::FUNC_CODE_INST_EXTRACTELT: {
      // EXTRACTELT: [opval, opval]
      if (Values.size() != 2) {
        Errors() << "Extract element record expects 2 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      uint32_t VecValue = RelativeToAbsId(Values[0]);
      uint32_t IdxValue = RelativeToAbsId(Values[1]);
      VerifyIndexedVector("extractelement", VecValue, IdxValue);
      Type *VecType = GetValueType(VecValue);
      Type *IdxType = GetValueType(IdxValue);
      Tokens() << NextInstId() << Space() << " = " << Space() << StartCluster()
               << "extractelement" << Space() << TokenizeType(VecType) << Space()
               << GetBitcodeId(VecValue) << Comma() << FinishCluster() << Space()
               << StartCluster() << TokenizeType(IdxType) << Space()
               << GetBitcodeId(IdxValue) << Semicolon() << FinishCluster();
      InstallInstType(UnderlyingType(VecType));
      break;
    }
    case naclbitc::FUNC_CODE_INST_INSERTELT: {
      // INSERTELT:  [opval, opval, opval]
      uint32_t VecValue = RelativeToAbsId(Values[0]);
      uint32_t EltValue = RelativeToAbsId(Values[1]);
      uint32_t IdxValue = RelativeToAbsId(Values[2]);
      VerifyIndexedVector("insertelement", VecValue, IdxValue);
      Type *VecType = GetValueType(VecValue);
      Type *EltType = GetValueType(EltValue);
      Type *IdxType = GetValueType(IdxValue);
      if (EltType != UnderlyingType(VecType)) {
        Errors() << "insertelement: Illegal element type " << *EltType
                 << ". Expected: " << *UnderlyingType(VecType) << "\n";
      }
      Tokens() << NextInstId() << Space() << " = " << Space() << StartCluster()
               << "insertelement" << Space() << TokenizeType(VecType) << Space()
               << GetBitcodeId(VecValue) << Comma() << FinishCluster() << Space()
               << StartCluster() << TokenizeType(EltType) << Space()
               << GetBitcodeId(EltValue) << Comma() << FinishCluster() << Space()
               << StartCluster() << TokenizeType(IdxType) << Space()
               << GetBitcodeId(IdxValue) << Semicolon() << FinishCluster();
      InstallInstType(VecType);
      break;
    }
    case naclbitc::FUNC_CODE_INST_CALL:
    case naclbitc::FUNC_CODE_INST_CALL_INDIRECT: {
      // CALL: [cc, fnid, arg0, arg1...]
      // CALL_INDIRECT: [cc, fnid, returnty, args...]
      if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) {
        if (Values.size() < 2) {
          Errors() << "Call record expects at least 2 arguments. Found: "
                   << Values.size() << "\n";
          break;
        }
      } else if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL_INDIRECT) {
        if (Values.size() < 3) {
          Errors() << "Call indirect record expects at least 3 arguments. Found: "
                   << Values.size() << "\n";
          break;
        }
      }
      unsigned IsTailCall = (Values[0] & 0x1);
      CallingConv::ID CallingConv;
      uint32_t FcnId = RelativeToAbsId(Values[1]);
      if (!naclbitc::DecodeCallingConv(Values[0]>>1, CallingConv))
        Errors() << "Call unknown calling convention:" << (Values[0]>>1) << "\n";
      if (!IgnorePNaClABIChecks &&
          !PNaClABIProps::isValidCallingConv(CallingConv)) {
        Errors() << "Call uses disallowed calling convention: "
                 << PNaClABIProps::CallingConvName(CallingConv) << "("
                 << CallingConv << ")\n";
      }
      FunctionType *FcnType = 0;
      Type *ReturnType = 0;
      size_t ArgIndex = 2;
      // Flag defining if type checking should be done on argument/return
      // types.
      bool CheckArgRetTypes = true;
      if (Record.GetCode() == naclbitc::FUNC_CODE_INST_CALL) {
        Type *FcnTy = GetFunctionValueType(FcnId);
        if (FunctionType *FcnTyp = dyn_cast<FunctionType>(FcnTy)) {
          // TODO(kschimpf) Add back signature checking once we know how
          // to handle intrinsics (which can violate general signature
          // rules).
          CheckArgRetTypes = false;
          FcnType = FcnTyp;
          ReturnType = FcnType->getReturnType();
        } else {
          Errors() << "Invalid function signature: " << *FcnTy << "\n";
          ReturnType = GetVoidType();
        }
      } else {
        ReturnType = GetType(Values[2]);
        ArgIndex = 3;
      }
      if (!ReturnType->isVoidTy()) {
        Tokens() << NextInstId() << Space() << "=" << Space();
      }
      if (IsTailCall) {
        Tokens() << "tail" << Space();
      }
      if (CheckArgRetTypes &&
          !IgnorePNaClABIChecks &&
          !PNaClABITypeChecker::isValidParamType(ReturnType)) {
        Errors() << "Invalid return type: " << *ReturnType << "\n";
      }
      Tokens() << "call" << Space();
      if (CallingConv != CallingConv::C) {
        Tokens() << PNaClABIProps::CallingConvName(CallingConv) << Space();
      }
      Tokens() << TokenizeType(ReturnType) << Space()
               << StartCluster() << GetBitcodeId(FcnId) << OpenParen()
               << StartCluster();
      unsigned ParamIndex = 0;
      unsigned NumParams = Values.size() + 1 - ArgIndex;
      for (size_t i = ArgIndex; i < Values.size(); ++i, ++ParamIndex) {
        uint32_t ParamId = RelativeToAbsId(Values[i]);
        Type *ParamType = GetValueType(ParamId);
        if (CheckArgRetTypes &&
            !IgnorePNaClABIChecks &&
            !PNaClABITypeChecker::isValidParamType(ParamType)) {
          Errors() << "invalid type for parameter " << i << ": "
                   << *ParamType << "\n";
        }
        if (FcnType) {
          if (ParamIndex < FcnType->getNumParams()) {
            Type *ExpectedType = FcnType->getParamType(ParamIndex);
            if (ParamType != ExpectedType) {
              Warnings() << "Parameter " << (ParamIndex + 1) << " mismatch: "
                         << *ParamType << " and " << *ExpectedType << "\n";
            }
          }
          else if (ParamIndex == FcnType->getNumParams()) {
            Warnings() << "Call expects " << FcnType->getNumParams()
                       << " arguments. Got: " << NumParams << "\n";
          }
        }
        if (i > ArgIndex) {
          Tokens() << Comma() << FinishCluster() << Space() << StartCluster();
        }
        Tokens() << TokenizeType(ParamType) << Space() << GetBitcodeId(ParamId);
      }
      Tokens() << CloseParen() << Semicolon() << FinishCluster()
               << FinishCluster();
      if (!ReturnType->isVoidTy()) InstallInstType(ReturnType);
      break;
    }
    case naclbitc::FUNC_CODE_INST_FORWARDTYPEREF: {
      // TYPE: [opval, ty]
      if (Values.size() != 2) {
        Errors() << "Forward declare record expects 2 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      Type *OpType = GetType(Values[1]);
      Tokens() << "declare" << Space() << StartCluster()
               << TokenizeType(OpType) << Space()
               << GetBitcodeId(Values[0]) << Semicolon() << FinishCluster();
      InstallInstType(OpType, AbsToValuedInstId(Values[0]));
      break;
    }
    default:
      Errors() << "Unknown record found in module block.\n";
      break;
    }
    Tokens() << TokenizeAbbrevIndex() << Endline();
    ObjDumpWrite(Record.GetStartBit(), Record);
  }
  
  /// Parses and disassembles the module block.
  class NaClDisModuleParser : public NaClDisBlockParser {
  public:
    NaClDisModuleParser(unsigned BlockID, NaClDisTopLevelParser *Context)
        : NaClDisBlockParser(BlockID, Context) {
    }
  
    ~NaClDisModuleParser() override;
  
    bool ParseBlock(unsigned BlockID) override;
  
    void PrintBlockHeader() override;
  
    void ProcessRecord() override;
  };
  
  NaClDisModuleParser::~NaClDisModuleParser() {
    // Note: Since we can't check type signatures of most functions till
    // we know intrinsic names, and that isn't known until the (optional)
    // valuesymtab block is parsed, the only reasonable spot to check
    // function signatures is once the module block has been processed.
    unsigned NextFcnDefinedId = 0;
    for (unsigned i = 0, e = GetNumFunctions(); i < e; ++i) {
      // Note: If the type of a function isn't a function type, that
      // was checked in method ProcessRecord.
      // Note: If the function was defined, the type was checked in
      // NaClDisFunctionParser::PrintBlockHeader.
      if (Context->HasDefinedFunctionIndex(NextFcnDefinedId)
          && i == Context->GetDefinedFunctionIndex(NextFcnDefinedId)) {
        ++NextFcnDefinedId;
        continue;
      }
      if (FunctionType *FcnTy = dyn_cast<FunctionType>(GetFunctionValueType(i))) {
        if (!Context->IsFunctionIntrinsic(i) &&
            !IgnorePNaClABIChecks &&
            !PNaClABITypeChecker::isValidFunctionType(FcnTy)) {
          Context->SetRecordAddressToFunctionIdAddress(i);
          Errors() << "Invalid type signature for "
                   << BitcodeId('f', i) << ": " << *FcnTy << "\n";
        }
      }
    }
  }
  
  bool NaClDisModuleParser::ParseBlock(unsigned BlockID) {
    ObjDumpSetRecordBitAddress(GetBlock().GetStartBit());
    switch (BlockID) {
    case naclbitc::BLOCKINFO_BLOCK_ID: {
      NaClDisBlockInfoParser Parser(BlockID, this);
      return Parser.ParseThisBlock();
    }
    case naclbitc::TYPE_BLOCK_ID_NEW: {
      NaClDisTypesParser Parser(BlockID, this);
      return Parser.ParseThisBlock();
    }
    case naclbitc::GLOBALVAR_BLOCK_ID: {
      NaClDisGlobalsParser Parser(BlockID, this);
      return Parser.ParseThisBlock();
    }
    case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
      NaClDisValueSymtabParser Parser(BlockID, this);
      return Parser.ParseThisBlock();
    }
    case naclbitc::FUNCTION_BLOCK_ID: {
      NaClDisFunctionParser Parser(BlockID, this);
      return Parser.ParseThisBlock();
    }
    default:
      return NaClDisBlockParser::ParseBlock(BlockID);
    }
  }
  
  void NaClDisModuleParser::PrintBlockHeader() {
    Tokens() << "module" << Space() << OpenCurly()
             << Space() << Space() << "// BlockID = " << GetBlockID()
             << Endline();
  }
  
  void NaClDisModuleParser::ProcessRecord() {
    ObjDumpSetRecordBitAddress(Record.GetStartBit());
    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
    switch (Record.GetCode()) {
    case naclbitc::MODULE_CODE_VERSION:
      // [version#]
      if (Values.size() != 1) {
        Errors() << "Version record should have one argument. Found: "
                 << Values.size() << "\n";
        break;
      }
      Tokens() << "version" << Space() << Values[0] << Semicolon()
               << TokenizeAbbrevIndex() << Endline();
      break;
    case naclbitc::MODULE_CODE_FUNCTION: {
      // [type, callingconv, isproto, linkage]
      if (Values.size() != 4) {
        Errors() << "Function record should have 4 arguments. Found: "
                 << Values.size() << "\n";
        break;
      }
      bool IsProto = (Values[2] != 0);
      Tokens() << StartCluster() << (IsProto ? "declare" : "define");
      uint32_t FcnId = GetNumFunctions();
      BitcodeId FcnName('f', FcnId);
      std::string FcnStrName(FcnName.GetName());
      GlobalValue::LinkageTypes Linkage;
      if (!naclbitc::DecodeLinkage(Values[3], Linkage)) {
        Errors() << "Unknown linkage value: " << Values[3] << "\n";
      } else {
        if (!IgnorePNaClABIChecks &&
            !PNaClABIProps::isValidGlobalLinkage(Linkage)) {
          Errors() << "Disallowed linkage type: "
                   << PNaClABIProps::LinkageName(Linkage) << "\n";
        }
        Tokens() << Space() << PNaClABIProps::LinkageName(Linkage);
      }
      CallingConv::ID CallingConv;
      if (!naclbitc::DecodeCallingConv(Values[1], CallingConv)) {
        Errors() << "Unknown calling convention value: " << Values[1] << "\n";
      } else if (PNaClABIProps::isValidCallingConv(CallingConv)) {
        if (CallingConv != CallingConv::C) {
          Tokens() << Space() << PNaClABIProps::CallingConvName(CallingConv);
        }
      } else {
        Errors() << "Function " << FcnStrName
                 << " has disallowed calling convention: "
                 << PNaClABIProps::CallingConvName(CallingConv)
                 << " (" << CallingConv << ")\n";
      }
      Tokens() << FinishCluster() << Space() << StartCluster();
      Type *FcnType = GetType(Values[0]);
      FunctionType *FunctionTy = dyn_cast<FunctionType>(FcnType);
      if (FunctionTy) {
        Tokens() << TokenizeFunctionType(FunctionTy, &FcnName);
      } else {
        BitcodeId FcnTypeId('t', Values[0]);
        Errors() << "Not function type: " << FcnTypeId << " = "
                 << *FcnType << "\n";
        Tokens() << "???";
        SmallVector<Type*, 1> Signature;
        FunctionTy = FunctionType::get(GetVoidType(), Signature, 0);
      }
      Tokens() << Semicolon() << FinishCluster() << TokenizeAbbrevIndex()
               << Endline();
      InstallFunctionType(FunctionTy);
      if (!IsProto) InstallDefinedFunction(FcnId);
      break;
    }
    default:
      Errors() << "Unknown record found in module block\n";
      break;
    }
    ObjDumpWrite(Record.GetStartBit(), Record);
  }
  
  bool NaClDisTopLevelParser::ParseBlock(unsigned BlockID) {
    // Before parsing top-level module block. Describe header by
    // reconstructing the corresponding header record.
    NaClBitcodeRecordData HeaderRecord;
    size_t HeaderSize = Header.getHeaderSize();
    HeaderRecord.Code = naclbitc::BLK_CODE_HEADER;
    NaClBitstreamCursor &Cursor = Record.GetCursor();
    uint64_t CurPos = Cursor.GetCurrentBitNo();
    Cursor.JumpToBit(0);
    for (size_t i = 0; i < HeaderSize; ++i) {
      HeaderRecord.Values.push_back(Cursor.Read(CHAR_BIT));
    }
    Cursor.JumpToBit(CurPos);
    if (ObjDump.GetDumpRecords() && ObjDump.GetDumpAssembly()) {
      if (HeaderSize >= 4) {
        const NaClRecordVector &Values = HeaderRecord.Values;
        Tokens() << "Magic" << Space() << "Number" << Colon()
                 << Space() << StartCluster() << StartCluster() << "'"
                 << (char) Values[0] << (char) Values[1]
                 << (char) Values[2] << (char) Values[3]
                 << "'" << FinishCluster() << Space()
                 << StartCluster() << OpenParen()
                 << Values[0] << Comma() << Space()
                 << Values[1] << Comma() << Space()
                 << Values[2] << Comma() << Space()
                 << Values[3] << CloseParen() << FinishCluster()
                 << FinishCluster() << Endline();
      }
      // Show interpretation of header as assembly.
      for (size_t i = 0; i < Header.NumberFields(); ++i) {
        Tokens() << Header.GetField(i)->Contents() << Endline();
      }
    }
    ObjDump.Write(0, HeaderRecord);
  
    if (BlockID != naclbitc::MODULE_BLOCK_ID)
      return Error("Module block expected at top-level, but not found");
  
    // Now parse a module block.
    NaClDisModuleParser Parser(BlockID, this);
    return Parser.ParseThisBlock();
  }
  
  }
  
  namespace llvm {
  
  bool NaClObjDump(MemoryBufferRef MemBuf, raw_ostream &Output,
                   bool NoRecords, bool NoAssembly) {
    // Create objects needed to run parser.
    naclbitc::ObjDumpStream ObjDump(Output, !NoRecords, !NoAssembly);
  
    if (MemBuf.getBufferSize() % 4 != 0) {
      ObjDump.Error()
          << "Bitcode stream should be a multiple of 4 bytes in length.\n";
      return true;
    }
  
    const unsigned char *BufPtr = (const unsigned char *)MemBuf.getBufferStart();
    const unsigned char *EndBufPtr = BufPtr+MemBuf.getBufferSize();
    const unsigned char *HeaderPtr = BufPtr;
  
    // Read header and verify it is good.
    NaClBitcodeHeader Header;
    if (Header.Read(HeaderPtr, EndBufPtr) || !Header.IsSupported()) {
      ObjDump.Error() << "Invalid PNaCl bitcode header.\n";
      return true;
    }
  
    // Create a bitstream reader to read the bitcode file.
    NaClBitstreamReader InputStreamFile(BufPtr, EndBufPtr,
                                        Header.getHeaderSize());
    NaClBitstreamCursor InputStream(InputStreamFile);
  
    // Parse the the bitcode file.
    ::NaClDisTopLevelParser Parser(Header, InputStream, ObjDump);
    int NumBlocksRead = 0;
    bool ErrorsFound = false;
    while (!InputStream.AtEndOfStream()) {
      ++NumBlocksRead;
      if (Parser.Parse()) ErrorsFound = true;
    }
  
    if (NumBlocksRead != 1) {
      ObjDump.Error() << "Expected 1 top level block in bitcode: Found:"
                      << NumBlocksRead << "\n";
      ErrorsFound = true;
    }
  
    ObjDump.Flush();
    return ErrorsFound || Parser.GetNumErrors() > 0;
  }
  
  }
  