unsigned is_res : 1; /**< 1: the call argument is a return value. 0: it's a call parameter. */
unsigned in_reg : 1; /**< 1: this argument is transmitted in registers. */
unsigned on_stack : 1; /**< 1: this argument is transmitted on the stack. */
+ unsigned callee : 1; /**< 1: someone called us. 0: We call another function */
int pos;
const arch_register_t *reg;
{
const be_abi_call_arg_t *p = a, *q = b;
(void) n;
- return !(p->is_res == q->is_res && p->pos == q->pos);
+ return !(p->is_res == q->is_res && p->pos == q->pos && p->callee == q->callee);
}
/**
* @param call the abi call
* @param is_res true for call results, false for call arguments
* @param pos position of the argument
+ * @param callee context type - if we are callee or caller
*/
-static be_abi_call_arg_t *get_call_arg(be_abi_call_t *call, int is_res, int pos)
+static be_abi_call_arg_t *get_call_arg(be_abi_call_t *call, int is_res, int pos, int callee)
{
be_abi_call_arg_t arg;
unsigned hash;
memset(&arg, 0, sizeof(arg));
arg.is_res = is_res;
arg.pos = pos;
+ arg.callee = callee;
hash = is_res * 128 + pos;
/**
* Set an ABI call object argument.
- *
- * @param call the abi call
- * @param is_res true for call results, false for call arguments
- * @param pos position of the argument
*/
-static be_abi_call_arg_t *create_call_arg(be_abi_call_t *call, int is_res, int pos)
+static void remember_call_arg(be_abi_call_arg_t *arg, be_abi_call_t *call, be_abi_context_t context)
{
- be_abi_call_arg_t arg;
- unsigned hash;
-
- memset(&arg, 0, sizeof(arg));
- arg.is_res = is_res;
- arg.pos = pos;
-
- hash = is_res * 128 + pos;
-
- return set_insert(call->params, &arg, sizeof(arg), hash);
+ unsigned hash = arg->is_res * 128 + arg->pos;
+ if (context & ABI_CONTEXT_CALLEE) {
+ arg->callee = 1;
+ set_insert(call->params, arg, sizeof(*arg), hash);
+ }
+ if (context & ABI_CONTEXT_CALLER) {
+ arg->callee = 0;
+ set_insert(call->params, arg, sizeof(*arg), hash);
+ }
}
/* Set the flags for a call. */
}
-void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos, ir_mode *load_mode, unsigned alignment, unsigned space_before, unsigned space_after)
+void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos,
+ ir_mode *load_mode, unsigned alignment,
+ unsigned space_before, unsigned space_after,
+ be_abi_context_t context)
{
- be_abi_call_arg_t *arg = create_call_arg(call, 0, arg_pos);
- arg->on_stack = 1;
- arg->load_mode = load_mode;
- arg->alignment = alignment;
- arg->space_before = space_before;
- arg->space_after = space_after;
+ be_abi_call_arg_t arg;
+ memset(&arg, 0, sizeof(arg));
assert(alignment > 0 && "Alignment must be greater than 0");
+ arg.on_stack = 1;
+ arg.load_mode = load_mode;
+ arg.alignment = alignment;
+ arg.space_before = space_before;
+ arg.space_after = space_after;
+ arg.is_res = 0;
+ arg.pos = arg_pos;
+
+ remember_call_arg(&arg, call, context);
}
-void be_abi_call_param_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg)
+void be_abi_call_param_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg, be_abi_context_t context)
{
- be_abi_call_arg_t *arg = create_call_arg(call, 0, arg_pos);
- arg->in_reg = 1;
- arg->reg = reg;
+ be_abi_call_arg_t arg;
+ memset(&arg, 0, sizeof(arg));
+
+ arg.in_reg = 1;
+ arg.reg = reg;
+ arg.is_res = 0;
+ arg.pos = arg_pos;
+
+ remember_call_arg(&arg, call, context);
}
-void be_abi_call_res_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg)
+void be_abi_call_res_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg, be_abi_context_t context)
{
- be_abi_call_arg_t *arg = create_call_arg(call, 1, arg_pos);
- arg->in_reg = 1;
- arg->reg = reg;
+ be_abi_call_arg_t arg;
+ memset(&arg, 0, sizeof(arg));
+
+ arg.in_reg = 1;
+ arg.reg = reg;
+ arg.is_res = 1;
+ arg.pos = arg_pos;
+
+ remember_call_arg(&arg, call, context);
}
/* Get the flags of a ABI call object. */
return frame;
}
-/**
- * Returns non-zero if the call argument at given position
- * is transfered on the stack.
- */
-static inline int is_on_stack(be_abi_call_t *call, int pos)
-{
- be_abi_call_arg_t *arg = get_call_arg(call, 0, pos);
- return arg && !arg->in_reg;
-}
-
/*
____ _ _
/ ___|__ _| | |___
assert(obstack_object_size(obst) == 0);
stack_param_idx = ALLOCAN(int, n_params);
for (i = 0; i < n_params; ++i) {
- be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, i, 0);
assert(arg);
if (arg->on_stack) {
int arg_size = get_type_size_bytes(get_method_param_type(call_tp, i));
/* Collect all arguments which are passed in registers. */
reg_param_idxs = ALLOCAN(int, n_params);
for (i = 0; i < n_params; ++i) {
- be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, i, 0);
if (arg && arg->in_reg) {
reg_param_idxs[n_reg_params++] = i;
}
for (i = 0; i < n_stack_params; ++i) {
int p = stack_param_idx[i];
- be_abi_call_arg_t *arg = get_call_arg(call, 0, p);
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, p, 0);
ir_node *param = get_Call_param(irn, p);
ir_node *addr = curr_sp;
ir_node *mem = NULL;
for (i = 0; i < n_res; ++i) {
int pn;
ir_node *proj = res_projs[i];
- be_abi_call_arg_t *arg = get_call_arg(call, 1, i);
+ be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 0);
/* returns values on stack not supported yet */
assert(arg->in_reg);
/* Set the register classes and constraints of the Call parameters. */
for (i = 0; i < n_reg_params; ++i) {
int index = reg_param_idxs[i];
- be_abi_call_arg_t *arg = get_call_arg(call, 0, index);
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, index, 0);
assert(arg->reg != NULL);
be_set_constr_single_reg_in(low_call, be_pos_Call_first_arg + i,
/* Set the register constraints of the results. */
for (i = 0; i < n_res; ++i) {
ir_node *proj = res_projs[i];
- const be_abi_call_arg_t *arg = get_call_arg(call, 1, i);
+ const be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 0);
int pn = get_Proj_proj(proj);
assert(arg->in_reg);
ir_node *new_alloc;
ir_node *count;
ir_node *size;
- ir_node *addr;
ir_node *ins[2];
unsigned stack_alignment;
/* fix projnum of alloca res */
set_Proj_proj(alloc_res, pn_be_AddSP_res);
- addr = alloc_res;
curr_sp = new_r_Proj(new_alloc, get_irn_mode(curr_sp), pn_be_AddSP_sp);
return curr_sp;
break;
default:
panic("invalid call");
- break;
}
}
res = new_type_struct(id_mangle_u(id, new_id_from_chars("arg_type", 8)));
for (i = 0; i < n; ++i, curr += inc) {
ir_type *param_type = get_method_param_type(method_type, curr);
- be_abi_call_arg_t *arg = get_call_arg(call, 0, curr);
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, curr, 1);
map[i] = NULL;
if (arg->on_stack) {
/* Insert results for Return into the register map. */
for (i = 0; i < n_res; ++i) {
ir_node *res = get_Return_res(irn, i);
- be_abi_call_arg_t *arg = get_call_arg(call, 1, i);
+ be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 1);
assert(arg->in_reg && "return value must be passed in register");
pmap_insert(reg_map, (void *) arg->reg, res);
}
/* clear SP entry, since it has already been grown. */
pmap_insert(reg_map, (void *) arch_env->sp, NULL);
for (i = 0; i < n_res; ++i) {
- be_abi_call_arg_t *arg = get_call_arg(call, 1, i);
+ be_abi_call_arg_t *arg = get_call_arg(call, 1, i, 1);
in[n] = be_abi_reg_map_get(reg_map, arg->reg);
regs[n++] = arg->reg;
new_list = NULL;
for (i = 0; i < n; ++i) {
int pos = value_param_list[i].pos;
- be_abi_call_arg_t *arg = get_call_arg(call, 0, pos);
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, pos, 1);
if (arg->in_reg) {
DBG((dbg, LEVEL_2, "\targ #%d need backing store\n", pos));
if (new_list != NULL) {
/* ok, change the graph */
ir_node *start_bl = get_irg_start_block(irg);
- ir_node *first_bl = NULL;
- ir_node *frame, *imem, *nmem, *store, *mem, *args, *args_bl;
- const ir_edge_t *edge;
+ ir_node *first_bl = get_first_block_succ(start_bl);
+ ir_node *frame, *imem, *nmem, *store, *mem, *args;
optimization_state_t state;
unsigned offset;
- foreach_block_succ(start_bl, edge) {
- first_bl = get_edge_src_irn(edge);
- break;
- }
assert(first_bl && first_bl != start_bl);
/* we had already removed critical edges, so the following
assertion should be always true. */
store = NULL;
mem = imem;
args = get_irg_args(irg);
- args_bl = get_nodes_block(args);
for (entry = new_list; entry != NULL; entry = entry->next) {
int i = entry->pos;
ir_type *tp = get_entity_type(entry->ent);
/* Count the register params and add them to the number of Projs for the RegParams node */
for (i = 0; i < n_params; ++i) {
- be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, i, 1);
if (arg->in_reg && args[i]) {
assert(arg->reg != sp && "cannot use stack pointer as parameter register");
assert(i == get_Proj_proj(args[i]));
ir_mode *mode;
nr = MIN(nr, n_params);
- arg = get_call_arg(call, 0, nr);
+ arg = get_call_arg(call, 0, nr, 1);
param_type = get_method_param_type(method_type, nr);
if (arg->in_reg) {