fehler104: tarval problems with uneven sub bits
[libfirm] / ir / be / beabi.c
index 8e97d28..c6050e9 100644 (file)
@@ -61,12 +61,13 @@ 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 {
@@ -192,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;
@@ -1574,7 +1576,7 @@ static void fix_address_of_parameter_access(be_abi_irg_t *env, ir_entity *value_
                ir_node *frame, *imem, *nmem, *store, *mem, *args, *args_bl;
                const ir_edge_t *edge;
                optimization_state_t state;
-               int offset;
+               unsigned offset;
 
                foreach_block_succ(start_bl, edge) {
                        ir_node *succ = get_edge_src_irn(edge);
@@ -1628,11 +1630,11 @@ static void fix_address_of_parameter_access(be_abi_irg_t *env, ir_entity *value_
                frame_tp = get_irg_frame_type(irg);
                offset   = get_type_size_bytes(frame_tp);
                for (ent = new_list; ent; ent = get_entity_link(ent)) {
-                       ir_type *tp = get_entity_type(ent);
-                       int align = get_type_alignment_bytes(tp);
+                       ir_type  *tp   = get_entity_type(ent);
+                       unsigned align = get_type_alignment_bytes(tp);
 
                        offset += align - 1;
-                       offset &= -align;
+                       offset &= ~(align - 1);
                        set_entity_owner(ent, frame_tp);
                        add_class_member(frame_tp, ent);
                        /* must be automatic to set a fixed layout */
@@ -1890,25 +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);
+                                       ir_mode *mode      = get_type_mode(param_type);
+                                       ir_mode *load_mode = arg->load_mode;
+
+                                       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_rd_Proj(NULL, irg, reg_params_bl, load,
-                                                          mode, pn_Load_res);
-                               }
+                                       repl = new_r_Proj(irg, reg_params_bl, load, load_mode, pn_Load_res);
 
-                               /* 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 {
+                                       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;
                                }
                        }
@@ -2209,10 +2211,10 @@ static int process_stack_bias(be_abi_irg_t *env, ir_node *bl, int bias)
 
                        if(be_is_IncSP(irn)) {
                                if(ofs == BE_STACK_FRAME_SIZE_EXPAND) {
-                                       ofs = get_type_size_bytes(get_irg_frame_type(env->birg->irg));
+                                       ofs = (int)get_type_size_bytes(get_irg_frame_type(env->birg->irg));
                                        be_set_IncSP_offset(irn, ofs);
                                } else if(ofs == BE_STACK_FRAME_SIZE_SHRINK) {
-                                       ofs = - get_type_size_bytes(get_irg_frame_type(env->birg->irg));
+                                       ofs = - (int)get_type_size_bytes(get_irg_frame_type(env->birg->irg));
                                        be_set_IncSP_offset(irn, ofs);
                                }
                        }