Date: Mon, 17 Apr 2023 14:25:43 +0200
Hi Frederick,
there is no need that an architecture running C++ has a stack for storing return addresses.
Also the optimizer may inline functions or optimize them out altogether.
I think those ideas are too low-level and outside the scope of the standard and should be implementation or better implementation and architecture specific within each of the compilers.
You also saw yourself that you cannot detect indirect recursion in a simple way, even if no inlining happened.
This approach is not really stable / reliable for detecting recursion.
Why not just use a thread-local static bool variable?
-----Ursprüngliche Nachricht-----
Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]>
Gesendet:Mo 17.04.2023 13:09
Betreff:[std-proposals] Monitor recursion by checking the frame pointer
An:std-proposals <std-proposals_at_[hidden]>;
CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>;
Lately I've been messing around trying to write assembler thunks for
invoking lambdas without the hidden 'this' paramater, and I had to
consider the complications of multi-threading, and also of recursive
function calls.
Let me stick to single-threaded programs for now. I will use the term
'caller' to describe a recursive function which contains a lambda,
so something like:
extern void SomeLibraryFunc( void(*)(void) );
void Func(int const arg)
{
if ( -1 == arg ) return;
auto mylambda = [arg](void)->void { /* do something */ };
SomeLibraryFunc( thunk(mylambda) );
Func(arg - 1);
}
In order to write an efficient implementation of the thunk generator to
accommodate recursive calls, I was thinking it would be cool if I could
somehow get the thunk to correctly identify whether the caller has
been re-entered since the thunk was generated. Then I realised that this
could be ascertained from the stack pointer (i.e. the RSP register on
x86_64, or the x31sp register on aarch64). As a function is executed
though, it might push and pop and push and pop, and so the stack pointer
would be going up and down by 8 bytes here and there, it would be
fluctuating a little. But if the frame pointer is used instead (i.e. the
RBP register on x86_64, or the x29FP register on aarch64), then it could
be used to reliably check if re-entry has occurred.
What if the Standard library were to have:
namespace std {
void *frame_pointer(void) noexcept;
void *stack_pointer(void) noexcept;
}
The contents of "frame_and_stack_pointer.S" on x86_64 could be:
frame_pointer:
mov rax,rbp
ret
stack_pointer:
mov rax,rsp
add rax,8 ; disregard the return address on top of stack
ret
Also maybe it would be helpful if the return address were available too,
something like:
namespace std {
void (*return_address(void))(void) noexcept;
}
The contents of "return_address.S" on x86_64:
return_address:
mov rax,[rsp] ; return address is at top of stack
ret
Nine times out of ten, the return address will just be the 8 bytes at
the top of the stack, but it won't be if the function has supernumerary
parameters or a very big return type, so the compiler would have to
be a bit smarter.
If the function "std::frame_pointer" is invoked inside a function that
was compiled with a compiler flag to prevent the use of a frame pointer
(e.g. '-fomit-frame-pointer' on the GNU g++ compiler), or if it is a very
simply function that doesn't use the stack and so doesn't bother with
a frame pointer, then it should return a nullptr.
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2023-04-17 12:25:45