tlib9: hide uvlong/double conversions to placate gcc (John Gosset) - plan9port … | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 66f6e2b651124387f83b9af17104a79d6d93f67b | |
parent ada24b4005504a9cc8035987cf5175940ae568a7 | |
Author: Russ Cox <[email protected]> | |
Date: Sat, 10 May 2008 13:35:54 -0400 | |
lib9: hide uvlong/double conversions to placate gcc (John Gosset) | |
Diffstat: | |
M src/lib9/fmt/nan64.c | 57 +++++++++++++++++------------… | |
1 file changed, 31 insertions(+), 26 deletions(-) | |
--- | |
diff --git a/src/lib9/fmt/nan64.c b/src/lib9/fmt/nan64.c | |
t@@ -6,6 +6,7 @@ | |
*/ | |
#include "plan9.h" | |
+#include <assert.h> | |
#include "fmt.h" | |
#include "fmtdef.h" | |
t@@ -13,31 +14,43 @@ static uvlong uvnan = ((uvlong)0x7FF00000<<32)|0x000000… | |
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; | |
} | |
t@@ -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) |