compiler, runtime: Fix complex division of NaN / 0.

From-SVN: r203331
This commit is contained in:
Ian Lance Taylor 2013-10-09 22:31:15 +00:00
parent 4d5b5e9f2c
commit 215552adac
6 changed files with 107 additions and 1 deletions

View file

@ -5967,6 +5967,43 @@ Binary_expression::do_get_tree(Translate_context* context)
right);
}
// For complex division Go wants slightly different results than the
// GCC library provides, so we have our own runtime routine.
if (this->op_ == OPERATOR_DIV && this->left_->type()->complex_type() != NULL)
{
const char *name;
tree *pdecl;
Type* ctype;
static tree complex64_div_decl;
static tree complex128_div_decl;
switch (this->left_->type()->complex_type()->bits())
{
case 64:
name = "__go_complex64_div";
pdecl = &complex64_div_decl;
ctype = Type::lookup_complex_type("complex64");
break;
case 128:
name = "__go_complex128_div";
pdecl = &complex128_div_decl;
ctype = Type::lookup_complex_type("complex128");
break;
default:
go_unreachable();
}
Btype* cbtype = ctype->get_backend(gogo);
tree ctype_tree = type_to_tree(cbtype);
return Gogo::call_builtin(pdecl,
this->location(),
name,
2,
ctype_tree,
ctype_tree,
fold_convert_loc(gccloc, ctype_tree, left),
type,
fold_convert_loc(gccloc, ctype_tree, right));
}
tree compute_type = excess_precision_type(type);
if (compute_type != NULL_TREE)
{

View file

@ -42,6 +42,8 @@ enum Runtime_function_type
RFT_RUNE,
// Go type float64, C type double.
RFT_FLOAT64,
// Go type complex64, C type __complex float.
RFT_COMPLEX64,
// Go type complex128, C type __complex double.
RFT_COMPLEX128,
// Go type string, C type struct __go_string.
@ -126,6 +128,10 @@ runtime_function_type(Runtime_function_type bft)
t = Type::lookup_float_type("float64");
break;
case RFT_COMPLEX64:
t = Type::lookup_complex_type("complex64");
break;
case RFT_COMPLEX128:
t = Type::lookup_complex_type("complex128");
break;
@ -216,6 +222,7 @@ convert_to_runtime_function_type(Runtime_function_type bft, Expression* e,
case RFT_UINTPTR:
case RFT_RUNE:
case RFT_FLOAT64:
case RFT_COMPLEX64:
case RFT_COMPLEX128:
case RFT_STRING:
case RFT_POINTER:

View file

@ -68,6 +68,12 @@ DEF_GO_RUNTIME(STRING_TO_INT_ARRAY, "__go_string_to_int_array",
P1(STRING), R1(SLICE))
// Complex division.
DEF_GO_RUNTIME(COMPLEX64_DIV, "__go_complex64_div",
P2(COMPLEX64, COMPLEX64), R1(COMPLEX64))
DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div",
P2(COMPLEX128, COMPLEX128), R1(COMPLEX128))
// Make a slice.
DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE))
DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR),

View file

@ -424,6 +424,7 @@ runtime_files = \
runtime/go-caller.c \
runtime/go-callers.c \
runtime/go-can-convert-interface.c \
runtime/go-cdiv.c \
runtime/go-cgo.c \
runtime/go-check-interface.c \
runtime/go-construct-map.c \

View file

@ -195,7 +195,7 @@ libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
@LIBGO_IS_LINUX_TRUE@am__objects_5 = getncpu-linux.lo
am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \
go-byte-array-to-string.lo go-breakpoint.lo go-caller.lo \
go-callers.lo go-can-convert-interface.lo go-cgo.lo \
go-callers.lo go-can-convert-interface.lo go-cdiv.lo go-cgo.lo \
go-check-interface.lo go-construct-map.lo \
go-convert-interface.lo go-copy.lo go-defer.lo \
go-deferred-recover.lo go-eface-compare.lo \
@ -757,6 +757,7 @@ runtime_files = \
runtime/go-caller.c \
runtime/go-callers.c \
runtime/go-can-convert-interface.c \
runtime/go-cdiv.c \
runtime/go-cgo.c \
runtime/go-check-interface.c \
runtime/go-construct-map.c \
@ -2368,6 +2369,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-caller.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-callers.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-can-convert-interface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cdiv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-cgo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-check-interface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-construct-map.Plo@am__quote@
@ -2554,6 +2556,13 @@ go-can-convert-interface.lo: runtime/go-can-convert-interface.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-can-convert-interface.lo `test -f 'runtime/go-can-convert-interface.c' || echo '$(srcdir)/'`runtime/go-can-convert-interface.c
go-cdiv.lo: runtime/go-cdiv.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-cdiv.lo -MD -MP -MF $(DEPDIR)/go-cdiv.Tpo -c -o go-cdiv.lo `test -f 'runtime/go-cdiv.c' || echo '$(srcdir)/'`runtime/go-cdiv.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-cdiv.Tpo $(DEPDIR)/go-cdiv.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-cdiv.c' object='go-cdiv.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-cdiv.lo `test -f 'runtime/go-cdiv.c' || echo '$(srcdir)/'`runtime/go-cdiv.c
go-cgo.lo: runtime/go-cgo.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-cgo.lo -MD -MP -MF $(DEPDIR)/go-cgo.Tpo -c -o go-cgo.lo `test -f 'runtime/go-cgo.c' || echo '$(srcdir)/'`runtime/go-cgo.c
@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-cgo.Tpo $(DEPDIR)/go-cgo.Plo

46
libgo/runtime/go-cdiv.c Normal file
View file

@ -0,0 +1,46 @@
/* go-cdiv.c -- complex division routines
Copyright 2013 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. */
/* 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
default. When dividing NaN+1.0i / 0+0i, Go expects NaN+NaNi but
GCC generates NaN+Infi. NaN+Infi seems wrong seems the rules of
C99 Annex G specify that if either side of a complex number is Inf,
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)
{
if (__builtin_expect (b == 0+0i, 0))
{
if (!__builtin_isinff (__real__ a)
&& !__builtin_isinff (__imag__ a)
&& (__builtin_isnanf (__real__ a) || __builtin_isnanf (__imag__ a)))
{
/* Pass "1" to nanf to match math/bits.go. */
return __builtin_nanf("1") + __builtin_nanf("1")*1i;
}
}
return a / b;
}
__complex double
__go_complex128_div (__complex double a, __complex double b)
{
if (__builtin_expect (b == 0+0i, 0))
{
if (!__builtin_isinf (__real__ a)
&& !__builtin_isinf (__imag__ a)
&& (__builtin_isnan (__real__ a) || __builtin_isnan (__imag__ a)))
{
/* Pass "1" to nan to match math/bits.go. */
return __builtin_nan("1") + __builtin_nan("1")*1i;
}
}
return a / b;
}