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
This commit is contained in:
parent
bc2eed9a8e
commit
93c521ea9c
|
@ -4,6 +4,9 @@
|
||||||
Use of this source code is governed by a BSD-style
|
Use of this source code is governed by a BSD-style
|
||||||
license that can be found in the LICENSE file. */
|
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
|
/* Calls to these functions are generated by the Go frontend for
|
||||||
division of complex64 or complex128. We use these because Go's
|
division of complex64 or complex128. We use these because Go's
|
||||||
complex division expects slightly different results from the GCC
|
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
|
the the whole number is Inf, but an operation involving NaN ought
|
||||||
to result in NaN, not Inf. */
|
to result in NaN, not Inf. */
|
||||||
|
|
||||||
__complex float
|
complex float
|
||||||
__go_complex64_div (__complex float a, __complex float b)
|
__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)
|
if (!isinf (crealf (a))
|
||||||
&& !__builtin_isinff (__imag__ a)
|
&& !isinf (cimagf (a))
|
||||||
&& (__builtin_isnanf (__real__ a) || __builtin_isnanf (__imag__ a)))
|
&& (isnan (crealf (a)) || isnan (cimagf (a))))
|
||||||
{
|
{
|
||||||
/* Pass "1" to nanf to match math/bits.go. */
|
/* 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;
|
return a / b;
|
||||||
}
|
}
|
||||||
|
|
||||||
__complex double
|
complex double
|
||||||
__go_complex128_div (__complex double a, __complex double b)
|
__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)
|
if (!isinf (creal (a))
|
||||||
&& !__builtin_isinf (__imag__ a)
|
&& !isinf (cimag (a))
|
||||||
&& (__builtin_isnan (__real__ a) || __builtin_isnan (__imag__ a)))
|
&& (isnan (creal (a)) || isnan (cimag (a))))
|
||||||
{
|
{
|
||||||
/* Pass "1" to nan to match math/bits.go. */
|
/* 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;
|
return a / b;
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
Use of this source code is governed by a BSD-style
|
Use of this source code is governed by a BSD-style
|
||||||
license that can be found in the LICENSE file. */
|
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 "runtime.h"
|
||||||
#include "go-type.h"
|
#include "go-type.h"
|
||||||
|
|
||||||
/* The 64-bit type. */
|
|
||||||
|
|
||||||
typedef unsigned int DItype __attribute__ ((mode (DI)));
|
|
||||||
|
|
||||||
/* Hash function for float types. */
|
/* Hash function for float types. */
|
||||||
|
|
||||||
uintptr_t
|
uintptr_t
|
||||||
|
@ -18,69 +18,67 @@ __go_type_hash_complex (const void *vkey, uintptr_t key_size)
|
||||||
{
|
{
|
||||||
if (key_size == 8)
|
if (key_size == 8)
|
||||||
{
|
{
|
||||||
union
|
const complex float *cfp;
|
||||||
{
|
complex float cf;
|
||||||
unsigned char a[8];
|
|
||||||
__complex float cf;
|
|
||||||
DItype di;
|
|
||||||
} ucf;
|
|
||||||
__complex float cf;
|
|
||||||
float cfr;
|
float cfr;
|
||||||
float cfi;
|
float cfi;
|
||||||
|
uint64_t fi;
|
||||||
|
|
||||||
__builtin_memcpy (ucf.a, vkey, 8);
|
cfp = (const complex float *) vkey;
|
||||||
cf = ucf.cf;
|
cf = *cfp;
|
||||||
cfr = __builtin_crealf (cf);
|
|
||||||
cfi = __builtin_cimagf (cf);
|
cfr = crealf (cf);
|
||||||
if (__builtin_isinff (cfr) || __builtin_isinff (cfi))
|
cfi = cimagf (cf);
|
||||||
|
|
||||||
|
if (isinf (cfr) || isinf (cfi))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
|
/* 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. */
|
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 ();
|
return runtime_fastrand1 ();
|
||||||
|
|
||||||
/* Avoid negative zero. */
|
/* Avoid negative zero. */
|
||||||
if (cfr == 0 && cfi == 0)
|
if (cfr == 0 && cfi == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if (cfr == 0)
|
else if (cfr == 0)
|
||||||
ucf.cf = cfi * 1.0iF;
|
cf = cfi * I;
|
||||||
else if (cfi == 0)
|
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)
|
else if (key_size == 16)
|
||||||
{
|
{
|
||||||
union
|
const complex double *cdp;
|
||||||
{
|
complex double cd;
|
||||||
unsigned char a[16];
|
|
||||||
__complex double cd;
|
|
||||||
DItype adi[2];
|
|
||||||
} ucd;
|
|
||||||
__complex double cd;
|
|
||||||
double cdr;
|
double cdr;
|
||||||
double cdi;
|
double cdi;
|
||||||
|
uint64_t di[2];
|
||||||
|
|
||||||
__builtin_memcpy (ucd.a, vkey, 16);
|
cdp = (const complex double *) vkey;
|
||||||
cd = ucd.cd;
|
cd = *cdp;
|
||||||
cdr = __builtin_crealf (cd);
|
|
||||||
cdi = __builtin_cimagf (cd);
|
cdr = creal (cd);
|
||||||
if (__builtin_isinf (cdr) || __builtin_isinf (cdi))
|
cdi = cimag (cd);
|
||||||
|
|
||||||
|
if (isinf (cdr) || isinf (cdi))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (__builtin_isnan (cdr) || __builtin_isnan (cdi))
|
if (isnan (cdr) || isnan (cdi))
|
||||||
return runtime_fastrand1 ();
|
return runtime_fastrand1 ();
|
||||||
|
|
||||||
/* Avoid negative zero. */
|
/* Avoid negative zero. */
|
||||||
if (cdr == 0 && cdi == 0)
|
if (cdr == 0 && cdi == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if (cdr == 0)
|
else if (cdr == 0)
|
||||||
ucd.cd = cdi * 1.0i;
|
cd = cdi * I;
|
||||||
else if (cdi == 0)
|
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
|
else
|
||||||
runtime_throw ("__go_type_hash_complex: invalid complex size");
|
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)
|
if (key_size == 8)
|
||||||
{
|
{
|
||||||
union
|
const complex float *cfp1;
|
||||||
{
|
const complex float *cfp2;
|
||||||
unsigned char a[8];
|
|
||||||
__complex float cf;
|
cfp1 = (const complex float *) vk1;
|
||||||
} ucf;
|
cfp2 = (const complex float *) vk2;
|
||||||
__complex float cf1;
|
|
||||||
__complex float cf2;
|
|
||||||
|
|
||||||
__builtin_memcpy (ucf.a, vk1, 8);
|
return *cfp1 == *cfp2;
|
||||||
cf1 = ucf.cf;
|
|
||||||
__builtin_memcpy (ucf.a, vk2, 8);
|
|
||||||
cf2 = ucf.cf;
|
|
||||||
return cf1 == cf2;
|
|
||||||
}
|
}
|
||||||
else if (key_size == 16)
|
else if (key_size == 16)
|
||||||
{
|
{
|
||||||
union
|
const complex double *cdp1;
|
||||||
{
|
const complex double *cdp2;
|
||||||
unsigned char a[16];
|
|
||||||
__complex double cd;
|
cdp1 = (const complex double *) vk1;
|
||||||
} ucd;
|
cdp2 = (const complex double *) vk2;
|
||||||
__complex double cd1;
|
|
||||||
__complex double cd2;
|
|
||||||
|
|
||||||
__builtin_memcpy (ucd.a, vk1, 16);
|
return *cdp1 == *cdp2;
|
||||||
cd1 = ucd.cd;
|
|
||||||
__builtin_memcpy (ucd.a, vk2, 16);
|
|
||||||
cd2 = ucd.cd;
|
|
||||||
return cd1 == cd2;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
runtime_throw ("__go_type_equal_complex: invalid complex size");
|
runtime_throw ("__go_type_equal_complex: invalid complex size");
|
||||||
|
|
|
@ -4,14 +4,11 @@
|
||||||
Use of this source code is governed by a BSD-style
|
Use of this source code is governed by a BSD-style
|
||||||
license that can be found in the LICENSE file. */
|
license that can be found in the LICENSE file. */
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "go-type.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. */
|
/* Hash function for float types. */
|
||||||
|
|
||||||
uintptr_t
|
uintptr_t
|
||||||
|
@ -19,45 +16,41 @@ __go_type_hash_float (const void *vkey, uintptr_t key_size)
|
||||||
{
|
{
|
||||||
if (key_size == 4)
|
if (key_size == 4)
|
||||||
{
|
{
|
||||||
union
|
const float *fp;
|
||||||
{
|
|
||||||
unsigned char a[4];
|
|
||||||
float f;
|
|
||||||
SItype si;
|
|
||||||
} uf;
|
|
||||||
float f;
|
float f;
|
||||||
|
uint32_t si;
|
||||||
|
|
||||||
__builtin_memcpy (uf.a, vkey, 4);
|
fp = (const float *) vkey;
|
||||||
f = uf.f;
|
f = *fp;
|
||||||
if (__builtin_isinff (f) || f == 0)
|
|
||||||
|
if (isinf (f) || f == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* NaN != NaN, so the hash code of a NaN is irrelevant. Make it
|
/* 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. */
|
random so that not all NaNs wind up in the same place. */
|
||||||
if (__builtin_isnanf (f))
|
if (isnan (f))
|
||||||
return runtime_fastrand1 ();
|
return runtime_fastrand1 ();
|
||||||
|
|
||||||
return (uintptr_t) uf.si;
|
memcpy (&si, vkey, 4);
|
||||||
|
return (uintptr_t) si;
|
||||||
}
|
}
|
||||||
else if (key_size == 8)
|
else if (key_size == 8)
|
||||||
{
|
{
|
||||||
union
|
const double *dp;
|
||||||
{
|
|
||||||
unsigned char a[8];
|
|
||||||
double d;
|
|
||||||
DItype di;
|
|
||||||
} ud;
|
|
||||||
double d;
|
double d;
|
||||||
|
uint64_t di;
|
||||||
|
|
||||||
__builtin_memcpy (ud.a, vkey, 8);
|
dp = (const double *) vkey;
|
||||||
d = ud.d;
|
d = *dp;
|
||||||
if (__builtin_isinf (d) || d == 0)
|
|
||||||
|
if (isinf (d) || d == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (__builtin_isnan (d))
|
if (isnan (d))
|
||||||
return runtime_fastrand1 ();
|
return runtime_fastrand1 ();
|
||||||
|
|
||||||
return (uintptr_t) ud.di;
|
memcpy (&di, vkey, 8);
|
||||||
|
return (uintptr_t) di;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
runtime_throw ("__go_type_hash_float: invalid float size");
|
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)
|
if (key_size == 4)
|
||||||
{
|
{
|
||||||
union
|
const float *fp1;
|
||||||
{
|
const float *fp2;
|
||||||
unsigned char a[4];
|
|
||||||
float f;
|
|
||||||
} uf;
|
|
||||||
float f1;
|
|
||||||
float f2;
|
|
||||||
|
|
||||||
__builtin_memcpy (uf.a, vk1, 4);
|
fp1 = (const float *) vk1;
|
||||||
f1 = uf.f;
|
fp2 = (const float *) vk2;
|
||||||
__builtin_memcpy (uf.a, vk2, 4);
|
|
||||||
f2 = uf.f;
|
return *fp1 == *fp2;
|
||||||
return f1 == f2;
|
|
||||||
}
|
}
|
||||||
else if (key_size == 8)
|
else if (key_size == 8)
|
||||||
{
|
{
|
||||||
union
|
const double *dp1;
|
||||||
{
|
const double *dp2;
|
||||||
unsigned char a[8];
|
|
||||||
double d;
|
|
||||||
DItype di;
|
|
||||||
} ud;
|
|
||||||
double d1;
|
|
||||||
double d2;
|
|
||||||
|
|
||||||
__builtin_memcpy (ud.a, vk1, 8);
|
dp1 = (const double *) vk1;
|
||||||
d1 = ud.d;
|
dp2 = (const double *) vk2;
|
||||||
__builtin_memcpy (ud.a, vk2, 8);
|
|
||||||
d2 = ud.d;
|
return *dp1 == *dp2;
|
||||||
return d1 == d2;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
runtime_throw ("__go_type_equal_float: invalid float size");
|
runtime_throw ("__go_type_equal_float: invalid float size");
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include <complex.h>
|
||||||
|
#include <math.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "runtime.h"
|
#include "runtime.h"
|
||||||
#include "array.h"
|
#include "array.h"
|
||||||
|
@ -105,7 +107,7 @@ go_vprintf(const char *s, va_list va)
|
||||||
runtime_printfloat(va_arg(va, float64));
|
runtime_printfloat(va_arg(va, float64));
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
runtime_printcomplex(va_arg(va, __complex double));
|
runtime_printcomplex(va_arg(va, complex double));
|
||||||
break;
|
break;
|
||||||
case 'i':
|
case 'i':
|
||||||
runtime_printiface(va_arg(va, Iface));
|
runtime_printiface(va_arg(va, Iface));
|
||||||
|
@ -174,13 +176,12 @@ runtime_printfloat(double v)
|
||||||
gwrite("NaN", 3);
|
gwrite("NaN", 3);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i = __builtin_isinf_sign(v);
|
if(isinf(v)) {
|
||||||
if(i > 0) {
|
if(signbit(v)) {
|
||||||
gwrite("+Inf", 4);
|
gwrite("-Inf", 4);
|
||||||
return;
|
} else {
|
||||||
}
|
gwrite("+Inf", 4);
|
||||||
if(i < 0) {
|
}
|
||||||
gwrite("-Inf", 4);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,11 +244,11 @@ runtime_printfloat(double v)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
runtime_printcomplex(__complex double v)
|
runtime_printcomplex(complex double v)
|
||||||
{
|
{
|
||||||
gwrite("(", 1);
|
gwrite("(", 1);
|
||||||
runtime_printfloat(__builtin_creal(v));
|
runtime_printfloat(creal(v));
|
||||||
runtime_printfloat(__builtin_cimag(v));
|
runtime_printfloat(cimag(v));
|
||||||
gwrite("i)", 2);
|
gwrite("i)", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "go-assert.h"
|
#include "go-assert.h"
|
||||||
|
#include <complex.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -710,7 +711,7 @@ void runtime_printpointer(void*);
|
||||||
void runtime_printuint(uint64);
|
void runtime_printuint(uint64);
|
||||||
void runtime_printhex(uint64);
|
void runtime_printhex(uint64);
|
||||||
void runtime_printslice(Slice);
|
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 reflect_call(const struct __go_func_type *, FuncVal *, _Bool, _Bool,
|
||||||
void **, void **)
|
void **, void **)
|
||||||
__asm__ (GOSYM_PREFIX "reflect.call");
|
__asm__ (GOSYM_PREFIX "reflect.call");
|
||||||
|
|
Loading…
Reference in New Issue