Patchwork [gccgo] Always copy slice constructor in function

login
register
mail settings
Submitter Ian Taylor
Date June 30, 2010, 9:53 p.m.
Message ID <mcrmxucyypp.fsf@google.com>
Download mbox | patch
Permalink /patch/57456/
State New
Headers show

Comments

Ian Taylor - June 30, 2010, 9:53 p.m.
When a slice constructor is used in a function, as in a := []byte{0},
the program must always create a new copy even if the values are
constant.  This is not necessary outside of a function, as in that case
the value will only be built once.  This patch corrects gccgo to make a
copy when required.  Committed to gccgo branch.

Ian

Patch

diff -r 7c31cf858582 go/expressions.cc
--- a/go/expressions.cc	Wed Jun 30 14:29:56 2010 -0700
+++ b/go/expressions.cc	Wed Jun 30 14:47:58 2010 -0700
@@ -11055,9 +11055,10 @@ 
   if (values == error_mark_node)
     return error_mark_node;
 
-  tree space;
-  tree set;
-  if (TREE_CONSTANT(values))
+  bool is_constant_initializer = TREE_CONSTANT(values);
+  bool is_in_function = context->function() != NULL;
+
+  if (is_constant_initializer)
     {
       tree tmp = build_decl(this->location(), VAR_DECL,
 			    create_tmp_var_name("C"), TREE_TYPE(values));
@@ -11065,11 +11066,27 @@ 
       TREE_PUBLIC(tmp) = 0;
       TREE_STATIC(tmp) = 1;
       DECL_ARTIFICIAL(tmp) = 1;
-      // We can't make the decl readonly, because the program can
-      // change the values in the array.
+      if (is_in_function)
+	{
+	  // If this is not a function, we will only initialize the
+	  // value once, so we can use this directly rather than
+	  // copying it.  In that case we can't make it read-only,
+	  // because the program is permitted to change it.
+	  TREE_READONLY(tmp) = 1;
+	  TREE_CONSTANT(tmp) = 1;
+	}
       DECL_INITIAL(tmp) = values;
       rest_of_decl_compilation(tmp, 1, 0);
-      space = build_fold_addr_expr(tmp);
+      values = tmp;
+    }
+
+  tree space;
+  tree set;
+  if (!is_in_function && is_constant_initializer)
+    {
+      // Outside of a function, we know the initializer will only run
+      // once.
+      space = build_fold_addr_expr(values);
       set = NULL_TREE;
     }
   else
@@ -11109,7 +11126,7 @@ 
   elt->value = fold_convert(TREE_TYPE(field), length_tree);
 
   tree constructor = build_constructor(type_tree, init);
-  if (TREE_CONSTANT(values))
+  if (!is_in_function && is_constant_initializer)
     TREE_CONSTANT(constructor) = 1;
 
   if (set == NULL_TREE)