The point
Trace a call through the register conventions, including the case that breaks naive implementations: a call inside a call.
Do this
- Write the calling sequence out as two columns — what the caller does, what the callee does — for your own compiler. Then compare with the division in the lecture notes. Anything on the wrong side?
- Predict the TAC for
f(1, g(2)): write theparamandcallinstructions in order. Compile and compare. - Explain the ordering. Both calls emit arguments into the same buffer. Why does the inner call take the right ones? Work through
f(g(1), 2)as well — it comes out right for a different reason. - Recursion. Run
fact(5). Then answer: which registers had to be preserved across the recursive call, and who preserved them — caller or callee? - Find the limit. Write a function with five parameters. What does the compiler say? Is that a good error message? Improve it if not.
- Design. Sketch how you would pass a fifth argument. Real MIPS puts it on the stack — but where, relative to the caller's frame, and who pops it? Use Dragon's second design principle (§7.2.3) to justify your answer.
On step 3
A call consumes the LAST n buffered arguments, where n comes from the call instruction itself. Trace f(1, g(2)) under that rule and watch it come out right; then trace f(g(1), 2) and notice that the reason is different.
Deliverable
Your two-column calling sequence with any corrections; predicted vs actual TAC; your answer to step 3; the register-preservation answer from step 4; and your two-line design for step 6. Feeds Lab Question 15.