Avi Kivity
Mon Dec 13 17:48:41 GMT 2021

On 10/12/2021 03.06, Marc Feeley via Gcc-help wrote:
>> On Dec 9, 2021, at 6:36 PM, Segher Boessenkool <> wrote:
>>> The code generated by the Gambit compiler is sufficiently complex that it would be impossible (in the halting problem sense) to check that the tail-calling constraints are not violated. However, I know the constraints are not violated because the code was designed that way. And if I’m mistaken in this belief, then I am the one that will bare the blame of the ensuing problems.
>> On most architectures you can simply check if there are any "return"
>> instructions generated, no?  Or do you generate any actual calls (to
>> user code) as well?
> You mean a “return” at the assembly code level?  Seems very brittle… on x86 a “pop %eax; jmp *%eax” will do the same as a “ret” and gcc might generate that sequence (from my point of view).  In any case, as I said previously, I don’t want to check if gcc did not optimize the tail calls… it is too late to do anything other than essentially tell the programmer “sorry I couldn’t compile that program correctly”.
>>> So having a way to check during or after the compilation that tail-calls were optimized is not sufficient. A Scheme compiler that sometimes fails to compile is not very useful.  What is needed is a guarantee that specific C calls are optimized.
>> Then you need to write code that works as you want on all configurations
>> you support, state what those configs are, and test that it compiles on
>> all such configs, before every release.
> This does not solve my problem either. No testing will cover all possible situations because for a particular architecture the tail call optimization may work on all the tests I can come up with, but some programmer using Gambit may write a program for which the tail calls in the C code generated by the Gambit compiler are not optimized.
> I’m not looking for a guarantee that tail calls are supported transparently on all architectures.  Currently Gambit uses a trampoline to implement Scheme tail calls, and this can be used as a fallback for architectures where C TCO is not guaranteed.
> So what I need is some way to test at compile time if for the target architecture and compile options there is a guarantee that tail calls will be optimized (if the C code obeys the usual set of constraints).  Something like
>    #if __has_attribute(tail_call_supported_on_this_architecture)
>    /* use tail calls for jumping around... */
>    #else
>    /* use trampoline fallback... */
>    #endif
> Marc

Perhaps you should generate one function with a huge switch instead of 
separate functions. Each original function translates to a case, and a 
tail call translates to a goto. Calling one of the functions from 
outside translates to using the switch to select the initial case. This 
should work well if only a minority of the calls are from outside.

More information about the Gcc-help mailing list