diff options
author | Ken Thompson <ken@golang.org> | 2009-03-11 16:25:45 -0700 |
---|---|---|
committer | Ken Thompson <ken@golang.org> | 2009-03-11 16:25:45 -0700 |
commit | 196758e3ba136c195940a13a034014a8ea666348 (patch) | |
tree | cc15a056328a55e040e1b2dc34a43228ae5e2d47 | |
parent | 532bb647046fe186d60ba3f891baab101e5a7e10 (diff) | |
download | golang-196758e3ba136c195940a13a034014a8ea666348.tar.gz |
bug 137
R=r
OCL=26142
CL=26142
-rw-r--r-- | src/cmd/6g/gen.c | 150 | ||||
-rw-r--r-- | src/cmd/6g/gg.h | 4 | ||||
-rw-r--r-- | test/fixedbugs/bug137.go (renamed from test/bugs/bug137.go) | 0 | ||||
-rw-r--r-- | test/golden.out | 5 |
4 files changed, 81 insertions, 78 deletions
diff --git a/src/cmd/6g/gen.c b/src/cmd/6g/gen.c index 9bc6126ab..46c542aaf 100644 --- a/src/cmd/6g/gen.c +++ b/src/cmd/6g/gen.c @@ -82,8 +82,8 @@ compile(Node *fn) // inarggen(); ginit(); - gen(curfn->enter, L); - gen(curfn->nbody, L); + gen(curfn->enter); + gen(curfn->nbody); gclean(); checklabels(); @@ -143,16 +143,29 @@ allocparams(void) } } +void +newlab(int op, Sym *s) +{ + Label *lab; + + lab = mal(sizeof(*lab)); + lab->link = labellist; + labellist = lab; + + lab->sym = s; + lab->op = op; + lab->label = pc; +} + /* * compile statements */ void -gen(Node *n, Label *labloop) +gen(Node *n) { int32 lno; Prog *scontin, *sbreak; Prog *p1, *p2, *p3; - Node *l; Label *lab; lno = setlineno(n); @@ -160,8 +173,10 @@ gen(Node *n, Label *labloop) loop: if(n == N) goto ret; + + p3 = pc; // save pc for loop labels if(n->ninit) - gen(n->ninit, L); + gen(n->ninit); setlineno(n); @@ -171,24 +186,8 @@ loop: break; case OLIST: - l = n->left; - gen(l, L); - if(l != N && l->op == OLABEL) { - // call the next statement with a label - l = n->right; - if(l != N) { - if(l->op != OLIST) { - gen(l, labellist); - break; - } - gen(l->left, labellist); - n = l->right; - labloop = L; - goto loop; - } - } + gen(n->left); n = n->right; - labloop = L; goto loop; case OPANIC: @@ -203,37 +202,26 @@ loop: break; case OLABEL: - lab = mal(sizeof(*lab)); - lab->link = labellist; - labellist = lab; - lab->sym = n->left->sym; - - lab->op = OLABEL; - lab->label = pc; + newlab(OLABEL, n->left->sym); break; case OGOTO: - lab = mal(sizeof(*lab)); - lab->link = labellist; - labellist = lab; - lab->sym = n->left->sym; - - lab->op = OGOTO; - lab->label = pc; + newlab(OGOTO, n->left->sym); gbranch(AJMP, T); break; case OBREAK: if(n->left != N) { - lab = findlab(n->left->sym); - if(lab == L || lab->breakpc == P) { - yyerror("break label is not defined: %S", n->left->sym); - break; + for(lab=labellist; lab!=L; lab=lab->link) { + if(lab->breakpc != P) { + patch(gbranch(AJMP, T), lab->breakpc); + break; + } } - patch(gbranch(AJMP, T), lab->breakpc); + if(lab == L) + yyerror("break label not defined: %S", n->left->sym); break; } - if(breakpc == P) { yyerror("break is not in a loop"); break; @@ -243,12 +231,14 @@ loop: case OCONTINUE: if(n->left != N) { - lab = findlab(n->left->sym); - if(lab == L || lab->continpc == P) { - yyerror("continue label is not defined: %S", n->left->sym); - break; + for(lab=labellist; lab!=L; lab=lab->link) { + if(lab->continpc != P) { + patch(gbranch(AJMP, T), lab->continpc); + break; + } } - patch(gbranch(AJMP, T), lab->continpc); + if(lab == L) + yyerror("break label not defined: %S", n->left->sym); break; } @@ -265,18 +255,24 @@ loop: breakpc = gbranch(AJMP, T); // break: goto done scontin = continpc; continpc = pc; - gen(n->nincr, L); // contin: incr + + // define break and cotinue labels + for(lab=labellist; lab!=L; lab=lab->link) { + if(lab->label != p3) + break; + if(lab->op == OLABEL) { + lab->breakpc = breakpc; + lab->continpc = continpc; + } + } + + gen(n->nincr); // contin: incr patch(p1, pc); // test: if(n->ntest != N) if(n->ntest->ninit != N) - gen(n->ntest->ninit, L); + gen(n->ntest->ninit); bgen(n->ntest, 0, breakpc); // if(!test) goto break - if(labloop != L) { - labloop->op = OFOR; - labloop->continpc = continpc; - labloop->breakpc = breakpc; - } - gen(n->nbody, L); // body + gen(n->nbody); // body patch(gbranch(AJMP, T), continpc); // goto contin patch(breakpc, pc); // done: continpc = scontin; @@ -289,12 +285,12 @@ loop: patch(p1, pc); // test: if(n->ntest != N) if(n->ntest->ninit != N) - gen(n->ntest->ninit, L); + gen(n->ntest->ninit); bgen(n->ntest, 0, p2); // if(!test) goto p2 - gen(n->nbody, L); // then + gen(n->nbody); // then p3 = gbranch(AJMP, T); // goto done patch(p2, pc); // else: - gen(n->nelse, L); // else + gen(n->nelse); // else patch(p3, pc); // done: break; @@ -302,12 +298,18 @@ loop: sbreak = breakpc; p1 = gbranch(AJMP, T); // goto test breakpc = gbranch(AJMP, T); // break: goto done - patch(p1, pc); // test: - if(labloop != L) { - labloop->op = OFOR; - labloop->breakpc = breakpc; + + // define break label + for(lab=labellist; lab!=L; lab=lab->link) { + if(lab->label != p3) + break; + if(lab->op == OLABEL) { + lab->breakpc = breakpc; + } } - gen(n->nbody, L); // switch(test) body + + patch(p1, pc); // test: + gen(n->nbody); // switch(test) body patch(breakpc, pc); // done: breakpc = sbreak; break; @@ -316,12 +318,18 @@ loop: sbreak = breakpc; p1 = gbranch(AJMP, T); // goto test breakpc = gbranch(AJMP, T); // break: goto done - patch(p1, pc); // test: - if(labloop != L) { - labloop->op = OFOR; - labloop->breakpc = breakpc; + + // define break label + for(lab=labellist; lab!=L; lab=lab->link) { + if(lab->label != p3) + break; + if(lab->op == OLABEL) { + lab->breakpc = breakpc; + } } - gen(n->nbody, L); // select() body + + patch(p1, pc); // test: + gen(n->nbody); // select() body patch(breakpc, pc); // done: breakpc = sbreak; break; @@ -484,7 +492,7 @@ cgen_callinter(Node *n, Node *res, int proc) i = &tmpi; } - gen(n->right, L); // args + gen(n->right); // args regalloc(&nodr, types[tptr], res); regalloc(&nodo, types[tptr], &nodr); @@ -561,7 +569,7 @@ cgen_call(Node *n, int proc) cgen(n->left, &afun); } - gen(n->right, L); // assign the args + gen(n->right); // assign the args t = n->left->type; setmaxarg(t); @@ -694,7 +702,7 @@ cgen_aret(Node *n, Node *res) void cgen_ret(Node *n) { - gen(n->left, L); // copy out args + gen(n->left); // copy out args if(hasdefer) ginscall(deferreturn, 0); gins(ARET, N, N); diff --git a/src/cmd/6g/gg.h b/src/cmd/6g/gg.h index 741527c43..ae165ca83 100644 --- a/src/cmd/6g/gg.h +++ b/src/cmd/6g/gg.h @@ -74,7 +74,7 @@ struct Pool typedef struct Label Label; struct Label { - uchar op; // OFOR/OGOTO/OLABEL + uchar op; // OGOTO/OLABEL Sym* sym; Prog* label; // pointer to code Prog* breakpc; // pointer to code @@ -133,7 +133,7 @@ EXTERN int sizeof_Array; // runtime sizeof(Array) */ void compile(Node*); void proglist(void); -void gen(Node*, Label*); +void gen(Node*); Node* lookdot(Node*, Node*, int); void inarggen(void); void cgen_as(Node*, Node*); diff --git a/test/bugs/bug137.go b/test/fixedbugs/bug137.go index 152792411..152792411 100644 --- a/test/bugs/bug137.go +++ b/test/fixedbugs/bug137.go diff --git a/test/golden.out b/test/golden.out index 181da5229..64f7e2586 100644 --- a/test/golden.out +++ b/test/golden.out @@ -140,11 +140,6 @@ BUG: compilation succeeds incorrectly =========== bugs/bug136.go BUG: should not compile -=========== bugs/bug137.go -bugs/bug137.go:9: break label is not defined: L2 -bugs/bug137.go:15: break label is not defined: L4 -BUG should compile - =========== bugs/bug138.go bugs/bug138.go:8: overflow converting constant to uint bugs/bug138.go:8: illegal combination of literals CONV 7 |