42 lines
1.5 KiB
C
42 lines
1.5 KiB
C
/* On targets where the call instruction is an implicit probe of *sp, we
|
|
elide stack probes as long as the size of the local stack is less than
|
|
PROBE_INTERVAL.
|
|
|
|
But if the caller were to transform a tail call into a direct jump
|
|
we do not have that implicit probe. This normally isn't a problem as
|
|
the caller must not have a local frame for that optimization to apply.
|
|
|
|
However, a sufficiently smart compiler could realize that the caller's
|
|
local stack need not be torn down and thus could transform a call into
|
|
a jump if the target is a noreturn function, even if the caller has
|
|
a local frame.
|
|
|
|
To guard against that, targets that depend on *sp being probed by the
|
|
call itself must emit a probe if the target function is a noreturn
|
|
function, even if they just allocate a small amount of stack space.
|
|
|
|
Rather than try to parse RTL or assembly code, we instead require the
|
|
prologue code to emit information into the dump file that we can
|
|
scan for. We scan for both the positive and negative cases. */
|
|
|
|
/* { dg-do compile } */
|
|
/* { dg-options "-O2 -fstack-clash-protection -fdump-rtl-pro_and_epilogue -fno-optimize-sibling-calls" } */
|
|
/* { dg-require-effective-target supports_stack_clash_protection } */
|
|
|
|
extern void arf (char *);
|
|
|
|
__attribute__ ((noreturn)) void foo1 ()
|
|
{
|
|
char x[10];
|
|
while (1)
|
|
arf (x);
|
|
}
|
|
|
|
void foo2 ()
|
|
{
|
|
char x[10];
|
|
arf (x);
|
|
}
|
|
/* { dg-final { scan-rtl-dump-times "Stack clash noreturn" 1 "pro_and_epilogue" } } */
|
|
/* { dg-final { scan-rtl-dump-times "Stack clash not noreturn" 1 "pro_and_epilogue" } } */
|
|
|