Avoid using the RHS of an assignment twice.
authorEric Anholt <eric@anholt.net>
Wed, 23 Jun 2010 21:51:14 +0000 (14:51 -0700)
committerIan Romanick <ian.d.romanick@intel.com>
Wed, 23 Jun 2010 22:20:29 +0000 (15:20 -0700)
This would fix double-evaluation of assignment RHS expressions,
including possible side effects.

ast_to_hir.cpp

index c059abbff6a717eb61ead720200f271f465fbf47..61e0d01a900a6fb86fba70929e5eb61f14ac7633 100644 (file)
@@ -509,10 +509,26 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
       }
    }
 
-   ir_instruction *tmp = new ir_assignment(lhs, rhs, NULL);
-   instructions->push_tail(tmp);
+   /* Most callers of do_assignment (assign, add_assign, pre_inc/dec,
+    * but not post_inc) need the converted assigned value as an rvalue
+    * to handle things like:
+    *
+    * i = j += 1;
+    *
+    * So we always just store the computed value being assigned to a
+    * temporary and return a deref of that temporary.  If the rvalue
+    * ends up not being used, the temp will get copy-propagated out.
+    */
+   ir_variable *var = new ir_variable(rhs->type, "assignment_tmp");
+   instructions->push_tail(new ir_assignment(new ir_dereference_variable(var),
+                                            rhs,
+                                            NULL));
+
+   instructions->push_tail(new ir_assignment(lhs,
+                                            new ir_dereference_variable(var),
+                                            NULL));
 
-   return rhs;
+   return new ir_dereference_variable(var);
 }