structure MipsFrame : FRAME = struct structure T = Tree datatype access = InFrame of int | InReg of Temp.temp type frame = (access list (* formals *) * unit (* Instructions, don't know about this yet?*) * int ref (* locals allocated so far *) * Temp.label (* name of fun label *) ) datatype frag = PROC of {body: Tree.stm, frame: frame } | STRING of Temp.label * string (* ----------------------------------------------------------------- *) fun string (lab,value) = (Temp.labelname lab) ^ ": .asciiz \"" ^ value ^ "\"" (* ----------------------------------------------------------------- *) fun newFrame ({name=name : Temp.label, formals=formals}) : frame = (*map the bool list onto the access list, accumulating the count of local params along the way *) let fun mapBools(escapes::[], depth, regsAllocated, framespace) = if (escapes orelse (regsAllocated >= 4)) then (print ("allocating in frame (" ^ (Int.toString(4 * framespace)) ^ ")\n"); ([InFrame(4 * depth)], depth+1)) else (print ("allocating in register (T" ^ Int.toString(!Temp.tempcounter +1) ^ ")\n"); ([InReg (Temp.newtemp())], depth+1)) | mapBools (escapes::tail, depth, regsAllocated, framespace) = if (escapes orelse (regsAllocated >= 4)) then (print ("allocating in frame (" ^ Int.toString(4 * framespace) ^ ")\n"); (InFrame (4 * depth)::(#1(mapBools(tail, depth+1, regsAllocated, framespace+1))), depth+1)) else (print ("allocating in register (T" ^ Int.toString(!Temp.tempcounter +1) ^ ")\n"); ((InReg (Temp.newtemp()))::(#1(mapBools(tail, depth+1, regsAllocated+1, framespace))), depth+1)) | mapBools ([], _, _, _) = ([], 0) val (access', depth') = mapBools (formals,0,0,0) in (access', (), ref depth', name) end (* ----------------------------------------------------------------- *) fun name (_, _, _, n) = n (* ----------------------------------------------------------------- *) fun formals (f, _, _, _) = f (* ----------------------------------------------------------------- *) fun allocLocal (access, inst, numlocals, label) escapes = if (escapes) then (* we can't allocate in register *) (numlocals := (!numlocals)+1; print ("allocating in frame (" ^ Int.toString((!numlocals)-1 *4) ^ ")\n"); (* can we really use just numlocals here? that will move the stack position in a bad way, I think. *) InFrame ( ((!numlocals)-1)*4)) else (* maybe we can allocate it in a register *) (numlocals := (!numlocals)+1; print ("allocating in register (T" ^ Int.toString(!Temp.tempcounter +1) ^ ")\n"); InReg (Temp.newtemp())) (* ----------------------------------------------------------------- *) val RV = Temp.newtemp() val wordSize = 4 (*in bytes*) val FP = Temp.newtemp() val SP = Temp.newtemp() val ZERO = Temp.newtemp() val RETURN = Temp.newtemp() val ARG1 = Temp.newtemp() val ARG2 = Temp.newtemp() val ARG3 = Temp.newtemp() val ARG4 = Temp.newtemp() val CALLEESAVED1 = Temp.newtemp() val CALLEESAVED2 = Temp.newtemp() val CALLEESAVED3 = Temp.newtemp() val CALLEESAVED4 = Temp.newtemp() val CALLEESAVED5 = Temp.newtemp() val CALLEESAVED6 = Temp.newtemp() val CALLEESAVED7 = Temp.newtemp() val CALLEESAVED8 = Temp.newtemp() val CALLERSAVED1 = Temp.newtemp() val CALLERSAVED2 = Temp.newtemp() val CALLERSAVED3 = Temp.newtemp() val CALLERSAVED4 = Temp.newtemp() val CALLERSAVED5 = Temp.newtemp() val CALLERSAVED6 = Temp.newtemp() val CALLERSAVED7 = Temp.newtemp() val CALLERSAVED8 = Temp.newtemp() val CALLERSAVED9 = Temp.newtemp() val CALLERSAVED10 = Temp.newtemp() val argregisters = [ARG1, ARG2, ARG3, ARG4] val calleesaves = [CALLEESAVED1, CALLEESAVED2, CALLEESAVED3, CALLEESAVED4, CALLEESAVED5, CALLEESAVED6, CALLEESAVED7, CALLEESAVED8] val callersaves = [CALLERSAVED1, CALLERSAVED2, CALLERSAVED3, CALLERSAVED4, CALLERSAVED5, CALLERSAVED6, CALLERSAVED7, CALLERSAVED8,CALLERSAVED9,CALLERSAVED10] val tempMap : string Temp.Table.table = foldr (fn ((k,v), tab) => Temp.Table.enter (tab, k, v)) (Temp.Table.empty : string Temp.Table.table) [(ARG1, "$a0"), (ARG2, "$a1"), (ARG3, "$a2"), (ARG4, "$a3"), (CALLERSAVED1, "$t0"), (CALLERSAVED2, "$t1"), (CALLERSAVED3, "$t2"), (CALLERSAVED4, "$t3"), (CALLERSAVED5, "$t4"), (CALLERSAVED6, "$t5"), (CALLERSAVED7, "$t6"), (CALLERSAVED8, "$t7"), (CALLERSAVED9, "$t8"), (CALLERSAVED10, "$t9"), (CALLEESAVED1, "$s0"), (CALLEESAVED2, "$s1"), (CALLEESAVED3, "$s2"), (CALLEESAVED4, "$s3"), (CALLEESAVED5, "$s4"), (CALLEESAVED6, "$s5"), (CALLEESAVED7, "$s6"), (CALLEESAVED8, "$s7")] fun procEntryExit1(frame, body) = T.MOVE(T.TEMP RV, body) fun procEntryExit2 (frame,body) = body @ [Assem.OPER{assem="", src=[RV,FP,SP,ZERO]@calleesaves, dst=[],jump=NONE}] fun externalCall (s, args) = T.CALL (T.NAME(Temp.namedlabel ("_" ^ s)), args) fun exp (InFrame(k), fp) = T.MEM(T.BINOP(T.PLUS, fp, T.CONST k)) (*fun exp (InFrame(k), exp) = T.MEM(T.BINOP(T.PLUS,exp,T.BINOP(T.PLUS, T.TEMP FP, T.CONST k)))*) | exp (InReg(r), _) = T.TEMP r fun accessname (InReg t) = ("InReg(" ^ (Temp.tempname t) ^ ")") | accessname (InFrame i) = ("InFrame(" ^ (Int.toString i) ^ ")") fun string_of_temp t = case (Temp.Table.look (tempMap, t)) of SOME x => x | NONE => Temp.tempname t end