LCOV - code coverage report
Current view: top level - codegen - valaccodeassignmentmodule.vala (source / functions) Coverage Total Hit
Test: vala 0.57.0.298-a8cae1 Lines: 95.3 % 129 123
Test Date: 2024-04-25 11:34:36 Functions: - 0 0

            Line data    Source code
       1              : /* valaccodeassignmentmodule.vala
       2              :  *
       3              :  * Copyright (C) 2006-2010  Jürg Billeter
       4              :  * Copyright (C) 2006-2008  Raffaele Sandrini
       5              :  *
       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.
      10              : 
      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.
      15              : 
      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
      19              :  *
      20              :  * Author:
      21              :  *      Jürg Billeter <j@bitron.ch>
      22              :  *      Raffaele Sandrini <raffaele@sandrini.ch>
      23              :  */
      24              : 
      25              : using GLib;
      26              : 
      27              : /**
      28              :  * The link between an assignment and generated code.
      29              :  */
      30         2930 : public class Vala.CCodeAssignmentModule : CCodeMemberAccessModule {
      31          202 :         TargetValue emit_simple_assignment (Assignment assignment) {
      32          202 :                 if (requires_destroy (assignment.left.value_type)) {
      33              :                         /* unref old value */
      34           20 :                         ccode.add_expression (destroy_value (assignment.left.target_value));
      35              :                 }
      36              : 
      37          281 :                 if (assignment.operator == AssignmentOperator.SIMPLE) {
      38          123 :                         store_value (assignment.left.target_value, assignment.right.target_value, assignment.source_reference);
      39              :                 } else {
      40              :                         CCodeAssignmentOperator cop;
      41              : 
      42           79 :                         switch (assignment.operator) {
      43              :                         case AssignmentOperator.BITWISE_OR: cop = CCodeAssignmentOperator.BITWISE_OR; break;
      44            3 :                         case AssignmentOperator.BITWISE_AND: cop = CCodeAssignmentOperator.BITWISE_AND; break;
      45            3 :                         case AssignmentOperator.BITWISE_XOR: cop = CCodeAssignmentOperator.BITWISE_XOR; break;
      46           40 :                         case AssignmentOperator.ADD: cop = CCodeAssignmentOperator.ADD; break;
      47            9 :                         case AssignmentOperator.SUB: cop = CCodeAssignmentOperator.SUB; break;
      48            5 :                         case AssignmentOperator.MUL: cop = CCodeAssignmentOperator.MUL; break;
      49            5 :                         case AssignmentOperator.DIV: cop = CCodeAssignmentOperator.DIV; break;
      50              :                         case AssignmentOperator.PERCENT:
      51              :                                 // FIXME Code duplication with CCodeBaseModule.visit_binary_expression()
      52        40557 :                                 var cleft = get_cvalue (assignment.left);
      53            5 :                                 var cright = get_cvalue (assignment.right);
      54            6 :                                 if (assignment.value_type.equals (double_type)) {
      55            1 :                                         cfile.add_include ("math.h");
      56            1 :                                         var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmod"));
      57            1 :                                         ccall.add_argument (cleft);
      58            1 :                                         ccall.add_argument (cright);
      59            1 :                                         set_cvalue (assignment.right, ccall);
      60            1 :                                         cop = CCodeAssignmentOperator.SIMPLE;
      61            5 :                                 } else if (assignment.value_type.equals (float_type)) {
      62            1 :                                         cfile.add_include ("math.h");
      63            1 :                                         var ccall = new CCodeFunctionCall (new CCodeIdentifier ("fmodf"));
      64            1 :                                         ccall.add_argument (cleft);
      65            1 :                                         ccall.add_argument (cright);
      66            1 :                                         set_cvalue (assignment.right, ccall);
      67            1 :                                         cop = CCodeAssignmentOperator.SIMPLE;
      68              :                                 } else {
      69              :                                         cop = CCodeAssignmentOperator.PERCENT;
      70              :                                 }
      71            5 :                                 break;
      72            3 :                         case AssignmentOperator.SHIFT_LEFT: cop = CCodeAssignmentOperator.SHIFT_LEFT; break;
      73            3 :                         case AssignmentOperator.SHIFT_RIGHT: cop = CCodeAssignmentOperator.SHIFT_RIGHT; break;
      74            0 :                         default: assert_not_reached ();
      75              :                         }
      76              : 
      77           79 :                         CCodeExpression codenode = new CCodeAssignment (get_cvalue (assignment.left), get_cvalue (assignment.right), cop);
      78           79 :                         ccode.add_expression (codenode);
      79              :                 }
      80              : 
      81          202 :                 if (assignment.left.value_type is ArrayType && (((ArrayType) assignment.left.value_type).inline_allocated)) {
      82            0 :                         unowned Variable variable = (Variable) assignment.left.symbol_reference;
      83            0 :                         return load_variable (variable, assignment.left.target_value);
      84              :                 } else {
      85         3000 :                         return assignment.left.target_value;
      86              :                 }
      87              :         }
      88              : 
      89         1002 :         public override void visit_assignment (Assignment assignment) {
      90         1002 :                 if (assignment.left.error || assignment.right.error) {
      91            0 :                         assignment.error = true;
      92            0 :                         return;
      93              :                 }
      94              : 
      95         1002 :                 if (assignment.left.symbol_reference is Property) {
      96          797 :                         unowned MemberAccess ma = (MemberAccess) assignment.left;
      97          797 :                         unowned Property prop = (Property) assignment.left.symbol_reference;
      98              : 
      99          797 :                         store_property (prop, ma.inner, assignment.right.target_value);
     100          797 :                         assignment.target_value = assignment.right.target_value;
     101          205 :                 } else if (assignment.left.symbol_reference is Variable && is_simple_struct_creation ((Variable) assignment.left.symbol_reference, assignment.right)) {
     102              :                         // delegate to visit_object_creation_expression
     103              :                 } else {
     104          202 :                         assignment.target_value = emit_simple_assignment (assignment);
     105              :                 }
     106              :         }
     107              : 
     108        81121 :         public override void store_value (TargetValue lvalue, TargetValue value, SourceReference? source_reference = null) {
     109        45309 :                 var array_type = lvalue.value_type as ArrayType;
     110              : 
     111         2517 :                 if (array_type != null && array_type.fixed_length) {
     112           29 :                         cfile.add_include ("string.h");
     113              : 
     114              :                         // it is necessary to use memcpy for fixed-length (stack-allocated) arrays
     115              :                         // simple assignments do not work in C
     116           29 :                         var sizeof_call = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
     117           29 :                         sizeof_call.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
     118           29 :                         var size = new CCodeBinaryExpression (CCodeBinaryOperator.MUL, get_ccodenode (array_type.length), sizeof_call);
     119              : 
     120           29 :                         var ccopy = new CCodeFunctionCall (new CCodeIdentifier ("memcpy"));
     121           29 :                         ccopy.add_argument (get_cvalue_ (lvalue));
     122           29 :                         ccopy.add_argument (get_cvalue_ (value));
     123           29 :                         ccopy.add_argument (size);
     124           29 :                         ccode.add_expression (ccopy);
     125              : 
     126           29 :                         return;
     127              :                 }
     128              : 
     129        40546 :                 var cexpr = get_cvalue_ (value);
     130        40546 :                 if (get_ctype (lvalue) != null) {
     131            4 :                         cexpr = new CCodeCastExpression (cexpr, get_ctype (lvalue));
     132              :                 }
     133              : 
     134        40546 :                 ccode.add_assignment (get_cvalue_ (lvalue), cexpr);
     135              : 
     136        43007 :                 if (array_type != null && ((GLibValue) lvalue).array_length_cvalues != null) {
     137         2461 :                         var glib_value = (GLibValue) value;
     138         2461 :                         if (glib_value.array_length_cvalues != null) {
     139         4969 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     140         2526 :                                         ccode.add_assignment (get_array_length_cvalue (lvalue, dim), get_array_length_cvalue (value, dim));
     141              :                                 }
     142           20 :                         } else if (glib_value.array_null_terminated) {
     143            2 :                                 requires_array_length = true;
     144            2 :                                 var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
     145            2 :                                 len_call.add_argument (get_cvalue_ (value));
     146              : 
     147            2 :                                 ccode.add_assignment (get_array_length_cvalue (lvalue, 1), len_call);
     148              :                         } else {
     149           32 :                                 for (int dim = 1; dim <= array_type.rank; dim++) {
     150           16 :                                         ccode.add_assignment (get_array_length_cvalue (lvalue, dim), new CCodeConstant ("-1"));
     151              :                                 }
     152              :                         }
     153              : 
     154         2461 :                         if (array_type.rank == 1 && get_array_size_cvalue (lvalue) != null) {
     155          495 :                                 ccode.add_assignment (get_array_size_cvalue (lvalue), get_array_length_cvalue (lvalue, 1));
     156              :                         }
     157              :                 }
     158              : 
     159        40546 :                 var delegate_type = lvalue.value_type as DelegateType;
     160        41283 :                 if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
     161          236 :                         var lvalue_target = get_delegate_target_cvalue (lvalue);
     162          236 :                         var rvalue_target = get_delegate_target_cvalue (value);
     163          464 :                         if (lvalue_target != null) {
     164          228 :                                 if (rvalue_target != null) {
     165          227 :                                         ccode.add_assignment (lvalue_target, rvalue_target);
     166              :                                 } else {
     167            1 :                                         Report.error (source_reference, "Assigning delegate without required target in scope");
     168            1 :                                         ccode.add_assignment (lvalue_target, new CCodeInvalidExpression ());
     169              :                                 }
     170          228 :                                 var lvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue (lvalue);
     171          228 :                                 var rvalue_destroy_notify = get_delegate_target_destroy_notify_cvalue (value);
     172          228 :                                 if (lvalue_destroy_notify != null) {
     173          133 :                                         if (rvalue_destroy_notify != null) {
     174          133 :                                                 ccode.add_assignment (lvalue_destroy_notify, rvalue_destroy_notify);
     175              :                                         } else {
     176            0 :                                                 ccode.add_assignment (lvalue_destroy_notify, new CCodeConstant ("NULL"));
     177              :                                         }
     178              :                                 }
     179              :                         }
     180              :                 }
     181              :         }
     182              : 
     183         9035 :         public override void store_local (LocalVariable local, TargetValue value, bool initializer, SourceReference? source_reference = null) {
     184         9035 :                 if (!initializer && requires_destroy (local.variable_type)) {
     185              :                         /* unref old value */
     186          817 :                         ccode.add_expression (destroy_local (local));
     187              :                 }
     188              : 
     189         9035 :                 store_value (get_local_cvalue (local), value, source_reference);
     190              :         }
     191              : 
     192          674 :         public override void store_parameter (Parameter param, TargetValue _value, bool capturing_parameter = false, SourceReference? source_reference = null) {
     193          337 :                 var value = _value;
     194              : 
     195          337 :                 bool capturing_parameter_in_coroutine = capturing_parameter && is_in_coroutine ();
     196              : 
     197          337 :                 var param_type = param.variable_type.copy ();
     198          337 :                 if (param.captured || is_in_coroutine ()) {
     199           81 :                         if (!param_type.value_owned && !no_implicit_copy (param_type)) {
     200              :                                 // parameter value has been implicitly copied into a heap data structure
     201              :                                 // treat parameter as owned
     202           44 :                                 param_type.value_owned = true;
     203              : 
     204           44 :                                 var old_coroutine = is_in_coroutine ();
     205           44 :                                 if (old_coroutine) {
     206           27 :                                         current_method.coroutine = false;
     207              :                                 }
     208              : 
     209           44 :                                 if (requires_copy (param_type) && !capturing_parameter_in_coroutine) {
     210              :                                         // do not copy value when capturing parameter in coroutine
     211              :                                         // as the value was already copied on coroutine initialization
     212           21 :                                         value = copy_value (value, param);
     213              :                                 }
     214              : 
     215           44 :                                 if (old_coroutine) {
     216           27 :                                         current_method.coroutine = true;
     217              :                                 }
     218              :                         }
     219              :                 }
     220              : 
     221          337 :                 if (requires_destroy (param_type)) {
     222              :                         /* unref old value */
     223          100 :                         ccode.add_expression (destroy_parameter (param));
     224              :                 }
     225              : 
     226          337 :                 store_value (get_parameter_cvalue (param), value, source_reference);
     227              :         }
     228              : 
     229         4554 :         public override void store_field (Field field, TargetValue? instance, TargetValue value, bool initializer, SourceReference? source_reference = null) {
     230         2277 :                 var lvalue = get_field_cvalue (field, instance);
     231         2277 :                 var type = lvalue.value_type;
     232         2277 :                 if (lvalue.actual_value_type != null) {
     233         3912 :                         type = lvalue.actual_value_type;
     234              :                 }
     235         2277 :                 if (!initializer && (!(field.variable_type is DelegateType) || get_ccode_delegate_target (field)) && requires_destroy (type)) {
     236              :                         /* unref old value */
     237         1108 :                         ccode.add_expression (destroy_field (field, instance));
     238              :                 }
     239         2277 :                 if (initializer && instance != null && get_ccode_delegate_target (field) && get_delegate_target_cvalue (value) == null) {
     240            1 :                         unowned DelegateType delegate_type = field.variable_type as DelegateType;
     241            1 :                         if (delegate_type != null && delegate_type.delegate_symbol.has_target) {
     242            2 :                                 ((GLibValue) value).delegate_target_cvalue = get_cvalue_ (instance);
     243              :                         }
     244              :                 }
     245              : 
     246         2277 :                 store_value (lvalue, value, source_reference);
     247              :         }
     248              : }
        

Generated by: LCOV version 2.0-1