1 /* valaccodeassignmentmodule.vala
3 * Copyright (C) 2006-2010 Jürg Billeter
4 * Copyright (C) 2006-2008 Raffaele Sandrini
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 * Jürg Billeter <j@bitron.ch>
22 * Raffaele Sandrini <raffaele@sandrini.ch>
28 * The link between an assignment and generated code.
30 public class Vala
.CCodeAssignmentModule
: CCodeMemberAccessModule
{
31 TargetValue
emit_simple_assignment (Assignment assignment
) {
32 Variable variable
= (Variable
) assignment
.left
.symbol_reference
;
34 if (requires_destroy (assignment
.left
.value_type
)) {
36 ccode
.add_expression (destroy_value (assignment
.left
.target_value
));
39 if (assignment
.operator
== AssignmentOperator
.SIMPLE
) {
40 store_value (assignment
.left
.target_value
, assignment
.right
.target_value
);
42 CCodeAssignmentOperator cop
;
43 if (assignment
.operator
== AssignmentOperator
.BITWISE_OR
) {
44 cop
= CCodeAssignmentOperator
.BITWISE_OR
;
45 } else if (assignment
.operator
== AssignmentOperator
.BITWISE_AND
) {
46 cop
= CCodeAssignmentOperator
.BITWISE_AND
;
47 } else if (assignment
.operator
== AssignmentOperator
.BITWISE_XOR
) {
48 cop
= CCodeAssignmentOperator
.BITWISE_XOR
;
49 } else if (assignment
.operator
== AssignmentOperator
.ADD
) {
50 cop
= CCodeAssignmentOperator
.ADD
;
51 } else if (assignment
.operator
== AssignmentOperator
.SUB
) {
52 cop
= CCodeAssignmentOperator
.SUB
;
53 } else if (assignment
.operator
== AssignmentOperator
.MUL
) {
54 cop
= CCodeAssignmentOperator
.MUL
;
55 } else if (assignment
.operator
== AssignmentOperator
.DIV
) {
56 cop
= CCodeAssignmentOperator
.DIV
;
57 } else if (assignment
.operator
== AssignmentOperator
.PERCENT
) {
58 cop
= CCodeAssignmentOperator
.PERCENT
;
59 } else if (assignment
.operator
== AssignmentOperator
.SHIFT_LEFT
) {
60 cop
= CCodeAssignmentOperator
.SHIFT_LEFT
;
61 } else if (assignment
.operator
== AssignmentOperator
.SHIFT_RIGHT
) {
62 cop
= CCodeAssignmentOperator
.SHIFT_RIGHT
;
64 assert_not_reached ();
67 CCodeExpression codenode
= new
CCodeAssignment (get_cvalue (assignment
.left
), get_cvalue (assignment
.right
), cop
);
68 ccode
.add_expression (codenode
);
71 if (assignment
.left
.value_type is ArrayType
&& (((ArrayType
) assignment
.left
.value_type
).inline_allocated
)) {
72 return load_variable (variable
, assignment
.left
.target_value
);
74 return store_temp_value (assignment
.left
.target_value
, assignment
);
78 public override void visit_assignment (Assignment assignment
) {
79 if (assignment
.left
.error
|| assignment
.right
.error
) {
80 assignment
.error
= true;
84 if (assignment
.left
.symbol_reference is Property
) {
85 var ma
= assignment
.left as MemberAccess
;
86 var prop
= (Property
) assignment
.left
.symbol_reference
;
88 store_property (prop
, ma
.inner
, assignment
.right
.target_value
);
89 assignment
.target_value
= assignment
.right
.target_value
;
90 } else if (assignment
.left
.symbol_reference is Variable
&& is_simple_struct_creation ((Variable
) assignment
.left
.symbol_reference
, assignment
.right
)) {
91 // delegate to visit_object_creation_expression
93 assignment
.target_value
= emit_simple_assignment (assignment
);
97 public override void store_value (TargetValue lvalue
, TargetValue value
) {
98 var array_type
= lvalue
.value_type as ArrayType
;
100 if (array_type
!= null && array_type
.fixed_length
) {
101 cfile
.add_include ("string.h");
103 // it is necessary to use memcpy for fixed-length (stack-allocated) arrays
104 // simple assignments do not work in C
105 var sizeof_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("sizeof"));
106 sizeof_call
.add_argument (new
CCodeIdentifier (get_ccode_name (array_type
.element_type
)));
107 var size
= new
CCodeBinaryExpression (CCodeBinaryOperator
.MUL
, get_ccodenode (array_type
.length
), sizeof_call
);
109 var ccopy
= new
CCodeFunctionCall (new
CCodeIdentifier ("memcpy"));
110 ccopy
.add_argument (get_cvalue_ (lvalue
));
111 ccopy
.add_argument (get_cvalue_ (value
));
112 ccopy
.add_argument (size
);
113 ccode
.add_expression (ccopy
);
118 var cexpr
= get_cvalue_ (value
);
119 if (get_ctype (lvalue
) != null) {
120 cexpr
= new
CCodeCastExpression (cexpr
, get_ctype (lvalue
));
123 ccode
.add_assignment (get_cvalue_ (lvalue
), cexpr
);
125 if (array_type
!= null && ((GLibValue
) lvalue
).array_length_cvalues
!= null) {
126 var glib_value
= (GLibValue
) value
;
127 if (glib_value
.array_length_cvalues
!= null) {
128 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
129 ccode
.add_assignment (get_array_length_cvalue (lvalue
, dim
), get_array_length_cvalue (value
, dim
));
131 } else if (glib_value
.array_null_terminated
) {
132 requires_array_length
= true;
133 var len_call
= new
CCodeFunctionCall (new
CCodeIdentifier ("_vala_array_length"));
134 len_call
.add_argument (get_cvalue_ (value
));
136 ccode
.add_assignment (get_array_length_cvalue (lvalue
, 1), len_call
);
138 for (int dim
= 1; dim
<= array_type
.rank
; dim
++) {
139 ccode
.add_assignment (get_array_length_cvalue (lvalue
, dim
), new
CCodeConstant ("-1"));
143 if (array_type
.rank
== 1 && get_array_size_cvalue (lvalue
) != null) {
144 ccode
.add_assignment (get_array_size_cvalue (lvalue
), get_array_length_cvalue (lvalue
, 1));
148 var delegate_type
= lvalue
.value_type as DelegateType
;
149 if (delegate_type
!= null && delegate_type
.delegate_symbol
.has_target
) {
150 if (get_delegate_target_cvalue (lvalue
) != null) {
151 ccode
.add_assignment (get_delegate_target_cvalue (lvalue
), get_delegate_target_cvalue (value
));
152 var lvalue_destroy_notify
= get_delegate_target_destroy_notify_cvalue (lvalue
);
153 var rvalue_destroy_notify
= get_delegate_target_destroy_notify_cvalue (value
);
154 if (lvalue_destroy_notify
!= null) {
155 if (rvalue_destroy_notify
!= null) {
156 ccode
.add_assignment (lvalue_destroy_notify
, rvalue_destroy_notify
);
158 ccode
.add_assignment (lvalue_destroy_notify
, new
CCodeConstant ("NULL"));
165 public override void store_local (LocalVariable local
, TargetValue value
, bool initializer
) {
166 if (!initializer
&& requires_destroy (local
.variable_type
)) {
167 /* unref old value */
168 ccode
.add_expression (destroy_local (local
));
171 store_value (get_local_cvalue (local
), value
);
174 public override void store_parameter (Parameter param
, TargetValue _value
, bool capturing_parameter
= false) {
177 bool capturing_parameter_in_coroutine
= capturing_parameter
&& is_in_coroutine ();
179 var param_type
= param
.variable_type
.copy ();
180 if (param
.captured
|| is_in_coroutine ()) {
181 if (!param_type
.value_owned
&& !no_implicit_copy (param_type
)) {
182 // parameter value has been implicitly copied into a heap data structure
183 // treat parameter as owned
184 param_type
.value_owned
= true;
186 var old_coroutine
= is_in_coroutine ();
188 current_method
.coroutine
= false;
191 if (requires_copy (param_type
) && !capturing_parameter_in_coroutine
) {
192 // do not copy value when capturing parameter in coroutine
193 // as the value was already copied on coroutine initialization
194 value
= copy_value (value
, param
);
198 current_method
.coroutine
= true;
203 if (requires_destroy (param_type
)) {
204 /* unref old value */
205 ccode
.add_expression (destroy_parameter (param
));
208 store_value (get_parameter_cvalue (param
), value
);
211 public override void store_field (Field field
, TargetValue? instance
, TargetValue value
) {
212 var lvalue
= get_field_cvalue (field
, instance
);
213 var type
= lvalue
.value_type
;
214 if (lvalue
.actual_value_type
!= null) {
215 type
= lvalue
.actual_value_type
;
217 if (requires_destroy (type
)) {
218 /* unref old value */
219 ccode
.add_expression (destroy_field (field
, instance
));
222 store_value (lvalue
, value
);