gollvm: fix issue with integer constant creation

The recipe used for constructing integer constant expressions in the
bridge was not properly handling the case where you have a signed
mpz_val with value ((int64_t) -1) being forced into an unsigned
integer Btype with fewer bits (ex: uint16 or uint32). This triggered
an assert, since the mpz_val was being converted to a uint64 value of
18446744073709551615, then the llvm::ConstantInt::isValueValidForType
check for the smaller type failed. Fixed code converts constant
value into an llvm::APInt with the correct signed-ness and number of
bits before invoking llvm::ConstantInt::get.

Change-Id: I68741eea6833705cffe2eb06e33c3e771072aaeb
Reviewed-on: https://go-review.googlesource.com/48111
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/llvm-gofrontend/go-llvm.cpp b/llvm-gofrontend/go-llvm.cpp
index 99febaa..9b0766a 100644
--- a/llvm-gofrontend/go-llvm.cpp
+++ b/llvm-gofrontend/go-llvm.cpp
@@ -925,22 +925,20 @@
   assert(btype->type()->isIntegerTy());
 
   // Force mpz_val into either into uint64_t or int64_t depending on
-  // whether btype was declared as signed or unsigned.
-  //
-  // Q: better to use APInt here?
+  // whether btype was declared as signed or unsigned. 
 
   Bexpression *rval;
   BIntegerType *bit = btype->castToBIntegerType();
   if (bit->isUnsigned()) {
     uint64_t val = checked_convert_mpz_to_int<uint64_t>(mpz_val);
-    assert(llvm::ConstantInt::isValueValidForType(btype->type(), val));
-    llvm::Constant *lval = llvm::ConstantInt::get(btype->type(), val);
+    llvm::APInt apiv(bit->bits(), val);
+    llvm::Constant *lval = llvm::ConstantInt::get(btype->type(), apiv);
     Bexpression *bconst = nbuilder_.mkConst(btype, lval);
     return makeGlobalExpression(bconst, lval, btype, Location());
   } else {
     int64_t val = checked_convert_mpz_to_int<int64_t>(mpz_val);
-    assert(llvm::ConstantInt::isValueValidForType(btype->type(), val));
-    llvm::Constant *lval = llvm::ConstantInt::getSigned(btype->type(), val);
+    llvm::APInt apiv(bit->bits(), val, true);
+    llvm::Constant *lval = llvm::ConstantInt::get(btype->type(), apiv);
     Bexpression *bconst = nbuilder_.mkConst(btype, lval);
     return makeGlobalExpression(bconst, lval, btype, Location());
   }
diff --git a/unittests/BackendCore/BackendExprTests.cpp b/unittests/BackendCore/BackendExprTests.cpp
index e3d2d5c..7b4a942 100644
--- a/unittests/BackendCore/BackendExprTests.cpp
+++ b/unittests/BackendCore/BackendExprTests.cpp
@@ -65,6 +65,20 @@
     EXPECT_EQ(beval->value(), llvm::ConstantInt::get(bu64t->type(), val));
     mpz_clear(mpz_val);
   }
+
+  // Frontend will occasionally create create a signed -1 value with
+  // mpz_init_set_si and then hand this value off to to the bridge
+  // with a smaller unsigned type. Verify that this case works
+  // correctly.
+  mpz_t mpz_val;
+  memset(&mpz_val, '0', sizeof(mpz_val));
+  mpz_init_set_si(mpz_val, int64_t(-1));
+  Btype *bu32t = be->integer_type(true, 32);
+  Bexpression *beval = be->integer_constant_expression(bu32t, mpz_val);
+  ASSERT_TRUE(beval != nullptr);
+  uint32_t um1 = uint32_t(-1);
+  EXPECT_EQ(beval->value(), llvm::ConstantInt::get(bu32t->type(), um1));
+  mpz_clear(mpz_val);
 }
 
 TEST(BackendExprTests, MakeFloatConstExpr) {