begnuas: let user specify elf variants
[libfirm] / ir / lower / lower_calls.c
index 2560b3f..9e57bef 100644 (file)
@@ -77,6 +77,8 @@ static void fix_parameter_entities(ir_graph *irg, size_t n_compound_ret)
 
                /* increase parameter number since we added a new parameter in front */
                num = get_entity_parameter_number(member);
+               if (num == IR_VA_START_PARAMETER_NUMBER)
+                       continue;
                set_entity_parameter_number(member, num + n_compound_ret);
        }
 }
@@ -96,6 +98,7 @@ static ir_type *lower_mtp(compound_call_lowering_flags flags, ir_type *mtp)
        size_t    nn_ress;
        size_t    nn_params;
        size_t    i;
+       mtp_additional_properties mtp_properties;
 
        if (!is_Method_type(mtp))
                return mtp;
@@ -147,6 +150,7 @@ static ir_type *lower_mtp(compound_call_lowering_flags flags, ir_type *mtp)
 
        /* create the new type */
        lowered = new_d_type_method(nn_params, nn_ress, get_type_dbg_info(mtp));
+       lowered->attr.ma.has_compound_ret_parameter = true;
 
        /* fill it */
        for (i = 0; i < nn_params; ++i)
@@ -156,10 +160,14 @@ static ir_type *lower_mtp(compound_call_lowering_flags flags, ir_type *mtp)
 
        set_method_variadicity(lowered, get_method_variadicity(mtp));
 
-       /* associate the lowered type with the original one for easier access */
        set_method_calling_convention(lowered, get_method_calling_convention(mtp) | cc_compound_ret);
-       set_method_additional_properties(lowered, get_method_additional_properties(mtp));
+       mtp_properties = get_method_additional_properties(mtp);
+       /* after lowering the call is not const anymore, since it writes to the
+        * memory for the return value passed to it */
+       mtp_properties &= ~mtp_property_const;
+       set_method_additional_properties(lowered, mtp_properties);
 
+       /* associate the lowered type with the original one for easier access */
        set_lowered_type(mtp, lowered);
        pmap_insert(lowered_mtps, mtp, lowered);
 
@@ -360,6 +368,16 @@ static void fix_args_and_collect_calls(ir_node *n, void *ctx)
                }
                break;
        }
+       case iro_Sel: {
+               ir_entity *ent  = get_Sel_entity(n);
+               ir_type   *type = get_entity_type(ent);
+
+               /* we need to copy compound parameters */
+               if (is_parameter_entity(ent) && is_compound_type(type)) {
+                       env->only_local_mem = 0;
+               }
+               break;
+       }
        default:
                /* do nothing */
                break;
@@ -473,9 +491,14 @@ static void add_hidden_param(ir_graph *irg, size_t n_com, ir_node **ins,
                n = (ir_node*)get_irn_link(p);
 
                ins[idx] = get_CopyB_dst(p);
-               mem      = get_CopyB_mem(p);
                blk      = get_nodes_block(p);
 
+               /* use the memory output of the call and not the input of the CopyB
+                * otherwise stuff breaks if the call was mtp_property_const, because
+                * then the copyb skips the call. But after lowering the call is not
+                * const anymore, and its memory has to be used */
+               mem = new_r_Proj(entry->call, mode_M, pn_Call_M);
+
                /* get rid of the CopyB */
                turn_into_tuple(p, pn_CopyB_max+1);
                set_Tuple_pred(p, pn_CopyB_M,         mem);