void gendo(SNODE *stmt) /* * generate code for a do - while loop. */ { int oldcont, oldbreak; oldcont = contlab; oldbreak = breaklab; contlab = nextlabel++; gen_label(contlab); if( stmt->s1 != 0 && stmt->s1->next != 0 ) { breaklab = nextlabel++; genstmt(stmt->s1); /* generate body */ initstack(); truejp(stmt->exp,contlab); gen_label(breaklab); } else { genstmt(stmt->s1); initstack(); truejp(stmt->exp,contlab); } breaklab = oldbreak; contlab = oldcont; }
void genif(SNODE *stmt) /* * generate code to evaluate an if statement. */ { int lab1, lab2; int areg, sreg; lab1 = nextlabel++; /* else label */ lab2 = nextlabel++; /* exit label */ InitRegs(); /* clear temps */ ChooseRegs(&areg, &sreg); falsejp(stmt->exp, areg, sreg, lab1); genstmt(stmt->s1); if (stmt->s2 != 0) /* else part exists */ { gen_codes(op_jmp, 0, make_label(lab2), 0); gen_label(lab1); genstmt(stmt->s2); gen_label(lab2); } else /* no else code */ gen_label(lab1); }
void genwhile(SNODE *stmt) /* * generate code to evaluate a while statement. */ { int lab1, lab2, lab3; initstack(); /* initialize temp registers */ lab1 = contlab; /* save old continue label */ contlab = nextlabel++; /* new continue label */ if( stmt->s1 != 0 ) /* has block */ { lab2 = breaklab; /* save old break label */ breaklab = nextlabel++; gen_code(op_jmp,0,make_label(contlab),0); lab3 = nextlabel++; gen_label(lab3); genstmt(stmt->s1); gen_label(contlab); if (stmt->lst) gen_line(stmt->lst); initstack(); truejp(stmt->exp,lab3); gen_label(breaklab); breaklab = lab2; /* restore old break label */ } else /* no loop code */ { if (stmt->lst) gen_line(stmt->lst); gen_label(contlab); initstack(); truejp(stmt->exp,contlab); } contlab = lab1; /* restore old continue label */ }
void genif(SNODE *stmt) /* * generate code to evaluate an if statement. */ { int lab1, lab2; lab1 = nextlabel++; /* else label */ lab2 = nextlabel++; /* exit label */ initstack(); /* clear temps */ falsejp(stmt->exp,lab1); genstmt(stmt->s1); if( stmt->s2 != 0 ) /* else part exists */ { gen_code(op_jmp,0,make_label(lab2),0); gen_label(lab1); genstmt(stmt->s2); gen_label(lab2); } else /* no else code */ gen_label(lab1); }
void genASM(STATEMENT *st) { cseg(); contlab = breaklab = - 1; structret_imode = 0 ; tempCount = 0; blockCount = 0; blockMax = 0; exitBlock = 0; genstmt(st, NULL); rewrite_icode(); /* Translate to machine code & dump */ }
void gencase(SNODE *stmt) /* * generate all cases for a switch statement. */ { while( stmt != 0 ) { gen_label((int)stmt->label); if( stmt->s1 != 0 ) { genstmt(stmt->s1); } stmt = stmt->next; } }
/*-------------------------------------------------------------------------*/ static void gen_try(SYMBOL *funcsp, STATEMENT *stmt, int startLab, int endLab, int transferLab, STATEMENT *lower) { gen_label(startLab); stmt->tryStart = ++consIndex; xcexp->right->v.i = consIndex; gen_expr(funcsp, xcexp, F_NOVALUE, ISZ_ADDR); genstmt(lower, funcsp); stmt->tryEnd = ++consIndex; xcexp->right->v.i = consIndex; gen_expr(funcsp, xcexp, F_NOVALUE, ISZ_ADDR); gen_label(endLab); /* not using gen_igoto because it will make a new block */ gen_icode(i_goto, NULL, NULL, NULL); intermed_tail->dc.v.label = transferLab; tryStart = stmt->tryStart; tryEnd = stmt->tryEnd; }
void gen_for(SNODE *stmt) /* * generate code to evaluate a for loop */ { int old_break, old_cont, exit_label, loop_label, start_label; int areg, sreg; old_break = breaklab; old_cont = contlab; loop_label = nextlabel++; contlab = nextlabel++; start_label = nextlabel++; exit_label = nextlabel++; InitRegs(); if (stmt->label != 0) { gen_void_external(stmt->label); } gen_codes(op_jmp, 0, make_label(start_label), 0); gen_label(loop_label); if (stmt->s1 != 0) { breaklab = exit_label; genstmt(stmt->s1); } if (stmt->lst) gen_line(stmt->lst); gen_label(contlab); InitRegs(); if (stmt->s2 != 0) { gen_void_external(stmt->s2); } gen_label(start_label); InitRegs(); ChooseRegs(&areg, &sreg); if (stmt->exp != 0) truejp(stmt->exp, areg, sreg, loop_label); else gen_codes(op_jmp, 0, make_label(loop_label), 0); gen_label(exit_label); breaklab = old_break; contlab = old_cont; }
static void gen_catch(SYMBOL *funcsp, STATEMENT *stmt, int startLab, int transferLab, STATEMENT *lower) { int oldtryStart = tryStart; int oldtryEnd = tryEnd; gen_label(startLab); currentBlock->alwayslive = TRUE; intermed_tail->alwayslive = TRUE; catchLevel++; genstmt(lower, funcsp); catchLevel--; /* not using gen_igoto because it will make a new block */ gen_icode(i_goto, NULL, NULL, NULL); intermed_tail->dc.v.label = transferLab; tryStart = oldtryStart; tryEnd = oldtryEnd; stmt->tryStart = tryStart; stmt->tryEnd = tryEnd; }
void genfunc(SNODE *stmt) /* * generate a function body. */ { retlab = contlab = breaklab = -1; funcfloat = 0; init_muldivval(); stackdepth = 0; if (stmt->stype == st_line) { gen_line(stmt); stmt = stmt->next; } gen_codelab(currentfunc); /* name of function */ opt1(stmt); /* push args & also subtracts SP */ #ifdef CPLUSPLUS if (prm_cplusplus) scppinit(); #endif genstmt(stmt); genreturn(0,1); }
void gendo(SNODE *stmt) /* * generate code for a do - while loop. */ { int oldcont, oldbreak, looplab; int areg, sreg; oldcont = contlab; oldbreak = breaklab; looplab = nextlabel++; contlab = nextlabel++; breaklab = nextlabel++; gen_label(looplab); genstmt(stmt->s1); /* generate body */ gen_label(contlab); InitRegs(); ChooseRegs(&areg, &sreg); truejp(stmt->exp, areg, sreg, looplab); gen_label(breaklab); breaklab = oldbreak; contlab = oldcont; }
void gen_for(SNODE *stmt) /* * generate code to evaluate a for loop */ { int old_break, old_cont, exit_label, loop_label; old_break = breaklab; old_cont = contlab; loop_label = nextlabel++; exit_label = nextlabel++; contlab = nextlabel++; initstack(); if( stmt->label != 0 ) gen_expr(stmt->label,F_ALL | F_NOVALUE ,natural_size(stmt->label)); gen_code(op_jmp,0,make_label(contlab),0); gen_label(loop_label); if( stmt->s1 != 0 ) { breaklab = exit_label; genstmt(stmt->s1); } initstack(); if( stmt->s2 != 0 ) gen_expr(stmt->s2,F_ALL | F_NOVALUE,natural_size(stmt->s2)); gen_label(contlab); if (stmt->lst) gen_line(stmt->lst); initstack(); if( stmt->exp != 0 ) truejp(stmt->exp,loop_label); else gen_code(op_jmp,0,make_label(loop_label),0); gen_label(exit_label); breaklab = old_break; contlab = old_cont; }
void genstmt(NODE *n) { VREG *muuo_ac; if (n == NULL) return; switch (n->Nop) { case N_STATEMENT: { NODE *beg, *next; if (n->Nleft && n->Nleft->Nop == N_DATA) { /* Check for auto inits */ genadata(n->Nleft); /* Yep, do them */ n = n->Nright; /* then move on to real statements */ } for(beg = n; n != NULL; n = n->Nright) { if(n->Nop != N_STATEMENT) int_error("genstmt: bad stmt %N", n); if(n->Nleft == NULL) continue; /* Check out following stmt for possible optimizations */ if(n->Nright && (next = n->Nright->Nleft) != NULL && optgen) { switch(next->Nop) { /* Hack to encourage tail recursion */ case Q_RETURN: /* If next will be RETURN */ if(next->Nright == NULL) { /* and has no return val */ NODE *v; /* Then try to optimize */ if((v = laststmt(n->Nleft)) != NULL && v->Nop == N_FNCALL) v->Nflag |= NF_RETEXPR; } break; /* If next stmt is a GOTO, ensure that any jumps * within current stmt to end of stmt will * instead go directly to object of the GOTO. * Avoids jumping to jumps... * We do a similar hack for BREAK and CONTINUE, * which are similar to GOTOs except that their * destination is kept in variables global to the * code generation routines. */ case Q_CASE: /* Not sure about this one yet */ case N_LABEL: case Q_GOTO: n->Nleft->Nendlab = next->Nxfsym; break; case Q_BREAK: n->Nleft->Nendlab = brklabel; break; case Q_CONTINUE: n->Nleft->Nendlab = looplabel; break; default: ; /* do nothing */ } /* end of Nop switch */ } /* end of next-stmt check */ /* Optimize label usage */ if(n->Nright == NULL /* If this is last stmt in list */ && optgen) n->Nleft->Nendlab = beg->Nendlab; /* Copy from 1st */ genstmt(n->Nleft); } break; } /* end of N_STATEMENT case block */ case Q_CASE: codlabel(n->Nxfsym); /* send forward label */ n->Nleft->Nendlab = n->Nendlab; /* propagate end label */ genstmt (n->Nleft); /* finish rest of body */ break; case N_LABEL: if (n->Nxfsym->Sname[0] == '%' && isdigit(n->Nxfsym->Sname[1])) code_debugcall(n); else codgolab(n->Nxfsym); /* send goto label */ n->Nleft->Nendlab = n->Nendlab; /* propagate end label */ genstmt(n->Nleft); /* finish rest of body */ break; case Q_BREAK: code6(P_JRST, NULL, brklabel); break; case Q_GOTO: code6(P_JRST, NULL, n->Nxfsym); break; case Q_CONTINUE: code6(P_JRST, NULL, looplabel); break; case Q_DO: gdo(n); break; case Q_FOR: gfor(n); break; case Q_IF: gif(n); break; case Q_RETURN: greturn(n); break; case Q_SWITCH: gswitch(n); break; case Q_WHILE: gwhile(n); break; #if SYS_CSI /* Added 1/91 for in-line monitor calls; KAR */ case Q_MUUO: muuo_ac = gmuuo(n); vrfree(muuo_ac); break; #endif case N_EXPRLIST: /* Same as expression stmt */ default: /* None of above, assume expression stmt */ genxrelease(n); /* Generate it and flush any result */ break; } }
void genfunc(SYMBOL *funcsp) /* * generate a function body and dump the icode */ { IMODE *allocaAP = NULL; SYMBOL *oldCurrentFunc; EXPRESSION *funcexp = varNode(en_global, funcsp); if (total_errors) return; // //printf("%s\n", funcsp->name); contlab = breaklab = - 1; structret_imode = 0 ; tempCount = 0; blockCount = 0; blockMax = 0; exitBlock = 0; oldCurrentFunc = theCurrentFunc; theCurrentFunc = funcsp; iexpr_func_init(); /* firstlabel = nextLabel;*/ cseg(); gen_line(funcsp->linedata); gen_func(funcexp, 1); /* in C99 inlines can clash if declared 'extern' in multiple modules */ /* in C++ we introduce virtual functions that get coalesced at link time */ if (cparams.prm_cplusplus && funcsp->linkage == lk_inline) gen_virtual(funcsp, FALSE); else { if (funcsp->storage_class == sc_global) globaldef(funcsp); else localdef(funcsp); gen_strlab(funcsp); /* name of function */ } addblock( - 1); if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) { gen_icode(i_pushcontext, 0,0,0); /* if (funcsp->loadds) */ /* gen_icode(i_loadcontext, 0,0,0); */ } gen_icode(i_prologue,0,0,0); gen_label(startlab); /* if (funcsp->loadds && funcsp->farproc) */ /* gen_icode(i_loadcontext, 0,0,0); */ AllocateLocalContext(NULL, funcsp); if (funcsp->allocaUsed) { EXPRESSION *allocaExp = varNode(en_auto, anonymousVar(sc_auto, &stdpointer)); allocaAP = gen_expr(funcsp, allocaExp, 0, ISZ_ADDR); gen_icode(i_savestack, 0, allocaAP, 0); } /* Generate the icode */ /* LCSE is done while code is generated */ genstmt(funcsp->inlineFunc.stmt->lower, funcsp); if (funcsp->inlineFunc.stmt->blockTail) { gen_icode(i_functailstart, 0, 0, 0); genstmt(funcsp->inlineFunc.stmt->blockTail, funcsp); gen_icode(i_functailend, 0, 0, 0); } genreturn(0, funcsp, 1, 0, allocaAP); gen_func(funcexp, 0); tFree(); InsertParameterThunks(funcsp, blockArray[1]); optimize(funcsp); FreeLocalContext(NULL, funcsp); AllocateStackSpace(funcsp); FillInPrologue(intermed_head, funcsp); /* Code gen from icode */ rewrite_icode(); /* Translate to machine code & dump */ if (chosenAssembler->gen->post_function_gen) chosenAssembler->gen->post_function_gen(funcsp, intermed_head); if (cparams.prm_cplusplus && funcsp->linkage == lk_inline) gen_endvirtual(funcsp); intermed_head = NULL; dag_rundown(); oFree(); theCurrentFunc = oldCurrentFunc; if (blockCount > maxBlocks) maxBlocks = blockCount; if (tempCount > maxTemps) maxTemps = tempCount; }
void genstmt(STATEMENT *stmt, SYMBOL *funcsp) /* * genstmt will generate a statement and follow the next pointer * until the block is generated. */ { while (stmt != 0) { switch (stmt->type) { case st_varstart: gen_varstart(stmt->select); break; case st_dbgblock: gen_dbgblock(stmt->label); break; case st_tryblock: /* gen_tryblock(stmt->label); */ break; case st_block: genstmt(stmt->lower, funcsp); genstmt(stmt->blockTail, funcsp); break; case st_label: gen_label((int)stmt->label); break; case st_goto: gen_igoto(i_goto, (int)stmt->label); break; case st_asmgoto: gen_igoto(i_asmgoto, (int)stmt->label); break; case st_asmcond: gen_igoto(i_asmcond, (int)stmt->label); break; case st_throw: /* gen_throw((TYPE *)stmt->lst, stmt->select);*/ break; /* case st_functailexpr: gen_icode(i_functailstart, 0, 0, 0); gen_expr(funcsp, stmt->select, F_NOVALUE, natural_size(stmt->select)); * gen_icode(i_functailend, 0, 0, 0); break; */ case st_expr: case st_declare: gen_expr(funcsp, stmt->select, F_NOVALUE, natural_size(stmt->select)); break; case st_return: genreturn(stmt, funcsp, 0, 0, NULL); break; case st_line: gen_line(stmt->lineData); break; case st_select: genselect(stmt, funcsp, TRUE); break; case st_notselect: genselect(stmt, funcsp, FALSE); break; case st_switch: genxswitch(stmt, funcsp); break; case st__genword: gen_genword(stmt, funcsp); break; case st_passthrough: gen_asm(stmt); break; case st_datapassthrough: gen_asmdata(stmt); break; default: diag("unknown statement."); break; } stmt = stmt->next; } }
void genstmt(SNODE *stmt) /* * genstmt will generate a statement and follow the next pointer * until the block is generated. */ { while( stmt != 0 ) { switch( stmt->stype ) { case st_block: genstmt(stmt->exp); break; case st_label: gen_label((int)stmt->label); break; case st_goto: gen_code(op_jmp,0,make_label((int)stmt->label),0); break; case st_expr: initstack(); gen_expr(stmt->exp,F_ALL | F_NOVALUE, natural_size(stmt->exp)); break; case st_return: genreturn(stmt,0); break; case st_if: genif(stmt); break; case st_while: genwhile(stmt); break; case st_do: gendo(stmt); break; case st_for: gen_for(stmt); break; case st_continue: gen_code(op_jmp,0,make_label(contlab),0); break; case st_break: gen_code(op_jmp,0,make_label(breaklab),0); break; case st_switch: genxswitch(stmt); break; case st_line: gen_line(stmt); break; case st_asm: if (stmt->exp) add_peep(stmt->exp); break; case st__genword: gen_code(op_genword,0,make_immed((int)stmt->exp),0); break; default: diag("unknown statement."); break; } stmt = stmt->next; } }
IMODE *genstmt(STATEMENT *stmt, SYMBOL *funcsp) /* * genstmt will generate a statement and follow the next pointer * until the block is generated. */ { IMODE *rv = NULL; while (stmt != 0) { STATEMENT *last = stmt; switch (stmt->type) { case st_varstart: gen_varstart(stmt->select); break; case st_dbgblock: gen_dbgblock(stmt->label); break; break; case st_block: rv = genstmt(stmt->lower, funcsp); genstmt(stmt->blockTail, funcsp); break; case st_label: gen_label((int)stmt->label); break; case st_goto: gen_igoto(i_goto, (int)stmt->label); break; case st_asmgoto: gen_igoto(i_asmgoto, (int)stmt->label); break; case st_asmcond: gen_igoto(i_asmcond, (int)stmt->label); break; case st_try: gen_try(funcsp, stmt, stmt->label, stmt->endlabel, stmt->breaklabel, stmt->lower); break; case st_catch: { STATEMENT *last; while (stmt && stmt->type == st_catch) { gen_catch(funcsp, stmt, stmt->altlabel, stmt->breaklabel, stmt->lower); last = stmt; stmt = stmt->next; } stmt = last; gen_label(stmt->breaklabel); } break; case st_expr: case st_declare: if (stmt->select) rv = gen_expr(funcsp, stmt->select, F_NOVALUE, natural_size(stmt->select)); break; case st_return: genreturn(stmt, funcsp, 0, 0, NULL); break; case st_line: gen_line(stmt->lineData); break; case st_select: genselect(stmt, funcsp, TRUE); break; case st_notselect: genselect(stmt, funcsp, FALSE); break; case st_switch: genxswitch(stmt, funcsp); break; case st__genword: gen_genword(stmt, funcsp); break; case st_passthrough: gen_asm(stmt); break; case st_datapassthrough: gen_asmdata(stmt); break; default: diag("unknown statement."); break; } if (last->type != st_return && last->destexp) { gen_expr(funcsp, last->destexp, F_NOVALUE, ISZ_ADDR); } stmt = stmt->next; } return rv; }