copy result mode on final transformations (lea->add and sub->neg-add)
[libfirm] / ir / be / beabi.c
index ed6aeb1..b9783c8 100644 (file)
@@ -500,17 +500,29 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                        type *param_type       = get_method_param_type(mt, p);
                        int param_size         = get_type_size_bytes(param_type) + arg->space_after;
 
-                       curr_ofs += arg->space_before;
-                       curr_ofs =  round_up2(curr_ofs, arg->alignment);
+                       /*
+                        * If we wanted to build the arguments sequentially,
+                        * the stack pointer for the next must be incremented,
+                        * and the memory value propagated.
+                        */
+                       if (do_seq) {
+                               curr_ofs = 0;
+                               addr = curr_sp = be_new_IncSP(sp, irg, bl, curr_sp, curr_mem,
+                                       param_size + arg->space_before, be_stack_dir_expand);
+                       }
+                       else {
+                               curr_ofs += arg->space_before;
+                               curr_ofs =  round_up2(curr_ofs, arg->alignment);
 
-                       /* Make the expression to compute the argument's offset. */
-                       if(curr_ofs > 0) {
-                               addr = new_r_Const_long(irg, bl, mode_Is, curr_ofs);
-                               addr = new_r_Add(irg, bl, curr_sp, addr, mach_mode);
+                               /* Make the expression to compute the argument's offset. */
+                               if(curr_ofs > 0) {
+                                       addr = new_r_Const_long(irg, bl, mode_Is, curr_ofs);
+                                       addr = new_r_Add(irg, bl, curr_sp, addr, mach_mode);
+                               }
                        }
 
                        /* Insert a store for primitive arguments. */
-                       if(is_atomic_type(param_type)) {
+                       if (is_atomic_type(param_type)) {
                                mem = new_r_Store(irg, bl, curr_mem, addr, param);
                                mem = new_r_Proj(irg, bl, mem, mode_M, pn_Store_M);
                        }
@@ -522,20 +534,12 @@ static ir_node *adjust_call(be_abi_irg_t *env, ir_node *irn, ir_node *curr_sp)
                                mem = new_r_Proj(irg, bl, mem, mode_M, pn_CopyB_M_regular);
                        }
 
-                       obstack_ptr_grow(obst, mem);
-
                        curr_ofs += param_size;
 
-                       /*
-                        * If we wanted to build the arguments sequentially,
-                        * the stack pointer for the next must be incremented,
-                        * and the memory value propagated.
-                        */
-                       if(do_seq) {
-                               curr_ofs = 0;
-                               curr_sp  = be_new_IncSP(sp, irg, bl, curr_sp, curr_mem, param_size, be_stack_dir_expand);
+                       if (do_seq)
                                curr_mem = mem;
-                       }
+                       else
+                               obstack_ptr_grow(obst, mem);
                }
 
                in = (ir_node **) obstack_finish(obst);
@@ -1178,7 +1182,11 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, i
                it then. Else we use the stack from the start block and let
                the ssa construction fix the usage.
        */
-       stack = keep ? get_irn_n(keep, 0) : be_abi_reg_map_get(env->regs, isa->sp);
+       stack = be_abi_reg_map_get(env->regs, isa->sp);
+       if (keep) {
+               stack = get_irn_n(keep, 0);
+               exchange(keep, new_r_Bad(env->birg->irg));
+       }
        be_abi_reg_map_set(reg_map, isa->sp, stack);
 
        /* Insert results for Return into the register map. */
@@ -1237,7 +1245,7 @@ static ir_node *create_be_return(be_abi_irg_t *env, ir_node *irn, ir_node *bl, i
        }
 
        /* The in array for the new back end return is now ready. */
-       ret = be_new_Return(irn ? get_irn_dbg_info(irn) : NULL, env->birg->irg, bl, n, in);
+       ret = be_new_Return(irn ? get_irn_dbg_info(irn) : NULL, env->birg->irg, bl, n_res, n, in);
 
        /* Set the register classes of the return's parameter accordingly. */
        for(i = 0; i < n; ++i)
@@ -1442,16 +1450,16 @@ static void modify_irg(be_abi_irg_t *env)
                ir_node *irn = get_Block_cfgpred(end, i);
 
                if (get_irn_opcode(irn) == iro_Return) {
-      ir_node *ret = create_be_return(env, irn, get_nodes_block(irn), get_Return_mem(irn), get_Return_n_ress(irn));
-       exchange(irn, ret);
+                       ir_node *ret = create_be_return(env, irn, get_nodes_block(irn), get_Return_mem(irn), get_Return_n_ress(irn));
+                       exchange(irn, ret);
                }
        }
 
-  if (n <= 0) {
-    /* we have endless loops, add a dummy return without return vals */
-    ir_node *ret = create_be_return(env, NULL, end, get_irg_no_mem(irg), n);
-    add_End_keepalive(get_irg_end(irg), ret);
-  }
+       if (n <= 0) {
+               /* we have endless loops, add a dummy return without return vals */
+               ir_node *ret = create_be_return(env, NULL, end, get_irg_no_mem(irg), n);
+               add_End_keepalive(get_irg_end(irg), ret);
+       }
 
        del_pset(dont_save);
        obstack_free(&env->obst, args);