Suppose function f calls function g(a0, a1, a2, a3, a4, a5).
a0, a2, a4 are escape variables(they are pushed on frame so they can be accessed by inner function), and a1, a3, a5 are not(so they can be passed to MIPS' input registers.
In Appel's compiler book, a frame will be created whenever a function is called. Since there are three escape variables, the new stack will have three word-size cells above the frame pointer. But how am I suppose to know which input parameters should go to which cell in code generation phase?
My workaround:
Pass first four parameter in input register, and the rest of them on stack.
And when frame g is created, do a view shift: copy all input registers and stack memory to local variables. But I think function arguments should be at known offset from frame pointer. So i am not sure if this is even a workaround.
When f calls g, f has no idea about g's frame layout. So how can I implement function call in code generation phase?
UPDATE: I think my question should be rephrased to this: the caller passes a0, a1, a2, a3 to the input registers, and the rest on stack. The callee however, decided at compile time that a0, a2, a4 should be pushed on stack since they escape. So how can callee do a proper view shift before actually execute function body?
In type checking phase of my compiler, whenever it sees a function declaration. It will try to decide if any formal parameters escape or not (whether they will be accessed by any inner function). If it escape, it will be on stack, or it will be in a register. Sample code in OCaml:
type access =
(* whether it will be in frame or in a register *)
| In_frame of offset
| In_reg of Temp.temp
When a new frame needs to be created, the function name and a list of boolean variables will be passed into new_frame function:
let gen_offset () =
let res = !loc * word_size in
loc := !loc + 1; res
let new_frame name escapes =
loc := 0 ;
let fs = List.map escapes
~f:(fun t -> if t then (In_frame (gen_offset ())) else In_reg (Temp.new_temp ()))
in
let l = List.length fs in
{
name = name;
length = l;
formals = fs;
locals = [];
}