compiler, runtime: implement shifts by signed amounts

Shifting by signed types is a new language feature in Go 1.13.

This requires a patch to the testsuite:

    Index: go.test/test/fixedbugs/bug073.go
    ===================================================================
    --- go.test/test/fixedbugs/bug073.go	(revision 274239)
    +++ go.test/test/fixedbugs/bug073.go	(working copy)
    @@ -1,4 +1,4 @@
    -// errorcheck
    +// compile

     // Copyright 2009 The Go Authors. All rights reserved.
     // Use of this source code is governed by a BSD-style
    @@ -7,8 +7,8 @@
     package main

     func main() {
    -	var s int = 0;
    -	var x int = 0;
    -	x = x << s;  // ERROR "illegal|inval|shift"
    -	x = x >> s;  // ERROR "illegal|inval|shift"
    +	var s int = 0
    +	var x int = 0
    +	x = x << s // as of 1.13, these are ok
    +	x = x >> s // as of 1.13, these are ok
     }

Updates golang/go#19113

Change-Id: Ida01c07dff6c5f1f47559083374688ff3800b272
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/190977
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/go/expressions.cc b/go/expressions.cc
index 995a18c..aa0fda0 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -6734,11 +6734,10 @@
 	this->report_error(_("shift of non-integer operand"));
 
       if (right_type->is_string_type())
-        this->report_error(_("shift count not unsigned integer"));
+        this->report_error(_("shift count not integer"));
       else if (!right_type->is_abstract()
-	  && (right_type->integer_type() == NULL
-	      || !right_type->integer_type()->is_unsigned()))
-	this->report_error(_("shift count not unsigned integer"));
+	       && right_type->integer_type() == NULL)
+	this->report_error(_("shift count not integer"));
       else
 	{
 	  Numeric_constant nc;
@@ -6746,7 +6745,7 @@
 	    {
 	      mpz_t val;
 	      if (!nc.to_int(&val))
-		this->report_error(_("shift count not unsigned integer"));
+		this->report_error(_("shift count not integer"));
 	      else
 		{
 		  if (mpz_sgn(val) < 0)
@@ -6865,9 +6864,11 @@
 
   // In Go, a shift larger than the size of the type is well-defined.
   // This is not true in C, so we need to insert a conditional.
+  // We also need to check for a negative shift count.
   if (is_shift_op)
     {
       go_assert(left_type->integer_type() != NULL);
+      go_assert(right_type->integer_type() != NULL);
 
       int bits = left_type->integer_type()->bits();
 
@@ -6909,6 +6910,23 @@
 							ret, overflow, loc);
 	  mpz_clear(bitsval);
 	}
+
+      if (!right_type->integer_type()->is_unsigned()
+	  && (!this->right_->numeric_constant_value(&nc)
+	      || nc.to_unsigned_long(&ul) != Numeric_constant::NC_UL_VALID))
+	{
+	  Bexpression* zero_expr =
+	    gogo->backend()->integer_constant_expression(right_btype, zero);
+	  Bexpression* compare =
+	    gogo->backend()->binary_expression(OPERATOR_LT, right, zero_expr,
+					       loc);
+	  const int errcode = RUNTIME_ERROR_SHIFT_BY_NEGATIVE;
+	  Bexpression* crash =
+	    gogo->runtime_error(errcode, loc)->get_backend(context);
+	  Bfunction* bfn = context->function()->func_value()->get_decl();
+	  ret = gogo->backend()->conditional_expression(bfn, btype, compare,
+							crash, ret, loc);
+	}
     }
 
   // Add checks for division by zero and division overflow as needed.
diff --git a/go/gogo.h b/go/gogo.h
index b3ec629..0abd4b4 100644
--- a/go/gogo.h
+++ b/go/gogo.h
@@ -3745,6 +3745,9 @@
 // Go statement with nil function.
 static const int RUNTIME_ERROR_GO_NIL = 12;
 
+// Shift by negative value.
+static const int RUNTIME_ERROR_SHIFT_BY_NEGATIVE = 13;
+
 // This is used by some of the langhooks.
 extern Gogo* go_get_gogo();
 
diff --git a/libgo/runtime/go-runtime-error.c b/libgo/runtime/go-runtime-error.c
index c9ccf98..8179e68 100644
--- a/libgo/runtime/go-runtime-error.c
+++ b/libgo/runtime/go-runtime-error.c
@@ -55,7 +55,10 @@
   DIVISION_BY_ZERO = 11,
 
   /* Go statement with nil function.  */
-  GO_NIL = 12
+  GO_NIL = 12,
+
+  /* Shift by negative value.  */
+  SHIFT_BY_NEGATIVE = 13
 };
 
 extern void __go_runtime_error (int32) __attribute__ ((noreturn));
@@ -112,6 +115,9 @@
       runtime_g()->m->throwing = -1;
       runtime_throw ("go of nil func value");
 
+    case SHIFT_BY_NEGATIVE:
+      runtime_panicstring ("negative shift amount");
+
     default:
       runtime_panicstring ("unknown runtime error");
     }