|
|
|
|
|
by rayiner
4581 days ago
|
|
If you've got the freedom to design your calling convention, you don't need trampolines or anything like that. The basic idea is to compile every call in a tail position to a jump. You just need to clean up your stack before making the call, and make sure to arrange your calling convention such that A can call B, which can jump to C, which can return directly to A. In the A -> B -> C example, this means: 1) Using a callee-pops convention so that callees pop arguments off the stack rather than callers. If B and C take different numbers of arguments, A doesn't know how many arguments to pop. So functions should pop their arguments off the stack themselves before they return. 2) B must restore its callee-save registers before jumping to C, which will save those registers itself if it clobbers them. 3) To accommodate variadic functions, there has to be a hidden argument to let callees know how many arguments were actually pushed by the caller, so they can pop the right number. |
|