From 93c521ea9cf06574be59d946d160938accc4eb4c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 28 May 2014 23:10:47 +0000 Subject: [PATCH] runtime: fix misc gcc-isms and undefined behavior This includes the use of __complex and __builtin_ functions where unprefixed entities would suffice, and the use of a union for bit-casting between types. From-SVN: r211036 --- libgo/runtime/go-cdiv.c | 31 +++++----- libgo/runtime/go-type-complex.c | 106 ++++++++++++++------------------ libgo/runtime/go-type-float.c | 84 ++++++++++--------------- libgo/runtime/print.c | 23 +++---- libgo/runtime/runtime.h | 3 +- 5 files changed, 109 insertions(+), 138 deletions(-) diff --git a/libgo/runtime/go-cdiv.c b/libgo/runtime/go-cdiv.c index 0a81e458c84..0355e26fc8e 100644 --- a/libgo/runtime/go-cdiv.c +++ b/libgo/runtime/go-cdiv.c @@ -4,6 +4,9 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ +#include +#include + /* Calls to these functions are generated by the Go frontend for division of complex64 or complex128. We use these because Go's complex division expects slightly different results from the GCC @@ -13,33 +16,33 @@ the the whole number is Inf, but an operation involving NaN ought to result in NaN, not Inf. */ -__complex float -__go_complex64_div (__complex float a, __complex float b) +complex float +__go_complex64_div (complex float a, complex float b) { - if (__builtin_expect (b == 0+0i, 0)) + if (__builtin_expect (b == 0, 0)) { - if (!__builtin_isinff (__real__ a) - && !__builtin_isinff (__imag__ a) - && (__builtin_isnanf (__real__ a) || __builtin_isnanf (__imag__ a))) + if (!isinf (crealf (a)) + && !isinf (cimagf (a)) + && (isnan (crealf (a)) || isnan (cimagf (a)))) { /* Pass "1" to nanf to match math/bits.go. */ - return __builtin_nanf("1") + __builtin_nanf("1")*1i; + return nanf("1") + nanf("1")*I; } } return a / b; } -__complex double -__go_complex128_div (__complex double a, __complex double b) +complex double +__go_complex128_div (complex double a, complex double b) { - if (__builtin_expect (b == 0+0i, 0)) + if (__builtin_expect (b == 0, 0)) { - if (!__builtin_isinf (__real__ a) - && !__builtin_isinf (__imag__ a) - && (__builtin_isnan (__real__ a) || __builtin_isnan (__imag__ a))) + if (!isinf (creal (a)) + && !isinf (cimag (a)) + && (isnan (creal (a)) || isnan (cimag (a)))) { /* Pass "1" to nan to match math/bits.go. */ - return __builtin_nan("1") + __builtin_nan("1")*1i; + return nan("1") + nan("1")*I; } } return a / b; diff --git a/libgo/runtime/go-type-complex.c b/libgo/runtime/go-type-complex.c index 106024f5c88..0f8f0627d73 100644 --- a/libgo/runtime/go-type-complex.c +++ b/libgo/runtime/go-type-complex.c @@ -4,13 +4,13 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ +#include +#include +#include +#include #include "runtime.h" #include "go-type.h" -/* The 64-bit type. */ - -typedef unsigned int DItype __attribute__ ((mode (DI))); - /* Hash function for float types. */ uintptr_t @@ -18,69 +18,67 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size) { if (key_size == 8) { - union - { - unsigned char a[8]; - __complex float cf; - DItype di; - } ucf; - __complex float cf; + const complex float *cfp; + complex float cf; float cfr; float cfi; + uint64_t fi; - __builtin_memcpy (ucf.a, vkey, 8); - cf = ucf.cf; - cfr = __builtin_crealf (cf); - cfi = __builtin_cimagf (cf); - if (__builtin_isinff (cfr) || __builtin_isinff (cfi)) + cfp = (const complex float *) vkey; + cf = *cfp; + + cfr = crealf (cf); + cfi = cimagf (cf); + + if (isinf (cfr) || isinf (cfi)) return 0; /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it random so that not all NaNs wind up in the same place. */ - if (__builtin_isnanf (cfr) || __builtin_isnanf (cfi)) + if (isnan (cfr) || isnan (cfi)) return runtime_fastrand1 (); /* Avoid negative zero. */ if (cfr == 0 && cfi == 0) return 0; else if (cfr == 0) - ucf.cf = cfi * 1.0iF; + cf = cfi * I; else if (cfi == 0) - ucf.cf = cfr; + cf = cfr; - return ucf.di; + memcpy (&fi, &cf, 8); + return (uintptr_t) cfi; } else if (key_size == 16) { - union - { - unsigned char a[16]; - __complex double cd; - DItype adi[2]; - } ucd; - __complex double cd; + const complex double *cdp; + complex double cd; double cdr; double cdi; + uint64_t di[2]; - __builtin_memcpy (ucd.a, vkey, 16); - cd = ucd.cd; - cdr = __builtin_crealf (cd); - cdi = __builtin_cimagf (cd); - if (__builtin_isinf (cdr) || __builtin_isinf (cdi)) + cdp = (const complex double *) vkey; + cd = *cdp; + + cdr = creal (cd); + cdi = cimag (cd); + + if (isinf (cdr) || isinf (cdi)) return 0; - if (__builtin_isnan (cdr) || __builtin_isnan (cdi)) + if (isnan (cdr) || isnan (cdi)) return runtime_fastrand1 (); /* Avoid negative zero. */ if (cdr == 0 && cdi == 0) return 0; else if (cdr == 0) - ucd.cd = cdi * 1.0i; + cd = cdi * I; else if (cdi == 0) - ucd.cd = cdr; + cd = cdr; - return ucd.adi[0] ^ ucd.adi[1]; + memcpy (&di, &cd, 16); + return di[0] ^ di[1]; } else runtime_throw ("__go_type_hash_complex: invalid complex size"); @@ -93,35 +91,23 @@ __go_type_equal_complex (const void *vk1, const void *vk2, uintptr_t key_size) { if (key_size == 8) { - union - { - unsigned char a[8]; - __complex float cf; - } ucf; - __complex float cf1; - __complex float cf2; + const complex float *cfp1; + const complex float *cfp2; + + cfp1 = (const complex float *) vk1; + cfp2 = (const complex float *) vk2; - __builtin_memcpy (ucf.a, vk1, 8); - cf1 = ucf.cf; - __builtin_memcpy (ucf.a, vk2, 8); - cf2 = ucf.cf; - return cf1 == cf2; + return *cfp1 == *cfp2; } else if (key_size == 16) { - union - { - unsigned char a[16]; - __complex double cd; - } ucd; - __complex double cd1; - __complex double cd2; + const complex double *cdp1; + const complex double *cdp2; + + cdp1 = (const complex double *) vk1; + cdp2 = (const complex double *) vk2; - __builtin_memcpy (ucd.a, vk1, 16); - cd1 = ucd.cd; - __builtin_memcpy (ucd.a, vk2, 16); - cd2 = ucd.cd; - return cd1 == cd2; + return *cdp1 == *cdp2; } else runtime_throw ("__go_type_equal_complex: invalid complex size"); diff --git a/libgo/runtime/go-type-float.c b/libgo/runtime/go-type-float.c index e1c03e42843..4ae73470de9 100644 --- a/libgo/runtime/go-type-float.c +++ b/libgo/runtime/go-type-float.c @@ -4,14 +4,11 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. */ +#include +#include #include "runtime.h" #include "go-type.h" -/* The 32-bit and 64-bit types. */ - -typedef unsigned int SItype __attribute__ ((mode (SI))); -typedef unsigned int DItype __attribute__ ((mode (DI))); - /* Hash function for float types. */ uintptr_t @@ -19,45 +16,41 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size) { if (key_size == 4) { - union - { - unsigned char a[4]; - float f; - SItype si; - } uf; + const float *fp; float f; + uint32_t si; - __builtin_memcpy (uf.a, vkey, 4); - f = uf.f; - if (__builtin_isinff (f) || f == 0) + fp = (const float *) vkey; + f = *fp; + + if (isinf (f) || f == 0) return 0; /* NaN != NaN, so the hash code of a NaN is irrelevant. Make it random so that not all NaNs wind up in the same place. */ - if (__builtin_isnanf (f)) + if (isnan (f)) return runtime_fastrand1 (); - return (uintptr_t) uf.si; + memcpy (&si, vkey, 4); + return (uintptr_t) si; } else if (key_size == 8) { - union - { - unsigned char a[8]; - double d; - DItype di; - } ud; + const double *dp; double d; + uint64_t di; - __builtin_memcpy (ud.a, vkey, 8); - d = ud.d; - if (__builtin_isinf (d) || d == 0) + dp = (const double *) vkey; + d = *dp; + + if (isinf (d) || d == 0) return 0; - if (__builtin_isnan (d)) + if (isnan (d)) return runtime_fastrand1 (); - return (uintptr_t) ud.di; + memcpy (&di, vkey, 8); + return (uintptr_t) di; } else runtime_throw ("__go_type_hash_float: invalid float size"); @@ -70,36 +63,23 @@ __go_type_equal_float (const void *vk1, const void *vk2, uintptr_t key_size) { if (key_size == 4) { - union - { - unsigned char a[4]; - float f; - } uf; - float f1; - float f2; + const float *fp1; + const float *fp2; - __builtin_memcpy (uf.a, vk1, 4); - f1 = uf.f; - __builtin_memcpy (uf.a, vk2, 4); - f2 = uf.f; - return f1 == f2; + fp1 = (const float *) vk1; + fp2 = (const float *) vk2; + + return *fp1 == *fp2; } else if (key_size == 8) { - union - { - unsigned char a[8]; - double d; - DItype di; - } ud; - double d1; - double d2; + const double *dp1; + const double *dp2; - __builtin_memcpy (ud.a, vk1, 8); - d1 = ud.d; - __builtin_memcpy (ud.a, vk2, 8); - d2 = ud.d; - return d1 == d2; + dp1 = (const double *) vk1; + dp2 = (const double *) vk2; + + return *dp1 == *dp2; } else runtime_throw ("__go_type_equal_float: invalid float size"); diff --git a/libgo/runtime/print.c b/libgo/runtime/print.c index 766ddbdc499..1656a998529 100644 --- a/libgo/runtime/print.c +++ b/libgo/runtime/print.c @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include +#include #include #include "runtime.h" #include "array.h" @@ -105,7 +107,7 @@ go_vprintf(const char *s, va_list va) runtime_printfloat(va_arg(va, float64)); break; case 'C': - runtime_printcomplex(va_arg(va, __complex double)); + runtime_printcomplex(va_arg(va, complex double)); break; case 'i': runtime_printiface(va_arg(va, Iface)); @@ -174,13 +176,12 @@ runtime_printfloat(double v) gwrite("NaN", 3); return; } - i = __builtin_isinf_sign(v); - if(i > 0) { - gwrite("+Inf", 4); - return; - } - if(i < 0) { - gwrite("-Inf", 4); + if(isinf(v)) { + if(signbit(v)) { + gwrite("-Inf", 4); + } else { + gwrite("+Inf", 4); + } return; } @@ -243,11 +244,11 @@ runtime_printfloat(double v) } void -runtime_printcomplex(__complex double v) +runtime_printcomplex(complex double v) { gwrite("(", 1); - runtime_printfloat(__builtin_creal(v)); - runtime_printfloat(__builtin_cimag(v)); + runtime_printfloat(creal(v)); + runtime_printfloat(cimag(v)); gwrite("i)", 2); } diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index da2416335ec..7a578502176 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -5,6 +5,7 @@ #include "config.h" #include "go-assert.h" +#include #include #include #include @@ -710,7 +711,7 @@ void runtime_printpointer(void*); void runtime_printuint(uint64); void runtime_printhex(uint64); void runtime_printslice(Slice); -void runtime_printcomplex(__complex double); +void runtime_printcomplex(complex double); void reflect_call(const struct __go_func_type *, FuncVal *, _Bool, _Bool, void **, void **) __asm__ (GOSYM_PREFIX "reflect.call");