diff options
author | Ian Lance Taylor <iant@google.com> | 2016-08-08 19:53:44 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2016-08-08 19:53:44 +0000 |
commit | f432d1282d585bbedaa4293ec4bac0b7c8c2024a (patch) | |
tree | 30584249a7b8d17b5cdd6db69cfa4ce4069aa72c /gcc/go/go-gcc.cc | |
parent | 5c9343960762bda86bc64dc19862dcf3088102cd (diff) | |
download | gcc-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
Diffstat (limited to 'gcc/go/go-gcc.cc')
-rw-r--r-- | gcc/go/go-gcc.cc | 29 |
1 files changed, 29 insertions, 0 deletions
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, |