diff mbox

Go patch committed: pass constant arguments directly to thunk functions

Message ID mcriokjtpa8.fsf@iant-glaptop.roam.corp.google.com
State New
Headers show

Commit Message

Ian Lance Taylor Sept. 19, 2014, 6:53 p.m. UTC
When the Go frontend builds a thunk, for a go or defer statement, it
sets up a struct to hold the arguments to the function, passes a pointer
to that struct to the thunk, and the thunk then calls the function
passing the fields of the struct.  Something along these lines is
necessary when calling a function with variable arguments.  However, if
the arguments are constant, then it's not necessary to store the
constants in the struct; they can be encoded directly in the thunk.
This patch from Chris Manghane implements this in the Go frontend.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian
diff mbox

Patch

diff -r 3e0952791c91 go/statements.cc
--- a/go/statements.cc	Fri Sep 05 08:06:32 2014 -0700
+++ b/go/statements.cc	Fri Sep 19 11:35:43 2014 -0700
@@ -2178,7 +2178,11 @@ 
       for (Expression_list::const_iterator p = ce->args()->begin();
 	   p != ce->args()->end();
 	   ++p)
-	vals->push_back(*p);
+	{
+	  if ((*p)->is_constant())
+	    continue;
+	  vals->push_back(*p);
+	}
     }
 
   // Build the struct.
@@ -2281,6 +2285,9 @@ 
 	   p != args->end();
 	   ++p, ++i)
 	{
+	  if ((*p)->is_constant())
+	    continue;
+
 	  char buf[50];
 	  this->thunk_field_param(i, buf, sizeof buf);
 	  fields->push_back(Struct_field(Typed_identifier(buf, (*p)->type(),
@@ -2418,21 +2425,36 @@ 
     ++p;
   bool is_recover_call = ce->is_recover_call();
   Expression* recover_arg = NULL;
-  for (; p != fields->end(); ++p, ++next_index)
+
+  const Expression_list* args = ce->args();
+  if (args != NULL)
     {
-      Expression* thunk_param = Expression::make_var_reference(named_parameter,
-							       location);
-      thunk_param = Expression::make_unary(OPERATOR_MULT, thunk_param,
-					   location);
-      Expression* param = Expression::make_field_reference(thunk_param,
-							   next_index,
-							   location);
-      if (!is_recover_call)
-	call_params->push_back(param);
-      else
+      for (Expression_list::const_iterator arg = args->begin();
+	   arg != args->end();
+	   ++arg)
 	{
-	  go_assert(call_params->empty());
-	  recover_arg = param;
+	  Expression* param;
+	  if ((*arg)->is_constant())
+	    param = *arg;
+	  else
+	    {
+	      Expression* thunk_param =
+		Expression::make_var_reference(named_parameter, location);
+	      thunk_param =
+		Expression::make_unary(OPERATOR_MULT, thunk_param, location);
+	      param = Expression::make_field_reference(thunk_param,
+						       next_index,
+						       location);
+	      ++next_index;
+	    }
+
+	  if (!is_recover_call)
+	    call_params->push_back(param);
+	  else
+	    {
+	      go_assert(call_params->empty());
+	      recover_arg = param;
+	    }
 	}
     }