codegen: Use destroy_variable in store_*
[vala-lang.git] / codegen / valadovaassignmentmodule.vala
blobe2123144a44f9d6ecd7ccc9a6181134d1178e4f8
1 /* valadovaassignmentmodule.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Jürg Billeter <j@bitron.ch>
23 /**
24 * The link between an assignment and generated code.
26 public class Vala.DovaAssignmentModule : DovaMemberAccessModule {
27 CCodeExpression? emit_simple_assignment (Assignment assignment) {
28 CCodeExpression rhs = get_cvalue (assignment.right);
29 CCodeExpression lhs = (CCodeExpression) get_ccodenode (assignment.left);
31 bool unref_old = requires_destroy (assignment.left.value_type);
33 if (unref_old) {
34 if (!is_pure_ccode_expression (lhs)) {
35 /* Assign lhs to temp var to avoid repeating side effect */
36 var lhs_value_type = assignment.left.value_type.copy ();
37 string lhs_temp_name = "_tmp%d_".printf (next_temp_var_id++);
38 var lhs_temp = new LocalVariable (lhs_value_type, "*" + lhs_temp_name);
39 emit_temp_var (lhs_temp);
40 ccode.add_assignment (get_variable_cexpression (lhs_temp_name), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, lhs));
41 lhs = new CCodeParenthesizedExpression (new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (lhs_temp_name)));
44 var temp_decl = get_temp_variable (assignment.left.value_type);
45 emit_temp_var (temp_decl);
46 ccode.add_assignment (get_variable_cexpression (temp_decl.name), rhs);
47 if (unref_old) {
48 /* unref old value */
49 ccode.add_expression (get_unref_expression (lhs, assignment.left.value_type, assignment.left));
52 rhs = get_variable_cexpression (temp_decl.name);
55 var cop = CCodeAssignmentOperator.SIMPLE;
56 if (assignment.operator == AssignmentOperator.BITWISE_OR) {
57 cop = CCodeAssignmentOperator.BITWISE_OR;
58 } else if (assignment.operator == AssignmentOperator.BITWISE_AND) {
59 cop = CCodeAssignmentOperator.BITWISE_AND;
60 } else if (assignment.operator == AssignmentOperator.BITWISE_XOR) {
61 cop = CCodeAssignmentOperator.BITWISE_XOR;
62 } else if (assignment.operator == AssignmentOperator.ADD) {
63 cop = CCodeAssignmentOperator.ADD;
64 } else if (assignment.operator == AssignmentOperator.SUB) {
65 cop = CCodeAssignmentOperator.SUB;
66 } else if (assignment.operator == AssignmentOperator.MUL) {
67 cop = CCodeAssignmentOperator.MUL;
68 } else if (assignment.operator == AssignmentOperator.DIV) {
69 cop = CCodeAssignmentOperator.DIV;
70 } else if (assignment.operator == AssignmentOperator.PERCENT) {
71 cop = CCodeAssignmentOperator.PERCENT;
72 } else if (assignment.operator == AssignmentOperator.SHIFT_LEFT) {
73 cop = CCodeAssignmentOperator.SHIFT_LEFT;
74 } else if (assignment.operator == AssignmentOperator.SHIFT_RIGHT) {
75 cop = CCodeAssignmentOperator.SHIFT_RIGHT;
78 CCodeExpression codenode = new CCodeAssignment (lhs, rhs, cop);
80 ccode.add_expression (codenode);
82 if (assignment.parent_node is ExpressionStatement) {
83 return null;
84 } else {
85 return lhs;
89 CCodeExpression? emit_fixed_length_array_assignment (Assignment assignment, ArrayType array_type) {
90 CCodeExpression rhs = get_cvalue (assignment.right);
91 CCodeExpression lhs = (CCodeExpression) get_ccodenode (assignment.left);
93 // it is necessary to use memcpy for fixed-length (stack-allocated) arrays
94 // simple assignments do not work in C
95 var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
96 sizeof_call.add_argument (new CCodeIdentifier (array_type.element_type.get_cname ()));
97 var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, new CCodeConstant ("%d".printf (array_type.length)), sizeof_call);
98 var ccopy = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
99 ccopy.add_argument (lhs);
100 ccopy.add_argument (rhs);
101 ccopy.add_argument (size);
103 ccode.add_expression (ccopy);
105 if (assignment.parent_node is ExpressionStatement) {
106 return null;
107 } else {
108 return lhs;
112 public override void visit_assignment (Assignment assignment) {
113 if (assignment.left.error || assignment.right.error) {
114 assignment.error = true;
115 return;
118 if (assignment.left.symbol_reference is Property) {
119 var ma = assignment.left as MemberAccess;
120 var prop = (Property) assignment.left.symbol_reference;
122 store_property (prop, ma.inner, assignment.right.target_value);
124 set_cvalue (assignment, get_ccodenode (assignment.right));
125 } else {
126 var array_type = assignment.left.value_type as ArrayType;
127 if (array_type != null && array_type.fixed_length) {
128 set_cvalue (assignment, emit_fixed_length_array_assignment (assignment, array_type));
129 } else {
130 set_cvalue (assignment, emit_simple_assignment (assignment));
135 void store_variable (Variable variable, TargetValue lvalue, TargetValue value, bool initializer) {
136 if (!initializer && requires_destroy (variable.variable_type)) {
137 /* unref old value */
138 ccode.add_expression (destroy_value (lvalue));
141 ccode.add_assignment (get_cvalue_ (lvalue), get_cvalue_ (value));
144 public override void store_local (LocalVariable local, TargetValue value, bool initializer) {
145 store_variable (local, get_local_cvalue (local), value, initializer);
148 public override void store_parameter (Parameter param, TargetValue value) {
149 store_variable (param, get_parameter_cvalue (param), value, false);
152 public override void store_field (Field field, Expression? instance, TargetValue value) {
153 store_variable (field, get_field_cvalue (field, instance), value, false);