compiler: permit inlining variable declaration statements
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 10 May 2019 13:44:36 +0000 (13:44 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 10 May 2019 13:44:36 +0000 (13:44 +0000)
    This adds all of two inlinable functions to the standard library:
    crypto/subtle.ConstantTimeLessOrEq, regexp.(*Regexp).Copy.

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

From-SVN: r271063

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/statements.cc
gcc/go/gofrontend/statements.h

index b60177085409ba111ea8d650eef9d130544d43dc..8158367c62b38d2be476db2d70cfd205dfd10215 100644 (file)
@@ -1,4 +1,4 @@
-3dbf51c01c5d0acbf9ae47f77166fa9935881749
+b5e4ba88a2e7f3c34e9183f43370c38ea639c393
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 929571b29e452ea567105553f2548f7e16b14098..ed6585242401a5b230a75f10f4bbde52ca0e8ba3 100644 (file)
@@ -843,14 +843,14 @@ Var_expression::do_address_taken(bool escapes)
 }
 
 // The cost to inline a variable reference.  We currently only support
-// references to parameters.
+// references to parameters and local variables.
 
 int
 Var_expression::do_inlining_cost() const
 {
   if (this->variable_->is_variable())
     {
-      if (this->variable_->var_value()->is_parameter())
+      if (!this->variable_->var_value()->is_global())
        return 1;
     }
   else if (this->variable_->is_result_variable())
index 67ab18469a55a344c18f1dd28dc581f26a8d13f0..cd1b60199e8dd2bd350336695868d8336c9db838 100644 (file)
@@ -155,6 +155,8 @@ Statement::import_statement(Import_function_body* ifb, Location loc)
       ifb->advance(6);
       return Statement::make_return_statement(NULL, loc);
     }
+  else if (ifb->match_c_string("var "))
+    return Variable_declaration_statement::do_import(ifb, loc);
 
   Expression* lhs = Expression::import_expression(ifb, loc);
   ifb->require_c_string(" = ");
@@ -408,6 +410,57 @@ Statement::make_variable_declaration(Named_object* var)
   return new Variable_declaration_statement(var);
 }
 
+// Export a variable declaration.
+
+void
+Variable_declaration_statement::do_export_statement(Export_function_body* efb)
+{
+  efb->write_c_string("var ");
+  efb->write_string(Gogo::unpack_hidden_name(this->var_->name()));
+  efb->write_c_string(" ");
+  Variable* var = this->var_->var_value();
+  Type* type = var->type();
+  efb->write_type(type);
+  Expression* init = var->init();
+  if (init != NULL)
+    {
+      efb->write_c_string(" = ");
+
+      go_assert(efb->type_context() == NULL);
+      efb->set_type_context(type);
+
+      init->export_expression(efb);
+
+      efb->set_type_context(NULL);
+    }
+}
+
+// Import a variable declaration.
+
+Statement*
+Variable_declaration_statement::do_import(Import_function_body* ifb,
+                                         Location loc)
+{
+  ifb->require_c_string("var ");
+  std::string id = ifb->read_identifier();
+  ifb->require_c_string(" ");
+  Type* type = ifb->read_type();
+  Expression* init = NULL;
+  if (ifb->match_c_string(" = "))
+    {
+      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();
+  // FIXME: The package we are importing does not yet exist, so we
+  // can't pass the correct package here.  It probably doesn't matter.
+  Named_object* no = ifb->block()->bindings()->add_variable(id, NULL, var);
+  return Statement::make_variable_declaration(no);
+}
+
 // Class Temporary_statement.
 
 // Return the type of the temporary variable.
index ec9ade3f9e7075f5516693add813bd0ac2dd3a55..19ccb85a4bd85c48b6c854b180d358419974fbc6 100644 (file)
@@ -16,6 +16,7 @@ class Block;
 class Function;
 class Unnamed_label;
 class Export_function_body;
+class Import_function_body;
 class Assignment_statement;
 class Temporary_statement;
 class Variable_declaration_statement;
@@ -332,8 +333,7 @@ class Statement
   inlining_cost()
   { return this->do_inlining_cost(); }
 
-  // Export data for this statement to BODY.  INDENT is an indentation
-  // level used if the export data requires multiple lines.
+  // Export data for this statement to BODY.
   void
   export_statement(Export_function_body* efb)
   { this->do_export_statement(efb); }
@@ -514,10 +514,8 @@ class Statement
   { return 0x100000; }
 
   // Implemented by child class: write export data for this statement
-  // to the string.  The integer is an indentation level used if the
-  // export data requires multiple lines.  This need only be
-  // implemented by classes that implement do_inlining_cost with a
-  // reasonable value.
+  // to the string.  This need only be implemented by classes that
+  // implement do_inlining_cost with a reasonable value.
   virtual void
   do_export_statement(Export_function_body*)
   { go_unreachable(); }
@@ -746,6 +744,10 @@ class Variable_declaration_statement : public Statement
   var()
   { return this->var_; }
 
+  // Import a variable declaration.
+  static Statement*
+  do_import(Import_function_body*, Location);
+
  protected:
   int
   do_traverse(Traverse*);
@@ -756,6 +758,13 @@ class Variable_declaration_statement : public Statement
   Statement*
   do_lower(Gogo*, Named_object*, Block*, Statement_inserter*);
 
+  int
+  do_inlining_cost()
+  { return 1; }
+
+  void
+  do_export_statement(Export_function_body*);
+
   Statement*
   do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*);