int pos;
const arch_register_t *reg;
+ entity *stack_ent;
} be_abi_call_arg_t;
struct _be_abi_call_t {
be_abi_call_flags_t flags;
- unsigned arg_gap;
+ type *between_type;
set *params;
};
+typedef struct _be_stack_frame_t {
+ type *arg_type;
+ type *between_type;
+ type *frame_type;
+
+ type *order[3]; /**< arg, between and frame types ordered. */
+
+ int initial_offset;
+ int stack_dir;
+} be_stack_frame_t;
+
+struct _be_stack_slot_t {
+ struct _be_stack_frame_t *frame;
+ entity *ent;
+};
+
struct _be_abi_irg_t {
struct obstack obst;
be_irg_t *birg;
ir_node *reg_params;
pset *stack_ops; /**< Contains all nodes modifying the stack pointer. */
- pmap *callee_save;
+ pmap *regs;
int start_block_bias;
unsigned omit_fp : 1;
unsigned dedicated_fp : 1;
unsigned left_to_right : 1;
+ unsigned save_old_fp : 1;
+
+ ir_node *store_bp_mem;
+ be_stack_frame_t *frame;
firm_dbg_module_t *dbg; /**< The debugging module. */
};
return get_or_set_call_arg(call, is_res, pos, 0);
}
-void be_abi_call_set_flags(be_abi_call_t *call, be_abi_call_flags_t flags, unsigned arg_gap)
+void be_abi_call_set_flags(be_abi_call_t *call, be_abi_call_flags_t flags, ir_type *between_type)
{
- call->flags = flags;
- call->arg_gap = arg_gap;
+ call->flags = flags;
+ call->between_type = between_type;
}
void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos)
void be_abi_call_param_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg)
{
be_abi_call_arg_t *arg = get_or_set_call_arg(call, 0, arg_pos, 1);
+ arg->in_reg = 1;
arg->reg = reg;
}
void be_abi_call_res_reg(be_abi_call_t *call, int arg_pos, const arch_register_t *reg)
{
be_abi_call_arg_t *arg = get_or_set_call_arg(call, 1, arg_pos, 1);
+ arg->in_reg = 1;
arg->reg = reg;
}
free(call);
}
+static int get_stack_entity_offset(be_stack_frame_t *frame, entity *ent, int bias)
+{
+ type *t = get_entity_type(ent);
+ int ofs = get_entity_offset_bytes(ent);
+
+ int i, index;
+
+ /* Find the type the entity is contained in. */
+ for(index = 0; index < 3; ++index) {
+ if(frame->order[index] == t)
+ break;
+ }
+
+ /* Add the size of all the types below the one of the entity to the entity's offset */
+ for(i = 0; i < index; ++i)
+ ofs += get_type_size_bytes(frame->order[i]);
+
+ /* correct the offset by the initial position of the frame pointer */
+ ofs -= frame->initial_offset;
+
+ /* correct the offset with the current bias. */
+ ofs += bias;
+
+ return ofs;
+}
+
+static int stack_frame_compute_initial_offset(be_stack_frame_t *frame, entity *ent)
+{
+ frame->initial_offset = 0;
+ frame->initial_offset = get_stack_entity_offset(frame, ent, 0);
+ return frame->initial_offset;
+}
+
+static be_stack_frame_t *stack_frame_init(be_stack_frame_t *frame, type *args, type *between, type *locals, int stack_dir)
+{
+ frame->arg_type = args;
+ frame->between_type = between;
+ frame->frame_type = locals;
+ frame->initial_offset = 0;
+ frame->stack_dir = stack_dir;
+ frame->order[1] = between;
+
+ if(stack_dir > 0) {
+ frame->order[0] = args;
+ frame->order[2] = locals;
+ }
+
+ else {
+ frame->order[0] = locals;
+ frame->order[2] = args;
+ }
+
+ return frame;
+}
+
+static INLINE entity *get_sel_ent(ir_node *irn)
+{
+ if(get_irn_opcode(irn) == iro_Sel
+ && get_Sel_ptr(irn) == get_irg_frame(get_irn_irg(irn))) {
+
+ return get_Sel_entity(irn);
+ }
+
+ return NULL;
+}
+
+static void lower_frame_sels_walker(ir_node *irn, void *data)
+{
+ const arch_register_class_t *cls;
+ be_abi_irg_t *env = data;
+ const arch_isa_t *isa = env->birg->main_env->arch_env->isa;
+ ir_graph *irg = get_irn_irg(irn);
+ ir_node *frame = get_irg_frame(irg);
+ ir_node *nw = NULL;
+ opcode opc = get_irn_opcode(irn);
+
+ if(opc == iro_Load) {
+ ir_node *bl = get_nodes_block(irn);
+ ir_node *sel = get_Load_ptr(irn);
+ entity *ent = get_sel_ent(sel);
+ cls = arch_isa_get_reg_class_for_mode(isa, get_Load_mode(irn));
+ if(ent != NULL)
+ nw = be_new_FrameLoad(isa->sp->reg_class, cls, irg, bl, get_Load_mem(irn), frame, ent);
+ }
+
+ else if(opc == iro_Store) {
+ ir_node *bl = get_nodes_block(irn);
+ ir_node *val = get_Store_value(irn);
+ ir_node *sel = get_Store_ptr(irn);
+ entity *ent = get_sel_ent(sel);
+ cls = arch_isa_get_reg_class_for_mode(isa, get_irn_mode(val));
+ if(ent != NULL)
+ nw = be_new_FrameStore(isa->sp->reg_class, cls, irg, bl, get_Store_mem(irn), frame, val, ent);
+ }
+
+ else {
+ entity *ent = get_sel_ent(irn);
+ if(ent != NULL) {
+ ir_node *bl = get_nodes_block(irn);
+ nw = be_new_FrameAddr(isa->sp->reg_class, irg, bl, frame, ent);
+ }
+ }
+
+ if(nw != NULL)
+ exchange(irn, nw);
+}
+
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);
/* Let the isa fill out the abi description for that call node. */
arch_isa_get_call_abi(isa, mt, call);
+ // assert(get_method_variadicity(mt) == variadicity_non_variadic);
+
/* Insert code to put the stack arguments on the stack. */
- for(i = get_irn_arity(irn); i >= 0; --i) {
- if(is_on_stack(call, i)) {
+ /* TODO: Vargargs */
+ assert(get_Call_n_params(irn) == n_params);
+ for(i = 0; i < n_params; ++i) {
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
+ assert(arg);
+ if(!arg->in_reg) {
stack_size += get_type_size_bytes(get_method_param_type(mt, i));
obstack_int_grow(obst, i);
n_pos++;
pos = obstack_finish(obst);
/* Collect all arguments which are passed in registers. */
- for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
+ for(i = 0, n = get_Call_n_params(irn); i < n; ++i) {
be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
if(arg && arg->in_reg) {
obstack_int_grow(obst, i);
assert(mode_is_reference(mach_mode) && "machine mode must be pointer");
for(i = 0; i < n_pos; ++i) {
int p = pos[i];
- ir_node *param = get_irn_n(irn, p);
+ ir_node *param = get_Call_param(irn, p);
ir_node *addr = curr_sp;
ir_node *mem = NULL;
type *param_type = get_method_param_type(mt, p);
}
/* Collect caller save registers */
- for(i = 0; env->birg->main_env->caller_save[i]; ++i)
- pset_insert_ptr(caller_save, env->birg->main_env->caller_save[i]);
+ for(i = 0, n = arch_isa_get_n_reg_class(isa); i < n; ++i) {
+ int j;
+ const arch_register_class_t *cls = arch_isa_get_reg_class(isa, i);
+ for(j = 0; j < cls->n_regs; ++j) {
+ const arch_register_t *reg = arch_register_for_index(cls, j);
+ if(arch_register_type_is(reg, caller_save))
+ pset_insert_ptr(caller_save, (void *) reg);
+ }
+ }
/* search the greatest result proj number */
foreach_out_edge(irn, edge) {
}
curr_res_proj++;
+ /* make the back end call node and set its register requirements. */
+ for(i = 0; i < n_low_args; ++i)
+ obstack_ptr_grow(obst, get_Call_param(irn, low_args[i]));
+
+ in = obstack_finish(obst);
+ low_call = be_new_Call(irg, bl, curr_mem, curr_sp, get_Call_ptr(irn), curr_res_proj, n_low_args, in);
+ obstack_free(obst, in);
+ exchange(irn, low_call);
+
/* Make additional projs for the caller save registers
and the Keep node which keeps them alive. */
if(pset_count(caller_save) > 0) {
ir_node **in;
if(!res_proj)
- res_proj = new_r_Proj(irg, bl, irn, mode_T, pn_Call_T_result);
+ res_proj = new_r_Proj(irg, bl, low_call, mode_T, pn_Call_T_result);
for(reg = pset_first(caller_save); reg; reg = pset_next(caller_save))
obstack_ptr_grow(obst, new_r_Proj(irg, bl, res_proj, reg->reg_class->mode, curr_res_proj++));
/* Get the result ProjT */
if(!res_proj)
- res_proj = new_r_Proj(irg, bl, irn, mode_T, pn_Call_T_result);
+ res_proj = new_r_Proj(irg, bl, low_call, mode_T, pn_Call_T_result);
/* Make a Proj for the stack pointer. */
sp_proj = new_r_Proj(irg, bl, res_proj, sp->reg_class->mode, curr_res_proj++);
pset_insert_ptr(env->stack_ops, last_inc_sp);
}
- /* at last make the backend call node and set its register requirements. */
- for(i = 0; i < n_low_args; ++i)
- obstack_ptr_grow(obst, get_irn_n(irn, low_args[i]));
- in = obstack_finish(obst);
- low_call = be_new_Call(irg, bl, curr_mem, curr_sp, get_Call_ptr(irn), curr_res_proj, n_low_args, in);
- obstack_free(obst, in);
-
- exchange(irn, low_call);
-
be_abi_call_free(call);
obstack_free(obst, pos);
del_pset(results);
ir_node *old_frame = get_irg_frame(irg);
int store_old_fp = 1;
int omit_fp = env->omit_fp;
- ir_node *stack = pmap_get(env->callee_save, (void *) sp);
- ir_node *frame = pmap_get(env->callee_save, (void *) bp);
+ ir_node *stack = pmap_get(env->regs, (void *) sp);
+ ir_node *frame = pmap_get(env->regs, (void *) bp);
int stack_nr = get_Proj_proj(stack);
if(store_old_fp) {
ir_node *irn;
- irn = new_r_Store(irg, bl, get_irg_initial_mem(irg), stack, frame);
- irn = new_r_Proj(irg, bl, irn, mode_M, pn_Store_M);
- stack = be_new_IncSP(sp, irg, bl, irn, no_mem, get_mode_size_bytes(bp->reg_class->mode), be_stack_dir_along);
+ irn = new_r_Store(irg, bl, get_irg_initial_mem(irg), stack, frame);
+ env->store_bp_mem = new_r_Proj(irg, bl, irn, mode_M, pn_Store_M);
+ stack = be_new_IncSP(sp, irg, bl, stack, env->store_bp_mem,
+ get_mode_size_bytes(bp->reg_class->mode), be_stack_dir_along);
}
frame = be_new_Copy(bp->reg_class, irg, bl, stack);
+ be_node_set_flags(frame, -1, arch_irn_flags_dont_spill);
if(env->dedicated_fp) {
be_set_constr_single_reg(frame, -1, bp);
be_node_set_flags(frame, -1, arch_irn_flags_ignore);
return frame;
}
-static ir_node *clearup_frame(be_abi_irg_t *env, ir_node *stack, ir_node *frame)
+static void clearup_frame(be_abi_irg_t *env, ir_node *bl, struct obstack *obst)
{
+ const arch_isa_t *isa = env->birg->main_env->arch_env->isa;
+ const arch_register_t *sp = isa->sp;
+ const arch_register_t *bp = isa->bp;
+ ir_graph *irg = env->birg->irg;
+ ir_node *no_mem = get_irg_no_mem(irg);
+ ir_node *frame = get_irg_frame(irg);
+ ir_node *stack = env->init_sp;
+ int store_old_fp = 1;
+
+ pmap_entry *ent;
+
+
+ if(env->omit_fp) {
+ stack = be_new_IncSP(sp, irg, bl, stack, no_mem, BE_STACK_FRAME_SIZE, be_stack_dir_against);
+ }
+
+ else {
+ stack = be_new_Copy(sp->reg_class, irg, bl, frame);
+ be_set_constr_single_reg(stack, -1, sp);
+ be_node_set_flags(stack, -1, arch_irn_flags_ignore);
+
+ if(store_old_fp) {
+ ir_mode *mode = sp->reg_class->mode;
+ ir_node *irn;
+
+ stack = be_new_IncSP(sp, irg, bl, stack, no_mem, get_mode_size_bytes(mode), be_stack_dir_against);
+ irn = new_r_Load(irg, bl, env->store_bp_mem, stack, mode);
+ irn = new_r_Proj(irg, bl, irn, mode, pn_Load_res);
+ frame = be_new_Copy(bp->reg_class, irg, bl, irn);
+ }
+ }
+
+ pmap_foreach(env->regs, ent) {
+ const arch_register_t *reg = ent->key;
+ ir_node *irn = ent->value;
+ if(reg == sp)
+ irn = stack;
+ else if(reg == bp)
+ irn = frame;
+
+ obstack_ptr_grow(obst, irn);
+ }
+}
+
+static ir_type *compute_arg_type(be_abi_irg_t *env, be_abi_call_t *call, ir_type *method_type)
+{
+ int inc = env->birg->main_env->arch_env->isa->stack_dir * (env->left_to_right ? 1 : -1);
+ int n = get_method_n_params(method_type);
+ int curr = inc > 0 ? 0 : n - 1;
+ int ofs = 0;
+
+ char buf[128];
+ ir_type *res;
+ int i;
+
+ snprintf(buf, sizeof(buf), "%s_arg_type", get_entity_name(get_irg_entity(env->birg->irg)));
+ res = new_type_class(new_id_from_str(buf));
+
+ for(i = 0; i < n; ++i, curr += inc) {
+ type *param_type = get_method_param_type(method_type, curr);
+ be_abi_call_arg_t *arg = get_call_arg(call, 0, curr);
+
+ if(!arg->in_reg) {
+ snprintf(buf, sizeof(buf), "param_%d", i);
+ arg->stack_ent = new_entity(res, new_id_from_str(buf), param_type);
+ add_class_member(res, arg->stack_ent);
+ set_entity_offset_bytes(arg->stack_ent, ofs);
+ ofs += get_type_size_bytes(param_type);
+ }
+ }
+
+ set_type_size_bytes(res, ofs);
+ return res;
+}
+
+static type *get_bp_type(const arch_register_t *bp)
+{
+ static type *bp_type = NULL;
+ if(!bp_type) {
+ bp_type = new_type_primitive(new_id_from_str("bp_type"), bp->reg_class->mode);
+ set_type_size_bytes(bp_type, get_mode_size_bytes(bp->reg_class->mode));
+ }
+ return bp_type;
}
/**
ir_node *no_mem = get_irg_no_mem(irg);
type *method_type = get_entity_type(get_irg_entity(irg));
int n_params = get_method_n_params(method_type);
- pmap *regs = pmap_create();
-
int max_arg = 0;
int reg_params_nr = 0;
int arg_offset = 0;
ir_node *reg_params, *reg_params_bl;
ir_node **args, **args_repl;
const ir_edge_t *edge;
+ ir_type *arg_type;
pmap_entry *ent;
-
DBG((dbg, LEVEL_1, "introducing abi on %+F\n", irg));
+ /* Convert the Sel nodes in the irg to frame load/store/addr nodes. */
+ irg_walk_graph(irg, lower_frame_sels_walker, NULL, env);
+
+ env->frame = obstack_alloc(&env->obst, sizeof(env->frame[0]));
+ env->regs = pmap_create();
+
/* Find the maximum proj number of the argument tuple proj */
foreach_out_edge(arg_tuple, edge) {
ir_node *irn = get_edge_src_irn(edge);
/* Get the ABI constraints from the ISA */
arch_isa_get_call_abi(isa, method_type, call);
+ arg_type = compute_arg_type(env, call, method_type);
+ stack_frame_init(env->frame, arg_type, call->between_type, get_irg_frame_type(irg), isa->stack_dir);
+
/* 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);
if(arg->in_reg) {
assert(arg->reg != sp && "cannot use stack pointer as parameter register");
- pmap_insert(regs, (void *) arg->reg, NULL);
+ pmap_insert(env->regs, (void *) arg->reg, NULL);
DBG((dbg, LEVEL_2, "\targ #%d -> reg %s\n", i, arg->reg->name));
}
}
for(j = 0; j < cls->n_regs; ++j) {
const arch_register_t *reg = &cls->regs[j];
if(arch_register_type_is(reg, callee_save))
- pmap_insert(regs, (void *) reg, NULL);
+ pmap_insert(env->regs, (void *) reg, NULL);
}
}
- /* The stack pointer must also be saved but not necessarily be marked as callee save */
- pmap_insert(regs, (void *) sp, NULL);
-
+ pmap_insert(env->regs, (void *) sp, NULL);
+ pmap_insert(env->regs, (void *) isa->bp, NULL);
reg_params_bl = get_irg_start_block(irg);
- env->reg_params = reg_params = be_new_RegParams(irg, reg_params_bl, pmap_count(regs));
+ env->reg_params = reg_params = be_new_RegParams(irg, reg_params_bl, pmap_count(env->regs));
reg_params_nr = 0;
/*
* make proj nodes for the callee save registers.
* memorize them, since Return nodes get those as inputs.
*/
- for(ent = pmap_first(regs); ent; ent = pmap_next(regs)) {
+ for(ent = pmap_first(env->regs); ent; ent = pmap_next(env->regs)) {
arch_register_t *reg = ent->key;
int pos = -(reg_params_nr + 1);
ent->value = new_r_Proj(irg, reg_params_bl, reg_params, reg->reg_class->mode, reg_params_nr);
/* Insert the code to set up the stack frame */
frame_pointer = setup_frame(env);
-#if 0
- proj_sp = pmap_get(regs, (void *) sp);
- proj_bp = pmap_get(regs, (void *) bp);
- assert(proj_sp != NULL && "There must be a Proj for the stack pointer");
- assert(proj_sp != NULL && "There must be a Proj for the base pointer");
-
- /* Set the Proj for the stack pointer to ignore. */
- be_node_set_flags(reg_params, -(get_Proj_proj(proj_sp) + 1), arch_irn_flags_ignore);
-
- /*
- * If a frame pointer is needed and the frame pointer is in a dedicated register,
- * also exclude that from register allocation by setting the corresponding
- * Proj to ignore.
- */
- if(!env->omit_fp && env->dedicated_fp)
- be_node_set_flags(reg_params, -(get_Proj_proj(proj_bp) + 1), arch_irn_flags_ignore);
-
-
- if(env->omit_fp) {
- /* This is the stack pointer add/sub which allocates the frame. remind it for later fix up. */
- env->init_sp = be_new_IncSP(sp, irg, reg_params_bl, proj_sp, no_mem, 0, be_stack_dir_along);
- frame_pointer = env->init_sp;
- }
-
- else {
- env->init_sp = proj_sp;
- frame_pointer = be_new_Copy(sp->reg_class, irg, reg_params_bl, proj_sp);
- }
-
- /* Set the new frame pointer. */
- exchange(get_irg_frame(irg), frame_pointer);
- set_irg_frame(irg, frame_pointer);
-#endif
-
- /* compute the start offset for the stack parameters. */
- {
- int arg_offset = 0;
- int arg_size = 0;
- int inc_dir = isa->stack_dir * (env->left_to_right ? 1 : -1);
-
- for(i = 0; i < n_params; ++i) {
- be_abi_call_arg_t *arg = get_call_arg(call, 0, i);
- if(!arg->in_reg)
- arg_size += get_type_size_bytes(get_method_param_type(method_type, i));
- }
-
- arg_offset = -isa->stack_dir * call->arg_gap + env->left_to_right * arg_size;
-
- /* Now, introduce stack param nodes for all parameters passed on the stack */
- for(i = 0; i < max_arg; ++i) {
- ir_node *arg_proj = args[i];
- if(arg_proj != NULL) {
- be_abi_call_arg_t *arg;
- ir_type *param_type;
- int nr = get_Proj_proj(arg_proj);
+ /* Now, introduce stack param nodes for all parameters passed on the stack */
+ for(i = 0; i < max_arg; ++i) {
+ ir_node *arg_proj = args[i];
+ if(arg_proj != NULL) {
+ be_abi_call_arg_t *arg;
+ ir_type *param_type;
+ int nr = get_Proj_proj(arg_proj);
+
+ nr = MIN(nr, n_params);
+ arg = get_call_arg(call, 0, nr);
+ param_type = get_method_param_type(method_type, nr);
+
+ if(arg->in_reg) {
+ args_repl[i] = new_r_Proj(irg, reg_params_bl, reg_params, get_irn_mode(arg_proj), reg_params_nr);
+ be_set_constr_single_reg(reg_params, -(reg_params_nr + 1), arg->reg);
+ reg_params_nr++;
+ }
- nr = MIN(nr, n_params);
- arg = get_call_arg(call, 0, nr);
- param_type = get_method_param_type(method_type, nr);
+ /* when the (stack) parameter is primitive, we insert a StackParam
+ node representing the load of that parameter */
+ else {
- if(arg->in_reg) {
- args_repl[i] = new_r_Proj(irg, reg_params_bl, reg_params, get_irn_mode(arg_proj), reg_params_nr);
- be_set_constr_single_reg(reg_params, -(reg_params_nr + 1), arg->reg);
- reg_params_nr++;
+ /* For atomic parameters which are actually used, we create a StackParam node. */
+ if(is_atomic_type(param_type) && get_irn_n_edges(args[i]) > 0) {
+ ir_mode *mode = get_type_mode(param_type);
+ const arch_register_class_t *cls = arch_isa_get_reg_class_for_mode(isa, mode);
+ args_repl[i] = be_new_StackParam(cls, irg, reg_params_bl, mode, frame_pointer, arg->stack_ent);
}
- /* when the (stack) parameter is primitive, we insert a StackParam
- node representing the load of that parameter */
+ /* The stack parameter is not primitive (it is a struct or array),
+ we thus will create a node representing the parameter's address
+ on the stack. */
else {
- int size = get_type_size_bytes(param_type) * isa->stack_dir;
-
- if(inc_dir < 0)
- arg_offset -= size;
-
- if(is_atomic_type(param_type)) {
- ir_mode *mode = get_type_mode(param_type);
- const arch_register_class_t *cls = arch_isa_get_reg_class_for_mode(isa, mode);
- args_repl[i] = be_new_StackParam(cls, irg, reg_params_bl, mode, frame_pointer, arg_offset);
- }
-
- /* The stack parameter is not primitive (it is a struct or array),
- we thus will create a node representing the parameter's address
- on the stack. */
- else {
- assert(0 && "struct parameters are not supported");
- }
-
- if(inc_dir > 0)
- arg_offset += size;
+ args_repl[i] = be_new_FrameAddr(sp->reg_class, irg, reg_params_bl, frame_pointer, arg->stack_ent);
}
}
}
ir_node *irn = get_irn_n(end, i);
if(get_irn_opcode(irn) == iro_Return) {
- ir_node *bl = get_nodes_block(irn);
+ ir_node *bl = get_nodes_block(irn);
+ int n_res = get_Return_n_ress(irn);
+ pmap *reg_map = pmap_create_ex(n_res);
ir_node *ret;
int i, n;
ir_node **in;
/* collect all arguments of the return */
- for(i = 0, n = get_irn_arity(irn); i < n; ++i)
- obstack_ptr_grow(&env->obst, get_irn_n(irn, i));
+ 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);
- /* Add the Proj nodes representing the caller save registers. */
- for(ent = pmap_first(regs); ent; ent = pmap_next(regs), ++n) {
- const arch_register_t *reg = ent->key;
- ir_node *irn = ent->value;
-
- /*
- * If the register is the stack pointer,
- * add the fix up code. Either add the size of the stack
- * frame if we omitted the frame pointer or move the
- * frame pointer back to the stack register.
- */
- if(reg == sp) {
- irn = be_new_IncSP(sp, irg, bl, frame_pointer, no_mem, env->omit_fp ? BE_STACK_FRAME_SIZE : 0, be_stack_dir_against);
- }
- obstack_ptr_grow(&env->obst, irn);
+ assert(arg->in_reg && "return value must be passed in register");
+ pmap_insert(reg_map, res, (void *) arg->reg);
+ obstack_ptr_grow(&env->obst, res);
}
+ /* generate the clean up code and add additional parameters to the return. */
+ clearup_frame(env, bl, &env->obst);
+
/* The in array for the new back end return is now ready. */
+ n = obstack_object_size(&env->obst) / sizeof(in[0]);
in = obstack_finish(&env->obst);
ret = be_new_Return(irg, bl, n, in);
- edges_reroute(irn, ret, irg);
+
+ /* Set the constraints for some arguments of the return. */
+ for(i = 0; i < n; i++) {
+ const arch_register_t *reg = pmap_get(reg_map, in[i]);
+ if(reg != NULL)
+ be_set_constr_single_reg(ret, i, reg);
+ }
+ exchange(irn, ret);
obstack_free(&env->obst, in);
+ pmap_destroy(reg_map);
}
}
obstack_free(&env->obst, args);
be_abi_call_free(call);
- env->callee_save = regs;
}
static void collect_alloca_walker(ir_node *irn, void *data)
env->omit_fp = (env->call->flags & BE_ABI_TRY_OMIT_FRAME_POINTER) != 0;
env->dedicated_fp = (env->call->flags & BE_ABI_FRAME_POINTER_DEDICATED) != 0;
env->left_to_right = (env->call->flags & BE_ABI_LEFT_TO_RIGHT) != 0;
+ env->save_old_fp = (env->call->flags & BE_ABI_SAVE_OLD_FRAME_POINTER) != 0;
env->birg = birg;
env->stack_ops = pset_new_ptr(32);
env->dbg = firm_dbg_register("firm.be.abi");
bias += dir * ofs;
}
- else
+ else {
arch_set_stack_bias(aenv, irn, bias);
+ }
}
return bias;
free(env);
}
-ir_node *be_abi_get_callee_save_node(be_abi_irg_t *abi, const arch_register_t *reg)
+ir_node *be_abi_get_callee_save_irn(be_abi_irg_t *abi, const arch_register_t *reg)
{
assert(arch_register_type_is(reg, callee_save));
- assert(pmap_contains(abi->callee_save, (void *) reg));
- return pmap_get(abi->callee_save, (void *) reg);
+ assert(pmap_contains(abi->regs, (void *) reg));
+ return pmap_get(abi->regs, (void *) reg);
}