aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1994-03-13 08:30:50 -0500
committerRichard Kenner <kenner@gcc.gnu.org>1994-03-13 08:30:50 -0500
commit649ff3b44f1adaca0ee5c2a51f568f334cb476eb (patch)
tree10f334e93637d357f239c92a898fd640d576eb19
parent831522a46e410eb9332a0883cfd3b50105aea4db (diff)
downloadgcc-649ff3b44f1adaca0ee5c2a51f568f334cb476eb.zip
gcc-649ff3b44f1adaca0ee5c2a51f568f334cb476eb.tar.gz
gcc-649ff3b44f1adaca0ee5c2a51f568f334cb476eb.tar.bz2
(force_fit_value): Operate on REAL_CST as well.
(real_value_truncate): Don't use its own handler. (const_binop): Set overflow on FP error and call force_fit_type. (fold_convert): Likewise. From-SVN: r6768
-rw-r--r--gcc/fold-const.c90
1 files changed, 53 insertions, 37 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 304eac8..453af6c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -140,7 +140,10 @@ decode (shorts, low, hi)
that don't belong in the type.
Yield 1 if a signed overflow occurs, 0 otherwise.
If OVERFLOW is nonzero, a signed overflow has already occurred
- in calculating T, so propagate it. */
+ in calculating T, so propagate it.
+
+ Make the real constant T valid for its type by calling CHECK_FLOAT_VALUE,
+ if it exists. */
int
force_fit_type (t, overflow)
@@ -150,7 +153,16 @@ force_fit_type (t, overflow)
HOST_WIDE_INT low, high;
register int prec;
- if (TREE_CODE (t) != INTEGER_CST)
+ if (TREE_CODE (t) == REAL_CST)
+ {
+#ifdef CHECK_FLOAT_VALUE
+ CHECK_FLOAT_VALUE (TYPE_MODE (TREE_TYPE (t)), TREE_REAL_CST (t),
+ overflow);
+#endif
+ return overflow;
+ }
+
+ else if (TREE_CODE (t) != INTEGER_CST)
return overflow;
low = TREE_INT_CST_LOW (t);
@@ -803,34 +815,19 @@ div_and_round_double (code, uns,
}
#ifndef REAL_ARITHMETIC
-/* Effectively truncate a real value to represent
- the nearest possible value in a narrower mode.
- The result is actually represented in the same data type as the argument,
- but its value is usually different. */
+/* Effectively truncate a real value to represent the nearest possible value
+ in a narrower mode. The result is actually represented in the same data
+ type as the argument, but its value is usually different.
+
+ A trap may occur during the FP operations and it is the responsibility
+ of the calling function to have a handler established. */
REAL_VALUE_TYPE
real_value_truncate (mode, arg)
enum machine_mode mode;
REAL_VALUE_TYPE arg;
{
-#ifdef __STDC__
- /* Make sure the value is actually stored in memory before we turn off
- the handler. */
- volatile
-#endif
- REAL_VALUE_TYPE value;
- jmp_buf handler, old_handler;
- int handled;
-
- if (setjmp (handler))
- {
- error ("floating overflow");
- return dconst0;
- }
- handled = push_float_handler (handler, old_handler);
- value = REAL_VALUE_TRUNCATE (mode, arg);
- pop_float_handler (handled, old_handler);
- return value;
+ return REAL_VALUE_TRUNCATE (mode, arg);
}
#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
@@ -1333,18 +1330,19 @@ const_binop (code, arg1, arg2, notrunc)
#if ! defined (REAL_IS_NOT_DOUBLE) || defined (REAL_ARITHMETIC)
if (TREE_CODE (arg1) == REAL_CST)
{
- REAL_VALUE_TYPE d1;
- REAL_VALUE_TYPE d2;
+ REAL_VALUE_TYPE d1 = TREE_REAL_CST (arg1);
+ REAL_VALUE_TYPE d2 = TREE_REAL_CST (arg2);
+ int overflow = 0;
REAL_VALUE_TYPE value;
tree t;
- d1 = TREE_REAL_CST (arg1);
- d2 = TREE_REAL_CST (arg2);
if (setjmp (float_error))
{
- pedwarn ("floating overflow in constant expression");
- return build (code, TREE_TYPE (arg1), arg1, arg2);
+ t = copy_node (arg1);
+ overflow = 1;
+ goto got_float;
}
+
set_float_handler (float_error);
#ifdef REAL_ARITHMETIC
@@ -1387,7 +1385,16 @@ const_binop (code, arg1, arg2, notrunc)
#endif /* no REAL_ARITHMETIC */
t = build_real (TREE_TYPE (arg1),
real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)), value));
+ got_float:
set_float_handler (NULL_PTR);
+
+ TREE_OVERFLOW (t)
+ = (force_fit_type (t, overflow)
+ | TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2));
+ TREE_CONSTANT_OVERFLOW (t)
+ = TREE_OVERFLOW (t)
+ | TREE_CONSTANT_OVERFLOW (arg1)
+ | TREE_CONSTANT_OVERFLOW (arg2);
return t;
}
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
@@ -1540,6 +1547,7 @@ fold_convert (t, arg1)
register tree arg1;
{
register tree type = TREE_TYPE (t);
+ int overflow = 0;
if (TREE_CODE (type) == POINTER_TYPE || INTEGRAL_TYPE_P (type))
{
@@ -1583,10 +1591,8 @@ fold_convert (t, arg1)
u++;
#endif
if (! (REAL_VALUES_LESS (l, x) && REAL_VALUES_LESS (x, u)))
- {
- pedwarn ("real constant out of range for integer conversion");
- return t;
- }
+ overflow = 1;
+
#ifndef REAL_ARITHMETIC
{
REAL_VALUE_TYPE d;
@@ -1619,7 +1625,10 @@ fold_convert (t, arg1)
}
#endif
TREE_TYPE (t) = type;
- force_fit_type (t, 0);
+ TREE_OVERFLOW (t)
+ = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
+ TREE_CONSTANT_OVERFLOW (t)
+ = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
}
#endif /* not REAL_IS_NOT_DOUBLE, or REAL_ARITHMETIC */
TREE_TYPE (t) = type;
@@ -1634,14 +1643,21 @@ fold_convert (t, arg1)
{
if (setjmp (float_error))
{
- pedwarn ("floating overflow in constant expression");
- return t;
+ overflow = 1;
+ t = copy_node (arg1);
+ goto got_it;
}
set_float_handler (float_error);
t = build_real (type, real_value_truncate (TYPE_MODE (type),
TREE_REAL_CST (arg1)));
set_float_handler (NULL_PTR);
+
+ got_it:
+ TREE_OVERFLOW (t)
+ = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
+ TREE_CONSTANT_OVERFLOW (t)
+ = TREE_OVERFLOW (t) | TREE_CONSTANT_OVERFLOW (arg1);
return t;
}
}