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:
diff --git a/tests_lit/reader_tests/constants.ll b/tests_lit/reader_tests/constants.ll
new file mode 100644
index 0000000..43827b0
--- /dev/null
+++ b/tests_lit/reader_tests/constants.ll
@@ -0,0 +1,155 @@
+; Test handling of constants in function blocks.
+
+; RUN: llvm-as < %s | pnacl-freeze \
+; RUN:              | %llvm2ice -notranslate -verbose=inst -build-on-read \
+; RUN:                -allow-pnacl-reader-error-recovery \
+; RUN:              | FileCheck %s
+
+define void @TestIntegers() {
+; CHECK: __0:
+
+  ; Test various sized integers
+  %v0 = or i1 true, false
+; CHECK-NEXT:   %__0 = or i1 true, false
+
+  %v1 = add i8 0, 0
+; CHECK-NEXT:   %__1 = add i8 0, 0
+
+  %v2 = add i8 5, 0
+; CHECK-NEXT:   %__2 = add i8 5, 0
+
+  %v3 = add i8 -5, 0
+; CHECK-NEXT:   %__3 = add i8 -5, 0
+
+  %v4 = and i16 10, 0
+; CHECK-NEXT:   %__4 = and i16 10, 0
+
+  %v5 = add i16 -10, 0
+; CHECK-NEXT:   %__5 = add i16 -10, 0
+
+  %v6 = add i32 20, 0
+; CHECK-NEXT:   %__6 = add i32 20, 0
+
+  %v7 = add i32 -20, 0
+; CHECK-NEXT:   %__7 = add i32 -20, 0
+
+  %v8 = add i64 30, 0
+; CHECK-NEXT:   %__8 = add i64 30, 0
+
+  %v9 = add i64 -30, 0
+; CHECK-NEXT:   %__9 = add i64 -30, 0
+
+  ; Test undefined integer values.
+  %v10 = xor i1 undef, false
+; CHECK-NEXT:   %__10 = xor i1 undef, false
+
+  %v11 = add i8 undef, 0
+; CHECK-NEXT:   %__11 = add i8 undef, 0
+
+  %v12 = add i16 undef, 0
+; CHECK-NEXT:   %__12 = add i16 undef, 0
+
+  %v13 = add i32 undef, 0
+; CHECK-NEXT:   %__13 = add i32 undef, 0
+
+  %v14 = add i64 undef, 0
+; CHECK-NEXT:   %__14 = add i64 undef, 0
+
+  ret void
+; CHECK-NEXT:   ret void
+
+}
+
+define void @TestFloats() {
+; CHECK: __0:
+
+  ; Test float and double constants
+  %v0 = fadd float 1.0, 0.0
+; CHECK-NEXT:   %__0 = fadd float 1.000000e+00, 0.000000e+00
+
+  %v1 = fadd double 1.0, 0.0
+; CHECK-NEXT:   %__1 = fadd double 1.000000e+00, 0.000000e+00
+
+  %v2 = fsub float 7.000000e+00, 8.000000e+00
+; CHECK-NEXT:   %__2 = fsub float 7.000000e+00, 8.000000e+00
+
+  %v3 = fsub double 5.000000e+00, 6.000000e+00
+; CHECK-NEXT:   %__3 = fsub double 5.000000e+00, 6.000000e+00
+
+  ; Test undefined float and double.
+  %v4 = fadd float undef, 0.0
+; CHECK-NEXT:   %__4 = fadd float undef, 0.000000e+00
+
+  %v5 = fsub double undef, 6.000000e+00
+; CHECK-NEXT:   %__5 = fsub double undef, 6.000000e+00
+
+  ; Test special floating point constants. Note: LLVM assembly appears
+  ; to use 64-bit integer constants for both float and double.
+
+  ; Generated from NAN in <math.h>
+  %v6 = fadd float 0x7FF8000000000000, 0.0
+; CHECK-NEXT:   %__6 = fadd float nan, 0.000000e+00
+
+  ; Generated from -NAN in <math.h>
+  %v7 = fadd float 0xFFF8000000000000, 0.0
+; CHECK-NEXT:   %__7 = fadd float -nan, 0.000000e+00
+
+  ; Generated from INFINITY in <math.h>
+  %v8 = fadd float 0x7FF0000000000000, 0.0
+; CHECK-NEXT:   %__8 = fadd float inf, 0.000000e+00
+
+  ; Generated from -INFINITY in <math.h>
+  %v9 = fadd float 0xFFF0000000000000, 0.0
+; CHECK-NEXT:   %__9 = fadd float -inf, 0.000000e+00
+
+  ; Generated from FLT_MIN in <float.h>
+  %v10 = fadd float 0x381000000000000000, 0.0
+; CHECK-NEXT:   %__10 = fadd float 0.000000e+00, 0.000000e+00
+
+  ; Generated from -FLT_MIN in <float.h>
+  %v11 = fadd float 0xb81000000000000000, 0.0
+; CHECK-NEXT:   %__11 = fadd float 0.000000e+00, 0.000000e+00
+
+  ; Generated from FLT_MAX in <float.h>
+  %v12 = fadd float 340282346638528859811704183484516925440.000000, 0.0
+; CHECK-NEXT:   %__12 = fadd float 3.402823e+38, 0.000000e+00
+
+  ; Generated from -FLT_MAX in <float.h>
+  %v13 = fadd float -340282346638528859811704183484516925440.000000, 0.0
+; CHECK-NEXT:   %__13 = fadd float -3.402823e+38, 0.000000e+00
+
+  ; Generated from NAN in <math.h>
+  %v14 = fadd double 0x7FF8000000000000, 0.0
+; CHECK-NEXT:   %__14 = fadd double nan, 0.000000e+00
+
+  ; Generated from -NAN in <math.h>
+  %v15 = fadd double 0xFFF8000000000000, 0.0
+; CHECK-NEXT:   %__15 = fadd double -nan, 0.000000e+00
+
+  ; Generated from INFINITY in <math.h>
+  %v16 = fadd double 0x7FF0000000000000, 0.0
+; CHECK-NEXT:   %__16 = fadd double inf, 0.000000e+00
+
+  ; Generated from -INFINITY in <math.h>
+  %v17 = fadd double 0xFFF0000000000000, 0.0
+; CHECK-NEXT:   %__17 = fadd double -inf, 0.000000e+00
+
+  ; Generated from DBL_MIN in <float.h>
+  %v18 = fadd double 0x0010000000000000, 0.0
+; CHECK-NEXT:   %__18 = fadd double 2.225074e-308, 0.000000e+00
+
+  ; Generated from -DBL_MIN in <float.h>
+  %v19 = fadd double 0x8010000000000000, 0.0
+; CHECK-NEXT:   %__19 = fadd double -2.225074e-308, 0.000000e+00
+
+  ; Generated from DBL_MAX in <float.h>
+  %v20 = fadd double 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000, 0.0
+; CHECK-NEXT:   %__20 = fadd double 1.797693e+308, 0.000000e+00
+
+  ; Generated from -DBL_MAX in <float.h>
+  %v21 = fadd double -179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000, 0.0
+; CHECK-NEXT:   %__21 = fadd double -1.797693e+308, 0.000000e+00
+
+  ret void
+; CHECK-NEXT:   ret void
+}