My programming language compiles to C, I want to implement tail recursion optimization. The question here is how to transfer control to another function without โreturningโ from the current function.
This is quite easy if the control is passed to the same function:
void f() { __begin: do something here... goto __begin; // "call" itself }
As you can see, there is no return value and no parameters; they are passed in a separate stack addressed to the global variable.
Another option is to use the built-in assembly:
#ifdef __clang__ #define tail_call(func_name) asm("jmp " func_name " + 8"); #else #define tail_call(func_name) asm("jmp " func_name " + 4"); #endif void f() { __begin: do something here... tail_call(f); // "call" itself }
This is similar to goto , but since goto transfers control to the first statement in the function, skipping the "input code" generated by the compiler, jmp is different, this argument is a pointer to the function, and you need to add 4 or 8 bytes to skip the input code.
Both of the above will work, but only if the caller and the caller use the same stack amount for local variables that are allocated by the callerโs input code.
I thought of doing leave manually with the built-in assembly, then replacing the return address on the stack, and then making a legal function call, like f() . But my attempts all failed. You need to somehow change the BP and SP .
So how to implement this for x64? (Again, assuming functions have no arguments and return void ). A portable way without an integrated assembly is better, but the assembly is accepted. Maybe you can use longjump ?
Perhaps you can even push the called address on the stack by replacing the original return address and just ret ?
c compiler-construction tail-recursion
exebook
source share