aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-02-06 15:30:06 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-02-06 15:30:06 +0000
commit3e12b42be93c14a599df9c96e58ba66cd864bf77 (patch)
tree4d375844ea14bdf771954d9e232206931c69405e /gcc/go
parent3ca8e91f0e4452f618dbdc82090ecf47d1bd984c (diff)
downloadgcc-3e12b42be93c14a599df9c96e58ba66cd864bf77.zip
gcc-3e12b42be93c14a599df9c96e58ba66cd864bf77.tar.gz
gcc-3e12b42be93c14a599df9c96e58ba66cd864bf77.tar.bz2
compiler: avoid negative zero in float constants
Check for negative numbers with very small magnitudes that will round to negative zero, and force them to positive zero instead. This implements the spec clarification in https://golang.org/cl/14727. The test is in https://golang.org/cl/91895. Fixes golang/go#12621 Reviewed-on: https://go-review.googlesource.com/92175 From-SVN: r257415
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc62
-rw-r--r--gcc/go/gofrontend/expressions.h3
3 files changed, 64 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 91bebe5..8c49b2b 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-1927b40e59e7c2067ecb03384b331d1be3cb5eea
+02f11a2d5cf0db2c2675c13d92bb69529f2175dd
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 8555c05..f50de0a 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -16158,10 +16158,16 @@ Numeric_constant::set_float(Type* type, const mpfr_t val)
this->clear();
this->classification_ = NC_FLOAT;
this->type_ = type;
+
// Numeric constants do not have negative zero values, so remove
// them here. They also don't have infinity or NaN values, but we
// should never see them here.
- if (mpfr_zero_p(val))
+ int bits = 0;
+ if (type != NULL
+ && type->float_type() != NULL
+ && !type->float_type()->is_abstract())
+ bits = type->float_type()->bits();
+ if (Numeric_constant::is_float_neg_zero(val, bits))
mpfr_init_set_ui(this->u_.float_val, 0, GMP_RNDN);
else
mpfr_init_set(this->u_.float_val, val, GMP_RNDN);
@@ -16175,8 +16181,60 @@ Numeric_constant::set_complex(Type* type, const mpc_t val)
this->clear();
this->classification_ = NC_COMPLEX;
this->type_ = type;
+
+ // Avoid negative zero as in set_float.
+ int bits = 0;
+ if (type != NULL
+ && type->complex_type() != NULL
+ && !type->complex_type()->is_abstract())
+ bits = type->complex_type()->bits() / 2;
+
+ mpfr_t real;
+ mpfr_init_set(real, mpc_realref(val), GMP_RNDN);
+ if (Numeric_constant::is_float_neg_zero(real, bits))
+ mpfr_set_ui(real, 0, GMP_RNDN);
+
+ mpfr_t imag;
+ mpfr_init_set(imag, mpc_imagref(val), GMP_RNDN);
+ if (Numeric_constant::is_float_neg_zero(imag, bits))
+ mpfr_set_ui(imag, 0, GMP_RNDN);
+
mpc_init2(this->u_.complex_val, mpc_precision);
- mpc_set(this->u_.complex_val, val, MPC_RNDNN);
+ mpc_set_fr_fr(this->u_.complex_val, real, imag, MPC_RNDNN);
+
+ mpfr_clear(real);
+ mpfr_clear(imag);
+}
+
+// Return whether VAL, at a precision of BITS, is a negative zero.
+// BITS may be zero in which case it is ignored.
+
+bool
+Numeric_constant::is_float_neg_zero(const mpfr_t val, int bits)
+{
+ if (!mpfr_signbit(val))
+ return false;
+ if (mpfr_zero_p(val))
+ return true;
+ mp_exp_t min_exp;
+ switch (bits)
+ {
+ case 0:
+ return false;
+ case 32:
+ // In a denormalized float32 the exponent is -126, and there are
+ // 24 bits of which at least the last must be 1, so the smallest
+ // representable non-zero exponent is -126 - (24 - 1) == -149.
+ min_exp = -149;
+ break;
+ case 64:
+ // Minimum exponent is -1022, there are 53 bits.
+ min_exp = -1074;
+ break;
+ default:
+ go_unreachable();
+ }
+ return mpfr_get_exp(val) < min_exp;
}
// Get an int value.
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index d16a284..a58c79c 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -4220,6 +4220,9 @@ class Numeric_constant
bool
check_complex_type(Complex_type*, bool, Location);
+ static bool
+ is_float_neg_zero(const mpfr_t, int bits);
+
// The kinds of constants.
enum Classification
{