From 3b1a4ee674e9522acfd95b6d49c91f86f9b97d32 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Christian=20W=C3=BCrdig?= Date: Mon, 23 Jan 2006 14:05:47 +0000 Subject: [PATCH] added if layer for irn_ops fixed up reg param stuff --- ir/be/ia32/bearch_ia32.c | 66 +++++++++--- ir/be/ia32/bearch_ia32_t.h | 22 ++-- ir/be/ia32/ia32_emitter.c | 2 - ir/be/ia32/ia32_map_regs.c | 145 ++++++++++++++++++++++++- ir/be/ia32/ia32_map_regs.h | 5 + ir/be/ia32/ia32_spec.pl | 1 + ir/be/ia32/ia32_transform.c | 205 ++++++++---------------------------- 7 files changed, 259 insertions(+), 187 deletions(-) diff --git a/ir/be/ia32/bearch_ia32.c b/ir/be/ia32/bearch_ia32.c index a3af2ef49..a40891558 100644 --- a/ir/be/ia32/bearch_ia32.c +++ b/ir/be/ia32/bearch_ia32.c @@ -27,7 +27,8 @@ /* TODO: ugly */ static set *cur_reg_set = NULL; - +#undef is_Start +#define is_Start(irn) (get_irn_opcode(irn) == iro_Start) /************************************************** * _ _ _ __ @@ -58,9 +59,21 @@ static int is_Call_Proj(const ir_node *n) { return 0; } +static int is_Start_Proj(const ir_node *n) { + if (is_Proj(n) && + is_Proj(get_Proj_pred(n)) && + get_irn_mode(get_Proj_pred(n)) == mode_T && + is_Start(get_Proj_pred(get_Proj_pred(n)))) + { + return 1; + } + + return 0; +} + static int is_P_frame_base_Proj(const ir_node *n) { if (is_Proj(n) && - get_irn_opcode(get_Proj_pred(n)) == iro_Start && + is_Start(n) && get_Proj_proj(n) == pn_Start_P_frame_base) { return 1; @@ -78,11 +91,12 @@ static int is_used_by_Keep(const ir_node *n) { * If the node returns a tuple (mode_T) then the proj's * will be asked for this information. */ -static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *self, arch_register_req_t *req, const ir_node *irn, int pos) { +static const arch_register_req_t *ia32_get_irn_reg_req(const void *self, arch_register_req_t *req, const ir_node *irn, int pos) { const ia32_register_req_t *irn_req; long node_pos = pos == -1 ? 0 : pos; ir_mode *mode = get_irn_mode(irn); firm_dbg_module_t *mod = firm_dbg_register(DEBUG_MODULE); + const ia32_irn_ops_t *ops = self; if (mode == mode_T || mode == mode_M) { DBG((mod, LEVEL_1, "ignoring mode_T, mode_M node %+F\n", irn)); @@ -97,6 +111,12 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *sel memcpy(req, &(irn_req->req), sizeof(*req)); return req; } + else if (is_Start_Proj(irn)) { + irn_req = ops->cg->reg_param_req[get_Proj_proj(irn)]; + assert(irn_req && "missing requirement for regparam"); + memcpy(req, &(irn_req->req), sizeof(*req)); + return req; + } else if (is_Proj(irn)) { if (pos == -1) { node_pos = ia32_translate_proj_pos(irn); @@ -143,7 +163,7 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *sel else assert(0 && "unsupported Phi-Mode"); } - else if (get_irn_op(irn) == op_Start) { + else if (is_Start(irn)) { DBG((mod, LEVEL_1, "returning reqs none for ProjX -> Start (%+F )\n", irn)); switch (node_pos) { case pn_Start_X_initial_exec: @@ -169,10 +189,13 @@ static const arch_register_req_t *ia32_get_irn_reg_req(const arch_irn_ops_t *sel return req; } -static void ia32_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn, const arch_register_t *reg) { +static void ia32_set_irn_reg(const void *self, ir_node *irn, const arch_register_t *reg) { int pos = 0; - if ((is_Call_Proj(irn) && is_used_by_Keep(irn)) || is_P_frame_base_Proj(irn)) { + if ((is_Call_Proj(irn) && is_used_by_Keep(irn)) || + is_P_frame_base_Proj(irn) || + is_Start_Proj(irn)) + { /* don't skip the proj, we want to take the else below */ } else if (is_Proj(irn)) { @@ -191,11 +214,14 @@ static void ia32_set_irn_reg(const arch_irn_ops_t *self, ir_node *irn, const arc } } -static const arch_register_t *ia32_get_irn_reg(const arch_irn_ops_t *self, const ir_node *irn) { +static const arch_register_t *ia32_get_irn_reg(const void *self, const ir_node *irn) { int pos = 0; const arch_register_t *reg = NULL; - if ((is_Call_Proj(irn) && is_used_by_Keep(irn)) || is_P_frame_base_Proj(irn)) { + if ((is_Call_Proj(irn) && is_used_by_Keep(irn)) || + is_P_frame_base_Proj(irn) || + is_Start_Proj(irn)) + { /* don't skip the proj, we want to take the else below */ } else if (is_Proj(irn)) { @@ -215,7 +241,7 @@ static const arch_register_t *ia32_get_irn_reg(const arch_irn_ops_t *self, const return reg; } -static arch_irn_class_t ia32_classify(const arch_irn_ops_t *self, const ir_node *irn) { +static arch_irn_class_t ia32_classify(const void *self, const ir_node *irn) { irn = my_skip_proj(irn); if (is_cfop(irn)) return arch_irn_class_branch; @@ -227,7 +253,7 @@ static arch_irn_class_t ia32_classify(const arch_irn_ops_t *self, const ir_node return 0; } -static arch_irn_flags_t ia32_get_flags(const arch_irn_ops_t *self, const ir_node *irn) { +static arch_irn_flags_t ia32_get_flags(const void *self, const ir_node *irn) { irn = my_skip_proj(irn); if (is_ia32_irn(irn)) return get_ia32_flags(irn); @@ -239,7 +265,7 @@ static arch_irn_flags_t ia32_get_flags(const arch_irn_ops_t *self, const ir_node /* fill register allocator interface */ -static const arch_irn_ops_t ia32_irn_ops = { +static const arch_irn_ops_if_t ia32_irn_ops_if = { ia32_get_irn_reg_req, ia32_set_irn_reg, ia32_get_irn_reg, @@ -247,6 +273,11 @@ static const arch_irn_ops_t ia32_irn_ops = { ia32_get_flags }; +ia32_irn_ops_t ia32_irn_ops = { + &ia32_irn_ops_if, + NULL +}; + /************************************************** @@ -275,17 +306,18 @@ static void check_for_alloca(ir_node *irn, void *env) { * an ia32 firm graph */ static void ia32_prepare_graph(void *self) { - ia32_code_gen_t *cg = self; - int has_alloca = 0; + ia32_code_gen_t *cg = self; if (! is_pseudo_ir_graph(cg->irg)) { /* If there is a alloca in the irg, we use %ebp for stack addressing */ /* instead of %esp, as alloca destroys %esp. */ + cg->has_alloca = 0; + /* check for alloca node */ - irg_walk_blkwise_graph(cg->irg, check_for_alloca, NULL, &has_alloca); + irg_walk_blkwise_graph(cg->irg, check_for_alloca, NULL, &(cg->has_alloca)); - if (has_alloca) { + if (cg->has_alloca) { ia32_general_purpose_regs[REG_EBP].type = arch_register_type_ignore; } @@ -388,6 +420,8 @@ static void *ia32_cg_init(FILE *F, ir_graph *irg, const arch_env_t *arch_env) { cur_reg_set = cg->reg_set; + ia32_irn_ops.cg = cg; + return (arch_code_generator_t *)cg; } @@ -446,7 +480,7 @@ static const arch_register_class_t *ia32_get_reg_class(const void *self, int i) return &ia32_reg_classes[i]; } -static const arch_irn_ops_t *ia32_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) { +static const void *ia32_get_irn_ops(const arch_irn_handler_t *self, const ir_node *irn) { return &ia32_irn_ops; } diff --git a/ir/be/ia32/bearch_ia32_t.h b/ir/be/ia32/bearch_ia32_t.h index f77cac0a6..1440a4996 100644 --- a/ir/be/ia32/bearch_ia32_t.h +++ b/ir/be/ia32/bearch_ia32_t.h @@ -3,15 +3,18 @@ #include "debug.h" #include "bearch_ia32.h" +#include "ia32_nodes_attr.h" typedef struct _ia32_code_gen_t { - const arch_code_generator_if_t *impl; /* implementation */ - ir_graph *irg; /* current irg */ - FILE *out; /* output file */ - const arch_env_t *arch_env; /* the arch env */ - set *reg_set; /* set to memorize registers for non-ia32 nodes (e.g. phi nodes) */ - firm_dbg_module_t *mod; /* debugging module */ - int emit_decls; + const arch_code_generator_if_t *impl; /* implementation */ + ir_graph *irg; /* current irg */ + FILE *out; /* output file */ + const arch_env_t *arch_env; /* the arch env */ + set *reg_set; /* set to memorize registers for non-ia32 nodes (e.g. phi nodes) */ + firm_dbg_module_t *mod; /* debugging module */ + int emit_decls; /* flag indicating if decls were already emitted */ + int has_alloca; /* indicates whether the irg contains an alloca or not */ + const ia32_register_req_t **reg_param_req; /* hold the requirements for the reg param nodes */ } ia32_code_gen_t; typedef struct _ia32_isa_t { @@ -20,4 +23,9 @@ typedef struct _ia32_isa_t { set *reg_projnum_map; } ia32_isa_t; +typedef struct _ia32_irn_ops_t { + const arch_irn_ops_if_t *impl; + ia32_code_gen_t *cg; +} ia32_irn_ops_t; + #endif /* _BEARCH_IA32_T_H_ */ diff --git a/ir/be/ia32/ia32_emitter.c b/ir/be/ia32/ia32_emitter.c index 381694236..358e1cecc 100644 --- a/ir/be/ia32/ia32_emitter.c +++ b/ir/be/ia32/ia32_emitter.c @@ -138,7 +138,6 @@ static const arch_register_t *get_out_reg(ir_node *irn, int pos) { */ int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) { const arch_register_t *reg; - ir_node *op; if (in_out == 1) { reg = get_in_reg(irn, pos); @@ -155,7 +154,6 @@ int get_ia32_reg_nr(ir_node *irn, int pos, int in_out) { */ const char *get_ia32_reg_name(ir_node *irn, int pos, int in_out) { const arch_register_t *reg; - ir_node *op; if (in_out == 1) { reg = get_in_reg(irn, pos); diff --git a/ir/be/ia32/ia32_map_regs.c b/ir/be/ia32/ia32_map_regs.c index c804755b2..1173cedb7 100644 --- a/ir/be/ia32/ia32_map_regs.c +++ b/ir/be/ia32/ia32_map_regs.c @@ -10,6 +10,54 @@ #include "ia32_map_regs.h" #include "ia32_new_nodes.h" +#include "gen_ia32_regalloc_if.h" + +static int maxnum_gpreg_args = 3; /* maximum number of int arguments passed in registers; default 3 */ +static int maxnum_fpreg_args = 5; /* maximum number of float arguments passed in registers; default 5 */ + +/* this is the order of the assigned registers usesd for parameter passing */ + +const ia32_register_req_t *gpreg_param_req_std[] = { + &ia32_default_req_ia32_general_purpose_eax, + &ia32_default_req_ia32_general_purpose_ecx, + &ia32_default_req_ia32_general_purpose_edx, + &ia32_default_req_ia32_general_purpose_ebx, + &ia32_default_req_ia32_general_purpose_edi, + &ia32_default_req_ia32_general_purpose_esi +}; + +const ia32_register_req_t *gpreg_param_req_this[] = { + &ia32_default_req_ia32_general_purpose_ecx, + &ia32_default_req_ia32_general_purpose_eax, + &ia32_default_req_ia32_general_purpose_edx, + &ia32_default_req_ia32_general_purpose_ebx, + &ia32_default_req_ia32_general_purpose_edi, + &ia32_default_req_ia32_general_purpose_esi +}; + +const ia32_register_req_t *fpreg_param_req_std[] = { + &ia32_default_req_ia32_floating_point_xmm0, + &ia32_default_req_ia32_floating_point_xmm1, + &ia32_default_req_ia32_floating_point_xmm2, + &ia32_default_req_ia32_floating_point_xmm3, + &ia32_default_req_ia32_floating_point_xmm4, + &ia32_default_req_ia32_floating_point_xmm5, + &ia32_default_req_ia32_floating_point_xmm6, + &ia32_default_req_ia32_floating_point_xmm7 +}; + +const ia32_register_req_t *fpreg_param_req_this[] = { + NULL, /* in case of a "this" pointer, the first parameter must not be a float */ + &ia32_default_req_ia32_floating_point_xmm0, + &ia32_default_req_ia32_floating_point_xmm1, + &ia32_default_req_ia32_floating_point_xmm2, + &ia32_default_req_ia32_floating_point_xmm3, + &ia32_default_req_ia32_floating_point_xmm4, + &ia32_default_req_ia32_floating_point_xmm5, + &ia32_default_req_ia32_floating_point_xmm6, + &ia32_default_req_ia32_floating_point_xmm7 +}; + /* Mapping to store registers in firm nodes */ @@ -86,6 +134,102 @@ long ia32_get_reg_projnum(const arch_register_t *reg, set *reg_set) { +/** + * Check all parameters and determine the maximum number of parameters + * to pass in gp regs resp. in fp regs. + * + * @param n The number of parameters + * @param modes The parameter list + * @param n_int Holds the number of int parameters to be passed in regs after the call + * @param n_float Holds the number of float parameters to be passed in regs after the call + * @return The number of the last parameter to be passed in register + */ +int ia32_get_n_regparam_class(int n, ir_node **params, int *n_int, int *n_float) { + int i, finished = 0; + + for (i = 0; i < n && !finished; i++) { + if (mode_is_int(get_irn_mode(params[i]))) { + *n_int = *n_int + 1; + } + else if (mode_is_float(get_irn_mode(params[i]))) { + *n_float = *n_float + 1; + } + else { + finished = 1; + } + + /* test for maximum */ + if (*n_int == maxnum_gpreg_args || *n_float == maxnum_fpreg_args) { + finished = 1; + } + } + + return i - 1; +} + + +/** + * Returns the register requirements for parameter nr. + * + * @param n The number of parameters + * @param modes The parameter list + * @param nr The number of the parameter to return the requirements for + * @param cc The calling convention + * @return The register requirements + */ +const ia32_register_req_t *ia32_get_RegParam_req(int n, ir_node **params, long nr, unsigned cc) { + const ia32_register_req_t **current_gpreg_param_req; + const ia32_register_req_t **current_fpreg_param_req; + const ia32_register_req_t *param_req = NULL; + int n_gpregparam = 0; + int n_fpregparam = 0; + int i, done = 0; + int cur_gp_idx = 0; + int cur_fp_idx = 0; + int biggest_n = ia32_get_n_regparam_class(n, params, &n_gpregparam, &n_fpregparam); + + /* Check if parameter #nr is in range for passing in register */ + if (nr <= biggest_n) { + current_gpreg_param_req = gpreg_param_req_std; + current_fpreg_param_req = fpreg_param_req_std; + + if (cc & cc_this_call) { + current_gpreg_param_req = gpreg_param_req_this; + current_fpreg_param_req = fpreg_param_req_this; + } + + /* loop over all parameters and determine whether its a int or float register parameter */ + for (i = 0; i < nr && !done && (cc & cc_reg_param); i++) { + if (mode_is_int(get_irn_mode(params[i])) && cur_gp_idx < maxnum_gpreg_args) { + /* param can be passed in general purpose register and we have some registers left */ + cur_gp_idx++; + } + else if (mode_is_float(get_irn_mode(params[i])) && cur_fp_idx < maxnum_fpreg_args) { + /* param can be passed in floating point register and we have some registers left */ + assert(current_gpreg_param_req[cur_fp_idx] && "'this' pointer cannot be passed as float"); + cur_fp_idx++; + } + } + + /* now: i == nr, that's the parameter requirement we want */ + if (mode_is_int(get_irn_mode(params[i])) && cur_gp_idx < maxnum_gpreg_args) { + /* parameter #nr can be passed in general purpose register */ + param_req = current_gpreg_param_req[i]; + } + else if (mode_is_float(get_irn_mode(params[i])) && cur_fp_idx < maxnum_fpreg_args) { + /* parameter #nr can be passed in floating point register */ + param_req = current_fpreg_param_req[i]; + } + else { + assert(0 && "This should not happen!"); + } + } + + return param_req; +} + + + /** * Translates the projnum into a "real" argument position for register * requirements dependend on the predecessor. @@ -128,7 +272,6 @@ long ia32_translate_proj_pos(const ir_node *proj) { return 0; } else if (is_Proj(pred)) { -// return nr + translate_proj_pos(pred); first = get_Proj_pred(pred); if (is_ia32_Call(first)) diff --git a/ir/be/ia32/ia32_map_regs.h b/ir/be/ia32/ia32_map_regs.h index 0a650171a..e32de6cee 100644 --- a/ir/be/ia32/ia32_map_regs.h +++ b/ir/be/ia32/ia32_map_regs.h @@ -5,6 +5,7 @@ #include "set.h" #include "../bearch.h" +#include "ia32_nodes_attr.h" int ia32_cmp_irn_reg_assoc(const void *a, const void *b, size_t len); void ia32_set_firm_reg(ir_node *irn, const arch_register_t *reg, set *reg_set); @@ -14,6 +15,10 @@ int ia32_cmp_reg_projnum_assoc(const void *a, const void *b, size_t len); void ia32_set_reg_projnum(const arch_register_t *reg, long proj_num, set *reg_set); long ia32_get_reg_projnum(const arch_register_t *reg, set *reg_set); +int ia32_get_n_regparam_class(int n, ir_node **params, int *n_int, int *n_float); + +const ia32_register_req_t *ia32_get_RegParam_req(int n, ir_node **params, long nr, unsigned cc); + long ia32_translate_proj_pos(const ir_node *proj); #endif /* _IA32_MAP_REGS_H_ */ diff --git a/ir/be/ia32/ia32_spec.pl b/ir/be/ia32/ia32_spec.pl index 2c2f96770..cabe150bb 100644 --- a/ir/be/ia32/ia32_spec.pl +++ b/ir/be/ia32/ia32_spec.pl @@ -731,6 +731,7 @@ $arch = "ia32"; "arity" => "variable", "spill" => 0, "comment" => "construct Call: Call(...)", + "emit" => '. call %C', "args" => [ { "type" => "int", "name" => "n" }, { "type" => "ir_node **", "name" => "in" } diff --git a/ir/be/ia32/ia32_transform.c b/ir/be/ia32/ia32_transform.c index 005ee4876..76ec0bde6 100644 --- a/ir/be/ia32/ia32_transform.c +++ b/ir/be/ia32/ia32_transform.c @@ -20,60 +20,12 @@ #include "../arch/archop.h" /* we need this for Min and Max nodes */ #include "ia32_transform.h" #include "ia32_new_nodes.h" +#include "ia32_map_regs.h" #include "gen_ia32_regalloc_if.h" extern ir_op *get_op_Mulh(void); -static int maxnum_gpreg_args = 3; /* maximum number of int arguments passed in registers; default 3 */ -static int maxnum_fpreg_args = 5; /* maximum number of float arguments passed in registers; default 5 */ - -static const ia32_register_req_t **current_gpreg_param_req; -static const ia32_register_req_t **current_fpreg_param_req; - -/* this is the order of the assigned registers usesd for parameter passing */ - -const ia32_register_req_t *gpreg_param_req_std[] = { - &ia32_default_req_ia32_general_purpose_eax, - &ia32_default_req_ia32_general_purpose_ecx, - &ia32_default_req_ia32_general_purpose_edx, - &ia32_default_req_ia32_general_purpose_ebx, - &ia32_default_req_ia32_general_purpose_edi, - &ia32_default_req_ia32_general_purpose_esi -}; - -const ia32_register_req_t *gpreg_param_req_this[] = { - &ia32_default_req_ia32_general_purpose_ecx, - &ia32_default_req_ia32_general_purpose_eax, - &ia32_default_req_ia32_general_purpose_edx, - &ia32_default_req_ia32_general_purpose_ebx, - &ia32_default_req_ia32_general_purpose_edi, - &ia32_default_req_ia32_general_purpose_esi -}; - -const ia32_register_req_t *fpreg_param_req_std[] = { - &ia32_default_req_ia32_floating_point_xmm0, - &ia32_default_req_ia32_floating_point_xmm1, - &ia32_default_req_ia32_floating_point_xmm2, - &ia32_default_req_ia32_floating_point_xmm3, - &ia32_default_req_ia32_floating_point_xmm4, - &ia32_default_req_ia32_floating_point_xmm5, - &ia32_default_req_ia32_floating_point_xmm6, - &ia32_default_req_ia32_floating_point_xmm7 -}; - -const ia32_register_req_t *fpreg_param_req_this[] = { - NULL, /* in case of a "this" pointer, the first parameter must not be a float */ - &ia32_default_req_ia32_floating_point_xmm0, - &ia32_default_req_ia32_floating_point_xmm1, - &ia32_default_req_ia32_floating_point_xmm2, - &ia32_default_req_ia32_floating_point_xmm3, - &ia32_default_req_ia32_floating_point_xmm4, - &ia32_default_req_ia32_floating_point_xmm5, - &ia32_default_req_ia32_floating_point_xmm6, - &ia32_default_req_ia32_floating_point_xmm7 -}; - /* this is a struct to minimize the number of parameters passed to each gen_xxx function */ typedef struct _transform_env_t { @@ -84,6 +36,7 @@ typedef struct _transform_env_t { ir_node *block; /**<< The block, the node should belong to */ ir_node *irn; /**<< The irn, to be transformed */ ir_mode *mode; /**<< The mode of the irn */ + ia32_code_gen_t *cg; /**<< The code generator */ } transform_env_t; @@ -1062,28 +1015,6 @@ ir_node *gen_Store(transform_env_t *env) { -/** - * Check all parameters and determine the maximum number of parameters - * to pass in gp regs resp. in fp regs. - */ -static void get_n_regparam_class(int n, ir_node **param, int *n_int, int *n_float) { - int i; - - for (i = 0; i < n; i++) { - if (mode_is_int(get_irn_mode(param[i]))) - *n_int = *n_int + 1; - else if (mode_is_float(get_irn_mode(param[i]))) - *n_float = *n_float + 1; - - /* test for maximum */ - if (*n_int == maxnum_gpreg_args) - break; - - if (*n_float == maxnum_fpreg_args) - break; - } -} - /** * Transforms a Call and its arguments corresponding to the calling convention. * @@ -1097,8 +1028,7 @@ static ir_node *gen_Call(transform_env_t *env) { const ia32_register_req_t **in_req; ir_node **in; ir_node *new_call, *sync; - ir_mode *mode; - int i, j, n_new_call_in; + int i, j, n_new_call_in, ignore = 0; asmop_attr *attr; firm_dbg_module_t *mod = env->mod; dbg_info *dbg = env->dbg; @@ -1110,57 +1040,28 @@ static ir_node *gen_Call(transform_env_t *env) { ir_node *call_Mem = get_Call_mem(call); unsigned cc = get_method_calling_convention(get_Call_type(call)); int n = get_Call_n_params(call); - int n_gpregparam = 0; - int n_fpregparam = 0; - int cur_gp_idx = 0; - int cur_fp_idx = 0; int stack_idx = 0; - int done = 0; + int biggest_n = -1; if (cc & cc_reg_param) - get_n_regparam_class(n, param, &n_gpregparam, &n_fpregparam); + biggest_n = ia32_get_n_regparam_class(n, param, &ignore, &ignore); + + /* remember: biggest_n = x means we can pass (x + 1) parameters in register */ /* do we need to pass arguments on stack? */ - if (n - n_gpregparam - n_fpregparam > 0) - stack_param = calloc(n - n_gpregparam - n_fpregparam, sizeof(ir_node *)); + if (biggest_n + 1 < n) + stack_param = calloc(n - biggest_n - 1, sizeof(ir_node *)); /* we need at least one in, either for the stack params or the call_Mem */ - n_new_call_in = 1 + n_gpregparam + n_fpregparam; - - current_gpreg_param_req = gpreg_param_req_std; - current_fpreg_param_req = fpreg_param_req_std; - - if (cc & cc_this_call) { - current_gpreg_param_req = gpreg_param_req_this; - current_fpreg_param_req = fpreg_param_req_this; - } + n_new_call_in = biggest_n + 2; /* the call has one IN for all stack parameter and one IN for each reg param */ in = calloc(n_new_call_in, sizeof(ir_node *)); in_req = calloc(n_new_call_in, sizeof(arch_register_req_t *)); - /* loop over all parameters and determine whether its a int or float register parameter */ - for (i = 0; i < n && !done && (cc & cc_reg_param); i++) { - mode = get_irn_mode(param[i]); - - if (mode_is_int(mode) && cur_gp_idx < maxnum_gpreg_args) { - /* param can be passed in general purpose register and we have some registers left */ - in[cur_gp_idx + cur_fp_idx] = param[i]; - in_req[cur_gp_idx] = current_gpreg_param_req[cur_gp_idx]; - cur_gp_idx++; - } - else if (mode_is_float(mode) && cur_fp_idx < maxnum_fpreg_args) { - /* param can be passed in floating point register and we have some registers left */ - assert(current_gpreg_param_req[cur_fp_idx] && "'this' pointer cannot be passed as float"); - in[cur_gp_idx + cur_fp_idx] = param[i]; - in_req[cur_fp_idx] = current_gpreg_param_req[cur_fp_idx]; - cur_fp_idx++; - } - - /* maximum number of register parameters in one class reached? */ - if (cur_gp_idx >= maxnum_gpreg_args || cur_fp_idx >= maxnum_fpreg_args) { - done = 1; - } + /* loop over all parameters and set the register requirements */ + for (i = 0; i <= biggest_n && (cc & cc_reg_param); i++) { + in_req[i] = ia32_get_RegParam_req(n, param, i, cc); } stack_idx = i; @@ -1193,7 +1094,7 @@ static ir_node *gen_Call(transform_env_t *env) { } if (stack_param) { - sync = new_r_Sync(irg, block, n - n_gpregparam - n_fpregparam, stack_param); + sync = new_r_Sync(irg, block, n - biggest_n - 1, stack_param); in[n_new_call_in - 1] = sync; } else { @@ -1208,9 +1109,10 @@ static ir_node *gen_Call(transform_env_t *env) { /* set register requirements for in and out */ attr = get_ia32_attr(new_call); attr->in_req = in_req; - attr->out_req = calloc(1, sizeof(ia32_register_req_t *)); + attr->out_req = calloc(2, sizeof(ia32_register_req_t *)); attr->out_req[0] = &ia32_default_req_ia32_general_purpose_eax; - attr->slots = calloc(1, sizeof(arch_register_t *)); + attr->out_req[1] = &ia32_default_req_ia32_general_purpose_edx; + attr->slots = calloc(2, sizeof(arch_register_t *)); /* stack parameter has no OUT register */ attr->in_req[n_new_call_in - 1] = &ia32_default_req_none; @@ -1384,6 +1286,7 @@ static ir_node *gen_Cond(transform_env_t *env) { * @return Should be always NULL */ static ir_node *gen_Proj_Start(transform_env_t *env, ir_node *proj, ir_node *start) { + const ia32_register_req_t *temp_req; const ir_edge_t *edge; ir_node *succ, *irn; ir_node **projargs; @@ -1393,10 +1296,7 @@ static ir_node *gen_Proj_Start(transform_env_t *env, ir_node *proj, ir_node *sta ir_node *proj_M = get_irg_initial_mem(current_ir_graph); entity *irg_ent = get_irg_entity(current_ir_graph); ir_type *tp = get_entity_type(irg_ent); - int cur_gp_idx = 0; - int cur_fp_idx = 0; - int stack_idx = 0; - int done = 0; + int cur_pn = 0; firm_dbg_module_t *mod = env->mod; dbg_info *dbg = env->dbg; ir_graph *irg = env->irg; @@ -1410,6 +1310,9 @@ static ir_node *gen_Proj_Start(transform_env_t *env, ir_node *proj, ir_node *sta be variadic or one argument is not used. */ n = get_irn_n_edges(proj); + /* Allocate memory for all non variadic parameters in advance to be on the save side */ + env->cg->reg_param_req = calloc(get_method_n_params(tp), sizeof(ia32_register_req_t *)); + /* we are done here when there are no parameters */ if (n < 1) break; @@ -1426,55 +1329,34 @@ static ir_node *gen_Proj_Start(transform_env_t *env, ir_node *proj, ir_node *sta cc = get_method_calling_convention(tp); - /* get the correct order in case of 'this' call */ - current_gpreg_param_req = gpreg_param_req_std; - current_fpreg_param_req = fpreg_param_req_std; - if (cc & cc_this_call) { - current_gpreg_param_req = gpreg_param_req_this; - current_fpreg_param_req = fpreg_param_req_this; - } - /* loop over all parameters and check whether its a int or float */ - for (i = 0; i < n && !done && (cc & cc_reg_param); i++) { - mode = get_irn_mode(projargs[i]); - - if (mode_is_int(mode) && cur_gp_idx < maxnum_gpreg_args) { - /* parameter got passed in general purpose register */ - irn = new_rd_ia32_RegParam(get_irn_dbg_info(proj), irg, block, proj, mode); - set_ia32_pncode(irn, get_Proj_proj(projargs[i])); - set_ia32_req_out(irn, current_gpreg_param_req[cur_gp_idx], 0); - cur_gp_idx++; + for (i = 0; i < n; i++) { + mode = get_irn_mode(projargs[i]); + cur_pn = get_Proj_proj(projargs[i]); + + if (cc & cc_reg_param) { + temp_req = ia32_get_RegParam_req(n, projargs, cur_pn, cc); } - else if (mode_is_float(mode) && cur_fp_idx < maxnum_fpreg_args) { - /* parameter got passed in floating point register*/ - irn = new_rd_ia32_RegParam(get_irn_dbg_info(proj), irg, block, proj, mode); - set_ia32_pncode(irn, get_Proj_proj(projargs[i])); - set_ia32_req_out(irn, current_fpreg_param_req[cur_fp_idx], 0); - cur_fp_idx++; + else { + temp_req = NULL; } - /* kill the old "Proj Arg" and replace with the new Arg */ - exchange(projargs[i], irn); - - if (cur_gp_idx >= maxnum_gpreg_args || cur_fp_idx >= maxnum_fpreg_args) { - stack_idx = i; - done = 1; + if (temp_req) { + /* passed in register */ + env->cg->reg_param_req[cur_pn] = temp_req; } - } - - /* create all remaining stack parameters */ - for (i = stack_idx; i < n; i++) { - mode = get_irn_mode(projargs[i]); - - if (mode_is_float(mode)) - irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode); - else - irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode); + else { + /* passed on stack */ + if (mode_is_float(mode)) + irn = new_rd_ia32_fStackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode); + else + irn = new_rd_ia32_StackParam(get_irn_dbg_info(projargs[i]), irg, block, proj_M, mode); - set_ia32_pncode(irn, get_Proj_proj(projargs[i])); + set_ia32_pncode(irn, cur_pn); - /* kill the old "Proj Arg" and replace with the new stack param */ - exchange(projargs[i], irn); + /* kill the old "Proj Arg" and replace with the new stack param */ + exchange(projargs[i], irn); + } } free(projargs); @@ -1554,6 +1436,7 @@ void ia32_transform_node(ir_node *node, void *env) { tenv.irn = node; tenv.mod = cgenv->mod; tenv.mode = get_irn_mode(node); + tenv.cg = cgenv; #define UNOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_op(node)); break #define BINOP(a) case iro_##a: asm_node = gen_##a(&tenv, get_##a##_left(node), get_##a##_right(node)); break -- 2.20.1