summaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2000-08-16 01:15:37 +0000
committerkenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4>2000-08-16 01:15:37 +0000
commitd490e2f2f1bcc2c534aa63496a502c829beaad03 (patch)
treefae62ef4946025fccda89bb881cd3b03f4785068 /gcc/calls.c
parent333b5b5444981a5f9ff808afccdfbd82e5a02c04 (diff)
downloadgcc-d490e2f2f1bcc2c534aa63496a502c829beaad03.tar.gz
* calls.c (ECF_SP_DEPRESSED): New macro.
(calls_function_1): Treat calling sp-depressed function as alloca. (emit_call_1): Don't adjust SP if calling sp-depressed function. (expand_call): Set ECF_SP_DEPRESSED if TYPE_RETURNS_STACK_DEPRESSED. If sp-depressed, ensure block saves and restores SP. * fold-const.c (extract_muldiv): Only check TYPE_IS_SIZETYPE for INTEGER_TYPE. * function.c (keep_stack_depressed): New function. (thread_prologue_and_epilogue_insns): Call it. * print-tree.c (print_node): Use HOST_WIDE_INT_PRINT_UNSIGNED to print DECL_OFFSET_ALIGN. Print no-force-blk and transparent-union flags properly. * stmt.c (expand_goto_internal): Don't restore stack if last block and function returns with sp depressed. (fixup_gotos): Likewise. (save_stack_pointer): New function, from code in expand_decl. (expand_decl): Call new function. * tree.h (TYPE_IS_SIZETYPE): Call INTEGER_TYPE_CHECK. (TYPE_RETURNS_STACK_DEPRESSED): New macro. (save_stack_pointer): New declaration. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@35734 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index f3ce50d4735..cd4fed72825 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -184,6 +184,9 @@ static int calls_function_1 PARAMS ((tree, int));
/* Nonzero if this is a call to "pure" function (like const function,
but may read memory. */
#define ECF_PURE 512
+/* Nonzero if this is a call to a function that returns with the stack
+ pointer depressed. */
+#define ECF_SP_DEPRESSED 1024
static void emit_call_1 PARAMS ((rtx, tree, tree, HOST_WIDE_INT,
HOST_WIDE_INT, HOST_WIDE_INT, rtx,
@@ -278,6 +281,9 @@ calls_function_1 (exp, which)
case CALL_EXPR:
if (which == 0)
return 1;
+ else if (TYPE_RETURNS_STACK_DEPRESSED
+ (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))))
+ return 1;
else if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR
&& (TREE_CODE (TREE_OPERAND (TREE_OPERAND (exp, 0), 0))
== FUNCTION_DECL)
@@ -428,8 +434,8 @@ prepare_call_address (funexp, fndecl, call_fusage, reg_parm_seen)
We restore `inhibit_defer_pop' to that value.
CALL_FUSAGE is either empty or an EXPR_LIST of USE expressions that
- denote registers used by the called function. */
-
+ denote registers used by the called function. */
+
static void
emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
struct_value_size, next_arg_reg, valreg, old_inhibit_defer_pop,
@@ -495,7 +501,7 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
even if the call has no arguments to pop. */
#if defined (HAVE_call) && defined (HAVE_call_value)
if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop
- && n_popped > 0)
+ && n_popped > 0 && ! (ecf_flags & ECF_SP_DEPRESSED))
#else
if (HAVE_call_pop && HAVE_call_value_pop)
#endif
@@ -624,10 +630,10 @@ emit_call_1 (funexp, fndecl, funtype, stack_size, rounded_stack_size,
If returning from the subroutine does pop the args, indicate that the
stack pointer will be changed. */
- if (rounded_stack_size != 0)
+ if (rounded_stack_size != 0 && ! (ecf_flags & ECF_SP_DEPRESSED))
{
if (flag_defer_pop && inhibit_defer_pop == 0
- && !(ecf_flags & (ECF_CONST | ECF_PURE)))
+ && ! (ecf_flags & (ECF_CONST | ECF_PURE)))
pending_stack_adjust += rounded_stack_size;
else
adjust_stack (rounded_stack_size_rtx);
@@ -756,6 +762,7 @@ special_function_p (fndecl, flags)
}
/* Return nonzero when tree represent call to longjmp. */
+
int
setjmp_call_p (fndecl)
tree fndecl;
@@ -764,11 +771,13 @@ setjmp_call_p (fndecl)
}
/* Detect flags (function attributes) from the function type node. */
+
static int
flags_from_decl_or_type (exp)
tree exp;
{
int flags = 0;
+
/* ??? We can't set IS_MALLOC for function types? */
if (DECL_P (exp))
{
@@ -784,7 +793,7 @@ flags_from_decl_or_type (exp)
flags |= ECF_NOTHROW;
}
- if (TREE_READONLY (exp) && !TREE_THIS_VOLATILE (exp))
+ if (TREE_READONLY (exp) && ! TREE_THIS_VOLATILE (exp))
flags |= ECF_CONST;
if (TREE_THIS_VOLATILE (exp))
@@ -2131,7 +2140,7 @@ expand_call (exp, target, ignore)
int old_inhibit_defer_pop = inhibit_defer_pop;
int old_stack_allocated;
rtx call_fusage;
- register tree p;
+ register tree p = TREE_OPERAND (exp, 0);
register int i;
/* The alignment of the stack, in bits. */
HOST_WIDE_INT preferred_stack_boundary;
@@ -2183,9 +2192,13 @@ expand_call (exp, target, ignore)
/* If we don't have specific function to call, see if we have a
attributes set in the type. */
else
+ flags |= flags_from_decl_or_type (TREE_TYPE (TREE_TYPE (p)));
+
+ /* Mark if the function returns with the stack pointer depressed. */
+ if (TYPE_RETURNS_STACK_DEPRESSED (TREE_TYPE (TREE_TYPE (p))))
{
- p = TREE_OPERAND (exp, 0);
- flags |= flags_from_decl_or_type (TREE_TYPE (TREE_TYPE (p)));
+ flags |= ECF_SP_DEPRESSED;
+ flags &= ~ (ECF_PURE | ECF_CONST);
}
#ifdef REG_PARM_STACK_SPACE
@@ -3271,7 +3284,7 @@ expand_call (exp, target, ignore)
/* If size of args is variable or this was a constructor call for a stack
argument, restore saved stack-pointer value. */
- if (old_stack_level)
+ if (old_stack_level && ! (flags & ECF_SP_DEPRESSED))
{
emit_stack_restore (SAVE_BLOCK, old_stack_level, NULL_RTX);
pending_stack_adjust = old_pending_adj;
@@ -3412,6 +3425,17 @@ expand_call (exp, target, ignore)
currently_expanding_call--;
+ /* If this function returns with the stack pointer depressed, ensure
+ this block saves and restores the stack pointer, show it was
+ changed, and adjust for any outgoing arg space. */
+ if (flags & ECF_SP_DEPRESSED)
+ {
+ clear_pending_stack_adjust ();
+ emit_insn (gen_rtx (CLOBBER, VOIDmode, stack_pointer_rtx));
+ emit_move_insn (virtual_stack_dynamic_rtx, stack_pointer_rtx);
+ save_stack_pointer ();
+ }
+
return target;
}