Update Subzero to start parsing PNaCl bitcode files.

This patch only handles global addresses in PNaCl bitcode files.
Function blocks are still not parsed. Also, factors out a common API
for translation, so that generated ICE can always be translated using
the same code.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=3892
R=jvoung@chromium.org, stichnot@chromium.org

Review URL: https://codereview.chromium.org/361733002
diff --git a/Makefile.standalone b/Makefile.standalone
index b65e648..6a50f9a 100644
--- a/Makefile.standalone
+++ b/Makefile.standalone
@@ -30,7 +30,7 @@
 OPTLEVEL := -O0
 CXX := g++
 CXXFLAGS := -Wall -Wextra -Werror -fno-rtti -fno-exceptions \
-	$(OPTLEVEL) -g $(LLVM_CXXFLAGS) -m32
+	$(OPTLEVEL) -g $(LLVM_CXXFLAGS) -m32 -Wno-error=unused-parameter
 LDFLAGS := -m32
 
 SRCS= \
@@ -46,8 +46,10 @@
 	IceRegAlloc.cpp \
 	IceTargetLowering.cpp \
 	IceTargetLoweringX8632.cpp \
+	IceTranslator.cpp \
 	IceTypes.cpp \
-	llvm2ice.cpp
+	llvm2ice.cpp \
+	PNaClTranslator.cpp
 
 OBJS=$(patsubst %.cpp, build/%.o, $(SRCS))
 
diff --git a/src/IceClFlags.h b/src/IceClFlags.h
new file mode 100644
index 0000000..55e2652
--- /dev/null
+++ b/src/IceClFlags.h
@@ -0,0 +1,30 @@
+//===- subzero/src/IceClFlags.h - Cl Flags for translation ------*- C++ -*-===//
+//
+//                        The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares command line flags controlling translation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUBZERO_SRC_ICECLFLAGS_H
+#define SUBZERO_SRC_ICECLFLAGS_H
+
+namespace Ice {
+
+class ClFlags {
+public:
+  ClFlags()
+      : DisableInternal(false), SubzeroTimingEnabled(false),
+        DisableTranslation(false) {}
+  bool DisableInternal;
+  bool SubzeroTimingEnabled;
+  bool DisableTranslation;
+};
+}
+
+#endif // SUBZERO_SRC_ICECLFLAGS_H
diff --git a/src/IceConverter.cpp b/src/IceConverter.cpp
index 654d5e8..af22d7b 100644
--- a/src/IceConverter.cpp
+++ b/src/IceConverter.cpp
@@ -15,11 +15,11 @@
 
 #include "IceCfg.h"
 #include "IceCfgNode.h"
+#include "IceClFlags.h"
 #include "IceDefs.h"
 #include "IceGlobalContext.h"
 #include "IceInst.h"
 #include "IceOperand.h"
-#include "IceTargetLowering.h"
 #include "IceTypes.h"
 
 #include "llvm/IR/Constant.h"
@@ -616,64 +616,24 @@
   std::map<const BasicBlock *, Ice::CfgNode *> NodeMap;
 };
 
-}
+} // end of anonymous namespace.
 
 int Ice::Converter::convertToIce(llvm::Module *Mod) {
-  int ExitStatus = 0;
-
-  // Ideally, Func would be declared inside the loop and its object
-  // would be automatically deleted at the end of the loop iteration.
-  // However, emitting the constant pool requires a valid Cfg object,
-  // so we need to defer deleting the last non-empty Cfg object until
-  // outside the loop and after emitting the constant pool.  TODO:
-  // Since all constants are globally pooled in the Ice::GlobalContext
-  // object, change all Ice::Constant related functions to use
-  // GlobalContext instead of Cfg, and then clean up this loop.
-  OwningPtr<Ice::Cfg> Func;
-
   for (Module::const_iterator I = Mod->begin(), E = Mod->end(); I != E; ++I) {
     if (I->empty())
       continue;
     LLVM2ICEConverter FunctionConverter(Ctx);
 
     Ice::Timer TConvert;
-    Func.reset(FunctionConverter.convertFunction(I));
-    if (DisableInternal)
-      Func->setInternal(false);
-
-    if (SubzeroTimingEnabled) {
+    Ice::Cfg *Fcn = FunctionConverter.convertFunction(I);
+    if (Flags.SubzeroTimingEnabled) {
       std::cerr << "[Subzero timing] Convert function "
-                << Func->getFunctionName() << ": " << TConvert.getElapsedSec()
+                << Fcn->getFunctionName() << ": " << TConvert.getElapsedSec()
                 << " sec\n";
     }
-
-    if (DisableTranslation) {
-      Func->dump();
-    } else {
-      Ice::Timer TTranslate;
-      Func->translate();
-      if (SubzeroTimingEnabled) {
-        std::cerr << "[Subzero timing] Translate function "
-                  << Func->getFunctionName() << ": "
-                  << TTranslate.getElapsedSec() << " sec\n";
-      }
-      if (Func->hasError()) {
-        errs() << "ICE translation error: " << Func->getError() << "\n";
-        ExitStatus = 1;
-      }
-
-      Ice::Timer TEmit;
-      Func->emit();
-      if (SubzeroTimingEnabled) {
-        std::cerr << "[Subzero timing] Emit function "
-                  << Func->getFunctionName() << ": " << TEmit.getElapsedSec()
-                  << " sec\n";
-      }
-    }
+    translateFcn(Fcn);
   }
 
-  if (!DisableTranslation && Func)
-    Func->getTarget()->emitConstants();
-
+  emitConstants();
   return ExitStatus;
 }
diff --git a/src/IceConverter.h b/src/IceConverter.h
index 71fc8aa..dc18e7a 100644
--- a/src/IceConverter.h
+++ b/src/IceConverter.h
@@ -14,7 +14,7 @@
 #ifndef SUBZERO_SRC_ICECONVERTER_H
 #define SUBZERO_SRC_ICECONVERTER_H
 
-#include "IceGlobalContext.h"
+#include "IceTranslator.h"
 
 namespace llvm {
 class Module;
@@ -22,27 +22,17 @@
 
 namespace Ice {
 
-class Converter {
+class Converter : public Translator {
 public:
-  Converter(Ice::GlobalContext *Ctx,
-            bool DisableInternal,
-            bool SubzeroTimingEnabled,
-            bool DisableTranslation)
-      : Ctx(Ctx),
-        DisableInternal(DisableInternal),
-        SubzeroTimingEnabled(SubzeroTimingEnabled),
-        DisableTranslation(DisableTranslation)
-  {}
+  Converter(GlobalContext *Ctx, Ice::ClFlags &Flags) : Translator(Ctx, Flags) {}
   /// Converts the LLVM Module to ICE. Returns exit status 0 if successful,
   /// Nonzero otherwise.
   int convertToIce(llvm::Module *Mod);
-private:
-  Ice::GlobalContext *Ctx;
-  bool DisableInternal;
-  bool SubzeroTimingEnabled;
-  bool DisableTranslation;
-};
 
+private:
+  Converter(const Converter &) LLVM_DELETED_FUNCTION;
+  Converter &operator=(const Converter &) LLVM_DELETED_FUNCTION;
+};
 }
 
-#endif  // SUBZERO_SRC_ICECONVERTER_H
+#endif // SUBZERO_SRC_ICECONVERTER_H
diff --git a/src/IceTranslator.cpp b/src/IceTranslator.cpp
new file mode 100644
index 0000000..7eb0fc0
--- /dev/null
+++ b/src/IceTranslator.cpp
@@ -0,0 +1,58 @@
+//===- subzero/src/IceTranslator.cpp - ICE to machine code ------*- C++ -*-===//
+//
+//                        The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the general driver class for translating ICE to
+// machine code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "IceTranslator.h"
+
+#include "IceCfg.h"
+#include "IceClFlags.h"
+#include "IceTargetLowering.h"
+
+#include <iostream>
+
+using namespace Ice;
+
+Translator::~Translator() {}
+
+void Translator::translateFcn(Ice::Cfg *Fcn) {
+  Func.reset(Fcn);
+  if (Flags.DisableInternal)
+    Func->setInternal(false);
+  if (Flags.DisableTranslation) {
+    Func->dump();
+  } else {
+    Ice::Timer TTranslate;
+    Func->translate();
+    if (Flags.SubzeroTimingEnabled) {
+      std::cerr << "[Subzero timing] Translate function "
+                << Func->getFunctionName() << ": " << TTranslate.getElapsedSec()
+                << " sec\n";
+    }
+    if (Func->hasError()) {
+      std::cerr << "ICE translation error: " << Func->getError() << "\n";
+      ExitStatus = 1;
+    }
+
+    Ice::Timer TEmit;
+    Func->emit();
+    if (Flags.SubzeroTimingEnabled) {
+      std::cerr << "[Subzero timing] Emit function " << Func->getFunctionName()
+                << ": " << TEmit.getElapsedSec() << " sec\n";
+    }
+  }
+}
+
+void Translator::emitConstants() {
+  if (!Flags.DisableTranslation && Func)
+    Func->getTarget()->emitConstants();
+}
diff --git a/src/IceTranslator.h b/src/IceTranslator.h
new file mode 100644
index 0000000..0450f09
--- /dev/null
+++ b/src/IceTranslator.h
@@ -0,0 +1,67 @@
+//===- subzero/src/IceTranslator.h - ICE to machine code --------*- C++ -*-===//
+//
+//                        The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the general driver class for translating ICE to
+// machine code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUBZERO_SRC_ICETRANSLATOR_H
+#define SUBZERO_SRC_ICETRANSLATOR_H
+
+#include "llvm/ADT/OwningPtr.h"
+
+namespace Ice {
+
+class ClFlags;
+class Cfg;
+class GlobalContext;
+
+// Base class for translating ICE to machine code.
+// Derived classes convert other intermediate representations down to ICE,
+// and then call the appropriate (inherited) methods to convert ICE into
+// machine instructions.
+class Translator {
+public:
+  Translator(GlobalContext *Ctx, ClFlags &Flags)
+      : Ctx(Ctx), Flags(Flags), ExitStatus(0) {}
+
+  ~Translator();
+  int getExitStatus() const { return ExitStatus; }
+
+protected:
+  GlobalContext *Ctx;
+  ClFlags &Flags;
+  // The exit status of the translation. 0 is successful. Nonzero
+  // otherwise.
+  bool ExitStatus;
+  // Ideally, Func would be inside the methods that converts IR to
+  // functions.  However, emitting the constant pool requires a valid
+  // Cfg object, so we need to defer deleting the last non-empty Cfg
+  // object to emit the constant pool (via emitConstants). TODO:
+  // Since all constants are globally pooled in the GlobalContext
+  // object, change all Constant related functions to use
+  // GlobalContext instead of Cfg, and then make emitConstantPool use
+  // that.
+  llvm::OwningPtr<Cfg> Func;
+
+  /// Translates the constructed ICE function Fcn to machine code.
+  /// Note: As a side effect, Field Func is set to Fcn.
+  void translateFcn(Cfg *Fcn);
+
+  /// Emits the constant pool.
+  void emitConstants();
+
+private:
+  Translator(const Translator &) LLVM_DELETED_FUNCTION;
+  Translator &operator=(const Translator &) LLVM_DELETED_FUNCTION;
+};
+}
+
+#endif // SUBZERO_SRC_ICETRANSLATOR_H
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
new file mode 100644
index 0000000..82ef5ac
--- /dev/null
+++ b/src/PNaClTranslator.cpp
@@ -0,0 +1,859 @@
+//===- subzero/src/PNaClTranslator.cpp - ICE from bitcode -----------------===//
+//
+//                        The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PNaCl bitcode file to Ice, to machine code
+// translator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PNaClTranslator.h"
+#include "IceCfg.h"
+#include "llvm/Bitcode/NaCl/NaClBitcodeDecoders.h"
+#include "llvm/Bitcode/NaCl/NaClBitcodeHeader.h"
+#include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
+#include "llvm/Bitcode/NaCl/NaClReaderWriter.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/ValueHandle.h"
+
+#include <vector>
+#include <cassert>
+
+using namespace llvm;
+
+namespace {
+
+// Top-level class to read PNaCl bitcode files, and translate to ICE.
+class TopLevelParser : public NaClBitcodeParser {
+  TopLevelParser(const TopLevelParser &) LLVM_DELETED_FUNCTION;
+  TopLevelParser &operator=(const TopLevelParser &) LLVM_DELETED_FUNCTION;
+
+public:
+  TopLevelParser(const std::string &InputName, NaClBitcodeHeader &Header,
+                 NaClBitstreamCursor &Cursor, int &ExitStatusFlag)
+      : NaClBitcodeParser(Cursor),
+        Mod(new Module(InputName, getGlobalContext())), Header(Header),
+        ExitStatusFlag(ExitStatusFlag), NumErrors(0), NumFunctionIds(0),
+        GlobalVarPlaceHolderType(Type::getInt8Ty(getLLVMContext())) {
+    Mod->setDataLayout(PNaClDataLayout);
+  }
+
+  virtual ~TopLevelParser() {}
+  LLVM_OVERRIDE;
+
+  virtual bool Error(const std::string &Message) LLVM_OVERRIDE {
+    ExitStatusFlag = 1;
+    ++NumErrors;
+    return NaClBitcodeParser::Error(Message);
+  }
+
+  /// Returns the number of errors found while parsing the bitcode
+  /// file.
+  unsigned getNumErrors() const { return NumErrors; }
+
+  /// Returns the LLVM module associated with the translation.
+  Module *getModule() const { return Mod.get(); }
+
+  /// Returns the number of bytes in the bitcode header.
+  size_t getHeaderSize() const { return Header.getHeaderSize(); }
+
+  /// Returns the llvm context to use.
+  LLVMContext &getLLVMContext() const { return Mod->getContext(); }
+
+  /// Changes the size of the type list to the given size.
+  void resizeTypeIDValues(unsigned NewSize) { TypeIDValues.resize(NewSize); }
+
+  /// Returns the type associated with the given index.
+  Type *getTypeByID(unsigned ID) {
+    // Note: method resizeTypeIDValues expands TypeIDValues
+    // to the specified size, and fills elements with NULL.
+    Type *Ty = ID < TypeIDValues.size() ? TypeIDValues[ID] : NULL;
+    if (Ty)
+      return Ty;
+    return reportTypeIDAsUndefined(ID);
+  }
+
+  /// Defines type for ID.
+  void setTypeID(unsigned ID, Type *Ty) {
+    if (ID < TypeIDValues.size() && TypeIDValues[ID] == NULL) {
+      TypeIDValues[ID] = Ty;
+      return;
+    }
+    reportBadSetTypeID(ID, Ty);
+  }
+
+  /// Sets the next function ID to the given LLVM function.
+  void setNextFunctionID(Function *Fcn) {
+    ++NumFunctionIds;
+    ValueIDValues.push_back(Fcn);
+  }
+
+  /// Defines the next function ID as one that has an implementation
+  /// (i.e a corresponding function block in the bitcode).
+  void setNextValueIDAsImplementedFunction() {
+    DefiningFunctionsList.push_back(ValueIDValues.size());
+  }
+
+  /// Returns the LLVM IR value associatd with the global value ID.
+  Value *getGlobalValueByID(unsigned ID) const {
+    if (ID >= ValueIDValues.size())
+      return 0;
+    return ValueIDValues[ID];
+  }
+
+  /// Returns the number of function addresses (i.e. ID's) defined in
+  /// the bitcode file.
+  unsigned getNumFunctionIDs() const { return NumFunctionIds; }
+
+  /// Returns the number of global values defined in the bitcode
+  /// file.
+  unsigned getNumGlobalValueIDs() const { return ValueIDValues.size(); }
+
+  /// Resizes the list of value IDs to include Count global variable
+  /// IDs.
+  void resizeValueIDsForGlobalVarCount(unsigned Count) {
+    ValueIDValues.resize(ValueIDValues.size() + Count);
+  }
+
+  /// Returns the global variable address associated with the given
+  /// value ID. If the ID refers to a global variable address not yet
+  /// defined, a placeholder is created so that we can fix it up
+  /// later.
+  Constant *getOrCreateGlobalVarRef(unsigned ID) {
+    if (ID >= ValueIDValues.size())
+      return 0;
+    if (Value *C = ValueIDValues[ID])
+      return dyn_cast<Constant>(C);
+    Constant *C = new GlobalVariable(*Mod, GlobalVarPlaceHolderType, false,
+                                     GlobalValue::ExternalLinkage, 0);
+    ValueIDValues[ID] = C;
+    return C;
+  }
+
+  /// Assigns the given global variable (address) to the given value
+  /// ID.  Returns true if ID is a valid global variable ID. Otherwise
+  /// returns false.
+  bool assignGlobalVariable(GlobalVariable *GV, unsigned ID) {
+    if (ID < NumFunctionIds || ID >= ValueIDValues.size())
+      return false;
+    WeakVH &OldV = ValueIDValues[ID];
+    if (OldV == 0) {
+      ValueIDValues[ID] = GV;
+      return true;
+    }
+
+    // If reached, there was a forward reference to this value. Replace it.
+    Value *PrevVal = OldV;
+    GlobalVariable *Placeholder = cast<GlobalVariable>(PrevVal);
+    Placeholder->replaceAllUsesWith(
+        ConstantExpr::getBitCast(GV, Placeholder->getType()));
+    Placeholder->eraseFromParent();
+    ValueIDValues[ID] = GV;
+    return true;
+  }
+
+private:
+  // The parsed module.
+  OwningPtr<Module> Mod;
+  // The bitcode header.
+  NaClBitcodeHeader &Header;
+  // The exit status flag that should be set to 1 if an error occurs.
+  int &ExitStatusFlag;
+  // The number of errors reported.
+  unsigned NumErrors;
+  // The types associated with each type ID.
+  std::vector<Type *> TypeIDValues;
+  // The (global) value IDs.
+  std::vector<WeakVH> ValueIDValues;
+  // The number of function IDs.
+  unsigned NumFunctionIds;
+  // The list of value IDs (in the order found) of defining function
+  // addresses.
+  std::vector<unsigned> DefiningFunctionsList;
+  // Cached global variable placeholder type. Used for all forward
+  // references to global variable addresses.
+  Type *GlobalVarPlaceHolderType;
+
+  virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
+
+  /// Reports that type ID is undefined, and then returns
+  /// the void type.
+  Type *reportTypeIDAsUndefined(unsigned ID);
+
+  /// Reports error about bad call to setTypeID.
+  void reportBadSetTypeID(unsigned ID, Type *Ty);
+};
+
+Type *TopLevelParser::reportTypeIDAsUndefined(unsigned ID) {
+  std::string Buffer;
+  raw_string_ostream StrBuf(Buffer);
+  StrBuf << "Can't find type for type id: " << ID;
+  Error(StrBuf.str());
+  Type *Ty = Type::getVoidTy(getLLVMContext());
+  // To reduce error messages, update type list if possible.
+  if (ID < TypeIDValues.size())
+    TypeIDValues[ID] = Ty;
+  return Ty;
+}
+
+void TopLevelParser::reportBadSetTypeID(unsigned ID, Type *Ty) {
+  std::string Buffer;
+  raw_string_ostream StrBuf(Buffer);
+  if (ID >= TypeIDValues.size()) {
+    StrBuf << "Type index " << ID << " out of range: can't install.";
+  } else {
+    // Must be case that index already defined.
+    StrBuf << "Type index " << ID << " defined as " << *TypeIDValues[ID]
+           << " and " << *Ty << ".";
+  }
+  Error(StrBuf.str());
+}
+
+// Base class for parsing blocks within the bitcode file.  Note:
+// Because this is the base class of block parsers, we generate error
+// messages if ParseBlock or ParseRecord is not overridden in derived
+// classes.
+class BlockParserBaseClass : public NaClBitcodeParser {
+public:
+  // Constructor for the top-level module block parser.
+  BlockParserBaseClass(unsigned BlockID, TopLevelParser *Context)
+      : NaClBitcodeParser(BlockID, Context), Context(Context) {}
+
+  virtual ~BlockParserBaseClass() LLVM_OVERRIDE {}
+
+protected:
+  // The context parser that contains the decoded state.
+  TopLevelParser *Context;
+
+  // Constructor for nested block parsers.
+  BlockParserBaseClass(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
+      : NaClBitcodeParser(BlockID, EnclosingParser),
+        Context(EnclosingParser->Context) {}
+
+  // Generates an error Message with the bit address prefixed to it.
+  virtual bool Error(const std::string &Message) LLVM_OVERRIDE {
+    uint64_t Bit = Record.GetStartBit() + Context->getHeaderSize() * 8;
+    std::string Buffer;
+    raw_string_ostream StrBuf(Buffer);
+    StrBuf << "(" << format("%" PRIu64 ":%u", (Bit / 8),
+                            static_cast<unsigned>(Bit % 8)) << ") " << Message;
+    return Context->Error(StrBuf.str());
+  }
+
+  // Default implementation. Reports that block is unknown and skips
+  // its contents.
+  virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
+
+  // Default implementation. Reports that the record is not
+  // understood.
+  virtual void ProcessRecord() LLVM_OVERRIDE;
+
+  /// Checks if the size of the record is Size. If not, an error is
+  /// produced using the given RecordName. Return true if error was
+  /// reported. Otherwise false.
+  bool checkRecordSize(unsigned Size, const char *RecordName) {
+    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+    if (Values.size() != Size) {
+      return RecordSizeError(Size, RecordName, 0);
+    }
+    return false;
+  }
+
+  /// Checks if the size of the record is at least as large as the
+  /// LowerLimit.
+  bool checkRecordSizeAtLeast(unsigned LowerLimit, const char *RecordName) {
+    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+    if (Values.size() < LowerLimit) {
+      return RecordSizeError(LowerLimit, RecordName, "at least");
+    }
+    return false;
+  }
+
+  /// Checks if the size of the record is no larger than the
+  /// UpperLimit.
+  bool checkRecordSizeNoMoreThan(unsigned UpperLimit, const char *RecordName) {
+    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+    if (Values.size() > UpperLimit) {
+      return RecordSizeError(UpperLimit, RecordName, "no more than");
+    }
+    return false;
+  }
+
+  /// Checks if the size of the record is at least as large as the
+  /// LowerLimit, and no larger than the UpperLimit.
+  bool checkRecordSizeInRange(unsigned LowerLimit, unsigned UpperLimit,
+                              const char *RecordName) {
+    return checkRecordSizeAtLeast(LowerLimit, RecordName) ||
+           checkRecordSizeNoMoreThan(UpperLimit, RecordName);
+  }
+
+private:
+  /// Generates a record size error. ExpectedSize is the number
+  /// of elements expected. RecordName is the name of the kind of
+  /// record that has incorrect size. ContextMessage (if not 0)
+  /// is appended to "record expects" to describe how ExpectedSize
+  /// should be interpreted.
+  bool RecordSizeError(unsigned ExpectedSize, const char *RecordName,
+                       const char *ContextMessage) {
+    std::string Buffer;
+    raw_string_ostream StrBuf(Buffer);
+    StrBuf << RecordName << " record expects";
+    if (ContextMessage)
+      StrBuf << " " << ContextMessage;
+    StrBuf << " " << ExpectedSize << " argument";
+    if (ExpectedSize > 1)
+      StrBuf << "s";
+    StrBuf << ". Found: " << Record.GetValues().size();
+    return Error(StrBuf.str());
+  }
+};
+
+bool BlockParserBaseClass::ParseBlock(unsigned BlockID) {
+  // If called, derived class doesn't know how to handle block.
+  // Report error and skip.
+  std::string Buffer;
+  raw_string_ostream StrBuf(Buffer);
+  StrBuf << "Don't know how to parse block id: " << BlockID;
+  Error(StrBuf.str());
+  SkipBlock();
+  return false;
+}
+
+void BlockParserBaseClass::ProcessRecord() {
+  // If called, derived class doesn't know how to handle.
+  std::string Buffer;
+  raw_string_ostream StrBuf(Buffer);
+  StrBuf << "Don't know how to process record: " << Record;
+  Error(StrBuf.str());
+}
+
+// Class to parse a types block.
+class TypesParser : public BlockParserBaseClass {
+public:
+  TypesParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
+      : BlockParserBaseClass(BlockID, EnclosingParser), NextTypeId(0) {}
+
+  ~TypesParser() LLVM_OVERRIDE {}
+
+private:
+  // The type ID that will be associated with the next type defining
+  // record in the types block.
+  unsigned NextTypeId;
+
+  virtual void ProcessRecord() LLVM_OVERRIDE;
+};
+
+void TypesParser::ProcessRecord() {
+  Type *Ty = NULL;
+  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+  switch (Record.GetCode()) {
+  case naclbitc::TYPE_CODE_NUMENTRY:
+    // NUMENTRY: [numentries]
+    if (checkRecordSize(1, "Type count"))
+      return;
+    Context->resizeTypeIDValues(Values[0]);
+    return;
+  case naclbitc::TYPE_CODE_VOID:
+    // VOID
+    if (checkRecordSize(0, "Type void"))
+      break;
+    Ty = Type::getVoidTy(Context->getLLVMContext());
+    break;
+  case naclbitc::TYPE_CODE_FLOAT:
+    // FLOAT
+    if (checkRecordSize(0, "Type float"))
+      break;
+    Ty = Type::getFloatTy(Context->getLLVMContext());
+    break;
+  case naclbitc::TYPE_CODE_DOUBLE:
+    // DOUBLE
+    if (checkRecordSize(0, "Type double"))
+      break;
+    Ty = Type::getDoubleTy(Context->getLLVMContext());
+    break;
+  case naclbitc::TYPE_CODE_INTEGER:
+    // INTEGER: [width]
+    if (checkRecordSize(1, "Type integer"))
+      break;
+    Ty = IntegerType::get(Context->getLLVMContext(), Values[0]);
+    // TODO(kschimpf) Check if size is legal.
+    break;
+  case naclbitc::TYPE_CODE_VECTOR:
+    // VECTOR: [numelts, eltty]
+    if (checkRecordSize(2, "Type vector"))
+      break;
+    Ty = VectorType::get(Context->getTypeByID(Values[1]), Values[0]);
+    break;
+  case naclbitc::TYPE_CODE_FUNCTION: {
+    // FUNCTION: [vararg, retty, paramty x N]
+    if (checkRecordSizeAtLeast(2, "Type signature"))
+      break;
+    SmallVector<Type *, 8> ArgTys;
+    for (unsigned i = 2, e = Values.size(); i != e; ++i) {
+      ArgTys.push_back(Context->getTypeByID(Values[i]));
+    }
+    Ty = FunctionType::get(Context->getTypeByID(Values[1]), ArgTys, Values[0]);
+    break;
+  }
+  default:
+    BlockParserBaseClass::ProcessRecord();
+    break;
+  }
+  // If Ty not defined, assume error. Use void as filler.
+  if (Ty == NULL)
+    Ty = Type::getVoidTy(Context->getLLVMContext());
+  Context->setTypeID(NextTypeId++, Ty);
+}
+
+/// Parses the globals block (i.e. global variables).
+class GlobalsParser : public BlockParserBaseClass {
+public:
+  GlobalsParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser)
+      : BlockParserBaseClass(BlockID, EnclosingParser), InitializersNeeded(0),
+        Alignment(1), IsConstant(false) {
+    NextGlobalID = Context->getNumFunctionIDs();
+  }
+
+  virtual ~GlobalsParser() LLVM_OVERRIDE {}
+
+private:
+  // Holds the sequence of initializers for the global.
+  SmallVector<Constant *, 10> Initializers;
+
+  // Keeps track of how many initializers are expected for
+  // the global variable being built.
+  unsigned InitializersNeeded;
+
+  // The alignment assumed for the global variable being built.
+  unsigned Alignment;
+
+  // True if the global variable being built is a constant.
+  bool IsConstant;
+
+  // The index of the next global variable.
+  unsigned NextGlobalID;
+
+  virtual void ExitBlock() LLVM_OVERRIDE {
+    verifyNoMissingInitializers();
+    unsigned NumIDs = Context->getNumGlobalValueIDs();
+    if (NextGlobalID < NumIDs) {
+      unsigned NumFcnIDs = Context->getNumFunctionIDs();
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Globals block expects " << (NumIDs - NumFcnIDs)
+             << " global definitions. Found: " << (NextGlobalID - NumFcnIDs);
+      Error(StrBuf.str());
+    }
+    BlockParserBaseClass::ExitBlock();
+  }
+
+  virtual void ProcessRecord() LLVM_OVERRIDE;
+
+  // Checks if the number of initializers needed is the same as the
+  // number found in the bitcode file. If different, and error message
+  // is generated, and the internal state of the parser is fixed so
+  // this condition is no longer violated.
+  void verifyNoMissingInitializers() {
+    if (InitializersNeeded != Initializers.size()) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Global variable @g"
+             << (NextGlobalID - Context->getNumFunctionIDs()) << " expected "
+             << InitializersNeeded << " initializer";
+      if (InitializersNeeded > 1)
+        StrBuf << "s";
+      StrBuf << ". Found: " << Initializers.size();
+      Error(StrBuf.str());
+      // Fix up state so that we can continue.
+      InitializersNeeded = Initializers.size();
+      installGlobalVar();
+    }
+  }
+
+  // Reserves a slot in the list of initializers being built. If there
+  // isn't room for the slot, an error message is generated.
+  void reserveInitializer(const char *RecordName) {
+    if (InitializersNeeded <= Initializers.size()) {
+      Error(std::string(RecordName) +
+            " record: Too many initializers, ignoring.");
+    }
+  }
+
+  // Takes the initializers (and other parser state values) and
+  // installs a global variable (with the initializers) into the list
+  // of ValueIDs.
+  void installGlobalVar() {
+    Constant *Init = NULL;
+    switch (Initializers.size()) {
+    case 0:
+      Error("No initializer for global variable in global vars block");
+      return;
+    case 1:
+      Init = Initializers[0];
+      break;
+    default:
+      Init = ConstantStruct::getAnon(Context->getLLVMContext(), Initializers,
+                                     true);
+      break;
+    }
+    GlobalVariable *GV =
+        new GlobalVariable(*Context->getModule(), Init->getType(), IsConstant,
+                           GlobalValue::InternalLinkage, Init, "");
+    GV->setAlignment(Alignment);
+    if (!Context->assignGlobalVariable(GV, NextGlobalID)) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Defining global V[" << NextGlobalID
+             << "] not allowed. Out of range.";
+      Error(StrBuf.str());
+    }
+    ++NextGlobalID;
+    Initializers.clear();
+    InitializersNeeded = 0;
+    Alignment = 1;
+    IsConstant = false;
+  }
+};
+
+void GlobalsParser::ProcessRecord() {
+  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+  switch (Record.GetCode()) {
+  case naclbitc::GLOBALVAR_COUNT:
+    // COUNT: [n]
+    if (checkRecordSize(1, "Globals count"))
+      return;
+    if (NextGlobalID != Context->getNumFunctionIDs()) {
+      Error("Globals count record not first in block.");
+      return;
+    }
+    verifyNoMissingInitializers();
+    Context->resizeValueIDsForGlobalVarCount(Values[0]);
+    return;
+  case naclbitc::GLOBALVAR_VAR: {
+    // VAR: [align, isconst]
+    if (checkRecordSize(2, "Globals variable"))
+      return;
+    verifyNoMissingInitializers();
+    InitializersNeeded = 1;
+    Initializers.clear();
+    Alignment = (1 << Values[0]) >> 1;
+    IsConstant = Values[1] != 0;
+    return;
+  }
+  case naclbitc::GLOBALVAR_COMPOUND:
+    // COMPOUND: [size]
+    if (checkRecordSize(1, "globals compound"))
+      return;
+    if (Initializers.size() > 0 || InitializersNeeded != 1) {
+      Error("Globals compound record not first initializer");
+      return;
+    }
+    if (Values[0] < 2) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Globals compound record size invalid. Found: " << Values[0];
+      Error(StrBuf.str());
+      return;
+    }
+    InitializersNeeded = Values[0];
+    return;
+  case naclbitc::GLOBALVAR_ZEROFILL: {
+    // ZEROFILL: [size]
+    if (checkRecordSize(1, "Globals zerofill"))
+      return;
+    reserveInitializer("Globals zerofill");
+    Type *Ty =
+        ArrayType::get(Type::getInt8Ty(Context->getLLVMContext()), Values[0]);
+    Constant *Zero = ConstantAggregateZero::get(Ty);
+    Initializers.push_back(Zero);
+    break;
+  }
+  case naclbitc::GLOBALVAR_DATA: {
+    // DATA: [b0, b1, ...]
+    if (checkRecordSizeAtLeast(1, "Globals data"))
+      return;
+    reserveInitializer("Globals data");
+    unsigned Size = Values.size();
+    SmallVector<uint8_t, 32> Buf;
+    for (unsigned i = 0; i < Size; ++i)
+      Buf.push_back(static_cast<uint8_t>(Values[i]));
+    Constant *Init = ConstantDataArray::get(
+        Context->getLLVMContext(), ArrayRef<uint8_t>(Buf.data(), Buf.size()));
+    Initializers.push_back(Init);
+    break;
+  }
+  case naclbitc::GLOBALVAR_RELOC: {
+    // RELOC: [val, [addend]]
+    if (checkRecordSizeInRange(1, 2, "Globals reloc"))
+      return;
+    Constant *BaseVal = Context->getOrCreateGlobalVarRef(Values[0]);
+    if (BaseVal == 0) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Can't find global relocation value: " << Values[0];
+      Error(StrBuf.str());
+      return;
+    }
+    Type *IntPtrType = IntegerType::get(Context->getLLVMContext(), 32);
+    Constant *Val = ConstantExpr::getPtrToInt(BaseVal, IntPtrType);
+    if (Values.size() == 2) {
+      Val = ConstantExpr::getAdd(Val, ConstantInt::get(IntPtrType, Values[1]));
+    }
+    Initializers.push_back(Val);
+    break;
+  }
+  default:
+    BlockParserBaseClass::ProcessRecord();
+    return;
+  }
+  // If reached, just processed another initializer. See if time
+  // to install global.
+  if (InitializersNeeded == Initializers.size())
+    installGlobalVar();
+}
+
+// Parses a valuesymtab block in the bitcode file.
+class ValuesymtabParser : public BlockParserBaseClass {
+  typedef SmallString<128> StringType;
+
+public:
+  ValuesymtabParser(unsigned BlockID, BlockParserBaseClass *EnclosingParser,
+                    bool AllowBbEntries)
+      : BlockParserBaseClass(BlockID, EnclosingParser),
+        AllowBbEntries(AllowBbEntries) {}
+
+  virtual ~ValuesymtabParser() LLVM_OVERRIDE {}
+
+private:
+  // True if entries to name basic blocks allowed.
+  bool AllowBbEntries;
+
+  virtual void ProcessRecord() LLVM_OVERRIDE;
+
+  void ConvertToString(StringType &ConvertedName) {
+    const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+    for (size_t i = 1, e = Values.size(); i != e; ++i) {
+      ConvertedName += static_cast<char>(Values[i]);
+    }
+  }
+};
+
+void ValuesymtabParser::ProcessRecord() {
+  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+  StringType ConvertedName;
+  switch (Record.GetCode()) {
+  case naclbitc::VST_CODE_ENTRY: {
+    // VST_ENTRY: [ValueId, namechar x N]
+    if (checkRecordSizeAtLeast(2, "Valuesymtab value entry"))
+      return;
+    ConvertToString(ConvertedName);
+    Value *V = Context->getGlobalValueByID(Values[0]);
+    if (V == 0) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Invalid global address ID in valuesymtab: " << Values[0];
+      Error(StrBuf.str());
+      return;
+    }
+    V->setName(StringRef(ConvertedName.data(), ConvertedName.size()));
+    return;
+  }
+  case naclbitc::VST_CODE_BBENTRY: {
+    // VST_BBENTRY: [BbId, namechar x N]
+    // For now, since we aren't processing function blocks, don't handle.
+    if (AllowBbEntries) {
+      Error("Valuesymtab bb entry not implemented");
+      return;
+    }
+    break;
+  }
+  default:
+    break;
+  }
+  // If reached, don't know how to handle record.
+  BlockParserBaseClass::ProcessRecord();
+  return;
+}
+
+/// Parses the module block in the bitcode file.
+class ModuleParser : public BlockParserBaseClass {
+public:
+  ModuleParser(unsigned BlockID, TopLevelParser *Context)
+      : BlockParserBaseClass(BlockID, Context) {}
+
+  virtual ~ModuleParser() LLVM_OVERRIDE {}
+
+protected:
+  virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
+
+  virtual void ProcessRecord() LLVM_OVERRIDE;
+};
+
+bool ModuleParser::ParseBlock(unsigned BlockID) LLVM_OVERRIDE {
+  switch (BlockID) {
+  case naclbitc::BLOCKINFO_BLOCK_ID:
+    return NaClBitcodeParser::ParseBlock(BlockID);
+  case naclbitc::TYPE_BLOCK_ID_NEW: {
+    TypesParser Parser(BlockID, this);
+    return Parser.ParseThisBlock();
+  }
+  case naclbitc::GLOBALVAR_BLOCK_ID: {
+    GlobalsParser Parser(BlockID, this);
+    return Parser.ParseThisBlock();
+  }
+  case naclbitc::VALUE_SYMTAB_BLOCK_ID: {
+    ValuesymtabParser Parser(BlockID, this, false);
+    return Parser.ParseThisBlock();
+  }
+  case naclbitc::FUNCTION_BLOCK_ID: {
+    Error("Function block parser not yet implemented, skipping");
+    SkipBlock();
+    return false;
+  }
+  default:
+    return BlockParserBaseClass::ParseBlock(BlockID);
+  }
+}
+
+void ModuleParser::ProcessRecord() {
+  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+  switch (Record.GetCode()) {
+  case naclbitc::MODULE_CODE_VERSION: {
+    // VERSION: [version#]
+    if (checkRecordSize(1, "Module version"))
+      return;
+    unsigned Version = Values[0];
+    if (Version != 1) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Unknown bitstream version: " << Version;
+      Error(StrBuf.str());
+    }
+    return;
+  }
+  case naclbitc::MODULE_CODE_FUNCTION: {
+    // FUNCTION:  [type, callingconv, isproto, linkage]
+    if (checkRecordSize(4, "Function heading"))
+      return;
+    Type *Ty = Context->getTypeByID(Values[0]);
+    FunctionType *FTy = dyn_cast<FunctionType>(Ty);
+    if (FTy == 0) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Function heading expects function type. Found: " << Ty;
+      Error(StrBuf.str());
+      return;
+    }
+    CallingConv::ID CallingConv;
+    if (!naclbitc::DecodeCallingConv(Values[1], CallingConv)) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Function heading has unknown calling convention: "
+             << Values[1];
+      Error(StrBuf.str());
+      return;
+    }
+    GlobalValue::LinkageTypes Linkage;
+    if (!naclbitc::DecodeLinkage(Values[3], Linkage)) {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "Function heading has unknown linkage. Found " << Values[3];
+      Error(StrBuf.str());
+      return;
+    }
+    Function *Func = Function::Create(FTy, Linkage, "", Context->getModule());
+    Func->setCallingConv(CallingConv);
+    if (Values[2] == 0)
+      Context->setNextValueIDAsImplementedFunction();
+    Context->setNextFunctionID(Func);
+    // TODO(kschimpf) verify if Func matches PNaCl ABI.
+    return;
+  }
+  default:
+    BlockParserBaseClass::ProcessRecord();
+    return;
+  }
+}
+
+bool TopLevelParser::ParseBlock(unsigned BlockID) {
+  if (BlockID == naclbitc::MODULE_BLOCK_ID) {
+    ModuleParser Parser(BlockID, this);
+    bool ReturnValue = Parser.ParseThisBlock();
+    // TODO(kschimpf): Remove once translating function blocks.
+    errs() << "Global addresses:\n";
+    for (size_t i = 0; i < ValueIDValues.size(); ++i) {
+      errs() << "[" << i << "]: " << *ValueIDValues[i] << "\n";
+    }
+    return ReturnValue;
+  }
+  // Generate error message by using default block implementation.
+  BlockParserBaseClass Parser(BlockID, this);
+  return Parser.ParseThisBlock();
+}
+
+} // end of anonymous namespace.
+
+namespace Ice {
+
+void PNaClTranslator::translate(const std::string &IRFilename) {
+  OwningPtr<MemoryBuffer> MemBuf;
+  if (error_code ec =
+          MemoryBuffer::getFileOrSTDIN(IRFilename.c_str(), MemBuf)) {
+    errs() << "Error reading '" << IRFilename << "': " << ec.message() << "\n";
+    ExitStatus = 1;
+    return;
+  }
+
+  if (MemBuf->getBufferSize() % 4 != 0) {
+    errs() << IRFilename
+           << ": Bitcode stream should be a multiple of 4 bytes in length.\n";
+    ExitStatus = 1;
+    return;
+  }
+
+  const unsigned char *BufPtr = (const unsigned char *)MemBuf->getBufferStart();
+  const unsigned char *EndBufPtr = BufPtr + MemBuf->getBufferSize();
+
+  // Read header and verify it is good.
+  NaClBitcodeHeader Header;
+  if (Header.Read(BufPtr, EndBufPtr) || !Header.IsSupported()) {
+    errs() << "Invalid PNaCl bitcode header.\n";
+    ExitStatus = 1;
+    return;
+  }
+
+  // Create a bitstream reader to read the bitcode file.
+  NaClBitstreamReader InputStreamFile(BufPtr, EndBufPtr);
+  NaClBitstreamCursor InputStream(InputStreamFile);
+
+  TopLevelParser Parser(MemBuf->getBufferIdentifier(), Header, InputStream,
+                        ExitStatus);
+  int TopLevelBlocks = 0;
+  while (!InputStream.AtEndOfStream()) {
+    if (Parser.Parse()) {
+      ExitStatus = 1;
+      return;
+    }
+    ++TopLevelBlocks;
+  }
+
+  if (TopLevelBlocks != 1) {
+    errs() << IRFilename
+           << ": Contains more than one module. Found: " << TopLevelBlocks
+           << "\n";
+    ExitStatus = 1;
+  }
+  return;
+}
+
+} // end of anonymous namespace.
diff --git a/src/PNaClTranslator.h b/src/PNaClTranslator.h
new file mode 100644
index 0000000..a0316d7
--- /dev/null
+++ b/src/PNaClTranslator.h
@@ -0,0 +1,38 @@
+//===- subzero/src/PNaClTranslator.h - ICE from bitcode ---------*- C++ -*-===//
+//
+//                        The Subzero Code Generator
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the PNaCl bitcode file to ICE, to machine code
+// translator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUBZERO_SRC_PNACLTRANSLATOR_H
+#define SUBZERO_SRC_PNACLTRANSLATOR_H
+
+#include "IceTranslator.h"
+#include <string>
+
+namespace Ice {
+
+class PNaClTranslator : public Translator {
+public:
+  PNaClTranslator(GlobalContext *Ctx, ClFlags &Flags)
+      : Translator(Ctx, Flags) {}
+  // Reads the PNaCl bitcode file and translates to ICE, which is then
+  // converted to machine code. Sets ExitStatus to non-zero if any
+  // errors occurred.
+  void translate(const std::string &IRFilename);
+
+private:
+  PNaClTranslator(const PNaClTranslator &) LLVM_DELETED_FUNCTION;
+  PNaClTranslator &operator=(const PNaClTranslator &) LLVM_DELETED_FUNCTION;
+};
+}
+
+#endif // SUBZERO_SRC_PNACLTRANSLATOR_H
diff --git a/src/llvm2ice.cpp b/src/llvm2ice.cpp
index 6d26cff53..822a0ce 100644
--- a/src/llvm2ice.cpp
+++ b/src/llvm2ice.cpp
@@ -14,12 +14,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "IceCfg.h"
+#include "IceClFlags.h"
 #include "IceConverter.h"
 #include "IceDefs.h"
 #include "IceTargetLowering.h"
 #include "IceTypes.h"
+#include "PNaClTranslator.h"
 
-#include "llvm/IR/Constant.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
@@ -128,9 +129,15 @@
 
   Ice::GlobalContext Ctx(Ls, Os, VMask, TargetArch, OptLevel, TestPrefix);
 
+  Ice::ClFlags Flags;
+  Flags.DisableInternal = DisableInternal;
+  Flags.SubzeroTimingEnabled = SubzeroTimingEnabled;
+  Flags.DisableTranslation = DisableTranslation;
+
   if (BuildOnRead) {
-    std::cerr << "Direct build from bitcode not implemented yet!\n";
-    return 1;
+    Ice::PNaClTranslator Translator(&Ctx, Flags);
+    Translator.translate(IRFilename);
+    return Translator.getExitStatus();
   } else {
     // Parse the input LLVM IR file into a module.
     SMDiagnostic Err;
@@ -189,8 +196,7 @@
     }
     GlobalLowering.reset();
 
-    Ice::Converter Converter(&Ctx, DisableInternal, SubzeroTimingEnabled,
-                             DisableTranslation);
+    Ice::Converter Converter(&Ctx, Flags);
     return Converter.convertToIce(Mod);
   }
 }