aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2014-01-12 04:44:27 +0100
committerMichael Matz <matz@suse.de>2014-01-12 04:44:27 +0100
commit05c9b76131e9d0a2e1b011eeb70ad7897efc9084 (patch)
tree6bb541490c316505c2a9ffccc39507057b4a6b1c /tccgen.c
parent9c6ddbfe903445763405d2c8bdec916c8a20f105 (diff)
downloadtinycc-05c9b76131e9d0a2e1b011eeb70ad7897efc9084.tar.gz
tinycc-05c9b76131e9d0a2e1b011eeb70ad7897efc9084.tar.bz2
Fix floating point unary minus and plus
negate(x) is subtract(-0,x), not subtract(+0,x), which makes a difference with signed zeros. Also +x was expressed as x+0, in order for the integer promotions to happen, but also mangles signed zeros, so just don't do that with floating types.
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c38
1 files changed, 21 insertions, 17 deletions
diff --git a/tccgen.c b/tccgen.c
index 4d7e1fb..6a5ba03 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -3702,12 +3702,16 @@ ST_FUNC void unary(void)
break;
case '+':
next();
- /* in order to force cast, we add zero */
unary();
if ((vtop->type.t & VT_BTYPE) == VT_PTR)
tcc_error("pointer not accepted for unary plus");
- vpushi(0);
- gen_op('+');
+ /* In order to force cast, we add zero, except for floating point
+ where we really need an noop (otherwise -0.0 will be transformed
+ into +0.0). */
+ if (!is_float(vtop->type.t)) {
+ vpushi(0);
+ gen_op('+');
+ }
break;
case TOK_SIZEOF:
case TOK_ALIGNOF1:
@@ -3822,20 +3826,20 @@ ST_FUNC void unary(void)
next();
unary();
t = vtop->type.t & VT_BTYPE;
- /* handle (-)0.0 */
- if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST &&
- is_float(t)) {
- if (t == VT_FLOAT)
- vtop->c.f = -vtop->c.f;
- else if (t == VT_DOUBLE)
- vtop->c.d = -vtop->c.d;
- else
- vtop->c.ld = -vtop->c.ld;
- } else {
- vpushi(0);
- vswap();
- gen_op('-');
- }
+ if (is_float(t)) {
+ /* In IEEE negate(x) isn't subtract(0,x), but rather
+ subtract(-0, x). */
+ vpush(&vtop->type);
+ if (t == VT_FLOAT)
+ vtop->c.f = -0.0f;
+ else if (t == VT_DOUBLE)
+ vtop->c.d = -0.0;
+ else
+ vtop->c.ld = -0.0;
+ } else
+ vpushi(0);
+ vswap();
+ gen_op('-');
break;
case TOK_LAND:
if (!gnu_ext)