Commit b412c330 authored by Christoph Mallon's avatar Christoph Mallon
Browse files

amd64, arm, ia32, sparc: Use be_start_info_t to handle all parameter Projs.

This is simpler, removes some code duplication and makes the backends more robust against duplicate Projs of Start, which can happen if optimisations are disabled.
parent 0ef1cbe7
......@@ -40,7 +40,6 @@ static ir_mode *mode_flags;
static x86_cconv_t *current_cconv = NULL;
static be_start_info_t start_mem;
static be_start_info_t start_val[N_AMD64_REGISTERS];
static size_t start_params_offset;
static pmap *node_to_stack;
static be_stackorder_t *stackorder;
......@@ -1431,17 +1430,11 @@ static ir_node *gen_Start(ir_node *node)
be_make_start_out(&start_val[REG_RSP], start, o++, &amd64_registers[REG_RSP], true);
/* function parameters in registers */
const unsigned *allocatable_regs = be_birg_from_irg(irg)->allocatable_regs;
start_params_offset = o;
for (size_t i = 0; i < get_method_n_params(function_type); ++i) {
const reg_or_stackslot_t *param = &current_cconv->parameters[i];
const arch_register_t *reg = param->reg;
if (reg != NULL) {
arch_set_irn_register_req_out(start, o, reg->single_req);
if (!rbitset_is_set(allocatable_regs, reg->global_index))
arch_set_irn_register_out(start, o, reg);
++o;
}
if (reg)
be_make_start_out(&start_val[reg->global_index], start, o++, reg, false);
}
/* callee saves */
......@@ -1814,25 +1807,17 @@ static ir_node *gen_Proj_Proj_Call(ir_node *node)
static ir_node *gen_Proj_Proj_Start(ir_node *node)
{
ir_node *new_block = be_transform_nodes_block(node);
unsigned pn = get_Proj_num(node);
ir_node *args = get_Proj_pred(node);
ir_node *start = get_Proj_pred(args);
ir_node *new_start = be_transform_node(start);
assert(get_Proj_num(get_Proj_pred(node)) == pn_Start_T_args);
assert(get_Proj_num(args) == pn_Start_T_args);
const reg_or_stackslot_t *param = &current_cconv->parameters[pn];
if (param->reg != NULL) {
ir_graph *const irg = get_irn_irg(node);
unsigned const pn = get_Proj_num(node);
reg_or_stackslot_t const *const param = &current_cconv->parameters[pn];
arch_register_t const *const reg = param->reg;
if (reg) {
/* argument transmitted in register */
const arch_register_t *reg = param->reg;
ir_mode *mode = reg->cls->mode;
unsigned new_pn = param->reg_offset + start_params_offset;
ir_node *value = new_r_Proj(new_start, mode, new_pn);
return value;
return be_get_start_proj(irg, &start_val[reg->global_index]);
} else {
/* argument transmitted on stack */
ir_graph *irg = get_irn_irg(node);
ir_mode *mode = get_type_mode(param->type);
ir_node *base = get_frame_base(irg);
......@@ -1847,6 +1832,7 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
ir_node *load;
ir_node *value;
ir_node *const new_block = be_transform_nodes_block(node);
if (mode_is_float(mode)) {
load = new_bd_amd64_movs_xmm(NULL, new_block, ARRAY_SIZE(in),
in, insn_mode, AMD64_OP_ADDR, addr);
......
......@@ -44,8 +44,7 @@ static ir_mode *mode_fp;
static be_stackorder_t *stackorder;
static calling_convention_t *cconv = NULL;
static be_start_info_t start_mem;
static be_start_info_t start_sp;
static unsigned start_params_offset;
static be_start_info_t start_val[N_ARM_REGISTERS];
static unsigned start_callee_saves_offset;
static pmap *node_to_stack;
......@@ -1486,38 +1485,31 @@ static ir_node *gen_Proj_Start(ir_node *node)
return new_r_Bad(get_irn_irg(node), mode_T);
case pn_Start_P_frame_base:
return be_get_start_proj(get_irn_irg(node), &start_sp);
return be_get_start_proj(get_irn_irg(node), &start_val[REG_SP]);
}
panic("unexpected start proj: %u", pn);
}
static ir_node *gen_Proj_Proj_Start(ir_node *node)
{
unsigned pn = get_Proj_num(node);
ir_node *new_block = be_transform_nodes_block(node);
ir_graph *irg = get_irn_irg(new_block);
ir_node *args = get_Proj_pred(node);
ir_node *start = get_Proj_pred(args);
ir_node *new_start = be_transform_node(start);
/* Proj->Proj->Start must be a method argument */
assert(get_Proj_num(args) == pn_Start_T_args);
const reg_or_stackslot_t *param = &cconv->parameters[pn];
assert(get_Proj_num(get_Proj_pred(node)) == pn_Start_T_args);
const arch_register_t *reg0 = param->reg0;
ir_node *const new_block = be_transform_nodes_block(node);
ir_graph *const irg = get_irn_irg(new_block);
unsigned const pn = get_Proj_num(node);
reg_or_stackslot_t const *const param = &cconv->parameters[pn];
arch_register_t const *const reg0 = param->reg0;
if (reg0 != NULL) {
/* argument transmitted in register */
ir_mode *mode = reg0->cls->mode;
unsigned new_pn = param->reg_offset + start_params_offset;
ir_node *value = new_r_Proj(new_start, mode, new_pn);
ir_node *value = be_get_start_proj(irg, &start_val[reg0->global_index]);
if (mode_is_float(mode)) {
if (mode_is_float(reg0->cls->mode)) {
ir_node *value1 = NULL;
const arch_register_t *reg1 = param->reg1;
if (reg1 != NULL) {
value1 = new_r_Proj(new_start, mode, new_pn+1);
value1 = be_get_start_proj(irg, &start_val[reg1->global_index]);
} else if (param->entity != NULL) {
ir_node *const fp = get_irg_frame(irg);
ir_node *const mem = be_get_start_proj(irg, &start_mem);
......@@ -1729,24 +1721,17 @@ static ir_node *gen_Start(ir_node *node)
be_make_start_mem(&start_mem, start, o++);
be_make_start_out(&start_sp, start, o++, &arm_registers[REG_SP], true);
be_make_start_out(&start_val[REG_SP], start, o++, &arm_registers[REG_SP], true);
/* function parameters in registers */
start_params_offset = o;
for (size_t i = 0; i < get_method_n_params(function_type); ++i) {
const reg_or_stackslot_t *param = &cconv->parameters[i];
const arch_register_t *reg0 = param->reg0;
if (reg0 != NULL) {
arch_set_irn_register_req_out(start, o, reg0->single_req);
arch_set_irn_register_out(start, o, reg0);
++o;
}
if (reg0)
be_make_start_out(&start_val[reg0->global_index], start, o++, reg0, false);
const arch_register_t *reg1 = param->reg1;
if (reg1 != NULL) {
arch_set_irn_register_req_out(start, o, reg1->single_req);
arch_set_irn_register_out(start, o, reg1);
++o;
}
if (reg1)
be_make_start_out(&start_val[reg1->global_index], start, o++, reg1, false);
}
/* callee save regs */
start_callee_saves_offset = o;
......@@ -1769,7 +1754,7 @@ static ir_node *get_stack_pointer_for(ir_node *node)
/* first stack user in the current block. We can simply use the
* initial sp_proj for it */
ir_graph *irg = get_irn_irg(node);
return be_get_start_proj(irg, &start_sp);
return be_get_start_proj(irg, &start_val[REG_SP]);
}
be_transform_node(stack_pred);
......
......@@ -59,7 +59,6 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg;)
static x86_cconv_t *current_cconv;
static be_start_info_t start_mem;
static be_start_info_t start_val[N_IA32_REGISTERS];
static unsigned start_params_offset;
static pmap *node_to_stack;
static be_stackorder_t *stackorder;
static ir_heights_t *heights;
......@@ -4164,15 +4163,11 @@ static ir_node *gen_Start(ir_node *node)
be_make_start_out(&start_val[REG_ESP], start, o++, &ia32_registers[REG_ESP], true);
/* function parameters in registers */
start_params_offset = o;
for (size_t i = 0; i < get_method_n_params(function_type); ++i) {
const reg_or_stackslot_t *param = &current_cconv->parameters[i];
const arch_register_t *reg = param->reg;
if (reg != NULL) {
arch_set_irn_register_req_out(start, o, reg->single_req);
arch_set_irn_register_out(start, o, reg);
++o;
}
if (reg)
be_make_start_out(&start_val[reg->global_index], start, o++, reg, false);
}
/* callee saves */
......@@ -4207,21 +4202,15 @@ static ir_node *gen_Proj_Start(ir_node *node)
static ir_node *gen_Proj_Proj_Start(ir_node *node)
{
unsigned pn = get_Proj_num(node);
ir_node *args = get_Proj_pred(node);
ir_node *start = get_Proj_pred(args);
ir_node *new_start = be_transform_node(start);
assert(get_Proj_num(args) == pn_Start_T_args);
assert(get_Proj_num(get_Proj_pred(node)) == pn_Start_T_args);
const reg_or_stackslot_t *param = &current_cconv->parameters[pn];
ir_graph *const irg = get_irn_irg(node);
unsigned const pn = get_Proj_num(node);
reg_or_stackslot_t const *const param = &current_cconv->parameters[pn];
/* stack paramter should have been lowered to loads already */
assert(param->reg != NULL);
/* argument transmitted in register */
ir_mode *const mode = param->reg->cls->mode;
unsigned const new_pn = param->reg_offset + start_params_offset;
ir_node *const value = new_r_Proj(new_start, mode, new_pn);
return value;
return be_get_start_proj(irg, &start_val[param->reg->global_index]);
}
static ir_node *get_stack_pointer_for(ir_node *node)
......
......@@ -52,12 +52,8 @@ static ir_mode *mode_fp2;
//static ir_mode *mode_fp4;
static pmap *node_to_stack;
static be_start_info_t start_mem;
static be_start_info_t start_g0;
static be_start_info_t start_g7;
static be_start_info_t start_sp;
static be_start_info_t start_fp;
static be_start_info_t start_val[N_SPARC_REGISTERS];
static ir_node *frame_base;
static size_t start_params_offset;
static size_t start_callee_saves_offset;
static const arch_register_t *const omit_fp_callee_saves[] = {
......@@ -562,12 +558,12 @@ static ir_node *gen_helper_binopx(ir_node *node, match_flags_t match_flags,
static ir_node *get_g0(ir_graph *irg)
{
return be_get_start_proj(irg, &start_g0);
return be_get_start_proj(irg, &start_val[REG_G0]);
}
static ir_node *get_g7(ir_graph *irg)
{
return be_get_start_proj(irg, &start_g7);
return be_get_start_proj(irg, &start_val[REG_G7]);
}
static ir_node *make_tls_offset(dbg_info *dbgi, ir_node *block,
......@@ -1585,34 +1581,26 @@ static ir_node *gen_Start(ir_node *node)
be_make_start_mem(&start_mem, start, o++);
/* the zero register */
be_make_start_out(&start_g0, start, o++, &sparc_registers[REG_G0], true);
be_make_start_out(&start_val[REG_G0], start, o++, &sparc_registers[REG_G0], true);
/* g7 is used for TLS data */
be_make_start_out(&start_g7, start, o++, &sparc_registers[REG_G7], true);
be_make_start_out(&start_val[REG_G7], start, o++, &sparc_registers[REG_G7], true);
/* we need an output for the stack pointer */
be_make_start_out(&start_sp, start, o++, sp_reg, true);
be_make_start_out(&start_val[REG_SP], start, o++, sp_reg, true);
if (!current_cconv->omit_fp) {
be_make_start_out(&start_fp, start, o++, fp_reg, true);
}
if (!current_cconv->omit_fp)
be_make_start_out(&start_val[REG_FP], start, o++, fp_reg, true);
/* function parameters in registers */
start_params_offset = o;
for (size_t i = 0; i < get_method_n_params(function_type); ++i) {
const reg_or_stackslot_t *param = &current_cconv->parameters[i];
const arch_register_t *reg0 = param->reg0;
const arch_register_t *reg1 = param->reg1;
if (reg0 != NULL) {
arch_set_irn_register_req_out(start, o, reg0->single_req);
arch_set_irn_register_out(start, o, reg0);
++o;
}
if (reg1 != NULL) {
arch_set_irn_register_req_out(start, o, reg1->single_req);
arch_set_irn_register_out(start, o, reg1);
++o;
}
reg_or_stackslot_t const *const param = &current_cconv->parameters[i];
arch_register_t const *const reg0 = param->reg0;
if (reg0)
be_make_start_out(&start_val[reg0->global_index], start, o++, reg0, false);
arch_register_t const *const reg1 = param->reg1;
if (reg1)
be_make_start_out(&start_val[reg1->global_index], start, o++, reg1, false);
}
/* we need the values of the callee saves (Note: non omit-fp mode has no
* callee saves) */
......@@ -1633,12 +1621,12 @@ static ir_node *gen_Start(ir_node *node)
static ir_node *get_initial_sp(ir_graph *irg)
{
return be_get_start_proj(irg, &start_sp);
return be_get_start_proj(irg, &start_val[REG_SP]);
}
static ir_node *get_initial_fp(ir_graph *irg)
{
return be_get_start_proj(irg, &start_fp);
return be_get_start_proj(irg, &start_val[REG_FP]);
}
static ir_node *get_initial_mem(ir_graph *irg)
......@@ -2397,25 +2385,18 @@ static ir_node *gen_Proj_Start(ir_node *node)
static ir_node *gen_Proj_Proj_Start(ir_node *node)
{
unsigned pn = get_Proj_num(node);
ir_graph *irg = get_irn_irg(node);
ir_node *new_block = be_transform_nodes_block(node);
ir_node *args = get_Proj_pred(node);
ir_node *start = get_Proj_pred(args);
ir_node *new_start = be_transform_node(start);
/* Proj->Proj->Start must be a method argument */
assert(get_Proj_num(get_Proj_pred(node)) == pn_Start_T_args);
const reg_or_stackslot_t *param = &current_cconv->parameters[pn];
if (param->reg0 != NULL) {
ir_graph *const irg = get_irn_irg(node);
ir_node *const new_block = be_transform_nodes_block(node);
unsigned const pn = get_Proj_num(node);
reg_or_stackslot_t const *const param = &current_cconv->parameters[pn];
arch_register_t const *const reg0 = param->reg0;
if (reg0) {
/* argument transmitted in register */
const arch_register_t *reg = param->reg0;
ir_mode *reg_mode = reg->cls->mode;
unsigned new_pn = param->reg_offset + start_params_offset;
ir_node *value = new_r_Proj(new_start, reg_mode, new_pn);
bool is_float = false;
ir_node *value = be_get_start_proj(irg, &start_val[reg0->global_index]);
bool is_float = false;
ir_entity *entity = get_irg_entity(irg);
ir_type *method_type = get_entity_type(entity);
......@@ -2430,8 +2411,7 @@ static ir_node *gen_Proj_Proj_Start(ir_node *node)
ir_node *value1 = NULL;
if (reg1 != NULL) {
ir_mode *const reg1_mode = reg1->cls->mode;
value1 = new_r_Proj(new_start, reg1_mode, new_pn+1);
value1 = be_get_start_proj(irg, &start_val[reg1->global_index]);
} else if (param->entity != NULL) {
ir_node *fp = get_initial_fp(irg);
ir_node *mem = get_initial_mem(irg);
......
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