Commit 93c521ea by Ian Lance Taylor

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
parent bc2eed9a
......@@ -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
......@@ -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;
......
......@@ -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");
......
......@@ -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");
......
......@@ -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);
}
......
......@@ -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");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment