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

            Line data    Source code
       1              : /* valaccodemethodcallmodule.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         2930 : public class Vala.CCodeMethodCallModule : CCodeAssignmentModule {
      28        35129 :         public override void visit_method_call (MethodCall expr) {
      29              :                 // the bare function call
      30        17572 :                 var ccall = new CCodeFunctionCall (get_cvalue (expr.call));
      31              : 
      32        17572 :                 CCodeFunctionCall async_call = null;
      33        17572 :                 CCodeFunctionCall finish_call = null;
      34              : 
      35        17572 :                 Method m = null;
      36        17572 :                 Delegate deleg = null;
      37              :                 List<Parameter> params;
      38              : 
      39        63042 :                 var ma = expr.call as MemberAccess;
      40              : 
      41        17572 :                 var itype = expr.call.value_type;
      42        17958 :                 params = itype.get_parameters ();
      43              : 
      44        17572 :                 if (itype is MethodType) {
      45        16799 :                         assert (ma != null);
      46        16799 :                         m = ((MethodType) itype).method_symbol;
      47              : 
      48        16799 :                         if (!get_ccode_simple_generics (m)) {
      49        16763 :                                 context.analyzer.check_type_arguments (ma);
      50              :                         }
      51              : 
      52        16799 :                         if (ma.inner != null && ma.inner.value_type is EnumValueType && ((EnumValueType) ma.inner.value_type).get_to_string_method() == m) {
      53              :                                 // Enum.VALUE.to_string()
      54            5 :                                 unowned Enum en = (Enum) ma.inner.value_type.type_symbol;
      55            5 :                                 ccall.call = new CCodeIdentifier (generate_enum_to_string_function (en));
      56        16794 :                         } else if (context.profile == Profile.POSIX && ma.inner != null && ma.inner.value_type != null && ma.inner.value_type.type_symbol == string_type.type_symbol && ma.member_name == "printf") {
      57            1 :                                 ccall.call = new CCodeIdentifier (generate_string_printf_function ());
      58        16793 :                         } else if (expr.is_constructv_chainup) {
      59            2 :                                 ccall.call = new CCodeIdentifier (get_ccode_constructv_name ((CreationMethod) m));
      60              :                         }
      61          869 :                 } else if (itype is SignalType) {
      62           96 :                         var sig_type = (SignalType) itype;
      63           96 :                         if (ma != null && ma.inner is BaseAccess && sig_type.signal_symbol.is_virtual) {
      64           97 :                                 m = sig_type.signal_symbol.default_handler;
      65              :                         } else {
      66        47973 :                                 ccall = (CCodeFunctionCall) get_cvalue (expr.call);
      67              :                         }
      68         1185 :                 } else if (itype is ObjectType) {
      69              :                         // constructor
      70          508 :                         var cl = (Class) ((ObjectType) itype).type_symbol;
      71          508 :                         m = cl.default_construction_method;
      72          508 :                         generate_method_declaration (m, cfile);
      73          508 :                         var real_name = get_ccode_real_name (m);
      74          508 :                         if (expr.is_constructv_chainup) {
      75            2 :                                 real_name = get_ccode_constructv_name ((CreationMethod) m);
      76              :                         }
      77          508 :                         ccall = new CCodeFunctionCall (new CCodeIdentifier (real_name));
      78          171 :                 } else if (itype is StructValueType) {
      79              :                         // constructor
      80            2 :                         var st = (Struct) ((StructValueType) itype).type_symbol;
      81            2 :                         m = st.default_construction_method;
      82            2 :                         generate_method_declaration (m, cfile);
      83            2 :                         ccall = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_real_name (m)));
      84          167 :                 } else if (itype is DelegateType) {
      85          167 :                         deleg = ((DelegateType) itype).delegate_symbol;
      86              :                 }
      87              : 
      88        17572 :                 var in_arg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
      89        37982 :                 var out_arg_map = in_arg_map;
      90              : 
      91        17572 :                 if (m != null && m.coroutine) {
      92              :                         // async call
      93              : 
      94          113 :                         async_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_name (m)));
      95          113 :                         finish_call = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_finish_name (m)));
      96              : 
      97          113 :                         if (ma.inner is BaseAccess) {
      98            2 :                                 CCodeExpression? vcast = null;
      99            2 :                                 if (m.base_method != null) {
     100            1 :                                         unowned Class base_class = (Class) m.base_method.parent_symbol;
     101            1 :                                         vcast = new CCodeFunctionCall (new CCodeIdentifier (get_ccode_class_type_function (base_class)));
     102            1 :                                         ((CCodeFunctionCall) vcast).add_argument (new CCodeIdentifier ("%s_parent_class".printf (get_ccode_lower_case_name (current_class))));
     103            1 :                                 } else if (m.base_interface_method != null) {
     104            1 :                                         unowned Interface base_iface = (Interface) m.base_interface_method.parent_symbol;
     105            1 :                                         vcast = get_this_interface_cexpression (base_iface);
     106              :                                 }
     107            2 :                                 if (vcast != null) {
     108            2 :                                         async_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m));
     109            2 :                                         finish_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_finish_vfunc_name (m));
     110              :                                 }
     111          115 :                         } else if (m != null && get_ccode_no_wrapper (m) && m.binding == MemberBinding.INSTANCE && !(m is CreationMethod)) {
     112        10009 :                                 var instance_value = ma.inner.target_value;
     113            8 :                                 if ((ma.member_name == "begin" || ma.member_name == "end") && ma.inner.symbol_reference == ma.symbol_reference) {
     114            4 :                                         var inner_ma = (MemberAccess) ma.inner;
     115            8 :                                         instance_value = inner_ma.inner.target_value;
     116              :                                 }
     117              : 
     118            4 :                                 CCodeExpression? vcast = null;
     119            4 :                                 if (m.parent_symbol is Class) {
     120            2 :                                         unowned Class base_class = (Class) m.parent_symbol;
     121            2 :                                         vcast = get_this_class_cexpression (base_class, instance_value);
     122            2 :                                 } else if (m.parent_symbol is Interface) {
     123            2 :                                         unowned Interface base_iface = (Interface) m.parent_symbol;
     124            2 :                                         vcast = get_this_interface_cexpression (base_iface, instance_value);
     125              :                                 }
     126            8 :                                 if (vcast != null) {
     127            4 :                                         async_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_vfunc_name (m));
     128            4 :                                         finish_call.call = new CCodeMemberAccess.pointer (vcast, get_ccode_finish_vfunc_name (m));
     129              :                                 }
     130              :                         }
     131              : 
     132          113 :                         if (ma.member_name == "begin" && ma.inner.symbol_reference == ma.symbol_reference) {
     133              :                                 // no finish call
     134           98 :                                 ccall = async_call;
     135           98 :                                 params = m.get_async_begin_parameters ();
     136           64 :                         } else if (ma.member_name == "end" && ma.inner.symbol_reference == ma.symbol_reference) {
     137              :                                 // no async call
     138           40 :                                 ccall = finish_call;
     139           40 :                                 params = m.get_async_end_parameters ();
     140           44 :                         } else if (!expr.is_yield_expression) {
     141              :                                 // same as .begin, backwards compatible to bindings without async methods
     142           10 :                                 ccall = async_call;
     143           10 :                                 params = m.get_async_begin_parameters ();
     144              :                         } else {
     145           78 :                                 ccall = finish_call;
     146              :                                 // output arguments used separately
     147           39 :                                 out_arg_map = new HashMap<int,CCodeExpression> (direct_hash, direct_equal);
     148              :                                 // pass GAsyncResult stored in closure to finish function
     149           39 :                                 out_arg_map.set (get_param_pos (get_ccode_async_result_pos (m)), get_variable_cexpression ("_res_"));
     150              :                         }
     151              :                 }
     152              : 
     153        17572 :                 if (m is CreationMethod && m.parent_symbol is Class) {
     154          513 :                         if (context.profile == Profile.GOBJECT) {
     155          513 :                                 if (!((Class) m.parent_symbol).is_compact) {
     156          500 :                                         ccall.add_argument (get_variable_cexpression ("object_type"));
     157              :                                 }
     158              :                         } else {
     159            0 :                                 ccall.add_argument (get_this_cexpression ());
     160              :                         }
     161              : 
     162          513 :                         if (!current_class.is_compact) {
     163          500 :                                 int type_param_index = 0;
     164          505 :                                 if (current_class != m.parent_symbol) {
     165              :                                         // chain up to base class
     166          497 :                                         foreach (DataType base_type in current_class.get_base_types ()) {
     167          496 :                                                 if (base_type.type_symbol is Class) {
     168          495 :                                                         List<TypeParameter> type_parameters = null;
     169          495 :                                                         if (get_ccode_real_name (m) == "g_object_new") {
     170              :                                                                 // gobject-style chainup
     171          312 :                                                                 type_parameters = ((Class) base_type.type_symbol).get_type_parameters ();
     172          312 :                                                                 type_param_index += type_parameters.size;
     173              :                                                         }
     174          495 :                                                         add_generic_type_arguments (m, in_arg_map, base_type.get_type_arguments (), expr, true, type_parameters);
     175          495 :                                                         break;
     176              :                                                 }
     177              :                                         }
     178              :                                 } else {
     179              :                                         // chain up to other constructor in same class
     180           10 :                                         var cl = (Class) m.parent_symbol;
     181            7 :                                         foreach (TypeParameter type_param in cl.get_type_parameters ()) {
     182            1 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeIdentifier (get_ccode_type_id (type_param)));
     183            1 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier (get_ccode_copy_function (type_param)));
     184            1 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeIdentifier (get_ccode_destroy_function (type_param)));
     185            1 :                                                 type_param_index++;
     186              :                                         }
     187              :                                 }
     188          500 :                                 if (current_class.has_type_parameters () && get_ccode_real_name (m) == "g_object_new") {
     189              :                                         // gobject-style construction
     190           49 :                                         foreach (var type_param in current_class.get_type_parameters ()) {
     191           17 :                                                 var type_param_name = type_param.name.ascii_down ().replace ("_", "-");
     192           17 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.01), new CCodeConstant ("\"%s-type\"".printf (type_param_name)));
     193           17 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.02), new CCodeIdentifier (get_ccode_type_id (type_param)));
     194           17 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.03), new CCodeConstant ("\"%s-dup-func\"".printf (type_param_name)));
     195           17 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.04), new CCodeIdentifier (get_ccode_copy_function (type_param)));
     196           17 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.05), new CCodeConstant ("\"%s-destroy-func\"".printf (type_param_name)));
     197           17 :                                                 in_arg_map.set (get_param_pos (0.1 * type_param_index + 0.06), new CCodeIdentifier (get_ccode_destroy_function (type_param)));
     198           17 :                                                 type_param_index++;
     199              :                                         }
     200              :                                 }
     201           16 :                         } else if (current_class.is_subtype_of (gsource_type)) {
     202              :                                 // g_source_new
     203              : 
     204            3 :                                 string class_prefix = get_ccode_lower_case_name (current_class);
     205            3 :                                 string prepare_func = "NULL";
     206            3 :                                 string check_func = "NULL";
     207           20 :                                 foreach (Method impl in current_class.get_methods ()) {
     208           10 :                                         if (!impl.overrides) {
     209            3 :                                                 continue;
     210              :                                         }
     211           22 :                                         switch (impl.name) {
     212              :                                         case "prepare":
     213            2 :                                                 prepare_func = "%s_real_prepare".printf (class_prefix);
     214            2 :                                                 break;
     215              :                                         case "check":
     216            2 :                                                 check_func = "%s_real_check".printf (class_prefix);
     217            2 :                                                 break;
     218              :                                         default:
     219              :                                                 break;
     220              :                                         }
     221              :                                 }
     222              : 
     223            3 :                                 var funcs = new CCodeDeclaration ("const GSourceFuncs");
     224            3 :                                 funcs.modifiers = CCodeModifiers.STATIC;
     225            3 :                                 funcs.add_declarator (new CCodeVariableDeclarator ("_source_funcs", new CCodeConstant ("{ %s, %s, %s_real_dispatch, %s_finalize, NULL, NULL}".printf (prepare_func, check_func, class_prefix, class_prefix))));
     226            3 :                                 ccode.add_statement (funcs);
     227              : 
     228            3 :                                 ccall.add_argument (new CCodeCastExpression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_source_funcs")), "GSourceFuncs *"));
     229              : 
     230            3 :                                 var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
     231            3 :                                 csizeof.add_argument (new CCodeIdentifier (get_ccode_name (current_class)));
     232            3 :                                 ccall.add_argument (csizeof);
     233           10 :                         } else if (current_class.base_class != null && get_ccode_simple_generics (m)) {
     234            3 :                                 if (current_class != m.parent_symbol) {
     235            3 :                                         foreach (DataType base_type in current_class.get_base_types ()) {
     236            3 :                                                 if (base_type.type_symbol is Class) {
     237            3 :                                                         add_generic_type_arguments (m, in_arg_map, base_type.get_type_arguments (), expr);
     238            3 :                                                         break;
     239              :                                                 }
     240              :                                         }
     241              :                                 } else {
     242              :                                         // TODO: simple generics are only supported in bindings.
     243              :                                 }
     244              :                         }
     245        17059 :                 } else if (m is CreationMethod && m.parent_symbol is Struct) {
     246            2 :                         ccall.add_argument (get_this_cexpression ());
     247        17057 :                 } else if (m != null && m.has_type_parameters () && !get_ccode_has_generic_type_parameter (m) && !get_ccode_simple_generics (m) && (ccall != finish_call || expr.is_yield_expression)) {
     248              :                         // generic method
     249              :                         // don't add generic arguments for .end() calls
     250           77 :                         add_generic_type_arguments (m, in_arg_map, ma.get_type_arguments (), expr);
     251              :                 }
     252              : 
     253              :                 // the complete call expression, might include casts, comma expressions, and/or assignments
     254        17572 :                 CCodeExpression ccall_expr = ccall;
     255              : 
     256        17584 :                 if (m is ArrayResizeMethod && context.profile != Profile.POSIX) {
     257           12 :                         var array_type = (ArrayType) ma.inner.value_type;
     258           12 :                         in_arg_map.set (get_param_pos (0), new CCodeIdentifier (get_ccode_name (array_type.element_type)));
     259        17560 :                 } else if (m is ArrayMoveMethod) {
     260            2 :                         requires_array_move = true;
     261        17558 :                 } else if (m is ArrayCopyMethod) {
     262            2 :                         expr.target_value = copy_value (ma.inner.target_value, expr);
     263            2 :                         return;
     264              :                 }
     265              : 
     266        17570 :                 CCodeExpression instance = null;
     267        17570 :                 if (m != null && m.is_async_callback) {
     268            6 :                         if (current_method.closure) {
     269            2 :                                 var block = ((Method) m.parent_symbol).body;
     270            2 :                                 instance = new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (block))), "_async_data_");
     271              :                         } else {
     272            2 :                                 instance = new CCodeIdentifier ("_data_");
     273              :                         }
     274              : 
     275            4 :                         in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
     276            4 :                         out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
     277        27537 :                 } else if (m != null && m.binding == MemberBinding.INSTANCE && !(m is CreationMethod)) {
     278         9971 :                         var instance_value = ma.inner.target_value;
     279        10001 :                         if ((ma.member_name == "begin" || ma.member_name == "end") && ma.inner.symbol_reference == ma.symbol_reference) {
     280           30 :                                 var inner_ma = (MemberAccess) ma.inner;
     281           60 :                                 instance_value = inner_ma.inner.target_value;
     282              :                         }
     283         9971 :                         instance = get_cvalue_ (instance_value);
     284              : 
     285         9971 :                         var st = m.parent_symbol as Struct;
     286          209 :                         if (st != null && !st.is_simple_type ()) {
     287              :                                 // we need to pass struct instance by reference
     288           48 :                                 if (!get_lvalue (instance_value)) {
     289            1 :                                         instance_value = store_temp_value (instance_value, expr);
     290              :                                 }
     291           48 :                                 instance = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue_ (instance_value));
     292              :                         }
     293              : 
     294         9971 :                         if (!m.coroutine) {
     295         9915 :                                 in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
     296           56 :                         } else if (expr.is_yield_expression) {
     297           24 :                                 in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
     298           24 :                                 if (get_ccode_finish_instance (m)) {
     299           24 :                                         out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
     300              :                                 }
     301           32 :                         } else if (ma.member_name != "end" || get_ccode_finish_instance (m)) {
     302           30 :                                 out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
     303           30 :                                 in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), instance);
     304              :                         }
     305         7599 :                 } else if (m != null && m.binding == MemberBinding.CLASS) {
     306            4 :                         unowned Class cl = (Class) m.parent_symbol;
     307            4 :                         var cast = get_this_class_cexpression (cl, ma.inner != null ? ma.inner.target_value : null);
     308            4 :                         in_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), cast);
     309            4 :                         out_arg_map.set (get_param_pos (get_ccode_instance_pos (m)), cast);
     310              :                 }
     311              : 
     312        17570 :                 if (m != null && get_ccode_has_generic_type_parameter (m)) {
     313              :                         // insert type argument for macros
     314           50 :                         if (m.has_type_parameters ()) {
     315              :                                 // generic method
     316           35 :                                 int type_param_index = 0;
     317          105 :                                 foreach (var type_arg in ma.get_type_arguments ()) {
     318              :                                         // real structs are passed by reference for simple generics
     319           35 :                                         if (get_ccode_simple_generics (m) && type_arg.is_real_struct_type () && !type_arg.nullable && !(type_arg is PointerType)) {
     320            2 :                                             type_arg = new PointerType (type_arg);
     321              :                                         }
     322           35 :                                         in_arg_map.set (get_param_pos (get_ccode_generic_type_pos (m) + 0.01 * type_param_index), new CCodeIdentifier (get_ccode_name (type_arg)));
     323           35 :                                         type_param_index++;
     324              :                                 }
     325              :                         } else {
     326              :                                 // method in generic type
     327           15 :                                 int type_param_index = 0;
     328           45 :                                 foreach (var type_arg in ma.inner.value_type.get_type_arguments ()) {
     329           15 :                                         in_arg_map.set (get_param_pos (get_ccode_generic_type_pos (m) + 0.01 * type_param_index), new CCodeIdentifier (get_ccode_name (type_arg)));
     330           15 :                                         type_param_index++;
     331              :                                 }
     332              :                         }
     333              :                 }
     334              : 
     335        17572 :                 if (m is ArrayMoveMethod) {
     336            2 :                         var array_type = (ArrayType) ma.inner.value_type;
     337            2 :                         var csizeof = new CCodeFunctionCall (new CCodeIdentifier ("sizeof"));
     338            2 :                         csizeof.add_argument (new CCodeIdentifier (get_ccode_name (array_type.element_type)));
     339            2 :                         in_arg_map.set (get_param_pos (0.1), csizeof);
     340        17568 :                 } else if (m is DynamicMethod) {
     341            1 :                         emit_context.push_symbol (m);
     342            1 :                         m.clear_parameters ();
     343            1 :                         int param_nr = 1;
     344            5 :                         foreach (Expression arg in expr.get_argument_list ()) {
     345            2 :                                 var unary = arg as UnaryExpression;
     346            3 :                                 if (unary != null && unary.operator == UnaryOperator.OUT) {
     347              :                                         // out argument
     348            1 :                                         var param = new Parameter ("param%d".printf (param_nr), unary.inner.value_type);
     349            1 :                                         param.direction = ParameterDirection.OUT;
     350            1 :                                         m.add_parameter (param);
     351            1 :                                 } else if (unary != null && unary.operator == UnaryOperator.REF) {
     352              :                                         // ref argument
     353            0 :                                         var param = new Parameter ("param%d".printf (param_nr), unary.inner.value_type);
     354            0 :                                         param.direction = ParameterDirection.REF;
     355            0 :                                         m.add_parameter (param);
     356              :                                 } else {
     357              :                                         // in argument
     358            1 :                                         m.add_parameter (new Parameter ("param%d".printf (param_nr), arg.value_type));
     359              :                                 }
     360            2 :                                 param_nr++;
     361              :                         }
     362            5 :                         foreach (Parameter param in m.get_parameters ()) {
     363            2 :                                 param.accept (this);
     364              :                         }
     365            1 :                         generate_dynamic_method_wrapper ((DynamicMethod) m);
     366            1 :                         emit_context.pop_symbol ();
     367        17567 :                 } else if (m is CreationMethod && context.profile == Profile.GOBJECT && m.parent_symbol is Class) {
     368          513 :                         ccode.add_assignment (get_this_cexpression (), new CCodeCastExpression (ccall, get_ccode_name (current_class) + "*"));
     369              : 
     370          518 :                         if (current_method.body.captured) {
     371              :                                 // capture self after setting it
     372            5 :                                 var ref_call = new CCodeFunctionCall (get_dup_func_expression (new ObjectType (current_class), expr.source_reference));
     373            5 :                                 ref_call.add_argument (get_this_cexpression ());
     374              : 
     375            5 :                                 ccode.add_assignment (new CCodeMemberAccess.pointer (get_variable_cexpression ("_data%d_".printf (get_block_id (current_method.body))), "self"), ref_call);
     376              :                         }
     377              : 
     378              :                         //FIXME Only needed for non-"g_object_new" calls, if there is no property clash
     379          532 :                         if (!current_class.is_compact && current_class.has_type_parameters ()) {
     380              :                                 /* type, dup func, and destroy func fields for generic types */
     381           19 :                                 var priv_access = new CCodeMemberAccess.pointer (new CCodeIdentifier ("self"), "priv");
     382           61 :                                 foreach (TypeParameter type_param in current_class.get_type_parameters ()) {
     383           21 :                                         var type = get_ccode_type_id (type_param);
     384           21 :                                         var dup_func = get_ccode_copy_function (type_param);
     385           21 :                                         var destroy_func = get_ccode_destroy_function (type_param);
     386           21 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, type), new CCodeIdentifier (type));
     387           21 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, dup_func), new CCodeIdentifier (dup_func));
     388           21 :                                         ccode.add_assignment (new CCodeMemberAccess.pointer (priv_access, destroy_func), new CCodeIdentifier (destroy_func));
     389              :                                 }
     390              :                         }
     391              :                         // object chainup can't be used as expression
     392          513 :                         ccall_expr = null;
     393              :                 }
     394              : 
     395        17570 :                 bool ellipsis = false;
     396              : 
     397        17570 :                 int i = 1;
     398              :                 int arg_pos;
     399        17570 :                 Iterator<Parameter> params_it = params.iterator ();
     400        57828 :                 foreach (Expression arg in expr.get_argument_list ()) {
     401        20129 :                         CCodeExpression cexpr = get_cvalue (arg);
     402              : 
     403        20129 :                         var carg_map = in_arg_map;
     404              : 
     405        20129 :                         Parameter? param = null;
     406        20129 :                         if (params_it.next ()) {
     407        19822 :                                 param = params_it.get ();
     408        19822 :                                 ellipsis = param.params_array || param.ellipsis;
     409              :                         }
     410              : 
     411        40258 :                         if (param != null && !ellipsis) {
     412        19087 :                                         if (param.direction == ParameterDirection.OUT) {
     413          512 :                                                 carg_map = out_arg_map;
     414              :                                         }
     415              : 
     416        19087 :                                         var unary = arg as UnaryExpression;
     417        19275 :                                         if (unary == null || unary.operator != UnaryOperator.OUT) {
     418        19527 :                                                 if (get_ccode_array_length (param) && param.variable_type is ArrayType && !((ArrayType) param.variable_type).fixed_length) {
     419          628 :                                                         var array_type = (ArrayType) param.variable_type;
     420          628 :                                                         var length_ctype = get_ccode_array_length_type (param);
     421          628 :                                                         if (unary != null && unary.operator == UnaryOperator.REF) {
     422           13 :                                                                 length_ctype = "%s*".printf (length_ctype);
     423              :                                                         }
     424         1896 :                                                         for (int dim = 1; dim <= array_type.rank; dim++) {
     425          634 :                                                                 var array_length_expr = new CCodeCastExpression (get_array_length_cexpression (arg, dim), length_ctype);
     426          634 :                                                                 carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), array_length_expr);
     427              :                                                         }
     428        18685 :                                                 } else if (get_ccode_delegate_target (param) && param.variable_type is DelegateType) {
     429          414 :                                                         var deleg_type = (DelegateType) param.variable_type;
     430          828 :                                                         if (deleg_type.delegate_symbol.has_target) {
     431              :                                                                 CCodeExpression delegate_target_destroy_notify;
     432          414 :                                                                 var delegate_target = get_delegate_target_cexpression (arg, out delegate_target_destroy_notify);
     433          414 :                                                                 assert (delegate_target != null);
     434          828 :                                                                 if (get_ccode_type (param) == "GClosure*") {
     435              :                                                                         // one single GClosure parameter
     436            2 :                                                                         var closure_new = new CCodeFunctionCall (new CCodeIdentifier ("g_cclosure_new"));
     437            2 :                                                                         closure_new.add_argument (new CCodeCastExpression (cexpr, "GCallback"));
     438            2 :                                                                         closure_new.add_argument (delegate_target);
     439            2 :                                                                         closure_new.add_argument (new CCodeCastExpression (delegate_target_destroy_notify, "GClosureNotify"));
     440              :                                                                         //TODO Use get_non_null (arg.target_value)
     441            2 :                                                                         if (arg.is_non_null ()) {
     442            2 :                                                                                 cexpr = closure_new;
     443              :                                                                         } else {
     444            1 :                                                                                 cexpr = new CCodeConditionalExpression (new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, cexpr, new CCodeConstant ("NULL")), new CCodeConstant ("NULL"), closure_new);
     445              :                                                                         }
     446              :                                                                 } else {
     447              :                                                                         // Override previously given target/destroy only if it was NULL
     448              :                                                                         // TODO https://gitlab.gnome.org/GNOME/vala/issues/59
     449          412 :                                                                         var node = carg_map.get (get_param_pos (get_ccode_delegate_target_pos (param)));
     450          412 :                                                                         if (node == null || (node is CCodeConstant && ((CCodeConstant) node).name == "NULL")) {
     451          408 :                                                                                 carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), delegate_target);
     452          408 :                                                                                 if (deleg_type.is_disposable ()) {
     453           73 :                                                                                         assert (delegate_target_destroy_notify != null);
     454           73 :                                                                                         carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), delegate_target_destroy_notify);
     455              :                                                                                 }
     456              :                                                                         }
     457              :                                                                 }
     458              :                                                         }
     459        17857 :                                                 } else if (param.variable_type is MethodType) {
     460              :                                                         // callbacks in dynamic method calls
     461              :                                                         CCodeExpression delegate_target_destroy_notify;
     462            0 :                                                         carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), get_delegate_target_cexpression (arg, out delegate_target_destroy_notify));
     463        17857 :                                                 } else if (param.variable_type is GenericType) {
     464         1009 :                                                         if (m != null && get_ccode_simple_generics (m)) {
     465            1 :                                                                 var generic_type = (GenericType) param.variable_type;
     466            1 :                                                                 int type_param_index = m.get_type_parameter_index (generic_type.type_parameter.name);
     467            1 :                                                                 var type_arg = ma.get_type_arguments ().get (type_param_index);
     468            1 :                                                                 if (param.variable_type.value_owned) {
     469            1 :                                                                         if (requires_copy (type_arg)) {
     470            1 :                                                                                 carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), get_destroy_func_expression (type_arg));
     471              :                                                                         } else {
     472            0 :                                                                                 carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), new CCodeConstant ("NULL"));
     473              :                                                                         }
     474              :                                                                 }
     475              :                                                         }
     476              :                                                 }
     477              : 
     478        18899 :                                                 cexpr = handle_struct_argument (param, arg, cexpr);
     479              :                                         } else {
     480          188 :                                                 arg.target_value = null;
     481              : 
     482          188 :                                                 var temp_var = get_temp_variable (param.variable_type, param.variable_type.value_owned, null, true);
     483          188 :                                                 emit_temp_var (temp_var);
     484          188 :                                                 set_cvalue (arg, get_variable_cexpression (temp_var.name));
     485          188 :                                                 arg.target_value.value_type = arg.target_type;
     486              : 
     487          188 :                                                 cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (arg));
     488              : 
     489          203 :                                                 if (get_ccode_array_length (param) && param.variable_type is ArrayType && !((ArrayType) param.variable_type).fixed_length) {
     490           15 :                                                         var array_type = (ArrayType) param.variable_type;
     491           15 :                                                         var length_ctype = get_ccode_array_length_type (param);
     492           53 :                                                         for (int dim = 1; dim <= array_type.rank; dim++) {
     493           19 :                                                                 var temp_array_length = get_temp_variable (new CType (length_ctype, "0"), true, null, true);
     494           19 :                                                                 emit_temp_var (temp_array_length);
     495           19 :                                                                 append_array_length (arg, get_variable_cexpression (temp_array_length.name));
     496           19 :                                                                 carg_map.set (get_param_pos (get_ccode_array_length_pos (param) + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_array_lengths (arg).get (dim - 1)));
     497              :                                                         }
     498          174 :                                                 } else if (get_ccode_delegate_target (param) && param.variable_type is DelegateType) {
     499            1 :                                                         var deleg_type = (DelegateType) param.variable_type;
     500            1 :                                                         if (deleg_type.delegate_symbol.has_target) {
     501            1 :                                                                 temp_var = get_temp_variable (delegate_target_type, true, null, true);
     502            1 :                                                                 emit_temp_var (temp_var);
     503            1 :                                                                 set_delegate_target (arg, get_variable_cexpression (temp_var.name));
     504            1 :                                                                 carg_map.set (get_param_pos (get_ccode_delegate_target_pos (param)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target (arg)));
     505            1 :                                                                 if (deleg_type.is_disposable ()) {
     506            1 :                                                                         temp_var = get_temp_variable (delegate_target_destroy_type, true, null, true);
     507            1 :                                                                         emit_temp_var (temp_var);
     508            1 :                                                                         set_delegate_target_destroy_notify (arg, get_variable_cexpression (temp_var.name));
     509            1 :                                                                         carg_map.set (get_param_pos (get_ccode_destroy_notify_pos (param)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_delegate_target_destroy_notify (arg)));
     510              :                                                                 }
     511              :                                                         }
     512          172 :                                                 } else if (param.variable_type is GenericType) {
     513            4 :                                                         set_cvalue (arg, convert_from_generic_pointer (get_cvalue (arg), arg.target_type));
     514              :                                                 }
     515              :                                         }
     516              : 
     517        19087 :                                         if (get_ccode_type (param) != null) {
     518           39 :                                                 cexpr = new CCodeCastExpression (cexpr, get_ccode_type (param));
     519              :                                         }
     520              :                         } else {
     521              :                                 // ellipsis arguments
     522         1042 :                                 var unary = arg as UnaryExpression;
     523         1067 :                                 if (ellipsis && unary != null && unary.operator == UnaryOperator.OUT) {
     524           50 :                                         carg_map = out_arg_map;
     525              : 
     526           25 :                                         arg.target_value = null;
     527              : 
     528              :                                         // infer type and ownership from argument expression
     529           25 :                                         var temp_var = get_temp_variable (arg.value_type, arg.value_type.value_owned, null, true);
     530           25 :                                         emit_temp_var (temp_var);
     531           25 :                                         set_cvalue (arg, get_variable_cexpression (temp_var.name));
     532           25 :                                         arg.target_value.value_type = arg.value_type;
     533              : 
     534           25 :                                         if (arg.value_type is DelegateType && ((DelegateType) arg.value_type).delegate_symbol.has_target) {
     535              :                                                 // Initialize target/destroy cvalues to allow assignment of delegates from varargs
     536            3 :                                                 unowned GLibValue arg_value = (GLibValue) arg.target_value;
     537            3 :                                                 if (arg_value.delegate_target_cvalue == null) {
     538            3 :                                                         arg_value.delegate_target_cvalue = new CCodeConstant ("NULL");
     539              :                                                 }
     540            3 :                                                 if (arg_value.delegate_target_destroy_notify_cvalue == null) {
     541            3 :                                                         arg_value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL");
     542              :                                                 }
     543              :                                         }
     544              : 
     545           25 :                                         cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_cvalue (arg));
     546              :                                 } else {
     547         1017 :                                         cexpr = handle_struct_argument (null, arg, cexpr);
     548              :                                 }
     549              :                         }
     550              : 
     551        20129 :                         if (itype is SignalType && ((SignalType) itype).signal_symbol is DynamicSignal) {
     552            4 :                                 arg_pos = get_param_pos (i, false);
     553              :                         } else {
     554        20125 :                                 arg_pos = get_param_pos (param != null && !ellipsis ? get_ccode_pos (param) : i, ellipsis);
     555              :                         }
     556        20129 :                         carg_map.set (arg_pos, cexpr);
     557              : 
     558        20130 :                         if (m is ArrayResizeMethod && context.profile == Profile.POSIX) {
     559            1 :                                 var csizeof = new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (((ArrayType) ma.inner.value_type).element_type)));
     560            1 :                                 carg_map.set (arg_pos, new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeof, cexpr));
     561              :                         } else {
     562        20128 :                                 carg_map.set (arg_pos, cexpr);
     563              :                         }
     564              : 
     565        20141 :                         if (arg is NamedArgument && ellipsis) {
     566           12 :                                 var named_arg = (NamedArgument) arg;
     567           36 :                                 string name = string.joinv ("-", named_arg.name.split ("_"));
     568           12 :                                 carg_map.set (get_param_pos (i - 0.1, ellipsis), new CCodeConstant ("\"%s\"".printf (name)));
     569              :                         }
     570              : 
     571        20129 :                         i++;
     572              :                 }
     573        18083 :                 if (params_it.next ()) {
     574          513 :                         var param = params_it.get ();
     575              : 
     576              :                         /* if there are more parameters than arguments,
     577              :                          * the additional parameter is an ellipsis parameter
     578              :                          * otherwise there is a bug in the semantic analyzer
     579              :                          */
     580          513 :                         assert (param.params_array || param.ellipsis);
     581          513 :                         ellipsis = true;
     582              :                 }
     583              : 
     584              :                 /* add length argument for methods returning arrays */
     585        17756 :                 if (m != null && m.return_type is ArrayType && async_call != ccall) {
     586          372 :                         var array_type = (ArrayType) m.return_type;
     587          379 :                         for (int dim = 1; dim <= array_type.rank; dim++) {
     588          260 :                                 if (get_ccode_array_null_terminated (m) && !get_ccode_array_length (m)) {
     589              :                                         // handle calls to methods returning null-terminated arrays
     590           67 :                                         var temp_var = get_temp_variable (itype.get_return_type (), true, null, false);
     591           67 :                                         var temp_ref = get_variable_cexpression (temp_var.name);
     592              : 
     593           67 :                                         emit_temp_var (temp_var);
     594              : 
     595           67 :                                         ccall_expr = new CCodeAssignment (temp_ref, ccall_expr);
     596              : 
     597           67 :                                         requires_array_length = true;
     598           67 :                                         var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
     599           67 :                                         len_call.add_argument (temp_ref);
     600              : 
     601           67 :                                         append_array_length (expr, len_call);
     602          246 :                                 } else if (get_ccode_array_length (m)) {
     603          120 :                                         var length_ctype = get_ccode_array_length_type (m);
     604          120 :                                         var temp_var = get_temp_variable (new CType (length_ctype, "0"), true, null, true);
     605          120 :                                         var temp_ref = get_variable_cexpression (temp_var.name);
     606              : 
     607          120 :                                         emit_temp_var (temp_var);
     608              : 
     609          120 :                                         out_arg_map.set (get_param_pos (get_ccode_array_length_pos (m) + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
     610              : 
     611          120 :                                         append_array_length (expr, temp_ref);
     612            6 :                                 } else if (get_ccode_array_length_expr (m) != null) {
     613            1 :                                         append_array_length (expr, new CCodeConstant (get_ccode_array_length_expr (m)));
     614              :                                 } else {
     615            5 :                                         append_array_length (expr, new CCodeConstant ("-1"));
     616              :                                 }
     617              :                         }
     618        17397 :                 } else if (m != null && m.return_type is DelegateType && async_call != ccall) {
     619           13 :                         var deleg_type = (DelegateType) m.return_type;
     620           21 :                         if (get_ccode_delegate_target (m) && deleg_type.delegate_symbol.has_target) {
     621            8 :                                 var temp_var = get_temp_variable (delegate_target_type, true, null, true);
     622            8 :                                 var temp_ref = get_variable_cexpression (temp_var.name);
     623              : 
     624            8 :                                 emit_temp_var (temp_var);
     625              : 
     626            8 :                                 out_arg_map.set (get_param_pos (get_ccode_delegate_target_pos (m)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
     627              : 
     628            8 :                                 set_delegate_target (expr, temp_ref);
     629              : 
     630            8 :                                 if (deleg_type.is_disposable ()) {
     631            6 :                                         temp_var = get_temp_variable (delegate_target_destroy_type, true, null, true);
     632            6 :                                         temp_ref = get_variable_cexpression (temp_var.name);
     633              : 
     634            6 :                                         emit_temp_var (temp_var);
     635              : 
     636            6 :                                         out_arg_map.set (get_param_pos (get_ccode_destroy_notify_pos (m)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
     637              : 
     638            6 :                                         set_delegate_target_destroy_notify (expr, temp_ref);
     639              :                                 } else {
     640            2 :                                         set_delegate_target_destroy_notify (expr, new CCodeConstant ("NULL"));
     641              :                                 }
     642              :                         } else {
     643            5 :                                 set_delegate_target (expr, new CCodeConstant ("NULL"));
     644            5 :                                 if (deleg_type.delegate_symbol.has_target) {
     645            4 :                                         set_delegate_target_destroy_notify (expr, new CCodeConstant ("NULL"));
     646              :                                 }
     647              :                         }
     648              :                 }
     649              : 
     650              :                 // add length argument for delegates returning arrays
     651              :                 // TODO: avoid code duplication with methods returning arrays, see above
     652        17576 :                 if (deleg != null && deleg.return_type is ArrayType) {
     653           12 :                         var array_type = (ArrayType) deleg.return_type;
     654           12 :                         for (int dim = 1; dim <= array_type.rank; dim++) {
     655            7 :                                 if (get_ccode_array_null_terminated (deleg) && !get_ccode_array_length (deleg)) {
     656              :                                         // handle calls to methods returning null-terminated arrays
     657            1 :                                         var temp_var = get_temp_variable (itype.get_return_type (), true, null, false);
     658            1 :                                         var temp_ref = get_variable_cexpression (temp_var.name);
     659              : 
     660            1 :                                         emit_temp_var (temp_var);
     661              : 
     662            1 :                                         ccall_expr = new CCodeAssignment (temp_ref, ccall_expr);
     663              : 
     664            1 :                                         requires_array_length = true;
     665            1 :                                         var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
     666            1 :                                         len_call.add_argument (temp_ref);
     667              : 
     668            1 :                                         append_array_length (expr, len_call);
     669            9 :                                 } else if (get_ccode_array_length (deleg)) {
     670            4 :                                         var length_ctype = get_ccode_array_length_type (deleg);
     671            4 :                                         var temp_var = get_temp_variable (new CType (length_ctype, "0"), true, null, true);
     672            4 :                                         var temp_ref = get_variable_cexpression (temp_var.name);
     673              : 
     674            4 :                                         emit_temp_var (temp_var);
     675              : 
     676            4 :                                         out_arg_map.set (get_param_pos (get_ccode_array_length_pos (deleg) + 0.01 * dim), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
     677              : 
     678            4 :                                         append_array_length (expr, temp_ref);
     679              :                                 } else {
     680            1 :                                         append_array_length (expr, new CCodeConstant ("-1"));
     681              :                                 }
     682              :                         }
     683        17565 :                 } else if (deleg != null && deleg.return_type is DelegateType && get_ccode_delegate_target (deleg)) {
     684            1 :                         var deleg_type = (DelegateType) deleg.return_type;
     685            2 :                         if (deleg_type.delegate_symbol.has_target) {
     686            1 :                                 var temp_var = get_temp_variable (delegate_target_type, true, null, true);
     687            1 :                                 var temp_ref = get_variable_cexpression (temp_var.name);
     688              : 
     689            1 :                                 emit_temp_var (temp_var);
     690              : 
     691            1 :                                 out_arg_map.set (get_param_pos (get_ccode_delegate_target_pos (deleg)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
     692              : 
     693            1 :                                 set_delegate_target (expr, temp_ref);
     694              : 
     695            1 :                                 if (deleg_type.is_disposable ()) {
     696            1 :                                         temp_var = get_temp_variable (delegate_target_destroy_type, true, null, true);
     697            1 :                                         temp_ref = get_variable_cexpression (temp_var.name);
     698              : 
     699            1 :                                         emit_temp_var (temp_var);
     700              : 
     701            1 :                                         out_arg_map.set (get_param_pos (get_ccode_destroy_notify_pos (deleg)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, temp_ref));
     702              : 
     703            1 :                                         set_delegate_target_destroy_notify (expr, temp_ref);
     704              :                                 }
     705              :                         }
     706              :                 }
     707              : 
     708        17570 :                 if (m != null && m.coroutine) {
     709          113 :                         if (expr.is_yield_expression) {
     710              :                                 // asynchronous call
     711           39 :                                 in_arg_map.set (get_param_pos (-1), new CCodeIdentifier (generate_ready_function (current_method)));
     712           39 :                                 in_arg_map.set (get_param_pos (-0.9), new CCodeIdentifier ("_data_"));
     713              :                         }
     714              :                 }
     715              : 
     716        17570 :                 if (expr.tree_can_fail) {
     717              :                         // method can fail
     718          428 :                         current_method_inner_error = true;
     719              :                         // add &inner_error before the ellipsis arguments
     720          428 :                         out_arg_map.set (get_param_pos (get_ccode_error_pos ((Callable) m ?? deleg)), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, get_inner_error_cexpression ()));
     721        17142 :                 } else if (m != null && m.has_error_type_parameter () && async_call != ccall) {
     722              :                         // inferred error argument from base method
     723            5 :                         out_arg_map.set (get_param_pos (get_ccode_error_pos (m)), new CCodeConstant ("NULL"));
     724              :                 }
     725              : 
     726        17570 :                 if (ellipsis) {
     727              :                         /* ensure variable argument list ends with NULL
     728              :                          * except when using printf-style arguments */
     729         1248 :                         if (itype is SignalType) {
     730              :                                 // g_signal_emit*() does not require more
     731         1246 :                         } else if (m == null) {
     732           11 :                                 in_arg_map.set (get_param_pos (-1, true), new CCodeConstant ("NULL"));
     733         1235 :                         } else if (!m.printf_format && !m.scanf_format && get_ccode_sentinel (m) != "" && !expr.is_constructv_chainup) {
     734          458 :                                 in_arg_map.set (get_param_pos (-1, true), new CCodeConstant (get_ccode_sentinel (m)));
     735              :                         }
     736              :                 }
     737              : 
     738        17694 :                 if (deleg != null && deleg.has_target) {
     739              :                         CCodeExpression delegate_target_destroy_notify;
     740          124 :                         in_arg_map.set (get_param_pos (get_ccode_instance_pos (deleg)), get_delegate_target_cexpression (expr.call, out delegate_target_destroy_notify));
     741          124 :                         out_arg_map.set (get_param_pos (get_ccode_instance_pos (deleg)), get_delegate_target_cexpression (expr.call, out delegate_target_destroy_notify));
     742              :                 }
     743              : 
     744              :                 // structs are returned via out parameter
     745        17570 :                 bool return_result_via_out_param = itype.get_return_type ().is_real_non_null_struct_type ();
     746              : 
     747              :                 // pass address for the return value of non-void signals without emitter functions
     748        17609 :                 if (itype is SignalType && !(itype.get_return_type () is VoidType)) {
     749           39 :                         var sig = ((SignalType) itype).signal_symbol;
     750              : 
     751           39 :                         if (ma != null && ma.inner is BaseAccess && sig.is_virtual) {
     752              :                                 // normal return value for base access
     753           39 :                         } else if (!get_ccode_has_emitter (sig) || ma.source_reference.file == sig.source_reference.file) {
     754              :                                 return_result_via_out_param = true;
     755              :                         }
     756              :                 }
     757              : 
     758        17570 :                 if (async_call == ccall) {
     759              :                         // skip out parameter for .begin() calls
     760              :                         return_result_via_out_param = false;
     761              :                 }
     762              : 
     763        17516 :                 CCodeExpression out_param_ref = null;
     764              : 
     765        17582 :                 if (return_result_via_out_param) {
     766           66 :                         var out_param_var = get_temp_variable (itype.get_return_type (), true, null, true);
     767           66 :                         out_param_ref = get_variable_cexpression (out_param_var.name);
     768           66 :                         emit_temp_var (out_param_var);
     769           66 :                         out_arg_map.set (get_param_pos (-3), new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, out_param_ref));
     770              :                 }
     771              : 
     772              :                 // append C arguments in the right order
     773              : 
     774              :                 int last_pos;
     775              :                 int min_pos;
     776              : 
     777        17570 :                 if (async_call != ccall) {
     778              :                         // don't append out arguments for .begin() calls
     779              :                         last_pos = -1;
     780        50316 :                         while (true) {
     781        50316 :                                 min_pos = -1;
     782       223954 :                                 foreach (int pos in out_arg_map.get_keys ()) {
     783       123322 :                                         if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
     784        46228 :                                                 min_pos = pos;
     785              :                                         }
     786              :                                 }
     787        50316 :                                 if (min_pos == -1) {
     788              :                                         break;
     789              :                                 }
     790        32800 :                                 ccall.add_argument (out_arg_map.get (min_pos));
     791              :                                 last_pos = min_pos;
     792              :                         }
     793              :                 }
     794              : 
     795        17570 :                 if (async_call != null) {
     796              :                         last_pos = -1;
     797          429 :                         while (true) {
     798          429 :                                 min_pos = -1;
     799         2208 :                                 foreach (int pos in in_arg_map.get_keys ()) {
     800         1350 :                                         if (pos > last_pos && (min_pos == -1 || pos < min_pos)) {
     801          419 :                                                 min_pos = pos;
     802              :                                         }
     803              :                                 }
     804          429 :                                 if (min_pos == -1) {
     805              :                                         break;
     806              :                                 }
     807          316 :                                 async_call.add_argument (in_arg_map.get (min_pos));
     808              :                                 last_pos = min_pos;
     809              :                         }
     810              :                 }
     811              : 
     812        17570 :                 if (expr.is_yield_expression) {
     813              :                         // set state before calling async function to support immediate callbacks
     814           39 :                         int state = emit_context.next_coroutine_state++;
     815              : 
     816           39 :                         ccode.add_assignment (get_variable_cexpression ("_state_"), new CCodeConstant (state.to_string ()));
     817           39 :                         ccode.add_expression (async_call);
     818           39 :                         ccode.add_return (new CCodeConstant ("FALSE"));
     819           39 :                         ccode.add_label ("_state_%d".printf (state));
     820              :                 }
     821              : 
     822        22004 :                 if (expr.is_assert) {
     823         4434 :                         string message = ((string) expr.source_reference.begin.pos).substring (0, (int) (expr.source_reference.end.pos - expr.source_reference.begin.pos));
     824         4434 :                         ccall.call = new CCodeIdentifier ("_vala_assert");
     825         4434 :                         ccall.add_argument (new CCodeConstant ("\"%s\"".printf (message.replace ("\n", " ").escape (""))));
     826         4434 :                         requires_assert = true;
     827              : 
     828              :                 }
     829              : 
     830              :                 // Transform and add free function argument to GLib.[List,Queue,SList].remove[_all] calls
     831        17570 :                 unowned DataType? collection_type = null;
     832        17570 :                 if (ma != null && ma.inner != null) {
     833        16033 :                         collection_type = ma.inner.value_type;
     834              :                 }
     835        16057 :                 if (collection_type != null
     836        10138 :                     && (collection_type.type_symbol == glist_type || collection_type.type_symbol == gslist_type || collection_type.type_symbol == gqueue_type)
     837          112 :                     && (ma.member_name == "remove" || ma.member_name == "remove_all")
     838              :                     //FIXME Perform stricter type argument check earlier
     839           12 :                     && collection_type.check_type_arguments (context)) {
     840           12 :                         var remove_method = (Method) collection_type.type_symbol.scope.lookup (ma.member_name + "_full");
     841           12 :                         var type_arg = collection_type.get_type_arguments ()[0];
     842           12 :                         if (remove_method != null && requires_destroy (type_arg)) {
     843              :                                 // only add them once per source file
     844            6 :                                 if (add_generated_external_symbol (remove_method)) {
     845            6 :                                         visit_method (remove_method);
     846              :                                 }
     847            6 :                                 ccall.call = new CCodeIdentifier (get_ccode_name (remove_method));
     848            6 :                                 ccall.add_argument (get_destroy0_func_expression (type_arg));
     849              :                         }
     850              :                 }
     851              : 
     852        17570 :                 if (return_result_via_out_param) {
     853           66 :                         ccode.add_expression (ccall_expr);
     854          132 :                         ccall_expr = out_param_ref;
     855              :                 }
     856              : 
     857        17570 :                 if (m != null && m.binding == MemberBinding.INSTANCE && m.returns_modified_pointer) {
     858           55 :                         if (ma != null && ma.inner.symbol_reference is Property && ma.inner is MemberAccess) {
     859            1 :                                 var prop = (Property) ma.inner.symbol_reference;
     860            1 :                                 store_property (prop, ((MemberAccess) ma.inner).inner, new GLibValue (expr.value_type, ccall_expr));
     861            1 :                                 ccall_expr = null;
     862              :                         } else {
     863           53 :                                 ccall_expr = new CCodeAssignment (instance, ccall_expr);
     864              :                         }
     865              :                 }
     866              : 
     867              :                 // real structs are passed by reference for simple generics
     868        17605 :                 if (m != null && get_ccode_simple_generics (m) && m.return_type is GenericType
     869           38 :                     && expr.value_type.is_real_struct_type () && !expr.value_type.nullable && !(expr.value_type is PointerType)) {
     870            2 :                     ccall_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeParenthesizedExpression (ccall_expr));
     871              :                 }
     872              : 
     873        17570 :                 if (m != null && get_ccode_type (m) != null && get_ccode_type (m) != get_ccode_name (m.return_type)) {
     874              :                         // Bug 699956: Implement cast for method return type if [CCode type=] annotation is specified
     875            1 :                         ccall_expr = new CCodeCastExpression (ccall_expr, get_ccode_name (m.return_type));
     876              :                 }
     877              : 
     878        17570 :                 if (m is ArrayResizeMethod) {
     879              :                         // FIXME: size expression must not be evaluated twice at runtime (potential side effects)
     880           13 :                         Iterator<Expression> arg_it = expr.get_argument_list ().iterator ();
     881           13 :                         arg_it.next ();
     882           26 :                         var new_size = get_cvalue (arg_it.get ());
     883              : 
     884           13 :                         var array_type = (ArrayType) ma.inner.value_type;
     885           13 :                         var temp_decl = get_temp_variable (array_type.length_type);
     886           13 :                         var temp_ref = get_variable_cexpression (temp_decl.name);
     887              : 
     888           13 :                         emit_temp_var (temp_decl);
     889              : 
     890              :                         /* memset needs string.h */
     891           13 :                         cfile.add_include ("string.h");
     892              : 
     893           13 :                         var clen = get_array_length_cexpression (ma.inner, 1);
     894           13 :                         var celems = get_cvalue (ma.inner);
     895           13 :                         var csizeof = new CCodeIdentifier ("sizeof (%s)".printf (get_ccode_name (array_type.element_type)));
     896           13 :                         var cdelta = new CCodeBinaryExpression (CCodeBinaryOperator.MINUS, temp_ref, clen);
     897           13 :                         var ccheck = new CCodeBinaryExpression (CCodeBinaryOperator.GREATER_THAN, temp_ref, clen);
     898              : 
     899           13 :                         var czero = new CCodeFunctionCall (new CCodeIdentifier ("memset"));
     900           13 :                         czero.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, celems, clen));
     901           13 :                         czero.add_argument (new CCodeConstant ("0"));
     902           13 :                         czero.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.MUL, csizeof, cdelta));
     903              : 
     904           13 :                         ccode.add_assignment (temp_ref, new_size);
     905           13 :                         ccode.add_expression (ccall_expr);
     906           13 :                         ccode.add_expression (new CCodeConditionalExpression (ccheck, czero, new CCodeConstant ("NULL")));
     907           13 :                         ccode.add_assignment (get_array_length_cexpression (ma.inner, 1), temp_ref);
     908              : 
     909           13 :                         var array_var = ma.inner.symbol_reference;
     910           13 :                         if (array_var != null && array_var.is_internal_symbol ()
     911           13 :                             && (array_var is LocalVariable || array_var is Field)) {
     912           11 :                                 ccode.add_assignment (get_array_size_cvalue (ma.inner.target_value), temp_ref);
     913              :                         }
     914              : 
     915           13 :                         return;
     916              :                 }
     917              : 
     918        24435 :                 if (expr.parent_node is ExpressionStatement && !expr.value_type.is_disposable ()) {
     919        10679 :                         if (ccall_expr != null && !return_result_via_out_param) {
     920        10164 :                                 ccode.add_expression (ccall_expr);
     921              :                         }
     922              :                 } else {
     923         6878 :                         var result_type = itype.get_return_type ();
     924              : 
     925         7384 :                         if (expr.formal_value_type is GenericType && !(expr.value_type is GenericType)) {
     926          506 :                                 var type_parameter = ((GenericType) expr.formal_value_type).type_parameter;
     927          506 :                                 var st = type_parameter.parent_symbol.parent_symbol as Struct;
     928          506 :                                 if (type_parameter.parent_symbol == garray_type ||
     929          489 :                                     (st != null && get_ccode_name (st) == "va_list")) {
     930              :                                         // GArray and va_list don't use pointer-based generics
     931              :                                         // above logic copied from visit_expression ()
     932              :                                         // TODO avoid code duplication
     933          104 :                                         result_type = expr.value_type;
     934              :                                 }
     935          506 :                                 if (st != null && get_ccode_name (st) == "va_list" && ma.member_name == "arg") {
     936           35 :                                         if (result_type is DelegateType && ((DelegateType) result_type).delegate_symbol.has_target) {
     937            1 :                                                 set_cvalue (expr, null);
     938              :                                                 // Initialize target/destroy cvalues to allow assignment of delegates from varargs
     939            1 :                                                 unowned GLibValue arg_value = (GLibValue) expr.target_value;
     940            1 :                                                 if (arg_value.delegate_target_cvalue == null) {
     941            1 :                                                         arg_value.delegate_target_cvalue = new CCodeConstant ("NULL");
     942              :                                                 }
     943            1 :                                                 if (arg_value.delegate_target_destroy_notify_cvalue == null) {
     944            1 :                                                         arg_value.delegate_target_destroy_notify_cvalue = new CCodeConstant ("NULL");
     945              :                                                 }
     946              :                                         }
     947              :                                 }
     948              :                         }
     949              : 
     950         6878 :                         if (m != null && m.get_format_arg_index () >= 0) {
     951           27 :                                 set_cvalue (expr, ccall_expr);
     952         6851 :                         } else if (m != null && m.get_attribute_bool ("CCode", "use_inplace", false)) {
     953            0 :                                 set_cvalue (expr, ccall_expr);
     954         6851 :                         } else if (!return_result_via_out_param
     955         6786 :                             && !has_ref_out_argument (expr)
     956         6700 :                             && (result_type is ValueType && !result_type.is_disposable ())) {
     957         1445 :                                 set_cvalue (expr, ccall_expr);
     958        10747 :                         } else if (!return_result_via_out_param) {
     959         5341 :                                 var temp_var = get_temp_variable (result_type, result_type.value_owned, null, false);
     960         5341 :                                 var temp_ref = get_variable_cexpression (temp_var.name);
     961              : 
     962         5341 :                                 emit_temp_var (temp_var);
     963              : 
     964         5341 :                                 ccode.add_assignment (temp_ref, ccall_expr);
     965         5341 :                                 set_cvalue (expr, temp_ref);
     966         5341 :                                 ((GLibValue) expr.target_value).lvalue = true;
     967              :                         } else {
     968           65 :                                 set_cvalue (expr, ccall_expr);
     969           65 :                                 ((GLibValue) expr.target_value).lvalue = true;
     970              :                         }
     971              :                 }
     972              : 
     973        17557 :                 params_it = params.iterator ();
     974        37886 :                 foreach (Expression arg in expr.get_argument_list ()) {
     975        20116 :                         Parameter param = null;
     976              : 
     977        20116 :                         if (params_it.next ()) {
     978        19809 :                                 param = params_it.get ();
     979              :                         }
     980              : 
     981        20116 :                         var unary = arg as UnaryExpression;
     982              : 
     983              :                         // handle ref null terminated arrays
     984          439 :                         if (unary != null && unary.operator == UnaryOperator.REF
     985           72 :                             && unary.inner.symbol_reference != null && get_ccode_array_length (unary.inner.symbol_reference)) {
     986           71 :                                 if (param != null && get_ccode_array_null_terminated (param) && !get_ccode_array_length (param)
     987            2 :                                     && param.variable_type is ArrayType && ((ArrayType) param.variable_type).rank == 1) {
     988            2 :                                         requires_array_length = true;
     989            2 :                                         var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
     990            2 :                                         len_call.add_argument (get_cvalue_ (unary.inner.target_value));
     991            2 :                                         ccode.add_assignment (get_array_length_cvalue (unary.inner.target_value, 1), len_call);
     992              :                                 }
     993              :                         }
     994              : 
     995              :                         // update possible stale _*_size_ variable
     996        20187 :                         if (unary != null && unary.operator == UnaryOperator.REF
     997           72 :                             && unary.inner.symbol_reference != null && get_ccode_array_length (unary.inner.symbol_reference)) {
     998           69 :                                 if (param != null && param.variable_type is ArrayType
     999           17 :                                     && !((ArrayType) param.variable_type).fixed_length && ((ArrayType) param.variable_type).rank == 1) {
    1000           15 :                                         unowned Variable? array_var = unary.inner.symbol_reference as Variable;
    1001           15 :                                         if ((array_var is LocalVariable || array_var is Field) && array_var.is_internal_symbol ()
    1002           11 :                                             && array_var.variable_type is ArrayType && !((ArrayType) array_var.variable_type).fixed_length) {
    1003           11 :                                                 ccode.add_assignment (get_array_size_cvalue (unary.inner.target_value), get_array_length_cvalue (unary.inner.target_value, 1));
    1004              :                                         }
    1005              :                                 }
    1006              :                         }
    1007              : 
    1008        20116 :                         if (unary == null || unary.operator != UnaryOperator.OUT) {
    1009        19903 :                                 continue;
    1010              :                         }
    1011              : 
    1012          213 :                         if (requires_destroy (unary.inner.value_type)) {
    1013              :                                 // unref old value
    1014           83 :                                 ccode.add_expression (destroy_value (unary.inner.target_value));
    1015              :                         }
    1016              : 
    1017              :                         // infer type of out-parameter from argument
    1018          213 :                         if (ma.symbol_reference is DynamicMethod && unary.target_value.value_type == null) {
    1019            1 :                                 unary.target_value.value_type = unary.inner.value_type.copy ();
    1020              :                         }
    1021              : 
    1022              :                         // assign new value
    1023          213 :                         store_value (unary.inner.target_value, transform_value (unary.target_value, unary.inner.value_type, arg), expr.source_reference);
    1024              : 
    1025              :                         // handle out null terminated arrays
    1026          220 :                         if (param != null && get_ccode_array_null_terminated (param) && !get_ccode_array_length (param)
    1027            4 :                             && unary.inner.symbol_reference != null && get_ccode_array_length (unary.inner.symbol_reference)) {
    1028            3 :                                 requires_array_length = true;
    1029            3 :                                 var len_call = new CCodeFunctionCall (new CCodeIdentifier ("_vala_array_length"));
    1030            3 :                                 len_call.add_argument (get_cvalue_ (unary.inner.target_value));
    1031              : 
    1032            3 :                                 ccode.add_assignment (get_array_length_cvalue (unary.inner.target_value, 1), len_call);
    1033              :                         }
    1034              :                 }
    1035              : 
    1036        17569 :                 if (m is CreationMethod && m.parent_symbol is Class && ((current_class.is_compact && current_class.base_class != null) || current_class.is_subtype_of (gsource_type))) {
    1037           12 :                         var cinitcall = new CCodeFunctionCall (new CCodeIdentifier ("%s_instance_init".printf (get_ccode_lower_case_name (current_class, null))));
    1038           12 :                         cinitcall.add_argument (get_this_cexpression ());
    1039           12 :                         if (!current_class.is_compact) {
    1040            0 :                                 cinitcall.add_argument (new CCodeConstant ("NULL"));
    1041              :                         }
    1042           12 :                         ccode.add_expression (cinitcall);
    1043              :                 }
    1044              :         }
    1045              : 
    1046            5 :         private string generate_enum_to_string_function (Enum en) {
    1047            5 :                 var to_string_func = "_%s_to_string".printf (get_ccode_lower_case_name (en));
    1048              : 
    1049            5 :                 if (!add_wrapper (to_string_func)) {
    1050              :                         // wrapper already defined
    1051            5 :                         return to_string_func;
    1052              :                 }
    1053              :                 // declaration
    1054              : 
    1055            3 :                 var function = new CCodeFunction (to_string_func, "const char*");
    1056            3 :                 function.modifiers = CCodeModifiers.STATIC;
    1057              : 
    1058            3 :                 function.add_parameter (new CCodeParameter ("value", get_ccode_name (en)));
    1059              : 
    1060              :                 // definition
    1061            3 :                 push_context (new EmitContext ());
    1062            3 :                 push_function (function);
    1063              : 
    1064            3 :                 ccode.open_switch (new CCodeConstant ("value"));
    1065           19 :                 foreach (var enum_value in en.get_values ()) {
    1066            8 :                         ccode.add_case (new CCodeIdentifier (get_ccode_name (enum_value)));
    1067            8 :                         ccode.add_return (new CCodeConstant ("\""+get_ccode_name (enum_value)+"\""));
    1068              :                 }
    1069            3 :                 ccode.close ();
    1070            3 :                 ccode.add_return (new CCodeConstant ("NULL"));
    1071              : 
    1072              :                 // append to file
    1073            3 :                 cfile.add_function_declaration (function);
    1074            3 :                 cfile.add_function (function);
    1075              : 
    1076            3 :                 pop_context ();
    1077              : 
    1078            3 :                 return to_string_func;
    1079              :         }
    1080              : 
    1081         6786 :         bool has_ref_out_argument (MethodCall c) {
    1082        20600 :                 foreach (var arg in c.get_argument_list ()) {
    1083         6993 :                         unowned UnaryExpression? unary = arg as UnaryExpression;
    1084         6993 :                         if (unary != null && (unary.operator == UnaryOperator.OUT || unary.operator == UnaryOperator.REF)) {
    1085           86 :                                 return true;
    1086              :                         }
    1087              :                 }
    1088         6786 :                 return false;
    1089              :         }
    1090              : 
    1091            1 :         string generate_string_printf_function () {
    1092            1 :                 if (!add_wrapper ("string_printf")) {
    1093              :                         // wrapper already defined
    1094            0 :                         return "string_printf";
    1095              :                 }
    1096              : 
    1097              :                 // declaration
    1098            1 :                 var function = new CCodeFunction ("string_printf", "char*");
    1099            1 :                 function.add_parameter (new CCodeParameter ("format", "const char*"));
    1100            1 :                 function.add_parameter (new CCodeParameter.with_ellipsis ());
    1101            1 :                 function.modifiers = CCodeModifiers.STATIC | CCodeModifiers.PRINTF;
    1102              : 
    1103              :                 // definition
    1104            1 :                 push_context (new EmitContext ());
    1105            1 :                 push_function (function);
    1106              : 
    1107            1 :                 ccode.add_declaration ("int", new CCodeVariableDeclarator ("length"));
    1108            1 :                 ccode.add_declaration ("va_list", new CCodeVariableDeclarator ("ap"));
    1109            1 :                 ccode.add_declaration ("char*", new CCodeVariableDeclarator ("result"));
    1110              : 
    1111            1 :                 var vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start"));
    1112            1 :                 vastart.add_argument (new CCodeIdentifier ("ap"));
    1113            1 :                 vastart.add_argument (new CCodeIdentifier ("format"));
    1114              : 
    1115            1 :                 ccode.add_expression (vastart);
    1116              : 
    1117            1 :                 if (context.profile == Profile.POSIX) {
    1118            1 :                         cfile.add_include ("stdio.h");
    1119              :                 }
    1120              : 
    1121            1 :                 var vsnprintf = new CCodeFunctionCall (new CCodeIdentifier ("vsnprintf"));
    1122            1 :                 vsnprintf.add_argument (new CCodeConstant ("NULL"));
    1123            1 :                 vsnprintf.add_argument (new CCodeConstant ("0"));
    1124            1 :                 vsnprintf.add_argument (new CCodeIdentifier ("format"));
    1125            1 :                 vsnprintf.add_argument (new CCodeIdentifier ("ap"));
    1126              : 
    1127            1 :                 ccode.add_assignment (new CCodeIdentifier ("length"), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, vsnprintf, new CCodeConstant ("1")));
    1128              : 
    1129            1 :                 var va_end = new CCodeFunctionCall (new CCodeIdentifier ("va_end"));
    1130            1 :                 va_end.add_argument (new CCodeIdentifier ("ap"));
    1131              : 
    1132            1 :                 ccode.add_expression (va_end);
    1133              : 
    1134            1 :                 var malloc = new CCodeFunctionCall (new CCodeIdentifier ("malloc"));
    1135            1 :                 malloc.add_argument (new CCodeIdentifier ("length"));
    1136              : 
    1137            1 :                 ccode.add_assignment (new CCodeIdentifier ("result"), malloc);
    1138              : 
    1139            1 :                 vastart = new CCodeFunctionCall (new CCodeIdentifier ("va_start"));
    1140            1 :                 vastart.add_argument (new CCodeIdentifier ("ap"));
    1141            1 :                 vastart.add_argument (new CCodeIdentifier ("format"));
    1142              : 
    1143            1 :                 ccode.add_expression (vastart);
    1144              : 
    1145            1 :                 vsnprintf = new CCodeFunctionCall (new CCodeIdentifier ("vsnprintf"));
    1146            1 :                 vsnprintf.add_argument (new CCodeIdentifier ("result"));
    1147            1 :                 vsnprintf.add_argument (new CCodeIdentifier ("length"));
    1148            1 :                 vsnprintf.add_argument (new CCodeIdentifier ("format"));
    1149            1 :                 vsnprintf.add_argument (new CCodeIdentifier ("ap"));
    1150              : 
    1151            1 :                 ccode.add_expression (vsnprintf);
    1152              : 
    1153            1 :                 va_end = new CCodeFunctionCall (new CCodeIdentifier ("va_end"));
    1154            1 :                 va_end.add_argument (new CCodeIdentifier ("ap"));
    1155              : 
    1156            1 :                 ccode.add_expression (va_end);
    1157              : 
    1158            1 :                 ccode.add_return (new CCodeIdentifier ("result"));
    1159              : 
    1160              :                 // append to file
    1161            1 :                 cfile.add_include ("stdarg.h");
    1162            1 :                 cfile.add_function_declaration (function);
    1163            1 :                 cfile.add_function (function);
    1164              : 
    1165            1 :                 pop_context ();
    1166              : 
    1167            1 :                 return "string_printf";
    1168              :         }
    1169              : }
    1170              : 
        

Generated by: LCOV version 2.0-1