re PR go/90482 (Many 32-bit Solaris/SPARC tests FAIL with SIGBUS)
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 17 May 2019 05:49:22 +0000 (05:49 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 17 May 2019 05:49:22 +0000 (05:49 +0000)
PR go/90482
    compiler: make value method of direct interface type takes pointer

    Currently, a value method of a direct interface type takes the
    value of the receiver, which is pointer shaped, as the first
    parameter. When this method is called through interface, we
    actually pass the interface data as a pointer. On most platforms
    this is ok, as the underlying calling convention is the same,
    except that on SPARC32, the calling convention is actually
    different.

    This CL changes the method function actually takes a pointer.
    The function will convert the pointer to the pointer-shaped
    receiver type (a no-op conversion from machine code's aspect).
    For a direct call, in the caller we convert the receiver to a
    pointer (also no-op conversion) before invoking the method. For
    an interface call, we pass the pointer as before. This way, it is
    consistent that we always pass a pointer.

    Hopefully this fixes SPARC32 build and https://gcc.gnu.org/PR90482.

    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/177758

From-SVN: r271310

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/types.cc

index 578bef74be308eebf334ae200ddb838032c7c423..304c910b2d01138bce6542bc59ba4c6213a7dfee 100644 (file)
@@ -1,4 +1,4 @@
-f8a3668cbcfa3f8cd6c26c62bce416714cd401fc
+b5ab7b419d6328f5126ba8d6795280129eaf6e79
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index dd559b4c0dd82af50b403f43ab6b18dbfa99edc7..ad898b7f38c8b591e8e7c22766bf3bd226aa8a67 100644 (file)
@@ -11263,6 +11263,16 @@ Call_expression::do_get_backend(Translate_context* context)
   else
     has_closure_arg = true;
 
+  Expression* first_arg = NULL;
+  if (!is_interface_method && fntype->is_method())
+    {
+      first_arg = this->args_->front();
+      if (first_arg->type()->points_to() == NULL
+          && first_arg->type()->is_direct_iface_type())
+        first_arg = Expression::unpack_direct_iface(first_arg,
+                                                    first_arg->location());
+    }
+
   int nargs;
   std::vector<Bexpression*> fn_args;
   if (this->args_ == NULL || this->args_->empty())
@@ -11279,7 +11289,7 @@ Call_expression::do_get_backend(Translate_context* context)
                && this->args_->size() == 1);
       nargs = 1;
       fn_args.resize(1);
-      fn_args[0] = this->args_->front()->get_backend(context);
+      fn_args[0] = first_arg->get_backend(context);
     }
   else
     {
@@ -11294,7 +11304,7 @@ Call_expression::do_get_backend(Translate_context* context)
       Expression_list::const_iterator pe = this->args_->begin();
       if (!is_interface_method && fntype->is_method())
        {
-          fn_args[i] = (*pe)->get_backend(context);
+          fn_args[i] = first_arg->get_backend(context);
          ++pe;
          ++i;
        }
index 21a214db632226e6c447881ddedcd0d843966f31..3527d7a897b454e83734a036b240ce6f8dd4badb 100644 (file)
@@ -1063,6 +1063,11 @@ class Expression
   static Expression*
   pack_direct_iface(Type*, Expression*, Location);
 
+  // Return an expression of the underlying pointer for a direct interface
+  // type (the opposite of pack_direct_iface).
+  static Expression*
+  unpack_direct_iface(Expression*, Location);
+
   // Dump an expression to a dump constext.
   void
   dump_expression(Ast_dump_context*) const;
@@ -1230,9 +1235,6 @@ class Expression
            : NULL);
   }
 
-  static Expression*
-  unpack_direct_iface(Expression*, Location);
-
   static Expression*
   get_interface_type_descriptor(Expression*);
 
index 02120f2e1fdbca8e96a73474dad33fba7331db9e..e94c5679d6d62f732a8981eb14a61ddcdf50d7b1 100644 (file)
@@ -6052,9 +6052,10 @@ Function::build(Gogo* gogo, Named_object* named_function)
 
          // We always pass the receiver to a method as a pointer.  If
          // the receiver is declared as a non-pointer type, then we
-         // copy the value into a local variable.
+         // copy the value into a local variable.  For direct interface
+          // type we pack the pointer into the type.
          if ((*p)->var_value()->is_receiver()
-             && !(*p)->var_value()->type()->is_direct_iface_type())
+              && (*p)->var_value()->type()->points_to() == NULL)
            {
              std::string name = (*p)->name() + ".pointer";
              Type* var_type = (*p)->var_value()->type();
@@ -6066,14 +6067,19 @@ Function::build(Gogo* gogo, Named_object* named_function)
               parm_bvar = parm_no->get_backend_variable(gogo, named_function);
 
               vars.push_back(bvar);
-             Expression* parm_ref =
+
+              Expression* parm_ref =
                   Expression::make_var_reference(parm_no, loc);
-              parm_ref =
-                  Expression::make_dereference(parm_ref,
-                                               Expression::NIL_CHECK_NEEDED,
-                                               loc);
-             if ((*p)->var_value()->is_in_heap())
-               parm_ref = Expression::make_heap_expression(parm_ref, loc);
+              Type* recv_type = (*p)->var_value()->type();
+              if (recv_type->is_direct_iface_type())
+                parm_ref = Expression::pack_direct_iface(recv_type, parm_ref, loc);
+              else
+                parm_ref =
+                    Expression::make_dereference(parm_ref,
+                                                 Expression::NIL_CHECK_NEEDED,
+                                                 loc);
+              if ((*p)->var_value()->is_in_heap())
+                parm_ref = Expression::make_heap_expression(parm_ref, loc);
               var_inits.push_back(parm_ref->get_backend(&context));
            }
          else if ((*p)->var_value()->is_in_heap())
@@ -7531,7 +7537,7 @@ Variable::get_backend_variable(Gogo* gogo, Named_object* function,
       else
        {
          bool is_parameter = this->is_parameter_;
-         if (this->is_receiver_ && !type->is_direct_iface_type())
+         if (this->is_receiver_ && type->points_to() == NULL)
            is_parameter = false;
          if (this->is_in_heap())
            {
index 371b65fc20effa9ceac80fbee190ae9577c4b21a..52606261833cef446da1c06d43e7f0f69d97e0ea 100644 (file)
@@ -4760,10 +4760,15 @@ Function_type::get_backend_fntype(Gogo* gogo)
           // We always pass the address of the receiver parameter, in
           // order to make interface calls work with unknown types,
           // except for direct interface types where the interface call
-          // actually passes value.
+          // actually passes the underlying pointer of the value.
           Type* rtype = this->receiver_->type();
-          if (!rtype->is_direct_iface_type())
-            rtype = Type::make_pointer_type(rtype);
+          if (rtype->points_to() == NULL)
+            {
+              if (rtype->is_direct_iface_type())
+                rtype = Type::make_pointer_type(Type::make_void_type());
+              else
+                rtype = Type::make_pointer_type(rtype);
+            }
           breceiver.btype = rtype->get_backend(gogo);
           breceiver.location = this->receiver_->location();
         }