After reading the recent posts, I have three questions:
- Say aaa (frame 17) calls bbb (frame 18) which launches a MUL and returns back to aaa (without any results values), then aaa immediately calls ccc (frame xx). As far as I understand, xx will not be 18 again because otherwise the MUL result would erroneously end up on ccc’s belt. Ideally a tail-call from bbb to ccc would try to closely mirror the above situation, wouldn’t it?
- Apropos security: is there anything to prevent the Bad Guy from creating a fake additional function entry point which launches a MUL and then simply *jump*s to the initial EBB of the target function, with the MUL still in flight?
- Would it simplify the handling of the situation if any unexpected in-flight values are not silently discarded but instead cause an processor fault? The underlying reasoning would be this:
- When bbb issues the MUL, it promises to handle the result N cycles later.
- When bbb tail-calls ccc, it basically asks for substituting its parent aaa for itself when it comes to handling any future values appearing on the belt (“continuation passing”).
- The return values of ccc will thus end up on aaa’s belt, provided their count is correct. If the return value count is incorrect, this will cause a fault.
- When the MUL result appears, it ends up on aaa’s belt as well, following the above reasoning. As this violates aaa’s expectations, it should cause a fault as well.
As some programming style relies on infinitely passing continuations around, the full power of tail-calls is realized only if the machine does not run out of any resources from an unlimited number of tail-calls. If a spiller frame is never empty and a new spiller frame is required even for a tail-call, then this ideal target probably cannot be achieved, I fear.