Mercurial > hg > CbC > CbC_gcc
diff gcc/calls.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | b7f97abdc517 |
children | 1b10fe6932e1 04ced10e8804 |
line wrap: on
line diff
--- a/gcc/calls.c Tue May 25 18:58:51 2010 +0900 +++ b/gcc/calls.c Tue Mar 22 17:18:12 2011 +0900 @@ -32,7 +32,7 @@ #include "libfuncs.h" #include "function.h" #include "regs.h" -#include "toplev.h" +#include "diagnostic-core.h" #include "output.h" #include "tm_p.h" #include "timevar.h" @@ -89,7 +89,7 @@ rtx stack; /* Location on the stack of the start of this argument slot. This can differ from STACK if this arg pads downward. This location is known - to be aligned to FUNCTION_ARG_BOUNDARY. */ + to be aligned to TARGET_FUNCTION_ARG_BOUNDARY. */ rtx stack_slot; /* Place that this stack area has been saved, if needed. */ rtx save_area; @@ -208,13 +208,15 @@ The CALL_INSN is the first insn generated. FNDECL is the declaration node of the function. This is given to the - macro RETURN_POPS_ARGS to determine whether this function pops its own args. - - FUNTYPE is the data type of the function. This is given to the macro - RETURN_POPS_ARGS to determine whether this function pops its own args. - We used to allow an identifier for library functions, but that doesn't - work when the return type is an aggregate type and the calling convention - says that the pointer to this aggregate is to be popped by the callee. + hook TARGET_RETURN_POPS_ARGS to determine whether this function pops + its own args. + + FUNTYPE is the data type of the function. This is given to the hook + TARGET_RETURN_POPS_ARGS to determine whether this function pops its + own args. We used to allow an identifier for library functions, but + that doesn't work when the return type is an aggregate type and the + calling convention says that the pointer to this aggregate is to be + popped by the callee. STACK_SIZE is the number of bytes of arguments on the stack, ROUNDED_STACK_SIZE is that number rounded up to @@ -226,7 +228,7 @@ It is zero if this call doesn't want a structure value. NEXT_ARG_REG is the rtx that results from executing - FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1) + targetm.calls.function_arg (&args_so_far, VOIDmode, void_type_node, true) just after all the args have had their registers assigned. This could be whatever you like, but normally it is the first arg-register beyond those used for args in this call, @@ -256,7 +258,8 @@ rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size); rtx call_insn; int already_popped = 0; - HOST_WIDE_INT n_popped = RETURN_POPS_ARGS (fndecl, funtype, stack_size); + HOST_WIDE_INT n_popped + = targetm.calls.return_pops_args (fndecl, funtype, stack_size); #ifdef CALL_POPS_ARGS n_popped += CALL_POPS_ARGS (* args_so_far); @@ -598,7 +601,7 @@ flags |= ECF_RETURNS_TWICE; /* Process the pure and const attributes. */ - if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)) + if (TREE_READONLY (exp)) flags |= ECF_CONST; if (DECL_PURE_P (exp)) flags |= ECF_PURE; @@ -607,17 +610,23 @@ if (DECL_IS_NOVOPS (exp)) flags |= ECF_NOVOPS; + if (lookup_attribute ("leaf", DECL_ATTRIBUTES (exp))) + flags |= ECF_LEAF; if (TREE_NOTHROW (exp)) flags |= ECF_NOTHROW; flags = special_function_p (exp, flags); } - else if (TYPE_P (exp) && TYPE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp)) + else if (TYPE_P (exp) && TYPE_READONLY (exp)) flags |= ECF_CONST; if (TREE_THIS_VOLATILE (exp)) - flags |= ECF_NORETURN; + { + flags |= ECF_NORETURN; + if (flags & (ECF_CONST|ECF_PURE)) + flags |= ECF_LOOPING_CONST_OR_PURE; + } return flags; } @@ -877,7 +886,7 @@ int bitsize = MIN (bytes * BITS_PER_UNIT, BITS_PER_WORD); args[i].aligned_regs[j] = reg; - word = extract_bit_field (word, bitsize, 0, 1, NULL_RTX, + word = extract_bit_field (word, bitsize, 0, 1, false, NULL_RTX, word_mode, word_mode); /* There is no need to restrict this code to loading items @@ -1083,14 +1092,19 @@ if (*old_stack_level == 0) { - emit_stack_save (SAVE_BLOCK, old_stack_level, NULL_RTX); + emit_stack_save (SAVE_BLOCK, old_stack_level); *old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; } - copy = gen_rtx_MEM (BLKmode, - allocate_dynamic_stack_space - (size_rtx, NULL_RTX, TYPE_ALIGN (type))); + /* We can pass TRUE as the 4th argument because we just + saved the stack pointer and will restore it right after + the call. */ + copy = allocate_dynamic_stack_space (size_rtx, + TYPE_ALIGN (type), + TYPE_ALIGN (type), + true); + copy = gen_rtx_MEM (BLKmode, copy); set_mem_attributes (copy, type, 1); } else @@ -1124,17 +1138,18 @@ args[i].unsignedp = unsignedp; args[i].mode = mode; - args[i].reg = FUNCTION_ARG (*args_so_far, mode, type, - argpos < n_named_args); -#ifdef FUNCTION_INCOMING_ARG + args[i].reg = targetm.calls.function_arg (args_so_far, mode, type, + argpos < n_named_args); + /* If this is a sibling call and the machine has register windows, the register window has to be unwinded before calling the routine, so arguments have to go into the incoming registers. */ - args[i].tail_call_reg = FUNCTION_INCOMING_ARG (*args_so_far, mode, type, - argpos < n_named_args); -#else - args[i].tail_call_reg = args[i].reg; -#endif + if (targetm.calls.function_incoming_arg != targetm.calls.function_arg) + args[i].tail_call_reg + = targetm.calls.function_incoming_arg (args_so_far, mode, type, + argpos < n_named_args); + else + args[i].tail_call_reg = args[i].reg; if (args[i].reg) args[i].partial @@ -1189,8 +1204,8 @@ /* Increment ARGS_SO_FAR, which has info about which arg-registers have been used, etc. */ - FUNCTION_ARG_ADVANCE (*args_so_far, TYPE_MODE (type), type, - argpos < n_named_args); + targetm.calls.function_arg_advance (args_so_far, TYPE_MODE (type), + type, argpos < n_named_args); } } @@ -1668,10 +1683,12 @@ { rtx mem = validize_mem (args[i].value); - /* Check for overlap with already clobbered argument area. */ + /* Check for overlap with already clobbered argument area, + providing that this has non-zero size. */ if (is_sibcall - && mem_overlaps_already_clobbered_arg_p (XEXP (args[i].value, 0), - size)) + && (size == 0 + || mem_overlaps_already_clobbered_arg_p + (XEXP (args[i].value, 0), size))) *sibcall_failure = 1; /* Handle a BLKmode that needs shifting. */ @@ -1886,7 +1903,7 @@ if (REG_P (x) && HARD_REGISTER_P (x) - && CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (REGNO (x)))) + && targetm.class_likely_spilled_p (REGNO_REG_CLASS (REGNO (x)))) { /* Make sure that we generate a REG rather than a CONCAT. Moves into CONCATs can need nontrivial instructions, @@ -2323,10 +2340,10 @@ - crtl->args.pretend_args_size) /* If the callee pops its own arguments, then it must pop exactly the same number of arguments as the current function. */ - || (RETURN_POPS_ARGS (fndecl, funtype, args_size.constant) - != RETURN_POPS_ARGS (current_function_decl, - TREE_TYPE (current_function_decl), - crtl->args.size)) + || (targetm.calls.return_pops_args (fndecl, funtype, args_size.constant) + != targetm.calls.return_pops_args (current_function_decl, + TREE_TYPE (current_function_decl), + crtl->args.size)) || !lang_hooks.decls.ok_for_sibcall (fndecl)) try_tail_call = 0; @@ -2471,7 +2488,7 @@ { if (old_stack_level == 0) { - emit_stack_save (SAVE_BLOCK, &old_stack_level, NULL_RTX); + emit_stack_save (SAVE_BLOCK, &old_stack_level); old_stack_pointer_delta = stack_pointer_delta; old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; @@ -2482,6 +2499,8 @@ stack_arg_under_construction = 0; } argblock = push_block (ARGS_SIZE_RTX (adjusted_args_size), 0, 0); + if (flag_stack_usage) + current_function_has_unbounded_dynamic_stack_size = 1; } else { @@ -2624,8 +2643,7 @@ : reg_parm_stack_space)); if (old_stack_level == 0) { - emit_stack_save (SAVE_BLOCK, &old_stack_level, - NULL_RTX); + emit_stack_save (SAVE_BLOCK, &old_stack_level); old_stack_pointer_delta = stack_pointer_delta; old_pending_adj = pending_stack_adjust; pending_stack_adjust = 0; @@ -2643,8 +2661,11 @@ stack_usage_map = stack_usage_map_buf; highest_outgoing_arg_in_use = 0; } - allocate_dynamic_stack_space (push_size, NULL_RTX, - BITS_PER_UNIT); + /* We can pass TRUE as the 4th argument because we just + saved the stack pointer and will restore it right after + the call. */ + allocate_dynamic_stack_space (push_size, 0, + BIGGEST_ALIGNMENT, true); } /* If argument evaluation might modify the stack pointer, @@ -2684,6 +2705,19 @@ be deferred during the evaluation of the arguments. */ NO_DEFER_POP; + /* Record the maximum pushed stack space size. We need to delay + doing it this far to take into account the optimization done + by combine_pending_stack_adjustment_and_call. */ + if (flag_stack_usage + && !ACCUMULATE_OUTGOING_ARGS + && pass + && adjusted_args_size.var == 0) + { + int pushed = adjusted_args_size.constant + pending_stack_adjust; + if (pushed > current_function_pushed_stack_size) + current_function_pushed_stack_size = pushed; + } + funexp = rtx_for_function_call (fndecl, addr); /* Figure out the register where the value, if any, will come back. */ @@ -2825,14 +2859,15 @@ /* Set up next argument register. For sibling calls on machines with register windows this should be the incoming register. */ -#ifdef FUNCTION_INCOMING_ARG if (pass == 0) - next_arg_reg = FUNCTION_INCOMING_ARG (args_so_far, VOIDmode, - void_type_node, 1); + next_arg_reg = targetm.calls.function_incoming_arg (&args_so_far, + VOIDmode, + void_type_node, + true); else -#endif - next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, - void_type_node, 1); + next_arg_reg = targetm.calls.function_arg (&args_so_far, + VOIDmode, void_type_node, + true); /* All arguments and registers used for the call must be set up by now! */ @@ -3065,7 +3100,7 @@ if (old_stack_level) { - emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX); + emit_stack_restore (SAVE_BLOCK, old_stack_level); stack_pointer_delta = old_stack_pointer_delta; pending_stack_adjust = old_pending_adj; old_stack_allocated = stack_pointer_delta - pending_stack_adjust; @@ -3419,7 +3454,8 @@ argvec[count].mode = Pmode; argvec[count].partial = 0; - argvec[count].reg = FUNCTION_ARG (args_so_far, Pmode, NULL_TREE, 1); + argvec[count].reg = targetm.calls.function_arg (&args_so_far, + Pmode, NULL_TREE, true); gcc_assert (targetm.calls.arg_partial_bytes (&args_so_far, Pmode, NULL_TREE, 1) == 0); @@ -3435,7 +3471,7 @@ || reg_parm_stack_space > 0) args_size.constant += argvec[count].locate.size.constant; - FUNCTION_ARG_ADVANCE (args_so_far, Pmode, (tree) 0, 1); + targetm.calls.function_arg_advance (&args_so_far, Pmode, (tree) 0, true); count++; } @@ -3494,7 +3530,8 @@ argvec[count].value = val; argvec[count].mode = mode; - argvec[count].reg = FUNCTION_ARG (args_so_far, mode, NULL_TREE, 1); + argvec[count].reg = targetm.calls.function_arg (&args_so_far, mode, + NULL_TREE, true); argvec[count].partial = targetm.calls.arg_partial_bytes (&args_so_far, mode, NULL_TREE, 1); @@ -3514,7 +3551,7 @@ || reg_parm_stack_space > 0) args_size.constant += argvec[count].locate.size.constant; - FUNCTION_ARG_ADVANCE (args_so_far, mode, (tree) 0, 1); + targetm.calls.function_arg_advance (&args_so_far, mode, (tree) 0, true); } /* If this machine requires an external definition for library @@ -3538,6 +3575,13 @@ if (args_size.constant > crtl->outgoing_args_size) crtl->outgoing_args_size = args_size.constant; + if (flag_stack_usage && !ACCUMULATE_OUTGOING_ARGS) + { + int pushed = args_size.constant + pending_stack_adjust; + if (pushed > current_function_pushed_stack_size) + current_function_pushed_stack_size = pushed; + } + if (ACCUMULATE_OUTGOING_ARGS) { /* Since the stack pointer will never be pushed, it is possible for @@ -3823,7 +3867,8 @@ build_function_type (tfom, NULL_TREE), original_args_size.constant, args_size.constant, struct_value_size, - FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1), + targetm.calls.function_arg (&args_so_far, + VOIDmode, void_type_node, true), valreg, old_inhibit_defer_pop + 1, call_fusage, flags, & args_so_far);