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
, assignment
.source_reference
);
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
, SourceReference? source_reference
= null) {
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 var lvalue_target
= get_delegate_target_cvalue (lvalue
);
151 var rvalue_target
= get_delegate_target_cvalue (value
);
152 if (lvalue_target
!= null) {
153 if (rvalue_target
!= null) {
154 ccode
.add_assignment (lvalue_target
, rvalue_target
);
156 Report
.error (source_reference
, "Assigning delegate without required target in scope");
157 ccode
.add_assignment (lvalue_target
, new
CCodeInvalidExpression ());
159 var lvalue_destroy_notify
= get_delegate_target_destroy_notify_cvalue (lvalue
);
160 var rvalue_destroy_notify
= get_delegate_target_destroy_notify_cvalue (value
);
161 if (lvalue_destroy_notify
!= null) {
162 if (rvalue_destroy_notify
!= null) {
163 ccode
.add_assignment (lvalue_destroy_notify
, rvalue_destroy_notify
);
165 ccode
.add_assignment (lvalue_destroy_notify
, new
CCodeConstant ("NULL"));
172 public override void store_local (LocalVariable local
, TargetValue value
, bool initializer
, SourceReference? source_reference
= null) {
173 if (!initializer
&& requires_destroy (local
.variable_type
)) {
174 /* unref old value */
175 ccode
.add_expression (destroy_local (local
));
178 store_value (get_local_cvalue (local
), value
, source_reference
);
181 public override void store_parameter (Parameter param
, TargetValue _value
, bool capturing_parameter
= false, SourceReference? source_reference
= null) {
184 bool capturing_parameter_in_coroutine
= capturing_parameter
&& is_in_coroutine ();
186 var param_type
= param
.variable_type
.copy ();
187 if (param
.captured
|| is_in_coroutine ()) {
188 if (!param_type
.value_owned
&& !no_implicit_copy (param_type
)) {
189 // parameter value has been implicitly copied into a heap data structure
190 // treat parameter as owned
191 param_type
.value_owned
= true;
193 var old_coroutine
= is_in_coroutine ();
195 current_method
.coroutine
= false;
198 if (requires_copy (param_type
) && !capturing_parameter_in_coroutine
) {
199 // do not copy value when capturing parameter in coroutine
200 // as the value was already copied on coroutine initialization
201 value
= copy_value (value
, param
);
205 current_method
.coroutine
= true;
210 if (requires_destroy (param_type
)) {
211 /* unref old value */
212 ccode
.add_expression (destroy_parameter (param
));
215 store_value (get_parameter_cvalue (param
), value
, source_reference
);
218 public override void store_field (Field field
, TargetValue? instance
, TargetValue value
, SourceReference? source_reference
= null) {
219 var lvalue
= get_field_cvalue (field
, instance
);
220 var type
= lvalue
.value_type
;
221 if (lvalue
.actual_value_type
!= null) {
222 type
= lvalue
.actual_value_type
;
224 if (get_ccode_delegate_target (field
) && requires_destroy (type
)) {
225 /* unref old value */
226 ccode
.add_expression (destroy_field (field
, instance
));
229 store_value (lvalue
, value
, source_reference
);