Add constants block to PNaCl bitcode reader.

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

Review URL: https://codereview.chromium.org/548553002
diff --git a/src/PNaClTranslator.cpp b/src/PNaClTranslator.cpp
index f315294..5bfa33b 100644
--- a/src/PNaClTranslator.cpp
+++ b/src/PNaClTranslator.cpp
@@ -821,6 +821,9 @@
 
   ~FunctionParser() LLVM_OVERRIDE;
 
+  // Set the next constant ID to the given constant C.
+  void setNextConstantID(Ice::Constant *C) { LocalOperands.push_back(C); }
+
 private:
   // Timer for reading function bitcode and converting to ICE.
   Ice::Timer TConvert;
@@ -843,6 +846,8 @@
   // instruction.
   bool InstIsTerminating;
 
+  virtual bool ParseBlock(unsigned BlockID) LLVM_OVERRIDE;
+
   virtual void ProcessRecord() LLVM_OVERRIDE;
 
   virtual void ExitBlock() LLVM_OVERRIDE;
@@ -1519,6 +1524,130 @@
     CurrentNode->appendInst(Inst);
 }
 
+/// Parses constants within a function block.
+class ConstantsParser : public BlockParserBaseClass {
+  ConstantsParser(const ConstantsParser &) LLVM_DELETED_FUNCTION;
+  ConstantsParser &operator=(const ConstantsParser &) LLVM_DELETED_FUNCTION;
+
+public:
+  ConstantsParser(unsigned BlockID, FunctionParser *FuncParser)
+      : BlockParserBaseClass(BlockID, FuncParser), FuncParser(FuncParser),
+        NextConstantType(Ice::IceType_void) {}
+
+  ~ConstantsParser() LLVM_OVERRIDE {}
+
+private:
+  // The parser of the function block this constants block appears in.
+  FunctionParser *FuncParser;
+  // The type to use for succeeding constants.
+  Ice::Type NextConstantType;
+
+  virtual void ProcessRecord() LLVM_OVERRIDE;
+
+  Ice::GlobalContext *getContext() { return getTranslator().getContext(); }
+
+  // Returns true if the type to use for succeeding constants is defined.
+  // If false, also generates an error message.
+  bool isValidNextConstantType() {
+    if (NextConstantType != Ice::IceType_void)
+      return true;
+    Error("Constant record not preceded by set type record");
+    return false;
+  }
+};
+
+void ConstantsParser::ProcessRecord() {
+  const NaClBitcodeRecord::RecordVector &Values = Record.GetValues();
+  switch (Record.GetCode()) {
+  case naclbitc::CST_CODE_SETTYPE: {
+    // SETTYPE: [typeid]
+    if (!isValidRecordSize(1, "constants block set type"))
+      return;
+    NextConstantType =
+        Context->convertToIceType(Context->getTypeByID(Values[0]));
+    if (NextConstantType == Ice::IceType_void)
+      Error("constants block set type not allowed for void type");
+    return;
+  }
+  case naclbitc::CST_CODE_UNDEF: {
+    // UNDEF
+    if (!isValidRecordSize(0, "constants block undef"))
+      return;
+    if (!isValidNextConstantType())
+      return;
+    FuncParser->setNextConstantID(
+        getContext()->getConstantUndef(NextConstantType));
+    return;
+  }
+  case naclbitc::CST_CODE_INTEGER: {
+    // INTEGER: [intval]
+    if (!isValidRecordSize(1, "constants block integer"))
+      return;
+    if (!isValidNextConstantType())
+      return;
+    if (IntegerType *IType = dyn_cast<IntegerType>(
+            Context->convertToLLVMType(NextConstantType))) {
+      APInt Value(IType->getBitWidth(), NaClDecodeSignRotatedValue(Values[0]));
+      Ice::Constant *C =
+          getContext()->getConstantInt(NextConstantType, Value.getSExtValue());
+      FuncParser->setNextConstantID(C);
+      return;
+    }
+    std::string Buffer;
+    raw_string_ostream StrBuf(Buffer);
+    StrBuf << "constant block integer record for non-integer type "
+           << NextConstantType;
+    Error(StrBuf.str());
+    return;
+  }
+  case naclbitc::CST_CODE_FLOAT: {
+    // FLOAT: [fpval]
+    if (!isValidRecordSize(1, "constants block float"))
+      return;
+    if (!isValidNextConstantType())
+      return;
+    switch (NextConstantType) {
+    case Ice::IceType_f32: {
+      APFloat Value(APFloat::IEEEsingle,
+                    APInt(32, static_cast<uint32_t>(Values[0])));
+      FuncParser->setNextConstantID(
+          getContext()->getConstantFloat(Value.convertToFloat()));
+      return;
+    }
+    case Ice::IceType_f64: {
+      APFloat Value(APFloat::IEEEdouble, APInt(64, Values[0]));
+      FuncParser->setNextConstantID(
+          getContext()->getConstantDouble(Value.convertToDouble()));
+      return;
+    }
+    default: {
+      std::string Buffer;
+      raw_string_ostream StrBuf(Buffer);
+      StrBuf << "constant block float record for non-floating type "
+             << NextConstantType;
+      Error(StrBuf.str());
+      return;
+    }
+    }
+  }
+  default:
+    // Generate error message!
+    BlockParserBaseClass::ProcessRecord();
+    return;
+  }
+}
+
+bool FunctionParser::ParseBlock(unsigned BlockID) {
+  switch (BlockID) {
+  case naclbitc::CONSTANTS_BLOCK_ID: {
+    ConstantsParser Parser(BlockID, this);
+    return Parser.ParseThisBlock();
+  }
+  default:
+    return BlockParserBaseClass::ParseBlock(BlockID);
+  }
+}
+
 /// Parses the module block in the bitcode file.
 class ModuleParser : public BlockParserBaseClass {
 public: