This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fix a nested function lowering bug


We were failing to properly lower assignments where the substitution
happens on the lhs.  E.g. from

	x = y & z

we'd get

	FRAME.x = y & z

instead of

	t.1 = y & z
	FRAME.x = t.1

which is what we would have gotten had FRAME.x been in the source.

Tested on i686-linux.



r~


        * tree-nested.c (save_tmp_var): New.
        (struct walk_stmt_info): Add is_lhs.
        (walk_stmts) <MODIFY_EXPR>: Be more accurate with setting of
        val_only; set is_lhs.
        (convert_nonlocal_reference): Use save_tmp_var when is_lhs;
        clear is_lhs when appropriate.
        (convert_local_reference): Likewise.

Index: tree-nested.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-nested.c,v
retrieving revision 2.22
diff -c -p -d -u -r2.22 tree-nested.c
--- tree-nested.c	30 Nov 2004 03:52:37 -0000	2.22
+++ tree-nested.c	18 Dec 2004 18:54:35 -0000
@@ -376,6 +376,23 @@ tsi_gimplify_val (struct nesting_info *i
     return init_tmp_var (info, exp, tsi);
 }
 
+/* Similarly, but copy from the temporary and insert the statement
+   after the iterator.  */
+
+static tree
+save_tmp_var (struct nesting_info *info, tree exp,
+	      tree_stmt_iterator *tsi)
+{
+  tree t, stmt;
+
+  t = create_tmp_var_for (info, TREE_TYPE (exp), NULL);
+  stmt = build (MODIFY_EXPR, TREE_TYPE (t), exp, t);
+  SET_EXPR_LOCUS (stmt, EXPR_LOCUS (tsi_stmt (*tsi)));
+  tsi_link_after (tsi, stmt, TSI_SAME_STMT);
+
+  return t;
+}
+
 /* Build or return the type used to represent a nested function trampoline.  */
 
 static GTY(()) tree trampoline_type;
@@ -517,6 +534,7 @@ struct walk_stmt_info
   tree_stmt_iterator tsi;
   struct nesting_info *info;
   bool val_only;
+  bool is_lhs;
   bool changed;
 };
 
@@ -567,12 +585,18 @@ walk_stmts (struct walk_stmt_info *wi, t
       break;
 
     case MODIFY_EXPR:
-      /* The immediate arguments of a MODIFY_EXPR may use COMPONENT_REF.  */
-      wi->val_only = false;
-      walk_tree (&TREE_OPERAND (t, 0), wi->callback, wi, NULL);
-      wi->val_only = false;
+      /* A formal temporary lhs may use a COMPONENT_REF rhs.  */
+      wi->val_only = !is_gimple_formal_tmp_var (TREE_OPERAND (t, 0));
       walk_tree (&TREE_OPERAND (t, 1), wi->callback, wi, NULL);
+
+      /* If the rhs is appropriate for a memory, we may use a
+	 COMPONENT_REF on the lhs.  */
+      wi->val_only = !is_gimple_mem_rhs (TREE_OPERAND (t, 1));
+      wi->is_lhs = true;
+      walk_tree (&TREE_OPERAND (t, 0), wi->callback, wi, NULL);
+
       wi->val_only = true;
+      wi->is_lhs = false;
       break;
 
     default:
@@ -789,8 +813,14 @@ convert_nonlocal_reference (tree *tp, in
 	      x = init_tmp_var (info, x, &wi->tsi);
 	      x = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (x)), x);
 	    }
+
 	  if (wi->val_only)
-	    x = init_tmp_var (info, x, &wi->tsi);
+	    {
+	      if (wi->is_lhs)
+		x = save_tmp_var (info, x, &wi->tsi);
+	      else
+		x = init_tmp_var (info, x, &wi->tsi);
+	    }
 
 	  *tp = x;
 	}
@@ -802,6 +832,7 @@ convert_nonlocal_reference (tree *tp, in
 	{
 	  *walk_subtrees = 1;
 	  wi->val_only = true;
+	  wi->is_lhs = false;
 	}
       break;
 
@@ -818,8 +849,9 @@ convert_nonlocal_reference (tree *tp, in
       {
 	bool save_val_only = wi->val_only;
 
-	wi->changed = false;
 	wi->val_only = false;
+	wi->is_lhs = false;
+	wi->changed = false;
 	walk_tree (&TREE_OPERAND (t, 0), convert_nonlocal_reference, wi, NULL);
 	wi->val_only = true;
 
@@ -848,6 +880,7 @@ convert_nonlocal_reference (tree *tp, in
 	 anything that describes the references.  Otherwise, we lose track
 	 of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value.  */
       wi->val_only = true;
+      wi->is_lhs = false;
       for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
 	{
 	  if (TREE_CODE (t) == COMPONENT_REF)
@@ -880,6 +913,7 @@ convert_nonlocal_reference (tree *tp, in
 	{
 	  *walk_subtrees = 1;
           wi->val_only = true;
+	  wi->is_lhs = false;
 	}
       break;
     }
@@ -922,8 +956,15 @@ convert_local_reference (tree *tp, int *
 	  wi->changed = true;
 
 	  x = get_frame_field (info, info->context, field, &wi->tsi);
+
 	  if (wi->val_only)
-	    x = init_tmp_var (info, x, &wi->tsi);
+	    {
+	      if (wi->is_lhs)
+		x = save_tmp_var (info, x, &wi->tsi);
+	      else
+		x = init_tmp_var (info, x, &wi->tsi);
+	    }
+
 	  *tp = x;
 	}
       break;
@@ -932,8 +973,9 @@ convert_local_reference (tree *tp, int *
       {
 	bool save_val_only = wi->val_only;
 
-	wi->changed = false;
 	wi->val_only = false;
+	wi->is_lhs = false;
+	wi->changed = false;
 	walk_tree (&TREE_OPERAND (t, 0), convert_local_reference, wi, NULL);
 	wi->val_only = save_val_only;
 
@@ -963,6 +1005,7 @@ convert_local_reference (tree *tp, int *
 	 anything that describes the references.  Otherwise, we lose track
 	 of whether a NOP_EXPR or VIEW_CONVERT_EXPR needs a simple value.  */
       wi->val_only = true;
+      wi->is_lhs = false;
       for (; handled_component_p (t); tp = &TREE_OPERAND (t, 0), t = *tp)
 	{
 	  if (TREE_CODE (t) == COMPONENT_REF)
@@ -995,6 +1038,7 @@ convert_local_reference (tree *tp, int *
 	{
 	  *walk_subtrees = 1;
 	  wi->val_only = true;
+	  wi->is_lhs = false;
 	}
       break;
     }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]