According to the sysv abi, every function has to have a stack frame; so for strict conformance (e.g. for unwinding the stack), you should have a stack frame for every function. In practice, this is kinda dumb. Gcc/clang will do TCO (and won't even generate a stack frame if you pass -fomit-frame-pointer). There's no particular reason why the generated code should abide internally by the sysv abi, only that it be able to call external code written according to said abi (and pass callbacks to said external code, but you'd need thunks for that anyway to account for closures).