diff options
author | Russ Cox <rsc@swtch.com> | 2008-05-10 13:35:54 -0400 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2008-05-10 13:35:54 -0400 |
commit | 66f6e2b651124387f83b9af17104a79d6d93f67b (patch) | |
tree | 54b976222ce9dc5f4273ea1c4f668d3ee3e41015 | |
parent | ada24b4005504a9cc8035987cf5175940ae568a7 (diff) | |
download | plan9port-66f6e2b651124387f83b9af17104a79d6d93f67b.tar.gz plan9port-66f6e2b651124387f83b9af17104a79d6d93f67b.tar.bz2 plan9port-66f6e2b651124387f83b9af17104a79d6d93f67b.zip |
lib9: hide uvlong/double conversions to placate gcc (John Gosset)
-rw-r--r-- | src/lib9/fmt/nan64.c | 57 |
1 files changed, 31 insertions, 26 deletions
diff --git a/src/lib9/fmt/nan64.c b/src/lib9/fmt/nan64.c index 7d719157..9c0cc7bf 100644 --- a/src/lib9/fmt/nan64.c +++ b/src/lib9/fmt/nan64.c @@ -6,6 +6,7 @@ */ #include "plan9.h" +#include <assert.h> #include "fmt.h" #include "fmtdef.h" @@ -13,31 +14,43 @@ static uvlong uvnan = ((uvlong)0x7FF00000<<32)|0x00000001; static uvlong uvinf = ((uvlong)0x7FF00000<<32)|0x00000000; static uvlong uvneginf = ((uvlong)0xFFF00000<<32)|0x00000000; +/* gcc sees through the obvious casts. */ +static uvlong +d2u(double d) +{ + union { + uvlong v; + double d; + } u; + assert(sizeof(u.d) == sizeof(u.v)); + u.d = d; + return u.v; +} + +static double +u2d(uvlong v) +{ + union { + uvlong v; + double d; + } u; + assert(sizeof(u.d) == sizeof(u.v)); + u.v = v; + return u.d; +} + double __NaN(void) { - uvlong *p; - - /* gcc complains about "return *(double*)&uvnan;" */ - p = &uvnan; - return *(double*)p; + return u2d(uvnan); } int __isNaN(double d) { - /* - * Used to just say x = *(uvlong*)&d, - * but gcc miscompiles that! - */ - union { - uvlong i; - double f; - } u; uvlong x; - u.f = d; - x = u.i; + x = d2u(d); /* IEEE 754: exponent bits 0x7FF and non-zero mantissa */ return (x&uvinf) == uvinf && (x&~uvneginf) != 0; } @@ -45,23 +58,15 @@ __isNaN(double d) double __Inf(int sign) { - uvlong *p; - - if(sign < 0) - p = &uvinf; - else - p = &uvneginf; - return *(double*)p; + return u2d(sign < 0 ? uvneginf : uvinf); } int __isInf(double d, int sign) { uvlong x; - double *p; - - p = &d; - x = *(uvlong*)p; + + x = d2u(d); if(sign == 0) return x==uvinf || x==uvneginf; else if(sign > 0) |