X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Farm%2Fbearch_arm.c;h=49f02261be25695d28169d0569e9ec5ec83cb38f;hb=e1397b01aceb38b6bb62c319007146af3b922f39;hp=ec6cbd52caa7b337615bd89ef2796d568cdc1435;hpb=c28fcf22c08f71b02ccd8edb2e091c1b6c22e540;p=libfirm diff --git a/ir/be/arm/bearch_arm.c b/ir/be/arm/bearch_arm.c index ec6cbd52c..49f02261b 100644 --- a/ir/be/arm/bearch_arm.c +++ b/ir/be/arm/bearch_arm.c @@ -23,9 +23,7 @@ * @author Oliver Richter, Tobias Gneist * @version $Id$ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif #include "lc_opts.h" #include "lc_opts_enum.h" @@ -43,6 +41,7 @@ #include "bitset.h" #include "debug.h" +#include "array_t.h" #include "irtools.h" #include "../bearch_t.h" /* the general register allocator interface */ @@ -131,58 +130,6 @@ static const arch_register_req_t *arm_get_irn_reg_req(const ir_node *node, return arch_no_register_req; } -static void arm_set_irn_reg(ir_node *irn, const arch_register_t *reg) -{ - int pos = 0; - - if (get_irn_mode(irn) == mode_X) { - return; - } - - if (is_Proj(irn)) { - pos = get_Proj_proj(irn); - irn = skip_Proj(irn); - } - - if (is_arm_irn(irn)) { - const arch_register_t **slots; - - slots = get_arm_slots(irn); - slots[pos] = reg; - } - else { - /* here we set the registers for the Phi nodes */ - arm_set_firm_reg(irn, reg, cur_reg_set); - } -} - -static const arch_register_t *arm_get_irn_reg(const ir_node *irn) -{ - int pos = 0; - const arch_register_t *reg = NULL; - - if (is_Proj(irn)) { - - if (get_irn_mode(irn) == mode_X) { - return NULL; - } - - pos = get_Proj_proj(irn); - irn = skip_Proj_const(irn); - } - - if (is_arm_irn(irn)) { - const arch_register_t **slots; - slots = get_arm_slots(irn); - reg = slots[pos]; - } - else { - reg = arm_get_firm_reg(irn, cur_reg_set); - } - - return reg; -} - static arch_irn_class_t arm_classify(const ir_node *irn) { irn = skip_Proj_const(irn); @@ -190,36 +137,10 @@ static arch_irn_class_t arm_classify(const ir_node *irn) if (is_cfop(irn)) { return arch_irn_class_branch; } - else if (is_arm_irn(irn)) { - return arch_irn_class_normal; - } return 0; } -static arch_irn_flags_t arm_get_flags(const ir_node *irn) -{ - arch_irn_flags_t flags = arch_irn_flags_none; - - if(is_Unknown(irn)) { - return arch_irn_flags_ignore; - } - - if (is_Proj(irn) && mode_is_datab(get_irn_mode(irn))) { - ir_node *pred = get_Proj_pred(irn); - if (is_arm_irn(pred)) { - flags = get_arm_out_flags(pred, get_Proj_proj(irn)); - } - irn = pred; - } - - if (is_arm_irn(irn)) { - flags |= get_arm_flags(irn); - } - - return flags; -} - static ir_entity *arm_get_frame_entity(const ir_node *irn) { /* we do NOT transform be_Spill or be_Reload nodes, so we never have frame access using ARM nodes. */ @@ -254,10 +175,7 @@ static int arm_get_sp_bias(const ir_node *irn) static const arch_irn_ops_t arm_irn_ops = { arm_get_irn_reg_req, - arm_set_irn_reg, - arm_get_irn_reg, arm_classify, - arm_get_flags, arm_get_frame_entity, arm_set_frame_entity, arm_set_stack_bias, @@ -314,15 +232,6 @@ static void arm_finish_irg(void *self) } -/** - * These are some hooks which must be filled but are probably not needed. - */ -static void arm_before_sched(void *self) -{ - (void) self; - /* Some stuff you need to do after scheduling but before register allocation */ -} - static void arm_before_ra(void *self) { (void) self; @@ -391,11 +300,11 @@ static ir_node *convert_dbl_to_int(ir_node *bl, ir_node *arg, ir_node *mem, ir_graph *irg = current_ir_graph; ir_node *conv; - conv = new_rd_arm_fpaDbl2GP(NULL, irg, bl, arg, mem); + conv = new_bd_arm_fpaDbl2GP(NULL, bl, arg, mem); /* move high/low */ - *resL = new_r_Proj(irg, bl, conv, mode_Is, pn_arm_fpaDbl2GP_low); - *resH = new_r_Proj(irg, bl, conv, mode_Is, pn_arm_fpaDbl2GP_high); - mem = new_r_Proj(irg, bl, conv, mode_M, pn_arm_fpaDbl2GP_M); + *resL = new_r_Proj(bl, conv, mode_Is, pn_arm_fpaDbl2GP_low); + *resH = new_r_Proj(bl, conv, mode_Is, pn_arm_fpaDbl2GP_high); + mem = new_r_Proj(bl, conv, mode_M, pn_arm_fpaDbl2GP_M); } return mem; } @@ -560,7 +469,6 @@ static const arch_code_generator_if_t arm_code_gen_if = { arm_before_abi, /* before abi introduce */ arm_prepare_graph, NULL, /* spill */ - arm_before_sched, /* before scheduling hook */ arm_before_ra, /* before register allocation hook */ arm_after_ra, arm_finish_irg, @@ -580,11 +488,10 @@ static void *arm_cg_init(be_irg_t *birg) { int_tp = new_type_primitive(new_id_from_chars("int", 3), mode_Is); } - cg = xmalloc(sizeof(*cg)); + cg = XMALLOC(arm_code_gen_t); cg->impl = &arm_code_gen_if; cg->irg = birg->irg; cg->reg_set = new_set(arm_cmp_irn_reg_assoc, 1024); - cg->arch_env = birg->main_env->arch_env; cg->isa = isa; cg->birg = birg; cg->int_tp = int_tp; @@ -745,6 +652,7 @@ static arm_isa_t arm_isa_template = { &arm_isa_if, /* isa interface */ &arm_gp_regs[REG_SP], /* stack pointer */ &arm_gp_regs[REG_R11], /* base pointer */ + &arm_reg_classes[CLASS_arm_gp], /* static link pointer class */ -1, /* stack direction */ 2, /* power of two stack alignment for calls, 2^2 == 4 */ NULL, /* main environment */ @@ -766,7 +674,7 @@ static arch_env_t *arm_init(FILE *file_handle) { if (inited) return NULL; - isa = xmalloc(sizeof(*isa)); + isa = XMALLOC(arm_isa_t); memcpy(isa, &arm_isa_template, sizeof(*isa)); arm_register_init(); @@ -878,27 +786,14 @@ typedef struct { static void *arm_abi_init(const be_abi_call_t *call, const arch_env_t *arch_env, ir_graph *irg) { - arm_abi_env_t *env = xmalloc(sizeof(env[0])); - be_abi_call_flags_t fl = be_abi_call_get_flags(call); + arm_abi_env_t *env = XMALLOC(arm_abi_env_t); + be_abi_call_flags_t fl = be_abi_call_get_flags(call); env->flags = fl.bits; env->irg = irg; env->arch_env = arch_env; return env; } -/** - * Put all registers which are saved by the prologue/epilogue in a set. - * - * @param self The callback object. - * @param s The result set. - */ -static void arm_abi_dont_save_regs(void *self, pset *s) -{ - arm_abi_env_t *env = self; - if (env->flags.try_omit_fp) - pset_insert_ptr(s, env->arch_env->bp); -} - /** * Generate the routine prologue. * @@ -913,7 +808,7 @@ static void arm_abi_dont_save_regs(void *self, pset *s) */ static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap *reg_map, int *stack_bias) { arm_abi_env_t *env = self; - ir_node *keep, *store; + ir_node *store; ir_graph *irg; ir_node *block; arch_register_class_t *gp; @@ -935,29 +830,39 @@ static const arch_register_t *arm_abi_prologue(void *self, ir_node **mem, pmap * irg = env->irg; block = get_irg_start_block(irg); - ip = be_new_Copy(gp, irg, block, sp); - arch_set_irn_register(env->arch_env, ip, &arm_gp_regs[REG_R12]); - be_set_constr_single_reg(ip, BE_OUT_POS(0), &arm_gp_regs[REG_R12] ); + /* mark bp register as ignore */ + be_set_constr_single_reg_out(get_Proj_pred(fp), + get_Proj_proj(fp), env->arch_env->bp, + arch_register_req_type_ignore); + + /* copy SP to IP (so we can spill it */ + ip = be_new_Copy(gp, block, sp); + be_set_constr_single_reg_out(ip, 0, &arm_gp_regs[REG_R12], 0); - store = new_rd_arm_StoreStackM4Inc(NULL, irg, block, sp, fp, ip, lr, pc, *mem); + /* spill stuff */ + store = new_bd_arm_StoreStackM4Inc(NULL, block, sp, fp, ip, lr, pc, *mem); - sp = new_r_Proj(irg, block, store, env->arch_env->sp->reg_class->mode, pn_arm_StoreStackM4Inc_ptr); - arch_set_irn_register(env->arch_env, sp, env->arch_env->sp); - *mem = new_r_Proj(irg, block, store, mode_M, pn_arm_StoreStackM4Inc_M); + sp = new_r_Proj(block, store, env->arch_env->sp->reg_class->mode, pn_arm_StoreStackM4Inc_ptr); + arch_set_irn_register(sp, env->arch_env->sp); + *mem = new_r_Proj(block, store, mode_M, pn_arm_StoreStackM4Inc_M); - keep = be_new_CopyKeep_single(gp, irg, block, ip, sp, get_irn_mode(ip)); - be_node_set_reg_class(keep, 1, gp); - arch_set_irn_register(env->arch_env, keep, &arm_gp_regs[REG_R12]); - be_set_constr_single_reg(keep, BE_OUT_POS(0), &arm_gp_regs[REG_R12] ); + /* frame pointer is ip-4 (because ip is our old sp value) */ + fp = new_bd_arm_Sub_i(NULL, block, ip, get_irn_mode(fp), 4); + arch_set_irn_register(fp, env->arch_env->bp); - fp = new_rd_arm_Sub_i(NULL, irg, block, keep, get_irn_mode(fp), 4); - arch_set_irn_register(env->arch_env, fp, env->arch_env->bp); - fp = be_new_Copy(gp, irg, block, fp); // XXX Gammelfix: only be_ nodes can have the ignore flag set - arch_set_irn_register(env->arch_env, fp, env->arch_env->bp); - be_node_set_flags(fp, BE_OUT_POS(0), arch_irn_flags_ignore); + /* beware: we change the fp but the StoreStackM4Inc above wants the old + * fp value. We are not allowed to spill or anything in the prolog, so we + * have to enforce some order here. (scheduler/regalloc are too stupid + * to extract this order from register requirements) */ + add_irn_dep(fp, store); + + fp = be_new_Copy(gp, block, fp); // XXX Gammelfix: only be_ have custom register requirements + be_set_constr_single_reg_out(fp, 0, env->arch_env->bp, + arch_register_req_type_ignore); + arch_set_irn_register(fp, env->arch_env->bp); be_abi_reg_map_set(reg_map, env->arch_env->bp, fp); - be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R12], keep); + be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_R12], ip); be_abi_reg_map_set(reg_map, env->arch_env->sp, sp); be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_LR], lr); be_abi_reg_map_set(reg_map, &arm_gp_regs[REG_PC], pc); @@ -977,37 +882,25 @@ static void arm_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_m // TODO: Activate Omit fp in epilogue if (env->flags.try_omit_fp) { - curr_sp = be_new_IncSP(env->arch_env->sp, env->irg, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0); - add_irn_dep(curr_sp, *mem); - - curr_lr = be_new_CopyKeep_single(&arm_reg_classes[CLASS_arm_gp], env->irg, bl, curr_lr, curr_sp, get_irn_mode(curr_lr)); - be_node_set_reg_class(curr_lr, 1, &arm_reg_classes[CLASS_arm_gp]); - arch_set_irn_register(env->arch_env, curr_lr, &arm_gp_regs[REG_LR]); - be_set_constr_single_reg(curr_lr, BE_OUT_POS(0), &arm_gp_regs[REG_LR] ); - - curr_pc = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], env->irg, bl, curr_lr ); - arch_set_irn_register(env->arch_env, curr_pc, &arm_gp_regs[REG_PC]); - be_set_constr_single_reg(curr_pc, BE_OUT_POS(0), &arm_gp_regs[REG_PC] ); - be_node_set_flags(curr_pc, BE_OUT_POS(0), arch_irn_flags_ignore); + curr_sp = be_new_IncSP(env->arch_env->sp, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0); + + curr_lr = be_new_CopyKeep_single(&arm_reg_classes[CLASS_arm_gp], bl, curr_lr, curr_sp, get_irn_mode(curr_lr)); + be_set_constr_single_reg_out(curr_lr, 0, &arm_gp_regs[REG_LR], 0); + + curr_pc = be_new_Copy(&arm_reg_classes[CLASS_arm_gp], bl, curr_lr ); + be_set_constr_single_reg_out(curr_pc, BE_OUT_POS(0), &arm_gp_regs[REG_PC], 0); } else { - ir_node *sub12_node; ir_node *load_node; - sub12_node = new_rd_arm_Sub_i(NULL, env->irg, bl, curr_bp, mode_Iu, 12); - // FIXME - //set_arm_req_out_all(sub12_node, sub12_req); - arch_set_irn_register(env->arch_env, sub12_node, env->arch_env->sp); - load_node = new_rd_arm_LoadStackM3( NULL, env->irg, bl, sub12_node, *mem ); - // FIXME - //set_arm_req_out(load_node, &arm_default_req_arm_gp_r11, 0); - //set_arm_req_out(load_node, &arm_default_req_arm_gp_sp, 1); - //set_arm_req_out(load_node, &arm_default_req_arm_gp_pc, 2); - curr_bp = new_r_Proj(env->irg, bl, load_node, env->arch_env->bp->reg_class->mode, pn_arm_LoadStackM3_res0); - curr_sp = new_r_Proj(env->irg, bl, load_node, env->arch_env->sp->reg_class->mode, pn_arm_LoadStackM3_res1); - curr_pc = new_r_Proj(env->irg, bl, load_node, mode_Iu, pn_arm_LoadStackM3_res2); - *mem = new_r_Proj(env->irg, bl, load_node, mode_M, pn_arm_LoadStackM3_M); - arch_set_irn_register(env->arch_env, curr_bp, env->arch_env->bp); - arch_set_irn_register(env->arch_env, curr_sp, env->arch_env->sp); - arch_set_irn_register(env->arch_env, curr_pc, &arm_gp_regs[REG_PC]); + + load_node = new_bd_arm_LoadStackM3Epilogue(NULL, bl, curr_bp, *mem); + + curr_bp = new_r_Proj(bl, load_node, env->arch_env->bp->reg_class->mode, pn_arm_LoadStackM3Epilogue_res0); + curr_sp = new_r_Proj(bl, load_node, env->arch_env->sp->reg_class->mode, pn_arm_LoadStackM3Epilogue_res1); + curr_pc = new_r_Proj(bl, load_node, mode_Iu, pn_arm_LoadStackM3Epilogue_res2); + *mem = new_r_Proj(bl, load_node, mode_M, pn_arm_LoadStackM3Epilogue_M); + arch_set_irn_register(curr_bp, env->arch_env->bp); + arch_set_irn_register(curr_sp, env->arch_env->sp); + arch_set_irn_register(curr_pc, &arm_gp_regs[REG_PC]); } be_abi_reg_map_set(reg_map, env->arch_env->sp, curr_sp); be_abi_reg_map_set(reg_map, env->arch_env->bp, curr_bp); @@ -1019,7 +912,6 @@ static const be_abi_callbacks_t arm_abi_callbacks = { arm_abi_init, free, arm_get_between_type, - arm_abi_dont_save_regs, arm_abi_prologue, arm_abi_epilogue, }; @@ -1235,13 +1127,15 @@ static const backend_params *arm_get_libfirm_params(void) { static backend_params p = { 1, /* need dword lowering */ 0, /* don't support inline assembler yet */ - 0, /* no immediate floating point mode. */ - NULL, /* no additional opcodes */ NULL, /* will be set later */ NULL, /* but yet no creator function */ NULL, /* context for create_intrinsic_fkt */ - NULL, /* will be set below */ - NULL /* no immediate fp mode */ + NULL, /* ifconv_info will be set below */ + NULL, /* float arithmetic mode (TODO) */ + 0, /* no trampoline support: size 0 */ + 0, /* no trampoline support: align 0 */ + NULL, /* no trampoline support: no trampoline builder */ + 4 /* alignment of stack parameter */ }; p.dep_param = &ad; @@ -1273,6 +1167,7 @@ static const lc_opt_table_entry_t arm_options[] = { const arch_isa_if_t arm_isa_if = { arm_init, arm_done, + NULL, /* handle_intrinsics */ arm_get_n_reg_class, arm_get_reg_class, arm_get_reg_class_for_mode, @@ -1285,6 +1180,7 @@ const arch_isa_if_t arm_isa_if = { arm_get_allowed_execution_units, arm_get_machine, arm_get_irg_list, + NULL, /* mark remat */ arm_parse_asm_constraint, arm_is_valid_clobber };