//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; }
Tr_exp Tr_logicExp(A_oper oper, Tr_exp left, Tr_exp right, bool isStrCompare){ T_stm stm; patchList tl; patchList fl; if(isStrCompare){ T_exp call = F_externalCall("stringEqual", T_ExpList(unEx(left), T_ExpList(unEx(right), NULL))); switch(oper){ case A_eqOp: stm = T_Cjump(T_eq, call, T_Const(1), NULL, NULL); break; case A_neqOp: stm = T_Cjump(T_eq, call, T_Const(0), NULL, NULL); break; default: //Should not reach here printf("Illegal logic operator on string comparison"); exit(2); } } else { switch(oper){ case A_eqOp: stm = T_Cjump(T_eq, unEx(left), unEx(right), NULL, NULL); break; case A_neqOp: stm = T_Cjump(T_ne, unEx(left), unEx(right), NULL, NULL); break; case A_ltOp: stm = T_Cjump(T_lt, unEx(left), unEx(right), NULL, NULL); break; case A_gtOp: stm = T_Cjump(T_gt, unEx(left), unEx(right), NULL, NULL); break; case A_leOp: stm = T_Cjump(T_le, unEx(left), unEx(right), NULL, NULL); break; case A_geOp: stm = T_Cjump(T_ge, unEx(left), unEx(right), NULL, NULL); break; default: //Should not reach here printf("Illegal logic operator"); exit(2); } } tl = PatchList(&stm->u.CJUMP.true, NULL); fl = PatchList(&stm->u.CJUMP.false, NULL); return Tr_Cx(tl, fl, stm); }
//Refer to FIGURE 7.4 (P168) //struct {T_stm left, right;} SEQ; T_stm_ //struct {T_stm stm; T_exp exp;} ESEQ; T_exp_ void Tr_recordExp_app(Tr_exp te, Tr_exp init, bool last){ debug("Tr_recordExp_app %s", last==TRUE?"(LAST)":""); //1) Retrieve T_stm, which should be an ESEQ T_exp ex = unEx(te); //2) Prepare for iteration //The first sub-node for field initialization T_stm* right = &(ex->u.ESEQ.stm->u.SEQ.right); //The register saving the base addr of record var T_exp temp = ex->u.ESEQ.exp; //3) Iterate over the SEQs, until the rightmost node is found, which should be NULL int i = 0; while(*right!=NULL){ right = &((*right)->u.SEQ.right); i++; } //4) Create a new sub-node to initialize the next field T_stm move = T_Move(T_Mem(T_Binop(T_plus, temp, T_Const(i*F_wordSize))), unEx(init)); //5) Substitue the rightmode node if(!last){ *right = T_Seq(move, NULL); } else { *right = move; } }
T_exp F_Exp(F_access access, T_exp framePtr) { if (access->kind == inFrame) { return T_Mem(T_Binop(T_plus, framePtr, T_Const(access->u.offset))); } else { return T_Temp(access->u.reg); } }
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); }
Tr_exp Tr_forExp(Tr_exp var, Tr_exp low, Tr_exp high, Tr_exp body){ debug("Tr_forExp"); T_stm st; T_exp v = unEx(var); Temp_label t = Temp_newlabel(); Temp_label f = LL_peek();//Get done label from the list, which should have been prepared before this function is called. Temp_label start = Temp_newlabel(); T_stm cond = T_Cjump(T_le, v, unEx(high), t, f); /* T_Move var <- low T_Label start T_CJump var <= high, t, f T_Label(t) body T_Move var + 1 T_Jump start T_Label(f) */ st = T_Seq(T_Move(v, unEx(low)), T_Seq(T_Label(start), T_Seq(cond, T_Seq(T_Label(t), T_Seq(unNx(body), T_Seq(T_Move(v, T_Binop(T_plus, v, T_Const(1))), T_Seq( T_Jump( T_Name(start), Temp_LabelList(start, NULL) ), T_Label(f) ) ) ) ) ) ) ); //Pop the label as it's no longer used LL_pop(); return Tr_Nx(st); }
static struct Cx unCx(Tr_exp e){ struct Cx cx; switch(e->kind){ case Tr_ex: cx.stm = T_Cjump(T_ne, e->u.ex, T_Const(0), NULL, NULL); cx.trues = PatchList(&cx.stm->u.CJUMP.true, NULL); cx.falses = PatchList(&cx.stm->u.CJUMP.false, NULL); break; case Tr_cx: cx = e->u.cx; break; case Tr_nx://Should not reach here cx.trues = NULL; cx.falses = NULL; cx.stm = e->u.nx; break; } return cx; }
Tr_exp Tr_nilExp(){ if(Tr_NIL==NULL){ Tr_NIL = Tr_Ex(T_Mem(T_Const(0))); } return Tr_NIL; }
Tr_exp Tr_voidExp(){ if(Tr_NOOP==NULL){ Tr_NOOP = Tr_Ex(T_Const(0)); } return Tr_NOOP; }
Tr_exp Tr_intExp(int int_val){ return Tr_Ex(T_Const(int_val)); }
Tr_exp Tr_arrayVar(Tr_exp base, Tr_exp offset_exp){ return Tr_Ex(T_Mem(T_Binop(T_plus, unEx(base), T_Binop(T_mul, unEx(offset_exp), T_Const(F_wordSize))))); }
Tr_exp Tr_fieldVar(Tr_exp base, int field_offset){ return Tr_Ex(T_Mem(T_Binop(T_plus, unEx(base), T_Const(field_offset * F_wordSize)))); }
T_exp F_Exp(F_access acc, T_exp framePtr) { if (acc->kind == inFrame) return T_Mem(T_Binop(T_plus, T_Const(acc->u.offset), framePtr)); else return T_Temp(acc->u.reg); }