aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c99
1 files changed, 96 insertions, 3 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index d83b353c0ee..6e83def3756 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -381,7 +381,14 @@ emit_call_1 (rtx funexp, tree fntree, tree fndecl ATTRIBUTE_UNUSED,
and we don't want to load it into a register as an optimization,
because prepare_call_address already did it if it should be done. */
if (GET_CODE (funexp) != SYMBOL_REF)
+/* APPLE LOCAL use R12 as register for indirect calls. This improves
+ codegen (computation of value will be into R12) and makes
+ indirect sibcalls possible by ensuring a volatile reg is used. */
+#ifdef MAGIC_INDIRECT_CALL_REG
+ funexp = gen_rtx_REG (SImode, MAGIC_INDIRECT_CALL_REG);
+#else
funexp = memory_address (FUNCTION_MODE, funexp);
+#endif
#if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop)
if ((ecf_flags & ECF_SIBCALL)
@@ -1256,8 +1263,8 @@ initialize_argument_information (int num_actuals ATTRIBUTE_UNUSED,
/* Compute the stack-size of this argument. */
if (args[i].reg == 0 || args[i].partial != 0
- || reg_parm_stack_space > 0
- || args[i].pass_on_stack)
+ || reg_parm_stack_space > 0
+ || args[i].pass_on_stack)
locate_and_pad_parm (mode, type,
#ifdef STACK_PARMS_IN_REG_PARM_AREA
1,
@@ -2014,12 +2021,18 @@ expand_call (tree exp, rtx target, int ignore)
tree actparms = TREE_OPERAND (exp, 1);
/* RTX for the function to be called. */
rtx funexp;
+ /* APPLE LOCAL use r12 for indirect calls */
+ /* A single rtx to be shared among multiple chains for indirect sibcalls */
+ rtx funexp_keep = NULL_RTX;
/* Sequence of insns to perform a normal "call". */
rtx normal_call_insns = NULL_RTX;
/* Sequence of insns to perform a tail "call". */
rtx tail_call_insns = NULL_RTX;
/* Data type of the function. */
tree funtype;
+ /* APPLE LOCAL objc stret methods */
+ /* Return type of the function. */
+ tree saved_return_type;
tree type_arg_types;
/* Declaration of the function being called,
or 0 if the function is computed (not known by name). */
@@ -2124,6 +2137,9 @@ expand_call (tree exp, rtx target, int ignore)
if (TREE_NOTHROW (exp))
flags |= ECF_NOTHROW;
+ /* See if we can find a DECL-node for the actual function.
+ As a result, decide whether this is a call to an integrable function. */
+
/* See if we can find a DECL-node for the actual function, and get the
function attributes (flags) from the function decl or type node. */
fndecl = get_callee_fndecl (exp);
@@ -2238,6 +2254,16 @@ expand_call (tree exp, rtx target, int ignore)
abort ();
funtype = TREE_TYPE (funtype);
+ /* APPLE LOCAL objc stret methods */
+ /* Set the return type of the function to the type of the call expression,
+ in case that's different from the function declaration.
+ (This is the case when calling _objc_msgSend_stret, for example,
+ which is declared to return id, but actually returns a struct.)
+ But save the original return type first, so it can be restored later
+ in case it's needed. */
+ saved_return_type = TREE_TYPE (funtype);
+ TREE_TYPE (funtype) = TREE_TYPE (exp);
+
/* Munge the tree to split complex arguments into their imaginary
and real parts. */
if (SPLIT_COMPLEX_ARGS)
@@ -2396,6 +2422,20 @@ expand_call (tree exp, rtx target, int ignore)
It does not seem worth the effort since few optimizable
sibling calls will return a structure. */
|| structure_value_addr != NULL_RTX
+/* APPLE LOCAL begin indirect sibcalls */
+#ifndef MAGIC_INDIRECT_CALL_REG
+/* The register holding the address is now always R12, so
+ we can consider indirect calls as sibcall candidates on ppc. */
+ /* If the register holding the address is a callee saved
+ register, then we lose. We have no way to prevent that,
+ so we only allow calls to named functions. */
+ /* ??? This could be done by having the insn constraints
+ use a register class that is all call-clobbered. Any
+ reload insns generated to fix things up would appear
+ before the sibcall_epilogue. */
+ || fndecl == NULL_TREE
+#endif
+/* APPLE LOCAL end indirect sibcalls */
/* Check whether the target is able to optimize the call
into a sibcall. */
|| !(*targetm.function_ok_for_sibcall) (fndecl, exp)
@@ -2490,6 +2530,14 @@ expand_call (tree exp, rtx target, int ignore)
function_call_count++;
+ /* APPLE LOCAL indirect sibcalls */
+ /* Do this before creating the chains, to avoid a branch within them.
+ The paired chains both branch to the same label, but only one
+ chain has a definition of that label, because of the way the
+ infrastructure works. */
+ if ( !fndecl )
+ funexp_keep = rtx_for_function_call (fndecl, addr);
+
/* We want to make two insn chains; one for a sibling call, the other
for a normal call. We will select one of the two chains after
initial RTL generation is complete. */
@@ -2812,7 +2860,11 @@ expand_call (tree exp, rtx target, int ignore)
be deferred during the evaluation of the arguments. */
NO_DEFER_POP;
- funexp = rtx_for_function_call (fndecl, addr);
+ /* APPLE LOCAL indirect sibcalls */
+ if ( !fndecl )
+ funexp = funexp_keep;
+ else
+ funexp = rtx_for_function_call (fndecl, addr);
/* Figure out the register where the value, if any, will come back. */
valreg = 0;
@@ -2950,6 +3002,24 @@ expand_call (tree exp, rtx target, int ignore)
next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode,
void_type_node, 1);
+ /* APPLE LOCAL begin indirect calls in R12 */
+#ifdef MAGIC_INDIRECT_CALL_REG
+ /* For indirect calls, put the callee address in R12. This is necessary
+ for ObjC methods. This could be handled by patterns in rs6000.md,
+ as in 2.95, but it is better to put this copy in the RTL so the
+ optimizer can see it, and sometimes get rid of it, and the scheduler
+ can move it around. Right now none of these good things seems to
+ happen, but this should be fixable. (But note FSF won't like
+ putting it here.) */
+ if (!fndecl)
+ {
+ rtx magic_reg = gen_rtx_REG (SImode, MAGIC_INDIRECT_CALL_REG);
+ emit_move_insn (magic_reg, funexp);
+ use_reg (&call_fusage, magic_reg);
+ }
+#endif
+ /* APPLE LOCAL end indirect calls in R12 */
+
/* All arguments and registers used for the call must be set up by
now! */
@@ -2963,6 +3033,11 @@ expand_call (tree exp, rtx target, int ignore)
next_arg_reg, valreg, old_inhibit_defer_pop, call_fusage,
flags, & args_so_far);
+ /* APPLE LOCAL objc stret methods */
+ /* Restore the function's original return type
+ in case it's needed later on. */
+ TREE_TYPE (funtype) = saved_return_type;
+
/* If call is cse'able, make appropriate pair of reg-notes around it.
Test valreg so we don't crash; may safely ignore `const'
if return type is void. Disable for PARALLEL return values, because
@@ -3323,6 +3398,24 @@ expand_call (tree exp, rtx target, int ignore)
abort ();
}
+ /* APPLE LOCAL begin sibcall 3007352 */
+ /* GCC for PPC on Darwin has always rounded 'current_function_args_size' up to a multiple of 16.
+ CodeWarrior doesn't.
+ A father() that passes, say, 40 bytes of parameters to daughter() will have eight bytes of
+ padding if compiled with GCC, and zero bytes of padding if compiled with CW.
+ If a GCC-compiled daughter() in turn sibcalls to granddaughter() with, say, 44 bytes of parameters,
+ GCC will generate a store of that extra parameter into padding of the father() parameter area.
+ Alas, if father() was compild by CW, father() will not have the parameter area padding,
+ and something in the father() stackframe will be stomped.
+ Parameter areas are guaranteed to be a minimum of 32 bytes. See Radar 3007352. */
+ if ( ( ! sibcall_failure)
+ && args_size.constant > 32
+ && args_size.constant > cfun->unrounded_args_size)
+ {
+ sibcall_failure = 1;
+ }
+ /* APPLE LOCAL end sibcall 3007352 */
+
/* If something prevents making this a sibling call,
zero out the sequence. */
if (sibcall_failure)