[gcc(refs/users/aoliva/heads/testme)] strub: sparc64: unbias the stack address [PR112917]
Alexandre Oliva
aoliva@gcc.gnu.org
Thu Dec 14 13:45:33 GMT 2023
https://gcc.gnu.org/g:d5eaad6f06d5b8903a2e2e530add56c9fb6117a5
commit d5eaad6f06d5b8903a2e2e530add56c9fb6117a5
Author: Alexandre Oliva <oliva@adacore.com>
Date: Thu Dec 14 04:50:45 2023 -0300
strub: sparc64: unbias the stack address [PR112917]
The stack pointer is biased by 2047 bytes on sparc64, so the range it
delimits is way off. Unbias the addresses returned by
__builtin_stack_address (), so that the strub builtins, inlined or
not, can function correctly. I've considered introducing a new target
macro, but using STACK_POINTER_OFFSET seems safe.
Because of the large fixed-size outgoing args area next to the
register save area on sparc, we still need __strub_leave to not
allocate its own frame, otherwise it won't be able to clear part of
the frame it should.
for gcc/ChangeLog
PR middle-end/112917
* builtins.cc (expand_bultin_stack_address): Add
STACK_POINTER_OFFSET.
Diff:
---
gcc/builtins.cc | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
diff --git a/gcc/builtins.cc b/gcc/builtins.cc
index 7c2732ab79e..71116c6ab45 100644
--- a/gcc/builtins.cc
+++ b/gcc/builtins.cc
@@ -5443,8 +5443,38 @@ expand_builtin_frame_address (tree fndecl, tree exp)
static rtx
expand_builtin_stack_address ()
{
- return convert_to_mode (ptr_mode, copy_to_reg (stack_pointer_rtx),
- STACK_UNSIGNED);
+ rtx ret = convert_to_mode (ptr_mode, copy_to_reg (stack_pointer_rtx),
+ STACK_UNSIGNED);
+
+ /* Unbias the stack pointer, bringing it to the boundary between the
+ stack area claimed by the active function calling this builtin,
+ and stack ranges that could get clobbered if it called another
+ function. It should NOT encompass any stack red zone, that is
+ used in leaf functions.
+
+ On SPARC, the register save area is *not* considered active or
+ used by the active function, but rather as akin to the area in
+ which call-preserved registers are saved by callees. This
+ enables __strub_leave to clear what would otherwise overlap with
+ its own register save area.
+
+ If the address is computed too high or too low, parts of a stack
+ range that should be scrubbed may be left unscrubbed, scrubbing
+ may corrupt active portions of the stack frame, and stack ranges
+ may be doubly-scrubbed by caller and callee.
+
+ In order for it to be just right, the area delimited by
+ @code{__builtin_stack_address} and @code{__builtin_frame_address
+ (0)} should encompass caller's registers saved by the function,
+ local on-stack variables and @code{alloca} stack areas.
+ Accumulated outgoing on-stack arguments, preallocated as part of
+ a function's own prologue, are to be regarded as part of the
+ (caller) function's active area as well, whereas those pushed or
+ allocated temporarily for a call are regarded as part of the
+ callee's stack range, rather than the caller's. */
+ ret = plus_constant (ptr_mode, ret, STACK_POINTER_OFFSET);
+
+ return force_operand (ptr_mode, ret);
}
/* Expand a call to builtin function __builtin_strub_enter. */
More information about the Gcc-cvs
mailing list