Allow selecting one past the last parameter to get variadic parameters.
authorChristoph Mallon <christoph.mallon@gmx.de>
Wed, 17 Aug 2011 19:00:50 +0000 (21:00 +0200)
committerChristoph Mallon <christoph.mallon@gmx.de>
Wed, 17 Aug 2011 19:00:50 +0000 (21:00 +0200)
ir/be/beabi.c
ir/lower/lower_dw.c

index 1da1d04..b823fa1 100644 (file)
@@ -1169,6 +1169,7 @@ static ir_type *compute_arg_type(ir_graph *irg, be_abi_call_t *call,
        ir_type *frame_type      = get_irg_frame_type(irg);
        size_t   n_params        = get_method_n_params(method_type);
        size_t   n_frame_members = get_compound_n_members(frame_type);
+       size_t   n_real_params   = n_params;
        size_t   f;
        int      ofs  = 0;
 
@@ -1176,7 +1177,12 @@ static ir_type *compute_arg_type(ir_graph *irg, be_abi_call_t *call,
        size_t i;
        ir_entity **map;
 
-       *param_map = map = OALLOCNZ(obst, ir_entity*, n_params);
+       /* Allow selecting one past the last parameter to get the variadic
+        * parameters. */
+       if (get_method_variadicity(method_type) == variadicity_variadic)
+               ++n_real_params;
+
+       *param_map = map = OALLOCNZ(obst, ir_entity*, n_real_params);
        res = new_type_struct(new_id_from_chars("arg_type", 8));
 
        /* collect existing entities for value_param_types */
@@ -1188,11 +1194,11 @@ static ir_type *compute_arg_type(ir_graph *irg, be_abi_call_t *call,
                if (!is_parameter_entity(entity))
                        continue;
                num = get_entity_parameter_number(entity);
-               assert(num < n_params);
+               assert(num < n_real_params);
                if (map[num] != NULL)
                        panic("multiple entities for parameter %u in %+F found", f, irg);
 
-               if (!get_call_arg(call, 0, num, 1)->on_stack) {
+               if (num != n_params && !get_call_arg(call, 0, num, 1)->on_stack) {
                        /* don't move this entity */
                        continue;
                }
@@ -1224,6 +1230,11 @@ static ir_type *compute_arg_type(ir_graph *irg, be_abi_call_t *call,
        }
        set_type_size_bytes(res, ofs);
        set_type_state(res, layout_fixed);
+
+       if (n_params != n_real_params && map[n_params] != NULL) {
+               set_entity_offset(map[n_params], ofs);
+       }
+
        return res;
 }
 
index 7b7db75..31a2bb3 100644 (file)
@@ -1606,7 +1606,15 @@ static void fix_parameter_entities(ir_graph *irg)
        ir_type   *orig_mtp = get_type_link(mtp);
 
        size_t      orig_n_params      = get_method_n_params(orig_mtp);
-       ir_entity **parameter_entities = ALLOCANZ(ir_entity*, orig_n_params);
+       size_t      orig_n_real_params = orig_n_params;
+       ir_entity **parameter_entities;
+
+       /* Allow selecting one past the last parameter to get the variadic
+        * parameters. */
+       if (get_method_variadicity(orig_mtp) == variadicity_variadic)
+               ++orig_n_real_params;
+
+       parameter_entities = ALLOCANZ(ir_entity*, orig_n_real_params);
 
        ir_type *frame_type = get_irg_frame_type(irg);
        size_t   n          = get_compound_n_members(frame_type);
@@ -1620,19 +1628,24 @@ static void fix_parameter_entities(ir_graph *irg)
                if (!is_parameter_entity(entity))
                        continue;
                p = get_entity_parameter_number(entity);
-               assert(p < orig_n_params);
+               assert(p < orig_n_real_params);
                assert(parameter_entities[p] == NULL);
                parameter_entities[p] = entity;
        }
 
        /* adjust indices */
        n_param = 0;
-       for (i = 0; i < orig_n_params; ++i, ++n_param) {
+       for (i = 0; i < orig_n_real_params; ++i, ++n_param) {
                ir_entity *entity = parameter_entities[i];
-               ir_type   *tp     = get_method_param_type(orig_mtp, i);
+               ir_type   *tp;
+
                if (entity != NULL)
                        set_entity_parameter_number(entity, n_param);
 
+               if (i == orig_n_params)
+                       break;
+
+               tp = get_method_param_type(orig_mtp, i);
                if (is_Primitive_type(tp)) {
                        ir_mode *mode = get_type_mode(tp);
                        if (mode == env->high_signed || mode == env->high_unsigned) {