/* * File: * irtframe.c * Author: * Samuel A. Rebelsky, based on code from Andrew Appel * Version: * 0.2 of 23 November 1998 * Description: * A very simple implementation of frames for a ``straight-line'' * IRT code used as a project in CSC362 1998 Fall at Grinnell College. */ /*********************************************************** * Headers * ***********/ #include #include "util.h" #include "symbol.h" #include "absyn.h" #include "temp.h" #include "tree.h" #include "assem.h" #include "frame.h" #include "irtframe.h" /*********************************************************** * Constants * *************/ /* * The size of words (in bytes). * Green book, p. 159. */ const int F_wordSize = 4; /*********************************************************** * Globals * ***********/ /* The registers */ static Temp_tempList registers = NULL; /*********************************************************** * Local Functions * *******************/ /* * Build an access list, given the head and tail. */ F_accessList F_AccessList(F_access head, F_accessList tail) { F_accessList list = checked_malloc(sizeof(struct F_accessList_)); list->head = head; list->tail = tail; return list; } /* F_AccessList(F_access, F_AccessList) */ /* * Add the formals. Done as a separate function so that I can build * the list in the correct order (which requires putting the first thing * in the list of escapes at the front, which suggests that I do recursion). */ static void addFormals(F_frame frame, U_boolList formals) { /* Are we done? */ if (formals == NULL) { return; } /* Recurse */ addFormals(frame, formals->tail); /* And add the head. */ frame->formals = F_AccessList(F_allocLocal(frame, formals->head), frame->formals); } /* addFormals() */ /* * Create a new access for a variable stored in a register. */ F_access inreg(F_frame frame) { /* Allocate the access and set its kind. */ F_access reg = (F_access) checked_malloc(sizeof(struct F_access_)); reg->kind = F_inRegister; /* Fill in the new temporary. */ reg->u.reg = Temp_newtemp(); /* Update the list of allocated registers. */ registers = Temp_TempList(reg->u.reg, registers); /* And that's it. */ return reg; } /* inreg(void) */ /* * Create a new access for a variable stored in the frame. */ F_access inframe(F_frame frame) { /* Allocate the access and set its kind. */ F_access var = (F_access) check_malloc(sizeof(struct F_access_)); var->kind = f_inFrame; /* Determine the offset in the current frame (in bytes). Note that frames grow downward, so we use a negative offset. */ var->u.offset = -4*(frame->allocated); /* Update the amount of space allocated in the current frame. */ frame->allocated += 1; /* And that's it. */ return var; } /* inframe(F_frame) */ /*********************************************************** * Exported Functions * **********************/ /* * Create a new frame, given information about the parameters to * the function. The booleans indicate whether or not the parameters * "escape" (must be stored in the frame, rather than in registers). * Green book, p. 136. */ F_frame F_newFrame(Temp_label name, U_boolList formals) { /* Allocate that puppy! */ F_frame newf = (F_frame) checked_malloc(sizeof(struct F_frame_)); /* Fill in the fields. */ /* Fill in the name. Thankfully, it's been supplied for us. We might also use Temp_newLabel(). */ newf->name = name; /* How many words are initially allocated? Let's do one for the return address. */ newf->allocated = 1; /* How many formals do we have? Initially, none. */ newf->formals = NULL; /* A useless view shift, but it may be useful to have something. */ newf->viewShift = T_Exp(T_Const(0)); /* Add the formals. */ addFormals(newf, formals); /* And that's it. */ return newf; } /* F_newFrame */ /* * Get the label associated with the frame. Used when calling the * function. (It's not clear that this really belongs here, but * that's how Appel designed it.) * Green book, p. 136. */ Temp_label F_name(F_frame f) { return f->name; } /* F_name */ /* * Get the locations associated with the parameters. Presumably, * this is only used by the stuff that manipulates the body of the * corresponding function. * Green book, p. 136. */ F_accessList F_formals(F_frame f) { return f->formals; } /* F_formals */ /* * Allocate a new local storage location, which might be a register * or space on the frame (or ....). In doing so, indicate whether it * must be stored in the frame. * Green book, p. 136. */ F_access F_allocLocal(F_frame f, bool escapes) { if (escapes) { return inframe(f); } else { return inreg(f); } } /* F_allocLocal */ /* * All the registers used in the various frames (I think). * Appears in Green book, p. 268. Defined earlier? */ Temp_tempList F_registers(void) { return registers; } /* F_registers */ /* * Compute the appropriate IRT for an access. This might be a TEMP, * or it might be a memory location. Requires the qualified base of * the frame, which is computed at a different level (by translate.c). * Green book, p. 159. */ T_exp F_Exp(F_access acc, T_exp framePtr) { return NULL; } /* F_Exp */ /* * Get the frame pointer. * Green book, p. 159. */ Temp_temp F_FP(void) { return NULL; } /* F_FP */ /* * Get the return-address register. * Green book, p. 268. Defined earlier? */ Temp_temp F_RA(void) { return NULL; } /* F_RA */ /* * Get the return-value register. * Green book, p. 172. */ Temp_temp F_RV(void) { return NULL; } /* F_RA */ /* * Get the stack pointer. * Green book, p. 268. Defined earlier? */ Temp_temp F_SP(void) { return NULL; } /* F_SP */ /* * Some special temporary? Perhaps register 0? * Green book, p. 268. Defined earlier? */ Temp_temp F_ZERO(void) { return NULL; } /* F_ZERO */ /* * Call an external function (one of the built-in functions). * Green book, p. 168. */ T_exp F_externalCall(string s, T_expList args) { return NULL; } /* F_externalCall */ /* * Create the IRT for the start and end of the frame. This includes * saving parameters and saving registers. The associated statement * is the body of the function (I hope). * Green book, p. 172 and 267. */ T_stm F_procEntryExit1(F_frame frame, T_stm stm) { return NULL; } /* F_procEntryExit1 */ /* * Add ``sink'' instructions to the function body so that the register * allocator can determine which registers are live at procedure exit. * Note that this does not seem to rely on the current frame. * Green book, p. 215. */ AS_instrList F_procEntryExit2(AS_instrList body) { return NULL; } /* F_procEntryExit2 */ /* * Create assembly code for the start and the end of the frame. * Handles sizing the frame. * Green book, p. 269. */ AS_proc F_procEntryExit3(F_frame frame, AS_instrList body) { return NULL; } /* F_procEntryExit3 */ /* * Create a new fragment corresponding to a string. * Green book, p. 172. */ F_frag F_StringFrag(Temp_label label, string str) { return NULL; } /* F_StringFrag */ /* * Create a new fragment corresopnding to a procedure body. * Green book, p. 173. */ F_frag F_ProcFrag(T_stm body, F_frame frame) { return NULL; } /* F_ProcFrag */ /* * Create a new list of fragments. */ F_fragList F_FragList(F_frag head, F_fragList tail) { return NULL; } /* F_FragList */ /*********************************************************** * Special Functions * *********************/ /* * The following are functions that I added to ease creation of * ``straight-line'' IRT code. They may not be appropriate for * all implementations. They may also be moved to irtframe.h. */ /* * Get the program counter. */ Temp_temp F_PC(void); /* * Get the heap pointer. */ Temp_temp F_HP(void); /* * Get the accumulator. */ Temp_temp F_ACC(void); /* * Get an argument register. Argument registers are numbered 0 through 9. */ Temp_temp F_A(int num);