aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2016-08-08 19:53:44 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2016-08-08 19:53:44 +0000
commitf432d1282d585bbedaa4293ec4bac0b7c8c2024a (patch)
tree30584249a7b8d17b5cdd6db69cfa4ce4069aa72c
parent5c9343960762bda86bc64dc19862dcf3088102cd (diff)
downloadgcc-f432d1282d585bbedaa4293ec4bac0b7c8c2024a.zip
gcc-f432d1282d585bbedaa4293ec4bac0b7c8c2024a.tar.gz
gcc-f432d1282d585bbedaa4293ec4bac0b7c8c2024a.tar.bz2
re PR go/72814 (reflect FAILs on 32-bit Solaris/SPARC: SIGILL)
PR go/72814 runtime: treat zero-sized result value as void Change the FFI interface to treat a call to a function that returns a zero-sized result as a call to a function that returns void. This is part of the fix for https://gcc.gnu.org/PR72814. On 32-bit SPARC systems, a call to a function that returns a non-zero-sized struct is followed by an unimp instruction that describes the size of the struct. The function returns to the address after the unimp instruction. The libffi library can not represent a zero-sized struct, so we wind up treating it as a 1-byte struct. Thus in that case libffi calls the function with an unimp instruction, but the function does not adjust the return address. The result is that the program attempts to execute the unimp instruction, causing a crash. This is part of a change that fixes the crash by treating all functions that return zero bytes as functions that return void. Reviewed-on: https://go-review.googlesource.com/25585 * go-gcc.cc (Gcc_backend::function_type): If the return type is zero bytes, treat the function as returning void. (return_statement): If the return type is zero bytes, don't actually return any values. From-SVN: r239252
-rw-r--r--gcc/go/ChangeLog8
-rw-r--r--gcc/go/go-gcc.cc29
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--libgo/runtime/go-ffi.c11
4 files changed, 49 insertions, 1 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog
index 20d5e9d..fef5c44 100644
--- a/gcc/go/ChangeLog
+++ b/gcc/go/ChangeLog
@@ -1,3 +1,11 @@
+2016-08-08 Ian Lance Taylor <iant@google.com>
+
+ PR go/72814
+ * go-gcc.cc (Gcc_backend::function_type): If the return type is
+ zero bytes, treat the function as returning void.
+ (return_statement): If the return type is zero bytes, don't
+ actually return any values.
+
2016-08-05 Ian Lance Taylor <iant@google.com>
PR go/72812
diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc
index 07d9b69..13407ea 100644
--- a/gcc/go/go-gcc.cc
+++ b/gcc/go/go-gcc.cc
@@ -953,6 +953,14 @@ Gcc_backend::function_type(const Btyped_identifier& receiver,
if (result == error_mark_node)
return this->error_type();
+ // The libffi library can not represent a zero-sized object. To
+ // avoid causing confusion on 32-bit SPARC, we treat a function that
+ // returns a zero-sized value as returning void. That should do no
+ // harm since there is no actual value to be returned. See
+ // https://gcc.gnu.org/PR72814 for details.
+ if (result != void_type_node && int_size_in_bytes(result) == 0)
+ result = void_type_node;
+
tree fntype = build_function_type(result, args);
if (fntype == error_mark_node)
return this->error_type();
@@ -2127,6 +2135,27 @@ Gcc_backend::return_statement(Bfunction* bfunction,
if (result == error_mark_node)
return this->error_statement();
+ // If the result size is zero bytes, we have set the function type
+ // to have a result type of void, so don't return anything.
+ // See the function_type method.
+ if (int_size_in_bytes(TREE_TYPE(result)) == 0)
+ {
+ tree stmt_list = NULL_TREE;
+ for (std::vector<Bexpression*>::const_iterator p = vals.begin();
+ p != vals.end();
+ p++)
+ {
+ tree val = (*p)->get_tree();
+ if (val == error_mark_node)
+ return this->error_statement();
+ append_to_statement_list(val, &stmt_list);
+ }
+ tree ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR,
+ void_type_node, NULL_TREE);
+ append_to_statement_list(ret, &stmt_list);
+ return this->make_statement(stmt_list);
+ }
+
tree ret;
if (vals.empty())
ret = fold_build1_loc(location.gcc_location(), RETURN_EXPR, void_type_node,
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index a5d7f51..6ec9f7b 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-eeeeff3e3dd6c09aaefdf13cce99a5beff47a095
+5e4c16d4fea39835e16f17c3d2b2e85f5c81d815
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/libgo/runtime/go-ffi.c b/libgo/runtime/go-ffi.c
index aafc7b2..8817080 100644
--- a/libgo/runtime/go-ffi.c
+++ b/libgo/runtime/go-ffi.c
@@ -288,6 +288,17 @@ go_func_return_ffi (const struct __go_func_type *func)
types = (const struct __go_type_descriptor **) func->__out.__values;
+ // We compile a function that returns a zero-sized value as though
+ // it returns void. This works around a problem in libffi: it can't
+ // represent a zero-sized value.
+ for (i = 0; i < count; ++i)
+ {
+ if (types[i]->__size > 0)
+ break;
+ }
+ if (i == count)
+ return &ffi_type_void;
+
if (count == 1)
return go_type_to_ffi (types[0]);