diff options
author | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-08-16 01:15:37 +0000 |
---|---|---|
committer | kenner <kenner@138bc75d-0d04-0410-961f-82ee72b054a4> | 2000-08-16 01:15:37 +0000 |
commit | d490e2f2f1bcc2c534aa63496a502c829beaad03 (patch) | |
tree | fae62ef4946025fccda89bb881cd3b03f4785068 /gcc/calls.c | |
parent | 333b5b5444981a5f9ff808afccdfbd82e5a02c04 (diff) | |
download | gcc-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.c | 44 |
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; } |