static Temp_tempList F_make_calle_saves(void) { Temp_temp rbx = Temp_newtemp(), r12 = Temp_newtemp(), r13 = Temp_newtemp(), r14 = Temp_newtemp(), r15 = Temp_newtemp(); F_add_to_map("rbx", rbx); F_add_to_map("r12", r12); F_add_to_map("r13", r13); F_add_to_map("r14", r14); F_add_to_map("r15", r15); return TL(F_SP(), TL(F_FP(), TL(rbx, TL(r12, TL(r13, TL(r14, TL(r15, NULL))))))); }
//Extractors static T_exp unEx(Tr_exp e){ Temp_temp r; Temp_label t,f; T_exp ex; switch(e->kind){ case Tr_ex: ex = e->u.ex; break; case Tr_cx: r = Temp_newtemp(); t = Temp_newlabel(); f = Temp_newlabel(); doPatch(e->u.cx.trues, t); doPatch(e->u.cx.falses, f); ex = T_Eseq(T_Move(T_Temp(r), T_Const(1)), T_Eseq(e->u.cx.stm, T_Eseq(T_Label(f), T_Eseq(T_Move(T_Temp(r), T_Const(0)), T_Eseq(T_Label(t), T_Temp(r) ) ) ) ) ); break; case Tr_nx: ex = T_Eseq(e->u.nx, T_Const(0)); break; } return ex; }
Temp_temp F_SP(void) { if (!sp) { sp = Temp_newtemp(); F_add_to_map("rsp", sp); } return sp; }
Temp_temp F_RV(void) { if (!rv) { rv = Temp_newtemp(); F_add_to_map("rax", rv); } return rv; }
Temp_temp F_FP(void) { if (!fp) { fp = Temp_newtemp(); F_add_to_map("rbp", fp); } return fp; }
Temp_tempList F_CALLER() { static Temp_tempList caller = NULL; if (caller) return caller; for (int i = 0; i < 2; ++i) { Temp_temp r = Temp_newtemp(); caller = Temp_TempList(r, caller); } return caller; }
Temp_tempList F_CALLEE() { static Temp_tempList callee = NULL; if (callee) return callee; for (int i = 0; i < 6; ++i) { Temp_temp r = Temp_newtemp(); callee = Temp_TempList(r, callee); } return callee; }
Temp_tempList F_ARGS() { static Temp_tempList argr = NULL; if (argr) return argr; for (int i = 0; i < 6; ++i) { Temp_temp r = Temp_newtemp(); argr = Temp_TempList(r, argr); } return argr; }
Tr_exp Tr_recordExp_new(int cnt){ debug("Tr_recordExp_new fields=%d", cnt); T_exp call = F_externalCall("malloc", T_ExpList(T_Const(cnt*F_wordSize), NULL)); Temp_temp r = Temp_newtemp(); T_stm move = T_Seq(T_Move(T_Temp(r), call), NULL); T_exp ex = T_Eseq(move, T_Temp(r)); return Tr_Ex(ex); }
F_access F_allocLocal(F_frame f, bool escape) { int offset = 0; F_accessList tail; for (F_accessList locals = f->locals; locals; locals = locals->tail) if (locals->head->kind == inFrame) offset -= F_wordSize; F_access l = (escape) ? InFrame(offset) : InReg(Temp_newtemp()); f->locals = F_AccessList(l, f->locals); return l; }
static Temp_tempList F_make_arg_regs(void) { Temp_temp rdi = Temp_newtemp(), rsi = Temp_newtemp(), rdx = Temp_newtemp(), rcx = Temp_newtemp(), r8 = Temp_newtemp(), r9 = Temp_newtemp(); F_add_to_map("rdi", rdi); F_add_to_map("rsi", rsi); F_add_to_map("rdx", rdx); F_add_to_map("rcx", rcx); F_add_to_map("r8", r8); F_add_to_map("r9", r9); return TL(rdi, TL(rsi, TL(rdx, TL(rcx, TL(r8, TL(r9, NULL)))))); }
F_frame F_newFrame(Temp_label label, U_boolList escape) { F_frame f = (F_frame)checked_malloc(sizeof(*f)); f->label = label; int offset = 0; int reg = 0; F_accessList h = F_AccessList(NULL, NULL), p = h; for (; escape; escape = escape->tail) { if (escape->head == TRUE || reg >= regNum) { p->tail = F_AccessList(InFrame(offset += F_wordSize), NULL); } else { p->tail = F_AccessList(InReg(Temp_newtemp()), NULL); } p = p->tail; } f->formals = h->tail; free(h); return f; }
static F_accessList makeFormalAccessList(F_frame f, U_boolList formals) { U_boolList fmls; F_accessList headList = NULL, tailList = NULL; int i = 1; for (fmls = formals; fmls; fmls = fmls->tail) { F_access access = NULL; if (i <= F_K && !fmls->head) { access = InReg(Temp_newtemp()); i++; } else { /* Add 1 for return address space. */ access = InFrame((1 + i) * F_WORD_SIZE); } if (headList) { tailList->tail = F_AccessList(access, NULL); tailList = tailList->tail; } else { headList = F_AccessList(access, NULL); tailList = headList; } } return headList; }
Temp_temp F_FP() { // ebp static Temp_temp r; if (r) return r = NULL; r = Temp_newtemp(); return r; }
Tr_exp Tr_ifExp(Tr_exp cond, Tr_exp thenb, Tr_exp elseb){ T_exp ex; T_stm st; Tr_exp ret; struct Cx cx_cond = unCx(cond); Temp_label t = Temp_newlabel(); Temp_label f = Temp_newlabel(); Temp_label join = Temp_newlabel(); doPatch(cx_cond.trues, t); doPatch(cx_cond.falses, f); if(elseb==NULL){ //case 1: if-then debug("Tr_ifExp: if-then"); st = T_Seq(cx_cond.stm, T_Seq(T_Label(t), T_Seq(unNx(thenb), T_Label(f) ) ) ); ret = Tr_Nx(st); } else { //case 2: if-then-else if(thenb->kind==Tr_nx && elseb->kind==Tr_nx){ debug("Tr_ifExp: if-then-else (2 nx)"); //special case: two statements st = T_Seq(cx_cond.stm, T_Seq(T_Label(t), T_Seq(unNx(thenb), T_Seq( T_Jump( T_Name(join), Temp_LabelList(join, NULL) ), T_Seq(T_Label(f), T_Seq(unNx(elseb), T_Label(join) ) ) ) ) ) ); ret = Tr_Nx(st); //TODO: special case - two cx. } else { debug("Tr_ifExp: if-then-else"); Temp_temp r = Temp_newtemp(); ex = T_Eseq(cx_cond.stm, T_Eseq(T_Label(t), T_Eseq(T_Move(T_Temp(r), unEx(thenb)), T_Eseq( T_Jump( T_Name(join), Temp_LabelList(join, NULL) ), T_Eseq(T_Label(f), T_Eseq(T_Move(T_Temp(r), unEx(elseb)), T_Eseq(T_Label(join), T_Temp(r) ) ) ) ) ) ) ); ret = Tr_Ex(ex); } } return ret; }
Temp_temp F_RV() { // rax static Temp_temp r = NULL; if (r) return r; r = Temp_newtemp(); return r; }
Temp_temp F_ZERO() { // zf static Temp_temp r = NULL; if (!r) r = Temp_newtemp(); return r; }
F_access F_allocLocal(F_frame f, bool escape) { f->local_count++; if (escape) return InFrame(F_WORD_SIZE * (- f->local_count)); return InReg(Temp_newtemp()); }
static Temp_tempList F_make_caller_saves(void) { Temp_temp r10 = Temp_newtemp(), r11 = Temp_newtemp(); F_add_to_map("r10", r10); F_add_to_map("r11", r11); return TL(F_RV(), TL(r10, TL(r11, F_make_arg_regs()))); }
Temp_temp F_SP() { // rsp static Temp_temp r = NULL; if (r) return r; r = Temp_newtemp(); return r; }
Temp_temp F_RV() { if (!returnValue) returnValue = Temp_newtemp(); return returnValue; }
Temp_temp F_FP() { if (!framePoint) framePoint = Temp_newtemp(); return framePoint; }