Mercurial > hg > CbC > old > device
changeset 292:6d4231b6f9fe
switch statement prepare
author | kono |
---|---|
date | Sat, 05 Jun 2004 00:08:09 +0900 |
parents | 7b6df595b205 |
children | 5bf2c3070d36 |
files | Changes mc-code-ia32.c mc-code-mips.c mc-code-powerpc.c mc-codegen.c mc-codegen.h mc-parse.c mc.h |
diffstat | 8 files changed, 154 insertions(+), 32 deletions(-) [+] |
line wrap: on
line diff
--- a/Changes Fri Jun 04 03:32:19 2004 +0900 +++ b/Changes Sat Jun 05 00:08:09 2004 +0900 @@ -4606,3 +4606,30 @@ code_bool で !use の時に、null branchが残っちゃうけど... ま、仕方がないか。 + +Fri Jun 4 12:57:28 JST 2004 + +switch 文をやるんだけど、 + + main() { + int i=3,j=1,k=0; + switch(i) + for(;j<10;j++) { + case 3: k++; case 2: k++; case 1: k++; case 0: k++; + } + printf("%d\n",k); + } + +なんだけど、j<10 などを評価する前にjmpする必要があるので、最 +初のcase文にjumpしないといけないが、jump する必要があるかど +うかは、switch の次の文を実際に評価してみないとわからない。 + +なので、 checkret() で、その処理を行う方が良い。 + if (first_case) { + jmp(first_case); first_case =0; + } +かな。もし、これが行われるなら、飛び先はtable jump routine であるべき。 + +switch をまとめるのはやったけど、現状のコードだとtable +は、ほとんどでないね。2分木は出るけど。IDが連続するように +工夫した方がいいのかな。
--- a/mc-code-ia32.c Fri Jun 04 03:32:19 2004 +0900 +++ b/mc-code-ia32.c Sat Jun 05 00:08:09 2004 +0900 @@ -464,10 +464,9 @@ void gexpr_init(void) { - while(reg_sp > 0) { - if (reg_stack[--reg_sp]>=0) - free_register(reg_stack[reg_sp]); - } + if (reg_sp>0) error(-1); + if (freg_sp>0) error(-1); + reg_sp = 0; freg_sp = 0; text_mode(); gexpr_code_init();
--- a/mc-code-mips.c Fri Jun 04 03:32:19 2004 +0900 +++ b/mc-code-mips.c Sat Jun 05 00:08:09 2004 +0900 @@ -948,12 +948,15 @@ gexpr_init(void) { while(reg_sp > 0) { + error(-1); free_register(reg_stack[--reg_sp]); } while(freg_sp > 0) { + error(-1); free_register(freg_stack[--freg_sp]); } while(lreg_sp > 0) { + error(-1); free_register(lreg_stack[--lreg_sp]); } use_int0();
--- a/mc-code-powerpc.c Fri Jun 04 03:32:19 2004 +0900 +++ b/mc-code-powerpc.c Sat Jun 05 00:08:09 2004 +0900 @@ -915,12 +915,15 @@ gexpr_init(void) { while(reg_sp > 0) { + error(-1); free_register(reg_stack[--reg_sp]); } while(freg_sp > 0) { + error(-1); free_register(freg_stack[--freg_sp]); } while(lreg_sp > 0) { + error(-1); free_register(lreg_stack[--lreg_sp]); } use_int0();
--- a/mc-codegen.c Fri Jun 04 03:32:19 2004 +0900 +++ b/mc-codegen.c Sat Jun 05 00:08:09 2004 +0900 @@ -474,7 +474,7 @@ { int op = car(e1); if (chk) return; - gexpr_init(); + // gexpr_init(); if (dual_ops(op) && (car(caddr(e1))==CONST||(car(caddr(e1))==DCONST))) b_expr(list3(rop_dual(op),caddr(e1),cadr(e1)),cond,l1,0); else @@ -1770,4 +1770,26 @@ return 0; } +#if CASE_CODE + +void +cascade_compare(int cslist,int cslabel,int dlabel) +{ + fwddef(cslabel); + for(;cslist; cslist=cadr(cslist)) { + cmpdimm(car(cslist),csvalue1,caddr(cslist),0); + } + if (dlabel) jmp(dlabel); +} + +void +switch_table(int cslist,int cslabel,int dlabel) +{ + cascade_compare(cslist,cslabel,dlabel); +} + +#endif + + + /* end */
--- a/mc-codegen.h Fri Jun 04 03:32:19 2004 +0900 +++ b/mc-codegen.h Sat Jun 05 00:08:09 2004 +0900 @@ -20,6 +20,9 @@ extern int backdef(void); extern int free_register_count(int); extern int fwdlabel(void); +#if CASE_CODE +extern void switch_table(int cslist,int cslabel,int dlabel); +#endif extern void b_expr(int e1, char cond, int l1,int err); extern void bexpr(int e1, char cond, int l1); extern void emit_init(void);
--- a/mc-parse.c Fri Jun 04 03:32:19 2004 +0900 +++ b/mc-parse.c Sat Jun 05 00:08:09 2004 +0900 @@ -1382,6 +1382,7 @@ } conv->localvar_end_(); control=1; + cslabel = -1; if(!chk) code_enter1(args); emit_init_vars(); while(sym!=RC) statement(); @@ -1498,6 +1499,7 @@ /* local variable declaration */ local_decl(); control=1; + cslabel = -1; if(!chk) enter1(); emit_init_vars(); while(sym!=RC) statement(); @@ -1603,7 +1605,10 @@ static void checkret(void) { - if (retpending) { + if (cslabel==0) { + if (!control) error(-1); // no excute code in switch + jmp(cslabel=fwdlabel()); + } else if (retpending) { ret(); control=0; retpending=0; @@ -1619,7 +1624,6 @@ conv->sm_(); getsym(0); return; } - checkret(); switch(sym) { case IF: doif(); @@ -1640,14 +1644,16 @@ docomp(); return; case BREAK: + checkret(); conv->break_(); - jmp(blabel); + if (control) jmp(blabel); getsym(0); checksym(SM); return; case CONTINUE: + checkret(); conv->continue_(); - jmp(clabel); + if (control) jmp(clabel); getsym(0); checksym(SM); return; @@ -1670,6 +1676,7 @@ dolabel(); statement(); } else { + checkret(); slfree=lfree; gexpr(expr(0),0); lfree=slfree; @@ -1687,6 +1694,7 @@ checksym(LPAR); conv->if_(); slfree=lfree; + checkret(); bexpr(expr(0),0,l1=fwdlabel()); lfree=slfree; conv->if_then_(); @@ -1715,6 +1723,8 @@ sbreak=blabel; scontinue=clabel; blabel=fwdlabel(); + control=1; + checkret(); clabel=backdef(); conv->while_(); getsym(0); @@ -1751,6 +1761,8 @@ scontinue=clabel; blabel=fwdlabel(); clabel=fwdlabel(); + control=1; + checkret(); l=backdef(); conv->dowhile_(); getsym(0); @@ -1784,6 +1796,7 @@ checksym(LPAR); slfree=lfree; if(sym!=SM) { + checkret(); gexpr(expr(0),0); checksym(SM); conv->for1_(); @@ -1792,6 +1805,8 @@ getsym(0); } lfree=slfree; + control=1; + checkret(); l=backdef(); if(sym!=SM) { bexpr(expr(0),0,blabel); @@ -1827,10 +1842,23 @@ } static void +docomp(void) +{ + conv->lc_(); + local_decl(); + emit_init_vars(); + while(sym!=RC) statement(); + conv->rc_(); + getsym(0); +} + +static void doswitch(void) { - int sbreak,scase,sdefault,slfree,svalue; - + int sbreak,scase,sdefault,slfree,svalue,slist; + + checkret(); + slist = cslist; sbreak=blabel; /* save parents break label */ blabel=fwdlabel(); sdefault=dlabel; /* save parents default label */ @@ -1847,37 +1875,66 @@ checksym(RPAR); conv->switch_body_(); cslabel = control = 0; - /* should be case statement but... */ + /* should be case statement but... for example, + main() { + int i=3,j=1,k=0; + switch(i) { + for(;j<10;j++) { + case 3: k++; case 2: k++; case 1: k++; case 0: k++; + } + } + printf("%d\n",k); + } + In this case, we have to jump into the first case label. + Can be done in checkret(); + */ statement(); conv->switch_end_(); checkret(); +#if CASE_CODE + if (control) jmp(blabel); + switch_table(cslist,cslabel,dlabel); +#else if(dlabel) def_label(cslabel,dlabel); else fwddef(cslabel); +#endif csvalue1=svalue; cslabel=scase; dlabel=sdefault; fwddef(blabel); blabel=sbreak; -} - -static void -docomp(void) -{ - conv->lc_(); - local_decl(); - emit_init_vars(); - while(sym!=RC) { statement(); checkret();} - conv->rc_(); - getsym(0); + cslist = slist; } static void docase(void) { +#if CASE_CODE + int l; + l = fwdlabel(); + while(sym==CASE) { + conv->case_begin_(0,0); + getsym(0); + cslist=list3(cexpr(expr(1)),cslist,l); + conv->case_(0,0); + checksym(COLON); + } + if (retpending) { ret(); retpending=0; } + if (!cslabel) { + if (!control) { + // immiediate after switch(i) (ususal case) + cmpdimm(car(cslist),csvalue1,cslabel=fwdlabel(),1); + cslist = cadr(cslist); + } else error(-1); // checkret() sequence inconsistent + } + fwddef(l); + control=1; +#else int c,l,slfree; - + l = 0; + if (retpending) ret(); + slfree=lfree; c=0; - slfree=lfree; while(sym==CASE) { conv->case_begin_(c,0); getsym(0); @@ -1885,28 +1942,29 @@ conv->case_(c,0); checksym(COLON); } - l=fwdlabel(); if (control) { control=0; - jmp(l); + jmp(l=fwdlabel()); } if (cslabel) fwddef(cslabel); while(cadr(c)) { cmpdimm(car(c),csvalue1,l,0); c=cadr(c); } + cmpdimm(car(c),csvalue1,cslabel=fwdlabel(),1); + if (l) fwddef(l); lfree=slfree; - cmpdimm(car(c),csvalue1,cslabel=fwdlabel(),1); - fwddef(l); +#endif } static void dodefault(void) { + control=1; + checkret(); getsym(0); checksym(COLON); - if (dlabel) error(STERR); - if (!cslabel) jmp(cslabel = fwdlabel()); + if (dlabel) error(STERR); // double default: dlabel = backdef(); conv->case_(0,1); } @@ -1916,7 +1974,9 @@ { int slfree,e,e1; + if (!cslabel) jmp(cslabel = fwdlabel()); if(getsym(0)==SM) { + // should check fnptr have no return value conv->return_(); conv->return_end_(); getsym(0); @@ -1966,6 +2026,7 @@ NMTBL *nptr0; int t,e1,e2,env; + checkret(); conv->goto_(); getsym(0); e1 = expr(0); @@ -2017,6 +2078,8 @@ static void dolabel(void) { + control=1; + checkret(); if(nptr->sc == FLABEL) fwddef(nptr->dsp); else if(nptr->sc != EMPTY && nptr->sc != EXTRN1)
--- a/mc.h Fri Jun 04 03:32:19 2004 +0900 +++ b/mc.h Sat Jun 05 00:08:09 2004 +0900 @@ -12,6 +12,7 @@ #define FLOAT_CODE 1 #define LONGLONG_CODE 1 +#define CASE_CODE 1 /* reserved word start */ @@ -411,7 +412,8 @@ EXTERN int sym,ch,type,mode,stmode,gfree,lfree,mflag,lineno,glineno; EXTERN int labelno,gpc,disp,reg_var,debug; EXTERN int symval,args,init_vars,heap[HEAPSIZE]; -EXTERN int blabel,clabel,dlabel,cslabel,ilabel,control,ac,ac2,lsrc,chk,asmf; +EXTERN int blabel,clabel,dlabel,cslist,cslabel,ilabel,control; +EXTERN int ac,ac2,lsrc,chk,asmf; EXTERN int MAX_REGISTER_VAR; EXTERN unsigned hash;