From 43055d2379cfb1b5b1b09e243a9829e52e12b60a Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 20 Aug 2019 21:15:46 +0000 Subject: [PATCH] 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 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 28 +++++++++++++++---- gcc/go/gofrontend/gogo.h | 3 ++ gcc/testsuite/ChangeLog | 4 +++ .../go.test/test/fixedbugs/bug073.go | 10 +++---- libgo/runtime/go-runtime-error.c | 8 +++++- 6 files changed, 43 insertions(+), 12 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 94bc2f7c084..2776fb80224 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 995a18c71b8..aa0fda091bd 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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. diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index b3ec6291d32..0abd4b4cb2a 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -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(); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0512a60019d..2e361d30350 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2019-08-20 Ian Lance Taylor + + * go.test/test/fixedbugs/bug073.go: Update for language changes. + 2019-08-20 Matthew Beliveau * gcc.dg/tree-ssa/redundant-assign-zero-1.c: New test. diff --git a/gcc/testsuite/go.test/test/fixedbugs/bug073.go b/gcc/testsuite/go.test/test/fixedbugs/bug073.go index 49b47ae4649..f3605b37cfe 100644 --- a/gcc/testsuite/go.test/test/fixedbugs/bug073.go +++ b/gcc/testsuite/go.test/test/fixedbugs/bug073.go @@ -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 } diff --git a/libgo/runtime/go-runtime-error.c b/libgo/runtime/go-runtime-error.c index c9ccf98736f..8179e685ef7 100644 --- a/libgo/runtime/go-runtime-error.c +++ b/libgo/runtime/go-runtime-error.c @@ -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"); } -- 2.30.2