remove #if 0 around arch_get_irn_ops, no idea why it was there...
[libfirm] / ir / be / beabi.c
index 0547a0c..b6400df 100644 (file)
@@ -61,16 +61,18 @@ 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 {
-       be_abi_call_flags_t         flags;
+       be_abi_call_flags_t          flags;
+       int                          pop;
        const be_abi_callbacks_t    *cb;
        ir_type                     *between_type;
        set                         *params;
@@ -178,6 +180,11 @@ void be_abi_call_set_flags(be_abi_call_t *call, be_abi_call_flags_t flags, const
        call->cb    = cb;
 }
 
+void be_abi_call_set_pop(be_abi_call_t *call, int pop)
+{
+       assert(pop >= 0);
+       call->pop = pop;
+}
 
 /* Set register class for call address */
 void be_abi_call_set_call_address_reg_class(be_abi_call_t *call, const arch_register_class_t *cls)
@@ -186,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;
@@ -224,6 +232,7 @@ be_abi_call_flags_t be_abi_call_get_flags(const be_abi_call_t *call)
 static be_abi_call_t *be_abi_call_new(const arch_register_class_t *cls_addr)
 {
        be_abi_call_t *call = xmalloc(sizeof(call[0]));
+       memset(call, 0, sizeof(call[0]));
 
        call->flags.val  = 0;
        call->params     = new_set(cmp_call_arg, 16);
@@ -648,6 +657,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                                       n_reg_results + pn_be_Call_first_res + pset_count(caller_save),
                                       n_ins, in, get_Call_type(irn));
        }
+       be_Call_set_pop(low_call, call->pop);
        ARR_APP1(ir_node *, env->calls, low_call);
 
        /* create new stack pointer */
@@ -776,6 +786,9 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
        }
 
        /* Clean up the stack. */
+       assert(stack_size >= call->pop);
+       stack_size -= call->pop;
+
        if (stack_size > 0) {
                ir_node *mem_proj = NULL;
 
@@ -794,15 +807,7 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
 
                 /* Clean up the stack frame if we allocated it */
                if (! no_alloc) {
-                       /* the callee pops the shadow parameter */
-                       if(get_method_calling_convention(mt) & cc_compound_ret) {
-                               unsigned size = get_mode_size_bytes(mode_P_data);
-                               stack_size -= size;
-                               be_Call_set_pop(low_call, size);
-                       }
-
                        curr_sp = be_new_IncSP(sp, irg, bl, curr_sp, -stack_size);
-                       //add_irn_dep(curr_sp, mem_proj);
                }
        }
 
@@ -1387,9 +1392,6 @@ static ir_node *create_barrier(be_abi_irg_t *env, ir_node *bl, ir_node **mem, pm
 static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
                ir_node *mem, int n_res)
 {
-       ir_graph      *irg         = env->birg->irg;
-       ir_entity     *entity      = get_irg_entity(irg);
-       ir_type       *method_type = get_entity_type(entity);
        be_abi_call_t *call        = env->call;
        const arch_isa_t *isa = env->birg->main_env->arch_env->isa;
        dbg_info *dbgi;
@@ -1481,10 +1483,7 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl,
                dbgi = NULL;
        }
        /* we have to pop the shadow parameter in in case of struct returns */
-       pop = 0;
-       if(get_method_calling_convention(method_type) & cc_compound_ret) {
-               pop = get_mode_size_bytes(mode_P_data);
-       }
+       pop = call->pop;
        ret = be_new_Return(dbgi, env->birg->irg, bl, n_res, pop, n, in);
 
        /* Set the register classes of the return's parameter accordingly. */
@@ -1893,24 +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);
-                                       repl = new_rd_Proj(NULL, irg, reg_params_bl, load,
-                                                          mode, pn_Load_res);
-                               }
+                                       ir_mode *mode      = get_type_mode(param_type);
+                                       ir_mode *load_mode = arg->load_mode;
 
-                               /* 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 {
+                                       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_r_Proj(irg, reg_params_bl, load, load_mode, pn_Load_res);
+
+                                       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;
                                }
                        }