Go patch committed: Support inlining functions that use index expressions

Message ID CAOyqgcXwy7rFRtzpBvNSLS7GsnwbHpMFCnNX6vHNU8EEHnuu5A@mail.gmail.com
State New
Headers show
Series
  • Go patch committed: Support inlining functions that use index expressions
Related show

Commit Message

Ian Lance Taylor June 10, 2019, 9:34 p.m.
This patch to the Go frontend supports inlining functions that use
index expressions.  It also moves the determine_types pass on an
inlined function body to one place, rather than doing it ad hoc as
needed.  This adds 79 new inlinable functions in the standard library,
such as bytes.HasPrefix and bytes.LastIndexByte.  Bootstrapped and ran
Go testsuite on x86_64-pc-linux-gnu.  Committed to mainline.

Ian

Patch

Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE	(revision 272132)
+++ gcc/go/gofrontend/MERGE	(working copy)
@@ -1,4 +1,4 @@ 
-764fe6702f2bb8650622d4102de31058e484ecb5
+b1ae35965cadac235d7d218e689944286cccdd90
 
 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 272132)
+++ gcc/go/gofrontend/expressions.cc	(working copy)
@@ -7110,6 +7110,12 @@  Binary_expression::do_import(Import_expr
       op = OPERATOR_BITCLEAR;
       imp->advance(4);
     }
+  else if (imp->match_c_string(")"))
+    {
+      // Not a binary operator after all.
+      imp->advance(1);
+      return left;
+    }
   else
     {
       go_error_at(imp->location(), "unrecognized binary operator");
@@ -12808,6 +12814,38 @@  Array_index_expression::do_get_backend(T
   return ret;
 }
 
+// Export an array index expression.
+
+void
+Array_index_expression::do_export(Export_function_body* efb) const
+{
+  efb->write_c_string("(");
+  this->array_->export_expression(efb);
+  efb->write_c_string(")[");
+
+  Type* old_context = efb->type_context();
+  efb->set_type_context(Type::lookup_integer_type("int"));
+
+  this->start_->export_expression(efb);
+  if (this->end_ == NULL)
+    go_assert(this->cap_ == NULL);
+  else
+    {
+      efb->write_c_string(":");
+      if (!this->end_->is_nil_expression())
+	this->end_->export_expression(efb);
+      if (this->cap_ != NULL)
+	{
+	  efb->write_c_string(":");
+	  this->cap_->export_expression(efb);
+	}
+    }
+
+  efb->set_type_context(old_context);
+
+  efb->write_c_string("]");
+}
+
 // Dump ast representation for an array index expression.
 
 void
@@ -13068,6 +13106,31 @@  String_index_expression::do_get_backend(
 						 crash, bstrslice, loc);
 }
 
+// Export a string index expression.
+
+void
+String_index_expression::do_export(Export_function_body* efb) const
+{
+  efb->write_c_string("(");
+  this->string_->export_expression(efb);
+  efb->write_c_string(")[");
+
+  Type* old_context = efb->type_context();
+  efb->set_type_context(Type::lookup_integer_type("int"));
+
+  this->start_->export_expression(efb);
+  if (this->end_ != NULL)
+    {
+      efb->write_c_string(":");
+      if (!this->end_->is_nil_expression())
+	this->end_->export_expression(efb);
+    }
+
+  efb->set_type_context(old_context);
+
+  efb->write_c_string("]");
+}
+
 // Dump ast representation for a string index expression.
 
 void
@@ -13338,6 +13401,25 @@  Map_index_expression::get_value_pointer(
   return this->value_pointer_;
 }
 
+// Export a map index expression.
+
+void
+Map_index_expression::do_export(Export_function_body* efb) const
+{
+  efb->write_c_string("(");
+  this->map_->export_expression(efb);
+  efb->write_c_string(")[");
+
+  Type* old_context = efb->type_context();
+  efb->set_type_context(this->get_map_type()->key_type());
+
+  this->index_->export_expression(efb);
+
+  efb->set_type_context(old_context);
+
+  efb->write_c_string("]");
+}
+
 // Dump ast representation for a map index expression
 
 void
@@ -17974,6 +18056,29 @@  Expression::import_expression(Import_exp
 	  imp->require_c_string(")");
 	  expr = Expression::make_call(expr, args, is_varargs, loc);
 	}
+      else if (imp->match_c_string("["))
+	{
+	  imp->advance(1);
+	  Expression* start = Expression::import_expression(imp, loc);
+	  Expression* end = NULL;
+	  Expression* cap = NULL;
+	  if (imp->match_c_string(":"))
+	    {
+	      imp->advance(1);
+	      int c = imp->peek_char();
+	      if (c == ':' || c == ']')
+		end = Expression::make_nil(loc);
+	      else
+		end = Expression::import_expression(imp, loc);
+	      if (imp->match_c_string(":"))
+		{
+		  imp->advance(1);
+		  cap = Expression::import_expression(imp, loc);
+		}
+	    }
+	  imp->require_c_string("]");
+	  expr = Expression::make_index(expr, start, end, cap, loc);
+	}
       else
 	break;
     }
Index: gcc/go/gofrontend/expressions.h
===================================================================
--- gcc/go/gofrontend/expressions.h	(revision 272127)
+++ gcc/go/gofrontend/expressions.h	(working copy)
@@ -3089,6 +3089,13 @@  class Array_index_expression : public Ex
   Bexpression*
   do_get_backend(Translate_context*);
 
+  int
+  do_inlining_cost() const
+  { return this->end_ != NULL ? 2 : 1; }
+
+  void
+  do_export(Export_function_body*) const;
+
   void
   do_dump_expression(Ast_dump_context*) const;
 
@@ -3161,6 +3168,13 @@  class String_index_expression : public E
   Bexpression*
   do_get_backend(Translate_context*);
 
+  int
+  do_inlining_cost() const
+  { return this->end_ != NULL ? 2 : 1; }
+
+  void
+  do_export(Export_function_body*) const;
+
   void
   do_dump_expression(Ast_dump_context*) const;
 
@@ -3247,6 +3261,13 @@  class Map_index_expression : public Expr
   Bexpression*
   do_get_backend(Translate_context*);
 
+  int
+  do_inlining_cost() const
+  { return 5; }
+
+  void
+  do_export(Export_function_body*) const;
+
   void
   do_dump_expression(Ast_dump_context*) const;
 
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc	(revision 272132)
+++ gcc/go/gofrontend/gogo.cc	(working copy)
@@ -7282,6 +7282,7 @@  Function_declaration::import_function_bo
     return;
 
   gogo->lower_block(no, outer);
+  outer->determine_types();
 
   gogo->add_imported_inline_function(no);
 }
Index: gcc/go/gofrontend/import.cc
===================================================================
--- gcc/go/gofrontend/import.cc	(revision 272131)
+++ gcc/go/gofrontend/import.cc	(working copy)
@@ -1238,7 +1238,7 @@  Import::register_builtin_type(Gogo* gogo
 // characters that stop an identifier, without worrying about
 // characters that are permitted in an identifier.  That lets us skip
 // UTF-8 parsing.
-static const char * const identifier_stop = " \n;,()[]";
+static const char * const identifier_stop = " \n;:,()[]";
 
 // Read an identifier from the stream.
 
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc	(revision 272131)
+++ gcc/go/gofrontend/statements.cc	(working copy)
@@ -465,8 +465,6 @@  Variable_declaration_statement::do_impor
     {
       ifb->advance(3);
       init = Expression::import_expression(ifb, loc);
-      Type_context context(type, false);
-      init->determine_type(&context);
     }
   Variable* var = new Variable(type, init, false, false, false, loc);
   var->set_is_used();
@@ -753,11 +751,6 @@  Temporary_statement::do_import(Import_fu
     {
       ifb->advance(3);
       init = Expression::import_expression(ifb, loc);
-      if (type != NULL)
-	{
-	  Type_context context(type, false);
-	  init->determine_type(&context);
-	}
     }
   if (type == NULL && init == NULL)
     {
@@ -3730,8 +3723,6 @@  If_statement::do_import(Import_function_
   ifb->require_c_string("if ");
 
   Expression* cond = Expression::import_expression(ifb, loc);
-  Type_context context(Type::lookup_bool_type(), false);
-  cond->determine_type(&context);
   ifb->require_c_string(" ");
 
   if (!ifb->match_c_string("{"))