(* frame.ml *) (* 15-411 *) (* by Arthur O'Dwyer *) (* @version $Id: frame.ml,v 1.2 2004/11/01 09:21:32 ajo Exp $ *) module A = Absyn module T = Ir module TP = Temp (* This module and |Finalize| between them ought to contain all the target-specific parts of the compiler. Module |Frame| knows the number of available registers (|nregs|) and how to deal with the stack frame. |Finalize| knows the prelude and postlude code and the names of all the registers. *) exception InternalError (* The number of registers in this architecture available for register allocation. *) let nregs = 6 (* Code related to allocation of variables on the current stack frame, as opposed to in register-allocatable temps. The routine |allocLocal| is called by the compiler's main routines whenever a variable name is encountered. *) type frame = FrameTemp of TP.temp | FrameStack of int | FrameNil let stack_counter = ref 0 let simpStack () = (stack_counter := !stack_counter+1; !stack_counter) let allLocals : (string * bool * frame) list ref = ref [] let clear () = (allLocals := []; stack_counter := 0) let size () = !stack_counter let allocLocal id escaped = ( let rec help = function | [] -> [(id, escaped, FrameNil)] | (s,b,f)::t -> if (s = id) then (s, b || escaped, f)::t else (s, b, f)::(help t) in allLocals := help !allLocals ) let assign () = ( let help (s,escaped,_) = ( if escaped then (s,escaped,FrameStack(simpStack())) else (s,escaped,FrameTemp(TP.simpTemp())) ) in allLocals := List.map help !allLocals; List.iter (function (s,b,f) -> Printf.printf "(%s, %s, %s)\n" s (if b then "true" else "false") (match f with FrameNil -> "nil" | FrameStack n -> Printf.sprintf "stack %d" n | FrameTemp n -> Printf.sprintf "temp %d" n ) ) !allLocals ) let getLocal id = ( let (s,b,f) = List.find (function (s,_,_) -> s=id) !allLocals in f ) let localIR id = ( match (getLocal id) with | FrameTemp t -> T.TEMP(t) | FrameStack n -> T.UNOP(A.DEREF, T.BINOP(A.PLUS, T.REG_EBP, T.CONST(Int32.of_int (-4*n)) ) ) | FrameNil -> raise InternalError )