Tr_exp Tr_seqExp(Tr_exp* array, int size){ T_exp _pex = (T_exp)checked_malloc(sizeof(struct T_exp_)); T_exp *pex = &_pex;//Always point to the rightmost node in the tree during the spanning T_exp ex_head; int i = 0; int last = size - 1; while(i<size){ Tr_printTrExp(array[i]); if(i!=last){ //Not the last one: substitute the rightmost node by T_Eseq (stm-exp pair), //where stm is the Tr_exp *pex = T_Eseq(unNx(array[i]), NULL); } else { //Last one: substitute the rightmost node by Tr_exp itself *pex = unEx(array[i]); } //In case of first node, remember it if(i==0){ ex_head = *pex; } //Not the last one: let pex point to the rightmost node again if(i!=last){ pex = &((*pex)->u.ESEQ.exp); } i++; } //debug("Tr_seqExp done"); return Tr_Ex(ex_head); }
Tr_exp Tr_simpleVar(Tr_access tr_acc, Tr_level level){ //printf("Tr_simpleVar\n"); F_access access = tr_acc->access; T_exp exp; if(level!=tr_acc->level){ int cnt = 0; //printf(" (Tr_simpleVar: Follow static link %d)\n", ++cnt); //Follow the static link exp = F_Exp(F_staticLink(), T_Temp(F_FP())); level = level->parent; //TODO check: level cannot be null while(level!=tr_acc->level){ //printf(" (Tr_simpleVar: Follow static link %d)\n", ++cnt); exp = F_Exp(F_staticLink(), exp); level = level->parent; //TODO check: level cannot be null } exp = F_Exp(access, exp); } else { //printf(" (Tr_simpleVar: Don't follow link)\n"); //Just use the current frame pointer exp = F_Exp(access, T_Temp(F_FP())); } return Tr_Ex(exp); }
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_arrayExp(Tr_exp size, Tr_exp init){ debug("Tr_arrayExp"); /* Dynamic array creation T_Move var <- 0 T_Label start T_CJump var < size, t, f T_Label(t) T_Move offset <- base + var * wordSize T_Move Mem(offset) <- init T_Move var <- var + 1 T_Jump start T_Label(f) */ /* T_exp call = F_externalCall("malloc", T_ExpList(unEx(size), NULL)); Temp_temp _var = Temp_newtemp(); Temp_temp _offset = Temp_newtemp(); Temp_temp _base = Temp_newtemp(); T_exp var = T_Temp(_var); T_exp offset = T_Temp(_offset); T_exp base = T_Temp(_base); Temp_label t = Temp_newlabel(); Temp_label f = Temp_newlabel(); Temp_label start = Temp_newlabel(); T_exp ex = T_Eseq(T_Move(base, call), //Allocate the memory; base := starting address of the allocated mem T_Eseq(T_Move(var, T_Const(0)), //var := 0 T_Eseq(T_Label(start), //start: T_Eseq(T_Cjump(T_lt, var, unEx(size), t, f), //if var < size then jump t else jump f T_Eseq(T_Label(t), //t: T_Eseq(T_Move(offset, T_Binop(T_plus, base, T_Binop(T_mul, var, T_Const(F_wordSize)))), //offset := base + var * wordSize T_Eseq(T_Move(T_Mem(offset), unEx(init)), //MEM[offset] := init T_Eseq(T_Move(var, T_Binop(T_plus, var, T_Const(1))), //var := var + 1 T_Eseq(T_Jump(T_Name(start), Temp_LabelList(start, NULL)), //jump t T_Eseq(T_Label(f), //f: base ) ))))))))); */ //Use system function initArray, which returns pointer to the allocated memory T_exp ex = F_externalCall("initArray", T_ExpList(unEx(size), T_ExpList(unEx(init), NULL))); return Tr_Ex(ex); }
void print_frag(F_fragList fl, FILE * out) { if (!fl) { puts("fragList is NULL"); return; } while (fl) { F_frag f = fl->head; switch(f->kind) { case F_stringFrag: print(Tr_Ex(T_Name(f->u.string.label)), out); fprintf(out, "\n"); break; case F_procFrag: print(Tr_Nx(f->u.proc.body), out); break; default: assert(0 && "frag-kind is error"); } fl = fl->tail; } }
Tr_exp Tr_arithExp(A_oper oper, Tr_exp left, Tr_exp right){ T_exp exp; switch(oper){ case A_plusOp: exp = T_Binop(T_plus, unEx(left), unEx(right)); break; case A_minusOp: exp = T_Binop(T_minus, unEx(left), unEx(right)); break; case A_timesOp: exp = T_Binop(T_mul, unEx(left), unEx(right)); break; case A_divideOp: exp = T_Binop(T_div, unEx(left), unEx(right)); break; default: //Should not reach here printf("Illegal arithmetic operator"); exit(2); } return Tr_Ex(exp); }
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_callExp(Tr_level caller_lvl, Tr_level callee_lvl, Temp_label fun_label, Tr_exp* argv, int args){ int z = 0; int cnt = 0; debug("caller = %d; callee = %d", caller_lvl->depth, callee_lvl->depth); //1) Get the static link for the called function T_exp slk; if(caller_lvl!=callee_lvl){ debug(" (Tr_callExp: Follow static link %d)", ++cnt); //Follow the static link slk = F_Exp(F_staticLink(), T_Temp(F_FP())); caller_lvl = caller_lvl->parent; //TODO check: caller_lvl cannot be null while(caller_lvl!=callee_lvl){ debug(" (Tr_callExp: Follow static link %d)", ++cnt); slk = F_Exp(F_staticLink(), slk); caller_lvl = caller_lvl->parent; //TODO check: caller_lvl cannot be null } } else { debug(" (Tr_callExp: Don't follow link)"); //Just use the current frame pointer slk = F_Exp(F_staticLink(), T_Temp(F_FP())); } debug("Static link done"); //2) Create the argument list, including the static link //2.1) Allocate memory T_expList listp_head = NULL; if(args>0){ /* Problematic on 64-bit machine int node_size = sizeof(struct T_expList_)/8; T_expList listp = (T_expList)checked_malloc((args+1) * sizeof(struct T_expList_)); listp_head = listp; //2.2) Initialize listp->head = slk; listp->tail = listp + node_size; listp = listp->tail; int i = 0; while(i < args){ //Let head point to the next argument listp->head = unEx(*argv); //Let tail point to next head listp->tail = listp + node_size; //Move the base pointer over one node if(i<args-1){ listp = listp->tail; argv++; } i++; } listp->tail = NULL; */ T_expList listp = (T_expList)checked_malloc(sizeof(struct T_expList_)); listp_head = listp; //2.2) Initialize listp->head = slk; listp->tail = NULL; int i = 0; while(i < args){ //Create new list on the tail listp->tail = (T_expList)checked_malloc(sizeof(struct T_expList_)); listp = listp->tail; //Let head point to the next argument listp->head = unEx(*argv); //Let tail point to next head listp->tail = NULL; //Get next argument argv++; i++; } } debug("argument list prepared"); //3) Generate IR T_exp exp = T_Call(T_Name(fun_label), listp_head); /* int i = 0; while(listp_head!=NULL){ printf("arg %d\n", i++);listp_head=listp_head->tail; } */ debug("call done"); return Tr_Ex(exp); }
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_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)))); }
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; }