re PR go/72814 (reflect FAILs on 32-bit Solaris/SPARC: SIGILL)
authorIan Lance Taylor <iant@google.com>
Mon, 8 Aug 2016 19:53:44 +0000 (19:53 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 8 Aug 2016 19:53:44 +0000 (19:53 +0000)
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

gcc/go/ChangeLog
gcc/go/go-gcc.cc
gcc/go/gofrontend/MERGE
libgo/runtime/go-ffi.c

index 20d5e9d2200fb6c62e1fde3333f14e673f726ad0..fef5c44dbebb99ba2fc73f39a559a1b6b4df5e95 100644 (file)
@@ -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
index 07d9b69906f871b40ddaf25465216d532d81fe5c..13407ea5d37a67c76ffd06e0b3d6636c6441430c 100644 (file)
@@ -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,
index a5d7f51f1adcbb037932ae1de0d6cc5310f7ace7..6ec9f7b551a8644f7e192776cbc5f958fb3601aa 100644 (file)
@@ -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.
index aafc7b205e0fb579a0fde75526eea84cc48a4d15..8817080c59516e20879e7171c6bda5e42cb78952 100644 (file)
@@ -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]);