From d2b480bc96f6ca12d7de236206e5e82e3cbabd57 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 8 Feb 2012 22:35:30 +0000 Subject: [PATCH] runtime: Add matherr function when appropriate. From-SVN: r184024 --- libgo/Makefile.am | 1 + libgo/Makefile.in | 55 ++++++++++++++---------- libgo/config.h.in | 6 +++ libgo/configure | 29 +++++++++++++ libgo/configure.ac | 15 +++++++ libgo/runtime/go-matherr.c | 88 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 172 insertions(+), 22 deletions(-) create mode 100644 libgo/runtime/go-matherr.c diff --git a/libgo/Makefile.am b/libgo/Makefile.am index b94bc06ac3b..bb70b0f8aef 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -422,6 +422,7 @@ runtime_files = \ runtime/go-map-index.c \ runtime/go-map-len.c \ runtime/go-map-range.c \ + runtime/go-matherr.c \ runtime/go-nanotime.c \ runtime/go-now.c \ runtime/go-new-map.c \ diff --git a/libgo/Makefile.in b/libgo/Makefile.in index 556de688dc7..d412e699f5a 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -192,12 +192,13 @@ am__libgo_la_SOURCES_DIST = runtime/go-append.c runtime/go-assert.c \ runtime/go-interface-val-compare.c runtime/go-make-slice.c \ runtime/go-map-delete.c runtime/go-map-index.c \ runtime/go-map-len.c runtime/go-map-range.c \ - runtime/go-nanotime.c runtime/go-now.c runtime/go-new-map.c \ - runtime/go-new.c runtime/go-nosys.c runtime/go-panic.c \ - runtime/go-print.c runtime/go-recover.c runtime/go-reflect.c \ - runtime/go-reflect-call.c runtime/go-reflect-map.c \ - runtime/go-rune.c runtime/go-runtime-error.c \ - runtime/go-setenv.c runtime/go-signal.c runtime/go-strcmp.c \ + runtime/go-matherr.c runtime/go-nanotime.c runtime/go-now.c \ + runtime/go-new-map.c runtime/go-new.c runtime/go-nosys.c \ + runtime/go-panic.c runtime/go-print.c runtime/go-recover.c \ + runtime/go-reflect.c runtime/go-reflect-call.c \ + runtime/go-reflect-map.c runtime/go-rune.c \ + runtime/go-runtime-error.c runtime/go-setenv.c \ + runtime/go-signal.c runtime/go-strcmp.c \ runtime/go-string-to-byte-array.c \ runtime/go-string-to-int-array.c runtime/go-strplus.c \ runtime/go-strslice.c runtime/go-trampoline.c \ @@ -230,22 +231,23 @@ am__objects_4 = go-append.lo go-assert.lo go-assert-interface.lo \ go-int-array-to-string.lo go-int-to-string.lo \ go-interface-compare.lo go-interface-eface-compare.lo \ go-interface-val-compare.lo go-make-slice.lo go-map-delete.lo \ - go-map-index.lo go-map-len.lo go-map-range.lo go-nanotime.lo \ - go-now.lo go-new-map.lo go-new.lo go-nosys.lo go-panic.lo \ - go-print.lo go-recover.lo go-reflect.lo go-reflect-call.lo \ - go-reflect-map.lo go-rune.lo go-runtime-error.lo go-setenv.lo \ - go-signal.lo go-strcmp.lo go-string-to-byte-array.lo \ - go-string-to-int-array.lo go-strplus.lo go-strslice.lo \ - go-trampoline.lo go-type-complex.lo go-type-eface.lo \ - go-type-error.lo go-type-float.lo go-type-identity.lo \ - go-type-interface.lo go-type-string.lo go-typedesc-equal.lo \ - go-typestring.lo go-unreflect.lo go-unsafe-new.lo \ - go-unsafe-newarray.lo go-unsafe-pointer.lo go-unwind.lo \ - chan.lo cpuprof.lo $(am__objects_1) mcache.lo mcentral.lo \ - $(am__objects_2) mfinal.lo mfixalloc.lo mgc0.lo mheap.lo \ - msize.lo proc.lo runtime.lo thread.lo yield.lo \ - $(am__objects_3) iface.lo malloc.lo map.lo mprof.lo reflect.lo \ - runtime1.lo sema.lo sigqueue.lo string.lo time.lo + go-map-index.lo go-map-len.lo go-map-range.lo go-matherr.lo \ + go-nanotime.lo go-now.lo go-new-map.lo go-new.lo go-nosys.lo \ + go-panic.lo go-print.lo go-recover.lo go-reflect.lo \ + go-reflect-call.lo go-reflect-map.lo go-rune.lo \ + go-runtime-error.lo go-setenv.lo go-signal.lo go-strcmp.lo \ + go-string-to-byte-array.lo go-string-to-int-array.lo \ + go-strplus.lo go-strslice.lo go-trampoline.lo \ + go-type-complex.lo go-type-eface.lo go-type-error.lo \ + go-type-float.lo go-type-identity.lo go-type-interface.lo \ + go-type-string.lo go-typedesc-equal.lo go-typestring.lo \ + go-unreflect.lo go-unsafe-new.lo go-unsafe-newarray.lo \ + go-unsafe-pointer.lo go-unwind.lo chan.lo cpuprof.lo \ + $(am__objects_1) mcache.lo mcentral.lo $(am__objects_2) \ + mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo proc.lo \ + runtime.lo thread.lo yield.lo $(am__objects_3) iface.lo \ + malloc.lo map.lo mprof.lo reflect.lo runtime1.lo sema.lo \ + sigqueue.lo string.lo time.lo am_libgo_la_OBJECTS = $(am__objects_4) libgo_la_OBJECTS = $(am_libgo_la_OBJECTS) libgo_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ @@ -839,6 +841,7 @@ runtime_files = \ runtime/go-map-index.c \ runtime/go-map-len.c \ runtime/go-map-range.c \ + runtime/go-matherr.c \ runtime/go-nanotime.c \ runtime/go-now.c \ runtime/go-new-map.c \ @@ -2391,6 +2394,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-index.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-len.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-map-range.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-matherr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-nanotime.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new-map.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-new.Plo@am__quote@ @@ -2679,6 +2683,13 @@ go-map-range.lo: runtime/go-map-range.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-map-range.lo `test -f 'runtime/go-map-range.c' || echo '$(srcdir)/'`runtime/go-map-range.c +go-matherr.lo: runtime/go-matherr.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-matherr.lo -MD -MP -MF $(DEPDIR)/go-matherr.Tpo -c -o go-matherr.lo `test -f 'runtime/go-matherr.c' || echo '$(srcdir)/'`runtime/go-matherr.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-matherr.Tpo $(DEPDIR)/go-matherr.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-matherr.c' object='go-matherr.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-matherr.lo `test -f 'runtime/go-matherr.c' || echo '$(srcdir)/'`runtime/go-matherr.c + go-nanotime.lo: runtime/go-nanotime.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-nanotime.lo -MD -MP -MF $(DEPDIR)/go-nanotime.Tpo -c -o go-nanotime.lo `test -f 'runtime/go-nanotime.c' || echo '$(srcdir)/'`runtime/go-nanotime.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-nanotime.Tpo $(DEPDIR)/go-nanotime.Plo diff --git a/libgo/config.h.in b/libgo/config.h.in index bd19873819c..44ae4282e18 100644 --- a/libgo/config.h.in +++ b/libgo/config.h.in @@ -48,6 +48,9 @@ /* Define to 1 if the system has the type `loff_t'. */ #undef HAVE_LOFF_T +/* Define to 1 if you have the `matherr' function. */ +#undef HAVE_MATHERR + /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H @@ -99,6 +102,9 @@ /* Define to 1 if you have the `strsignal' function. */ #undef HAVE_STRSIGNAL +/* Define to 1 if defines struct exception */ +#undef HAVE_STRUCT_EXCEPTION + /* Define to 1 if the compiler provides the __sync_bool_compare_and_swap function for uint32 */ #undef HAVE_SYNC_BOOL_COMPARE_AND_SWAP_4 diff --git a/libgo/configure b/libgo/configure index 5821d32ab71..a93b0515dd9 100755 --- a/libgo/configure +++ b/libgo/configure @@ -14623,6 +14623,21 @@ done CFLAGS="$CFLAGS_hold" LIBS="$LIBS_hold" +LIBS_hold="$LIBS" +LIBS="$LIBS $MATH_LIBS" +for ac_func in matherr +do : + ac_fn_c_check_func "$LINENO" "matherr" "ac_cv_func_matherr" +if test "x$ac_cv_func_matherr" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_MATHERR 1 +_ACEOF + +fi +done + +LIBS="$LIBS_hold" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for __sync_bool_compare_and_swap_4" >&5 $as_echo_n "checking for __sync_bool_compare_and_swap_4... " >&6; } if test "${libgo_cv_func___sync_bool_compare_and_swap_4+set}" = set; then : @@ -14784,6 +14799,20 @@ $as_echo "$libgo_cv_c_epoll_event_fd_offset" >&6; } STRUCT_EPOLL_EVENT_FD_OFFSET=${libgo_cv_c_epoll_event_fd_offset} +ac_fn_c_check_type "$LINENO" "struct exception" "ac_cv_type_struct_exception" "#include +" +if test "x$ac_cv_type_struct_exception" = x""yes; then : + libgo_has_struct_exception=yes +else + libgo_has_struct_exception=no +fi + +if test "$libgo_has_struct_exception" = "yes"; then + +$as_echo "#define HAVE_STRUCT_EXCEPTION 1" >>confdefs.h + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether setcontext clobbers TLS variables" >&5 $as_echo_n "checking whether setcontext clobbers TLS variables... " >&6; } if test "${libgo_cv_lib_setcontext_clobbers_tls+set}" = set; then : diff --git a/libgo/configure.ac b/libgo/configure.ac index 155a412ee68..67789032868 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -478,6 +478,11 @@ AC_CHECK_FUNCS(sem_timedwait) CFLAGS="$CFLAGS_hold" LIBS="$LIBS_hold" +LIBS_hold="$LIBS" +LIBS="$LIBS $MATH_LIBS" +AC_CHECK_FUNCS(matherr) +LIBS="$LIBS_hold" + AC_CACHE_CHECK([for __sync_bool_compare_and_swap_4], [libgo_cv_func___sync_bool_compare_and_swap_4], [AC_LINK_IFELSE([ @@ -566,6 +571,16 @@ AC_CACHE_CHECK([epoll_event data.fd offset], STRUCT_EPOLL_EVENT_FD_OFFSET=${libgo_cv_c_epoll_event_fd_offset} AC_SUBST(STRUCT_EPOLL_EVENT_FD_OFFSET) +dnl See if struct exception is defined in . +AC_CHECK_TYPE([struct exception], +[libgo_has_struct_exception=yes], +[libgo_has_struct_exception=no], +[#include ]) +if test "$libgo_has_struct_exception" = "yes"; then + AC_DEFINE(HAVE_STRUCT_EXCEPTION, 1, + [Define to 1 if defines struct exception]) +fi + dnl See whether setcontext changes the value of TLS variables. AC_CACHE_CHECK([whether setcontext clobbers TLS variables], [libgo_cv_lib_setcontext_clobbers_tls], diff --git a/libgo/runtime/go-matherr.c b/libgo/runtime/go-matherr.c new file mode 100644 index 00000000000..786f3169d6a --- /dev/null +++ b/libgo/runtime/go-matherr.c @@ -0,0 +1,88 @@ +/* go-matherr.c -- a Go version of the matherr function. + + Copyright 2012 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. */ + +/* The gccgo version of the math library calls libc functions. On + some systems, such as Solaris, those functions will call matherr on + exceptional conditions. This is a version of matherr appropriate + for Go, one which returns the values that the Go math library + expects. This is fine for pure Go programs. For mixed Go and C + programs this will be problematic if the C programs themselves use + matherr. Normally the C version of matherr will override this, and + the Go code will just have to cope. If this turns out to be too + problematic we can change to run pure Go code in the math library + on systems that use matherr. */ + +#include +#include + +#include "config.h" + +#if defined(HAVE_MATHERR) && defined(HAVE_STRUCT_EXCEPTION) + +#define PI 3.14159265358979323846264338327950288419716939937510582097494459 + +int +matherr (struct exception* e) +{ + const char *n; + + if (e->type != DOMAIN) + return 0; + + n = e->name; + if (__builtin_strcmp (n, "acos") == 0 + || __builtin_strcmp (n, "asin") == 0) + e->retval = NAN; + else if (__builtin_strcmp (n, "atan2") == 0) + { + if (e->arg1 == 0 && e->arg2 == 0) + { + double nz; + + nz = -0.0; + if (__builtin_memcmp (&e->arg2, &nz, sizeof (double)) != 0) + e->retval = e->arg1; + else + e->retval = copysign (PI, e->arg1); + } + else + return 0; + } + else if (__builtin_strcmp (n, "log") == 0 + || __builtin_strcmp (n, "log10") == 0) + e->retval = NAN; + else if (__builtin_strcmp (n, "pow") == 0) + { + if (e->arg1 < 0) + e->retval = NAN; + else if (e->arg1 == 0 && e->arg2 == 0) + e->retval = 1.0; + else if (e->arg1 == 0 && e->arg2 < 0) + { + double i; + + if (modf (e->arg2, &i) == 0 && ((int64_t) i & 1) == 1) + e->retval = copysign (INFINITY, e->arg1); + else + e->retval = INFINITY; + } + else + return 0; + } + else if (__builtin_strcmp (n, "sqrt") == 0) + { + if (e->arg1 < 0) + e->retval = NAN; + else + return 0; + } + else + return 0; + + return 1; +} + +#endif