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.
    
    Updates golang/go#19113
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/190977

	* go.test/test/fixedbugs/bug073.go: Update for language changes.

From-SVN: r274755
This commit is contained in:
Ian Lance Taylor 2019-08-20 21:15:46 +00:00 committed by Ian Lance Taylor
parent 5ba5ad304a
commit 43055d2379
6 changed files with 43 additions and 12 deletions

View File

@ -1,4 +1,4 @@
a453eebae76296a39a1ded5bd2bffa78bedf40bd
1846b07fec2b91facc02ea269f7ab250b30f90b4
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View File

@ -6734,11 +6734,10 @@ Binary_expression::do_check_types(Gogo*)
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 @@ Binary_expression::do_check_types(Gogo*)
{
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 @@ Binary_expression::do_get_backend(Translate_context* context)
// 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 @@ Binary_expression::do_get_backend(Translate_context* context)
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.

View File

@ -3745,6 +3745,9 @@ static const int RUNTIME_ERROR_DIVISION_BY_ZERO = 11;
// 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();

View File

@ -1,3 +1,7 @@
2019-08-20 Ian Lance Taylor <iant@golang.org>
* go.test/test/fixedbugs/bug073.go: Update for language changes.
2019-08-20 Matthew Beliveau <mbelivea@redhat.com>
* gcc.dg/tree-ssa/redundant-assign-zero-1.c: New test.

View File

@ -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
}

View File

@ -55,7 +55,10 @@ enum
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 @@ __go_runtime_error (int32 i)
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");
}