]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
runtime: fix misc gcc-isms and undefined behavior
authorIan Lance Taylor <ian@gcc.gnu.org>
Wed, 28 May 2014 23:10:47 +0000 (23:10 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 28 May 2014 23:10:47 +0000 (23:10 +0000)
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
libgo/runtime/go-type-complex.c
libgo/runtime/go-type-float.c
libgo/runtime/print.c
libgo/runtime/runtime.h

index 0a81e458c84d35f69bf8d5ad06a5a5df27c574e8..0355e26fc8ed2a955bddc7dcd41e180d33691f66 100644 (file)
@@ -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 <complex.h>
+#include <math.h>
+
 /* 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
    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;
index 106024f5c88b2c22348ab04798c7533fb90b0684..0f8f0627d73a2e0d7deb16a5f6e22b1a5a852ccb 100644 (file)
@@ -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 <complex.h>
+#include <math.h>
+#include <stdint.h>
+#include <string.h>
 #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;
+
+      cfp = (const complex float *) vkey;
+      cf = *cfp;
+
+      cfr = crealf (cf);
+      cfi = cimagf (cf);
 
-      __builtin_memcpy (ucf.a, vkey, 8);
-      cf = ucf.cf;
-      cfr = __builtin_crealf (cf);
-      cfi = __builtin_cimagf (cf);
-      if (__builtin_isinff (cfr) || __builtin_isinff (cfi))
+      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;
-
-      __builtin_memcpy (ucf.a, vk1, 8);
-      cf1 = ucf.cf;
-      __builtin_memcpy (ucf.a, vk2, 8);
-      cf2 = ucf.cf;
-      return cf1 == cf2;
+      const complex float *cfp1;
+      const complex float *cfp2;
+      
+      cfp1 = (const complex float *) vk1;
+      cfp2 = (const complex float *) vk2;
+
+      return *cfp1 == *cfp2;
     }
   else if (key_size == 16)
     {
-      union
-      {
-       unsigned char a[16];
-       __complex double cd;
-      } ucd;
-      __complex double cd1;
-      __complex double cd2;
-
-      __builtin_memcpy (ucd.a, vk1, 16);
-      cd1 = ucd.cd;
-      __builtin_memcpy (ucd.a, vk2, 16);
-      cd2 = ucd.cd;
-      return cd1 == cd2;
+      const complex double *cdp1;
+      const complex double *cdp2;
+      
+      cdp1 = (const complex double *) vk1;
+      cdp2 = (const complex double *) vk2;
+
+      return *cdp1 == *cdp2;
     }
   else
     runtime_throw ("__go_type_equal_complex: invalid complex size");
index e1c03e4284390d78c036a43b8b3aed863cf0d549..4ae73470de9ed68cb05afabdbac83f3cc54c0e8f 100644 (file)
@@ -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 <math.h>
+#include <stdint.h>
 #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;
+
+      dp = (const double *) vkey;
+      d = *dp;
 
-      __builtin_memcpy (ud.a, vkey, 8);
-      d = ud.d;
-      if (__builtin_isinf (d) || d == 0)
+      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;
-
-      __builtin_memcpy (uf.a, vk1, 4);
-      f1 = uf.f;
-      __builtin_memcpy (uf.a, vk2, 4);
-      f2 = uf.f;
-      return f1 == f2;
+      const float *fp1;
+      const float *fp2;
+
+      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;
-
-      __builtin_memcpy (ud.a, vk1, 8);
-      d1 = ud.d;
-      __builtin_memcpy (ud.a, vk2, 8);
-      d2 = ud.d;
-      return d1 == d2;
+      const double *dp1;
+      const double *dp2;
+
+      dp1 = (const double *) vk1;
+      dp2 = (const double *) vk2;
+
+      return *dp1 == *dp2;
     }
   else
     runtime_throw ("__go_type_equal_float: invalid float size");
index 766ddbdc499c3f8a09d46b2a2f9433a9e5f18b2a..1656a998529f61a87c762cd5b996347119a5155c 100644 (file)
@@ -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 <complex.h>
+#include <math.h>
 #include <stdarg.h>
 #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);
 }
 
index da2416335ec2805ac8770417eb9386736aab1b11..7a578502176421521d2d4d51c5ea591aa72698a3 100644 (file)
@@ -5,6 +5,7 @@
 #include "config.h"
 
 #include "go-assert.h"
+#include <complex.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -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");