BugFix: mode_b lowering might create new control flow (if ir_create_cond_set() is...
[libfirm] / ir / be / amd64 / bearch_amd64.c
index eb44063..ce10c56 100644 (file)
@@ -157,7 +157,7 @@ static void transform_Reload(ir_node *node)
        ir_node   *block  = get_nodes_block(node);
        dbg_info  *dbgi   = get_irn_dbg_info(node);
        ir_node   *ptr    = get_irg_frame(irg);
-       ir_node   *mem    = get_irn_n(node, be_pos_Reload_mem);
+       ir_node   *mem    = get_irn_n(node, n_be_Reload_mem);
        ir_mode   *mode   = get_irn_mode(node);
        ir_entity *entity = be_get_frame_entity(node);
        const arch_register_t *reg;
@@ -184,8 +184,8 @@ static void transform_Spill(ir_node *node)
        ir_node   *block  = get_nodes_block(node);
        dbg_info  *dbgi   = get_irn_dbg_info(node);
        ir_node   *ptr    = get_irg_frame(irg);
-       ir_node   *mem    = new_r_NoMem(irg);
-       ir_node   *val    = get_irn_n(node, be_pos_Spill_val);
+       ir_node   *mem    = get_irg_no_mem(irg);
+       ir_node   *val    = get_irn_n(node, n_be_Spill_val);
        //ir_mode   *mode   = get_irn_mode(val);
        ir_entity *entity = be_get_frame_entity(node);
        ir_node   *sched_point;
@@ -216,9 +216,35 @@ static void amd64_after_ra_walker(ir_node *block, void *data)
        }
 }
 
+static void amd64_set_frame_entity(ir_node *node, ir_entity *entity)
+{
+       assert(be_is_Reload(node));
+       be_node_set_frame_entity(node, entity);
+}
+
+/**
+ * Collects nodes that need frame entities assigned.
+ */
+static void amd64_collect_frame_entity_nodes(ir_node *node, void *data)
+{
+       if (be_is_Reload(node) && be_get_frame_entity(node) == NULL) {
+               be_fec_env_t  *env   = (be_fec_env_t*)data;
+               const ir_mode *mode  = get_irn_mode(node);
+               int            align = get_mode_size_bytes(mode);
+               be_node_needs_frame_entity(env, node, mode, align);
+       }
+}
+
 static void amd64_after_ra(ir_graph *irg)
 {
-       be_coalesce_spillslots(irg);
+       be_stack_layout_t *stack_layout = be_get_irg_stack_layout(irg);
+       bool               at_begin     = stack_layout->sp_relative ? true : false;
+       be_fec_env_t      *fec_env      = be_new_frame_entity_coalescer(irg);
+
+       /* create and coalesce frame entities */
+       irg_walk_graph(irg, NULL, amd64_collect_frame_entity_nodes, fec_env);
+       be_assign_entities(fec_env, amd64_set_frame_entity, at_begin);
+       be_free_frame_entity_coalescer(fec_env);
 
        irg_block_walk_graph(irg, NULL, amd64_after_ra_walker, NULL);
 }
@@ -269,7 +295,6 @@ static amd64_isa_t amd64_isa_template = {
                &amd64_registers[REG_RSP],  /* stack pointer register */
                &amd64_registers[REG_RBP],  /* base pointer register */
                &amd64_reg_classes[CLASS_amd64_gp],  /* link pointer register class */
-               -1,                          /* stack direction */
                3,                           /* power of two stack alignment for calls, 2^2 == 4 */
                NULL,                        /* main environment */
                7,                           /* costs for a spill instruction */
@@ -330,25 +355,16 @@ typedef struct {
        ir_graph *irg;
 } amd64_abi_env_t;
 
-static void *amd64_abi_init(const be_abi_call_t *call, ir_graph *irg)
-{
-       amd64_abi_env_t *env = XMALLOC(amd64_abi_env_t);
-       be_abi_call_flags_t fl = be_abi_call_get_flags(call);
-       env->flags    = fl.bits;
-       env->irg      = irg;
-       return env;
-}
-
 /**
  * Get the between type for that call.
  * @param self The callback object.
  * @return The between type of for that call.
  */
-static ir_type *amd64_get_between_type(void *self)
+static ir_type *amd64_get_between_type(ir_graph *irg)
 {
        static ir_type *between_type = NULL;
        static ir_entity *old_bp_ent = NULL;
-       (void) self;
+       (void) irg;
 
        if(!between_type) {
                ir_entity *ret_addr_ent;
@@ -367,53 +383,8 @@ static ir_type *amd64_get_between_type(void *self)
        return between_type;
 }
 
-/**
- * Build the prolog, return the BASE POINTER register
- */
-static const arch_register_t *amd64_abi_prologue(void *self, ir_node **mem,
-                                                    pmap *reg_map, int *stack_bias)
-{
-       amd64_abi_env_t  *env  = (amd64_abi_env_t*)self;
-       const arch_env_t *aenv = be_get_irg_arch_env(env->irg);
-       (void) mem;
-       (void) stack_bias;
-       (void) aenv;
-       (void) reg_map;
-
-       if (!env->flags.try_omit_fp) {
-               /* FIXME: maybe later here should be some code to generate
-                * the usual abi prologue */
-               return aenv->bp;
-       }
-
-       return aenv->sp;
-}
-
-/* Build the epilog */
-static void amd64_abi_epilogue(void *self, ir_node *bl, ir_node **mem,
-                               pmap *reg_map)
-{
-       amd64_abi_env_t  *env  = (amd64_abi_env_t*)self;
-       const arch_env_t *aenv = be_get_irg_arch_env(env->irg);
-       ir_node          *curr_sp  = be_abi_reg_map_get(reg_map, aenv->sp);
-       ir_node          *curr_bp  = be_abi_reg_map_get(reg_map, aenv->bp);
-       (void) bl;
-       (void) mem;
-
-       if (env->flags.try_omit_fp) {
-               curr_sp = be_new_IncSP(aenv->sp, bl, curr_sp, BE_STACK_FRAME_SIZE_SHRINK, 0);
-       }
-
-       be_abi_reg_map_set(reg_map, aenv->sp, curr_sp);
-       be_abi_reg_map_set(reg_map, aenv->bp, curr_bp);
-}
-
 static const be_abi_callbacks_t amd64_abi_callbacks = {
-       amd64_abi_init,
-       free,
        amd64_get_between_type,
-       amd64_abi_prologue,
-       amd64_abi_epilogue,
 };
 
 static const arch_register_t *gpreg_param_reg_std[] = {
@@ -500,6 +471,16 @@ static int amd64_get_reg_class_alignment(const arch_register_class_t *cls)
 
 static void amd64_lower_for_target(void)
 {
+       lower_params_t params = {
+               4,                                     /* def_ptr_alignment */
+               LF_COMPOUND_RETURN | LF_RETURN_HIDDEN, /* flags */
+               ADD_HIDDEN_ALWAYS_IN_FRONT,            /* hidden_params */
+               NULL,                                  /* find pointer type */
+               NULL,                                  /* ret_compound_in_regs */
+       };
+
+       /* lower compound param handling */
+       lower_calls_with_compounds(&params);
 }
 
 static int amd64_is_mux_allowed(ir_node *sel, ir_node *mux_false,
@@ -574,7 +555,7 @@ const arch_isa_if_t amd64_isa_if = {
        amd64_gen_routine,
 };
 
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_amd64);
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_arch_amd64)
 void be_init_arch_amd64(void)
 {
        be_register_isa_if("amd64", &amd64_isa_if);