aboutsummaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2013-10-09 22:31:15 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2013-10-09 22:31:15 +0000
commit215552adac04bc04778b3052c24d8c66b8455fef (patch)
treeecca99f169c43eb56f3f628b9248c8e0361b9a0e /gcc/go
parent4d5b5e9f2c37500cb85e18ce685be3bdd6ba549d (diff)
downloadgcc-215552adac04bc04778b3052c24d8c66b8455fef.zip
gcc-215552adac04bc04778b3052c24d8c66b8455fef.tar.gz
gcc-215552adac04bc04778b3052c24d8c66b8455fef.tar.bz2
compiler, runtime: Fix complex division of NaN / 0.
From-SVN: r203331
Diffstat (limited to 'gcc/go')
-rw-r--r--gcc/go/gofrontend/expressions.cc37
-rw-r--r--gcc/go/gofrontend/runtime.cc7
-rw-r--r--gcc/go/gofrontend/runtime.def6
3 files changed, 50 insertions, 0 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index d5e3a67..9d59349 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -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)
{
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index ecc508d..3b0f1880 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -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:
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 0d3fd3c..a303a50 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -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),