return res;
}
+static void fix_parameter_entities(ir_graph *irg, size_t n_compound_ret)
+{
+ ir_type *frame_type = get_irg_frame_type(irg);
+ size_t n_compound = get_compound_n_members(frame_type);
+ size_t i;
+
+ if (n_compound_ret == 0)
+ return;
+
+ for (i = 0; i < n_compound; ++i) {
+ ir_entity *member = get_compound_member(frame_type, i);
+ size_t num;
+ if (!is_parameter_entity(member))
+ continue;
+
+ /* 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);
+ }
+}
+
/**
* Creates a new lowered type for a method type with compound
* arguments. The new type is associated to the old one and returned.
size_t nn_ress;
size_t nn_params;
size_t i;
+ mtp_additional_properties mtp_properties;
if (!is_Method_type(mtp))
return 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)
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);
+ 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);
pmap *dummy_map; /**< A map for finding the dummy arguments. */
compound_call_lowering_flags flags;
ir_type *lowered_mtp; /**< The lowered method type of the current irg if any. */
- ir_type *value_params; /**< The value params type if any. */
unsigned only_local_mem:1; /**< Set if only local memory access was found. */
unsigned changed:1; /**< Set if the current graph was changed. */
} wlk_env;
ir_node *ptr;
switch (get_irn_opcode(n)) {
- case iro_Sel:
- if (env->lowered_mtp != NULL && env->value_params != NULL) {
- ir_entity *ent = get_Sel_entity(n);
-
- if (get_entity_owner(ent) == env->value_params) {
- size_t pos = get_struct_member_index(env->value_params, ent) + env->arg_shift;
- ir_entity *new_ent;
-
- new_ent = get_method_value_param_ent(env->lowered_mtp, pos);
- set_entity_ident(new_ent, get_entity_ident(ent));
- set_Sel_entity(n, new_ent);
- }
- }
- break;
case iro_Load:
case iro_Store:
if (env->only_local_mem) {
}
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;
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);
++n_ret_com;
}
+ fix_parameter_entities(irg, n_ret_com);
+
if (n_ret_com) {
/* much easier if we have only one return */
normalize_one_return(irg);
env.dummy_map = pmap_create_ex(8);
env.flags = flags;
env.lowered_mtp = lowered_mtp;
- env.value_params = get_method_value_param_type(mtp);
env.only_local_mem = 1;
env.changed = 0;