//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_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); }
Tr_exp transDec_functionDec(Tr_level level, S_table venv, S_table tenv, A_dec d, Temp_label breakk) { for (A_fundecList fundecs = d->u.function; fundecs; fundecs = fundecs->tail) { S_symbol name = fundecs->head->name; Ty_tyList formals = makeFormalTyList(tenv, fundecs->head->params); for (A_fundecList f = d->u.function; f != fundecs; f = f->tail) if (f->head->name == name) EM_error(f->head->pos, "there are two functions with the same name in the same batch " "of mutually recursive functions"); Ty_ty result = (fundecs->head->result)? S_look(tenv, fundecs->head->result) : Ty_Void(); Temp_label label = Temp_newlabel(); U_boolList escapeList = NULL; for (A_fieldList l = fundecs->head->params; l; l = l->tail) // todo: handle no escape escapeList = U_BoolList(TRUE, escapeList); S_enter(venv, name, E_FunEntry(Tr_newLevel(level, label, escapeList), label, formals, result)); } for (A_fundecList fundecs = d->u.function; fundecs; fundecs = fundecs->tail) { S_symbol name = fundecs->head->name; E_enventry x = S_look(venv, name); Ty_tyList formals = x->u.fun.formals; Ty_ty result = x->u.fun.result; Tr_level lev = x->u.fun.level; S_beginScope(venv); { A_fieldList l; Ty_tyList t; Tr_accessList a; for (l = fundecs->head->params, t = formals, a = Tr_formals(lev); l; l = l->tail, t = t->tail, a = a->tail) S_enter(venv, l->head->name, E_VarEntry(a->head, t->head)); // check return type struct expty body = transExp(lev, venv, tenv, fundecs->head->body, breakk); if (!has_same_ty(result, body.ty)) { if (has_same_ty(result, Ty_Void())) EM_error(fundecs->head->pos, "procedure returns value '%s'", type_msg(body.ty)); else EM_error(fundecs->head->pos, "return type mismatched '%s' and '%s')", type_msg(result), type_msg(body.ty)); } Tr_procEntryExit(lev, body.exp, a); } S_endScope(venv); } return Tr_noExp(); }
Tr_exp Tr_whileExp(Tr_exp cond, Tr_exp body){ debug("Tr_whileExp"); T_stm st; struct Cx cx_cond = unCx(cond); 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(); doPatch(cx_cond.trues, t); doPatch(cx_cond.falses, f); /* T_Label start cx_cond.stm (true->t, false->f) T_Label(t) body T_Jump start T_Label(f) */ st = T_Seq(T_Label(start), T_Seq(cx_cond.stm, T_Seq(T_Label(t), T_Seq(unNx(body), 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 T_stm unNx(Tr_exp e){ Temp_label t,f; T_stm st; switch(e->kind){ case Tr_ex: st = T_Exp(e->u.ex); break; case Tr_cx: t = Temp_newlabel(); f = Temp_newlabel(); doPatch(e->u.cx.trues, t); doPatch(e->u.cx.falses, f); st = T_Seq(e->u.cx.stm, T_Seq(T_Label(t), T_Label(f))); break; case Tr_nx: st = e->u.nx; break; } return st; }
struct expty transExp_whileExp(Tr_level level, S_table venv, S_table tenv, A_exp a, Temp_label breakk) { struct expty test = transExp(level, venv, tenv, a->u.whilee.test, breakk); struct expty body = transExp(level, venv, tenv, a->u.whilee.body, breakk); if (test.ty->kind != Ty_int) EM_error(a->u.whilee.test->pos, "expected unqualified-id"); if (body.ty->kind != Ty_void) EM_error(a->u.whilee.test->pos, "body of while not unit"); Temp_label newbreak = Temp_newlabel(); return expTy(Tr_whileExp(test.exp, body.exp, newbreak), Ty_Void()); }
Tr_exp Tr_stringExp(string str_val){ Temp_label tl = Temp_newlabel(); F_String(tl, str_val); return Tr_Ex(T_Name(tl)); }
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; }
void Tr_genLoopDoneLabel(){ //Put a new label into the label list Temp_label f = Temp_newlabel(); LL_push(f); debug("new loop done label generated"); }
Tr_level Tr_outermost(void) { if (!outer) outer = Tr_newLevel(NULL, Temp_newlabel(), NULL); return outer; }