diff options
Diffstat (limited to 'gcc/calls.c')
-rw-r--r-- | gcc/calls.c | 146 |
1 files changed, 73 insertions, 73 deletions
diff --git a/gcc/calls.c b/gcc/calls.c index 41725b57769..60af049e527 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -1,6 +1,6 @@ /* Convert function calls to rtl insns, for GNU C compiler. Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998 - 1999, 2000, 2001 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. This file is part of GCC. @@ -35,6 +35,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "sbitmap.h" #include "langhooks.h" #include "target.h" +#include "except.h" #if !defined FUNCTION_OK_FOR_SIBCALL #define FUNCTION_OK_FOR_SIBCALL(DECL) 1 @@ -227,6 +228,7 @@ static int check_sibcall_argument_overlap PARAMS ((rtx, struct arg_data *)); static int combine_pending_stack_adjustment_and_call PARAMS ((int, struct args_size *, int)); +static tree fix_unsafe_tree PARAMS ((tree)); #ifdef REG_PARM_STACK_SPACE static rtx save_fixed_argument_area PARAMS ((int, rtx, int *, int *)); @@ -616,6 +618,8 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size, if (ecf_flags & ECF_NOTHROW) REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_EH_REGION, const0_rtx, REG_NOTES (call_insn)); + else + note_eh_region_may_contain_throw (); if (ecf_flags & ECF_NORETURN) REG_NOTES (call_insn) = gen_rtx_EXPR_LIST (REG_NORETURN, const0_rtx, @@ -1662,6 +1666,7 @@ compute_argument_addresses (args, argblock, num_actuals) addr = plus_constant (addr, arg_offset); args[i].stack = gen_rtx_MEM (args[i].mode, addr); + set_mem_align (args[i].stack, PARM_BOUNDARY); set_mem_attributes (args[i].stack, TREE_TYPE (args[i].tree_value), 1); @@ -1672,6 +1677,7 @@ compute_argument_addresses (args, argblock, num_actuals) addr = plus_constant (addr, arg_offset); args[i].stack_slot = gen_rtx_MEM (args[i].mode, addr); + set_mem_align (args[i].stack_slot, PARM_BOUNDARY); set_mem_attributes (args[i].stack_slot, TREE_TYPE (args[i].tree_value), 1); @@ -1691,12 +1697,12 @@ compute_argument_addresses (args, argblock, num_actuals) FNDECL is the tree node for the target function. For an indirect call FNDECL will be NULL_TREE. - EXP is the CALL_EXPR for this call. */ + ADDR is the operand 0 of CALL_EXPR for this call. */ static rtx -rtx_for_function_call (fndecl, exp) +rtx_for_function_call (fndecl, addr) tree fndecl; - tree exp; + tree addr; { rtx funexp; @@ -1720,7 +1726,7 @@ rtx_for_function_call (fndecl, exp) rtx funaddr; push_temp_slots (); funaddr = funexp - = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, VOIDmode, 0); + = expand_expr (addr, NULL_RTX, VOIDmode, 0); pop_temp_slots (); /* FUNEXP can't be BLKmode. */ emit_queue (); } @@ -2081,6 +2087,35 @@ check_sibcall_argument_overlap (insn, arg) return insn != NULL_RTX; } +static tree +fix_unsafe_tree (t) + tree t; +{ + switch (unsafe_for_reeval (t)) + { + case 0: /* Safe. */ + break; + + case 1: /* Mildly unsafe. */ + t = unsave_expr (t); + break; + + case 2: /* Wildly unsafe. */ + { + tree var = build_decl (VAR_DECL, NULL_TREE, + TREE_TYPE (t)); + SET_DECL_RTL (var, + expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL)); + t = var; + } + break; + + default: + abort (); + } + return t; +} + /* Generate all the code for a function call and return an rtx for its value. Store the value in TARGET (specified as an rtx) if convenient. @@ -2192,6 +2227,7 @@ expand_call (exp, target, ignore) int old_stack_allocated; rtx call_fusage; tree p = TREE_OPERAND (exp, 0); + tree addr = TREE_OPERAND (exp, 0); int i; /* The alignment of the stack, in bits. */ HOST_WIDE_INT preferred_stack_boundary; @@ -2313,7 +2349,7 @@ expand_call (exp, target, ignore) preferred_stack_boundary = PREFERRED_STACK_BOUNDARY; /* Operand 0 is a pointer-to-function; get the type of the function. */ - funtype = TREE_TYPE (TREE_OPERAND (exp, 0)); + funtype = TREE_TYPE (addr); if (! POINTER_TYPE_P (funtype)) abort (); funtype = TREE_TYPE (funtype); @@ -2450,8 +2486,8 @@ expand_call (exp, target, ignore) /* Tail recursion fails, when we are not dealing with recursive calls. */ if (!try_tail_recursion - || TREE_CODE (TREE_OPERAND (exp, 0)) != ADDR_EXPR - || TREE_OPERAND (TREE_OPERAND (exp, 0), 0) != current_function_decl) + || TREE_CODE (addr) != ADDR_EXPR + || TREE_OPERAND (addr, 0) != current_function_decl) try_tail_recursion = 0; /* Rest of purposes for tail call optimizations to fail. */ @@ -2522,35 +2558,16 @@ expand_call (exp, target, ignore) for (; i != end; i += inc) { - switch (unsafe_for_reeval (args[i].tree_value)) - { - case 0: /* Safe. */ - break; - - case 1: /* Mildly unsafe. */ - args[i].tree_value = unsave_expr (args[i].tree_value); - break; - - case 2: /* Wildly unsafe. */ - { - tree var = build_decl (VAR_DECL, NULL_TREE, - TREE_TYPE (args[i].tree_value)); - SET_DECL_RTL (var, - expand_expr (args[i].tree_value, NULL_RTX, - VOIDmode, EXPAND_NORMAL)); - args[i].tree_value = var; - } - break; - - default: - abort (); - } + args[i].tree_value = fix_unsafe_tree (args[i].tree_value); /* We need to build actparms for optimize_tail_recursion. We can safely trash away TREE_PURPOSE, since it is unused by this function. */ if (try_tail_recursion) actparms = tree_cons (NULL_TREE, args[i].tree_value, actparms); } + /* Do the same for the function address if it is an expression. */ + if (!fndecl) + addr = fix_unsafe_tree (addr); /* Expanding one of those dangerous arguments could have added cleanups, but otherwise give it a whirl. */ if (any_pending_cleanups (1)) @@ -2944,7 +2961,7 @@ expand_call (exp, target, ignore) be deferred during the evaluation of the arguments. */ NO_DEFER_POP; - funexp = rtx_for_function_call (fndecl, exp); + funexp = rtx_for_function_call (fndecl, addr); /* Figure out the register where the value, if any, will come back. */ valreg = 0; @@ -4131,7 +4148,7 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) { rtx insns; - if (valreg == 0 || GET_CODE (valreg) == PARALLEL) + if (valreg == 0) { insns = get_insns (); end_sequence (); @@ -4140,9 +4157,18 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) else { rtx note = 0; - rtx temp = gen_reg_rtx (GET_MODE (valreg)); + rtx temp; int i; + if (GET_CODE (valreg) == PARALLEL) + { + temp = gen_reg_rtx (outmode); + emit_group_store (temp, valreg, outmode); + valreg = temp; + } + + temp = gen_reg_rtx (GET_MODE (valreg)); + /* Construct an "equal form" for the value which mentions all the arguments in order as well as the function name. */ for (i = 0; i < nargs; i++) @@ -4176,6 +4202,12 @@ emit_library_call_value_1 (retval, orgfun, value, fn_type, outmode, nargs, p) if (value != mem_value) emit_move_insn (value, mem_value); } + else if (GET_CODE (valreg) == PARALLEL) + { + if (value == 0) + value = gen_reg_rtx (outmode); + emit_group_store (value, valreg, outmode); + } else if (value != 0) emit_move_insn (value, valreg); else @@ -4394,13 +4426,6 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) } } } - /* Now that we have saved any slots that will be overwritten by this - store, mark all slots this store will use. We must do this before - we actually expand the argument since the expansion itself may - trigger library calls which might need to use the same stack slot. */ - if (argblock && ! variable_size && arg->stack) - for (i = lower_bound; i < upper_bound; i++) - stack_usage_map[i] = 1; } /* If this isn't going to be placed on both the stack and in registers, @@ -4453,7 +4478,7 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) (partial || TYPE_MODE (TREE_TYPE (pval)) != arg->mode) ? NULL_RTX : arg->stack, - VOIDmode, 0); + VOIDmode, EXPAND_STACK_PARM); /* If we are promoting object (or for any other reason) the mode doesn't agree, convert the mode. */ @@ -4596,37 +4621,6 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) } } - /* Special handling is required if part of the parameter lies in the - register parameter area. The argument may be copied into the stack - slot using memcpy(), but the original contents of the register - parameter area will be restored after the memcpy() call. - - To ensure that the part that lies in the register parameter area - is copied correctly, we emit a separate push for that part. This - push should be small enough to avoid a call to memcpy(). */ -#ifndef STACK_PARMS_IN_REG_PARM_AREA - if (arg->reg && arg->pass_on_stack) -#else - if (1) -#endif - { - if (arg->offset.constant < reg_parm_stack_space && arg->offset.var) - error ("variable offset is passed partially in stack and in reg"); - else if (arg->offset.constant < reg_parm_stack_space && arg->size.var) - error ("variable size is passed partially in stack and in reg"); - else if (arg->offset.constant < reg_parm_stack_space - && ((arg->offset.constant + arg->size.constant) - > reg_parm_stack_space)) - { - rtx size_rtx1 = GEN_INT (reg_parm_stack_space - arg->offset.constant); - emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx1, - parm_align, partial, reg, excess, argblock, - ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space, - ARGS_SIZE_RTX (arg->alignment_pad)); - } - } - - emit_push_insn (arg->value, arg->mode, TREE_TYPE (pval), size_rtx, parm_align, partial, reg, excess, argblock, ARGS_SIZE_RTX (arg->offset), reg_parm_stack_space, @@ -4644,6 +4638,12 @@ store_one_arg (arg, argblock, flags, variable_size, reg_parm_stack_space) arg->value = arg->stack_slot; } + /* Mark all slots this store used. */ + if (ACCUMULATE_OUTGOING_ARGS && !(flags & ECF_SIBCALL) + && argblock && ! variable_size && arg->stack) + for (i = lower_bound; i < upper_bound; i++) + stack_usage_map[i] = 1; + /* Once we have pushed something, pops can't safely be deferred during the rest of the arguments. */ NO_DEFER_POP; |