compiler: statically allocate constant interface data

When converting a constant to interface, such as interface{}(42)
or interface{}("hello"), if the interface escapes, we currently
generate a heap allocation to hold the constant value.

This CL changes it to generate a static allocation instead, as
the gc compiler does. This reduces allocations in such cases.

Change-Id: Ic53b202362917d1829f60f166ea50457e2fcb468
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/180277
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/go/expressions.cc b/go/expressions.cc
index 6aca5f8..d7bf4d7 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -323,9 +323,14 @@
     {
       // We are assigning a non-pointer value to the interface; the
       // interface gets a copy of the value in the heap if it escapes.
-      obj = Expression::make_heap_expression(rhs, location);
-      if (on_stack)
-        obj->heap_expression()->set_allocate_on_stack();
+      if (rhs->is_constant())
+        obj = Expression::make_unary(OPERATOR_AND, rhs, location);
+      else
+        {
+          obj = Expression::make_heap_expression(rhs, location);
+          if (on_stack)
+            obj->heap_expression()->set_allocate_on_stack();
+        }
     }
 
   return Expression::make_interface_value(lhs_type, first_field, obj, location);
@@ -4896,6 +4901,18 @@
 						     false, btype, loc, bexpr);
           bexpr = gogo->backend()->var_expression(decl, loc);
         }
+      else if (this->expr_->is_constant())
+        {
+          std::string var_name(gogo->initializer_name());
+          std::string asm_name(go_selectively_encode_id(var_name));
+          Bvariable* decl =
+              gogo->backend()->implicit_variable(var_name, asm_name, btype,
+                                                 true, true, false, 0);
+          gogo->backend()->implicit_variable_set_init(decl, var_name, btype,
+                                                      true, true, false,
+                                                      bexpr);
+          bexpr = gogo->backend()->var_expression(decl, loc);
+        }
 
       go_assert(!this->create_temp_ || this->expr_->is_variable());
       ret = gogo->backend()->address_expression(bexpr, loc);