diff mbox series

Go patch committed: Make value method of direct iface take pointer

Message ID CAOyqgcUHKbwoBZr5H2fCTxqsr9a3OBZ-Rn-yixaPSOOtgR--XQ@mail.gmail.com
State New
Headers show
Series Go patch committed: Make value method of direct iface take pointer | expand

Commit Message

Ian Lance Taylor May 17, 2019, 5:49 a.m. UTC
This patch to the Go frontend by Cherry Zhang make value methods of
direct interface types take a pointer argument.

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 patch 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.

Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu.  Committed
to mainline.

Ian
diff mbox series

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 271308)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -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: gcc/go/gofrontend/expressions.cc
===================================================================
--- gcc/go/gofrontend/expressions.cc	(revision 271308)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -11263,6 +11263,16 @@  Call_expression::do_get_backend(Translat
   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(Translat
 		&& 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(Translat
       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: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 271303)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -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;
@@ -1231,9 +1236,6 @@  class Expression
   }
 
   static Expression*
-  unpack_direct_iface(Expression*, Location);
-
-  static Expression*
   get_interface_type_descriptor(Expression*);
 
   static Expression*
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 271303)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -6052,9 +6052,10 @@  Function::build(Gogo* gogo, Named_object
 
 	  // 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
               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* gog
       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: gcc/go/gofrontend/types.cc
===================================================================
--- gcc/go/gofrontend/types.cc	(revision 271182)
+++ gcc/go/gofrontend/types.cc	(working copy)
@@ -4760,10 +4760,15 @@  Function_type::get_backend_fntype(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();
         }