I have not verified this, but instead of using gcc, use llvm-gcc (the gcc front-end merged with the llvm backend). The llvm IR supports tail calls, but I don't know if makes it through the gcc front-end.

An alternative mechanism is a trick used by the chicken scheme compiler.

Basically, you have to CPS transform your program and compile all your calls as noreturn calls (with __attribute__ ((noreturn)) in gcc). There is an entry function that kick starts the computation and keeps a jumpbuf for restarting at the top of the stack. The computation keeps growing the stack and when the stack is exhausted you jump back to the top with the continuation of the computation.

The downside is that your C calling conventions must use continuation passing style.