diff mbox

Go patch committed: More temporaries for interface conversion

Message ID CAOyqgcXX=Pww+Q21ma7W9-cBKfZE9MKnh1sE0i81z8DCCuzJUA@mail.gmail.com
State New
Headers show

Commit Message

Ian Lance Taylor Dec. 19, 2014, 10:21 p.m. UTC
More test cases, more cases where the Go frontend needs to create a
temporary in the case of interface conversion.  This is for map index
expressions and map composite literals.  Also only flatten call
expressions once; they tend to appear in the tree multiple times.
Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu.
Committed to mainline.

Ian
diff mbox

Patch

diff -r 9753943fcd89 go/expressions.cc
--- a/go/expressions.cc	Fri Dec 19 07:36:12 2014 -0800
+++ b/go/expressions.cc	Fri Dec 19 14:17:00 2014 -0800
@@ -8786,6 +8786,10 @@ 
   if (this->classification() == EXPRESSION_ERROR)
     return this;
 
+  if (this->is_flattened_)
+    return this;
+  this->is_flattened_ = true;
+
   // Add temporary variables for all arguments that require type
   // conversion.
   Function_type* fntype = this->get_function_type();
@@ -10590,21 +10594,31 @@ 
 // recomputation.
 
 Expression*
-Map_index_expression::do_flatten(Gogo*, Named_object*,
+Map_index_expression::do_flatten(Gogo* gogo, Named_object*,
 				 Statement_inserter* inserter)
 {
+  Location loc = this->location();
   Map_type* mt = this->get_map_type();
-  if (this->index_->type() != mt->key_type())
-    this->index_ = Expression::make_cast(mt->key_type(), this->index_,
-                                         this->location());
+  if (!Type::are_identical(mt->key_type(), this->index_->type(), false, NULL))
+    {
+      if (this->index_->type()->interface_type() != NULL
+	  && !this->index_->is_variable())
+	{
+	  Temporary_statement* temp =
+	    Statement::make_temporary(NULL, this->index_, loc);
+	  inserter->insert(temp);
+	  this->index_ = Expression::make_temporary_reference(temp, loc);
+	}
+      this->index_ = Expression::convert_for_assignment(gogo, mt->key_type(),
+							this->index_, loc);
+    }
 
   if (!this->index_->is_variable())
     {
       Temporary_statement* temp = Statement::make_temporary(NULL, this->index_,
-                                                            this->location());
+                                                            loc);
       inserter->insert(temp);
-      this->index_ = Expression::make_temporary_reference(temp,
-                                                          this->location());
+      this->index_ = Expression::make_temporary_reference(temp, loc);
     }
 
   if (this->value_pointer_ == NULL)
@@ -10612,11 +10626,9 @@ 
   if (!this->value_pointer_->is_variable())
     {
       Temporary_statement* temp =
-          Statement::make_temporary(NULL, this->value_pointer_,
-                                    this->location());
+	Statement::make_temporary(NULL, this->value_pointer_, loc);
       inserter->insert(temp);
-      this->value_pointer_ =
-          Expression::make_temporary_reference(temp, this->location());
+      this->value_pointer_ = Expression::make_temporary_reference(temp, loc);
     }
 
   return this;
@@ -12540,12 +12552,26 @@ 
            ++pv, ++i)
         {
           Expression_list* key_value_pair = new Expression_list();
-          Expression* key =
-              Expression::convert_for_assignment(gogo, key_type, *pv, loc);
+          Expression* key = *pv;
+	  if (key->type()->interface_type() != NULL && !key->is_variable())
+	    {
+	      Temporary_statement* temp =
+		Statement::make_temporary(NULL, key, loc);
+	      inserter->insert(temp);
+	      key = Expression::make_temporary_reference(temp, loc);
+	    }
+	  key = Expression::convert_for_assignment(gogo, key_type, key, loc);
 
           ++pv;
-          Expression* val =
-              Expression::convert_for_assignment(gogo, val_type, *pv, loc);
+          Expression* val = *pv;
+	  if (val->type()->interface_type() != NULL && !val->is_variable())
+	    {
+	      Temporary_statement* temp =
+		Statement::make_temporary(NULL, val, loc);
+	      inserter->insert(temp);
+	      val = Expression::make_temporary_reference(temp, loc);
+	    }
+	  val = Expression::convert_for_assignment(gogo, val_type, val, loc);
 
           key_value_pair->push_back(key);
           key_value_pair->push_back(val);
diff -r 9753943fcd89 go/expressions.h
--- a/go/expressions.h	Fri Dec 19 07:36:12 2014 -0800
+++ b/go/expressions.h	Fri Dec 19 14:17:00 2014 -0800
@@ -1632,7 +1632,8 @@ 
       fn_(fn), args_(args), type_(NULL), results_(NULL), call_(NULL),
       call_temp_(NULL), expected_result_count_(0), is_varargs_(is_varargs),
       varargs_are_lowered_(false), types_are_determined_(false),
-      is_deferred_(false), issued_error_(false), is_multi_value_arg_(false)
+      is_deferred_(false), issued_error_(false), is_multi_value_arg_(false),
+      is_flattened_(false)
   { }
 
   // The function to call.
@@ -1817,6 +1818,8 @@ 
   bool issued_error_;
   // True if this call is used as an argument that returns multiple results.
   bool is_multi_value_arg_;
+  // True if this expression has already been flattened.
+  bool is_flattened_;
 };
 
 // An expression which represents a pointer to a function.