Commit 5c87c3af authored by Christoph Mallon's avatar Christoph Mallon
Browse files

Allow loading of stack parameters with a different mode than the parameter...

Allow loading of stack parameters with a different mode than the parameter mode. This is useful for x86 where loading a char parameter as 32bit results in a shorter opcode.

[r16224]
parent 16c92be5
......@@ -571,7 +571,9 @@ void TEMPLATE_get_call_abi(const void *self, ir_type *method_type,
/* be_abi_call_param_reg(abi, i, reg); */
/* default: all parameters on stack */
be_abi_call_param_stack(abi, i, 4, 0, 0);
tp = get_method_param_type(method_type, i);
mode = get_type_mode(tp);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
}
/* TODO: set correct return register */
......
......@@ -1041,11 +1041,13 @@ void arm_get_call_abi(const void *self, ir_type *method_type, be_abi_call_t *abi
for (i = 0; i < n; i++) {
/* reg = get reg for param i; */
/* be_abi_call_param_reg(abi, i, reg); */
if (i < 4)
if (i < 4) {
be_abi_call_param_reg(abi, i, arm_get_RegParam_reg(i));
else
be_abi_call_param_stack(abi, i, 4, 0, 0);
} else {
tp = get_method_param_type(method_type, i);
mode = get_type_mode(tp);
be_abi_call_param_stack(abi, i, mode, 4, 0, 0);
}
}
/* set return registers */
......
......@@ -61,12 +61,13 @@ typedef struct _be_abi_call_arg_t {
unsigned in_reg : 1; /**< 1: this argument is transmitted in registers. */
unsigned on_stack : 1; /**< 1: this argument is transmitted on the stack. */
int pos;
int pos;
const arch_register_t *reg;
ir_entity *stack_ent;
unsigned alignment; /**< stack alignment */
unsigned space_before; /**< allocate space before */
unsigned space_after; /**< allocate space after */
ir_entity *stack_ent;
ir_mode *load_mode;
unsigned alignment; /**< stack alignment */
unsigned space_before; /**< allocate space before */
unsigned space_after; /**< allocate space after */
} be_abi_call_arg_t;
struct _be_abi_call_t {
......@@ -192,10 +193,11 @@ void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_regi
}
void be_abi_call_param_stack(be_abi_call_t *call, int arg_pos, 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_call_arg_t *arg = get_or_set_call_arg(call, 0, arg_pos, 1);
arg->on_stack = 1;
arg->load_mode = load_mode;
arg->alignment = alignment;
arg->space_before = space_before;
arg->space_after = space_after;
......@@ -1890,25 +1892,25 @@ static void modify_irg(be_abi_irg_t *env)
if (arg->in_reg) {
repl = pmap_get(env->regs, (void *) arg->reg);
}
else if(arg->on_stack) {
} else if(arg->on_stack) {
ir_node *addr = be_new_FrameAddr(sp->reg_class, irg, reg_params_bl, frame_pointer, arg->stack_ent);
/* For atomic parameters which are actually used, we create a Load node. */
if(is_atomic_type(param_type) && get_irn_n_edges(args[i]) > 0) {
ir_mode *mode = get_type_mode(param_type);
ir_node *load = new_rd_Load(NULL, irg, reg_params_bl,
new_NoMem(), addr, mode);
ir_mode *mode = get_type_mode(param_type);
ir_mode *load_mode = arg->load_mode;
ir_node *load = new_r_Load(irg, reg_params_bl, new_NoMem(), addr, load_mode);
set_irn_pinned(load, op_pin_state_floats);
repl = new_rd_Proj(NULL, irg, reg_params_bl, load,
mode, pn_Load_res);
}
repl = new_r_Proj(irg, reg_params_bl, load, load_mode, pn_Load_res);
/* 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 {
if (mode != load_mode) {
repl = new_r_Conv(irg, reg_params_bl, repl, mode);
}
} else {
/* 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. */
repl = addr;
}
}
......
......@@ -131,11 +131,12 @@ void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_regi
*
* @param call the abi call object
* @param pos the parameter position
* @param load_mode load the parameter with this mode (if the parameter mode is different from this mode a Conv is inserted)
* @param alignment stack alignment for the parameter on the current architecture
* @param space_before size of allocated additional space before the parameter
* @param space_after size of allocated additional space after the parameter
*/
void be_abi_call_param_stack(be_abi_call_t *call, int pos, unsigned alignment, unsigned space_before, unsigned space_after);
void be_abi_call_param_stack(be_abi_call_t *call, int pos, ir_mode *load_mode, unsigned alignment, unsigned space_before, unsigned space_after);
void be_abi_call_param_reg(be_abi_call_t *call, int pos, const arch_register_t *reg);
void be_abi_call_res_reg(be_abi_call_t *call, int pos, const arch_register_t *reg);
......
......@@ -1808,7 +1808,7 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_cal
n = get_method_n_params(method_type);
for (i = regnum = 0; i < n; i++) {
const ir_mode *mode;
ir_mode *mode;
const arch_register_t *reg = NULL;
tp = get_method_param_type(method_type, i);
......@@ -1820,7 +1820,11 @@ static void ia32_get_call_abi(const void *self, ir_type *method_type, be_abi_cal
be_abi_call_param_reg(abi, i, reg);
++regnum;
} else {
be_abi_call_param_stack(abi, i, 4, 0, 0);
/* Micro optimisation: if the mode is shorter than 4 bytes, load 4 bytes.
* movl has a shorter opcode than mov[sz][bw]l */
ir_mode *load_mode = mode;
if (mode != NULL && get_mode_size_bytes(mode) < 4) load_mode = mode_Iu;
be_abi_call_param_stack(abi, i, load_mode, 4, 0, 0);
}
}
......
......@@ -926,7 +926,7 @@ static void mips_get_call_abi(const void *self, ir_type *method_type,
be_abi_call_param_reg(abi, i, reg);
} else {
/* default: all parameters on stack */
be_abi_call_param_stack(abi, i, 4, 0, 0);
be_abi_call_param_stack(abi, i, modes[i], 4, 0, 0);
}
}
......
......@@ -792,10 +792,9 @@ static void ppc32_get_call_abi(const void *self, ir_type *method_type, be_abi_ca
for (i = 0; i < n; i++) {
tp = get_method_param_type(method_type, i);
mode = get_type_mode(tp);
if(is_atomic_type(tp))
{
mode = get_type_mode(tp);
if(mode_is_float(mode))
{
if(fpregi <= REG_F13)
......@@ -824,14 +823,14 @@ static void ppc32_get_call_abi(const void *self, ir_type *method_type, be_abi_ca
be_abi_call_param_reg(abi, i, reg);
else
{
be_abi_call_param_stack(abi, i, 4, stackoffs-lastoffs, 0);
be_abi_call_param_stack(abi, i, mode, 4, stackoffs - lastoffs, 0);
lastoffs = stackoffs+stackparamsize;
}
stackoffs += stackparamsize;
}
else
{
be_abi_call_param_stack(abi, i, 4, stackoffs-lastoffs, 0);
be_abi_call_param_stack(abi, i, mode, 4, stackoffs - lastoffs, 0);
stackoffs += (get_type_size_bytes(tp)+3) & -4;
lastoffs = stackoffs;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment