]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.r58] gc: work around goto bug
authorAndrew Gerrand <adg@golang.org>
Wed, 29 Jun 2011 05:32:06 +0000 (15:32 +1000)
committerAndrew Gerrand <adg@golang.org>
Wed, 29 Jun 2011 05:32:06 +0000 (15:32 +1000)
««« CL 4629042 / ec3b60d1fe6e
gc: work around goto bug

R=ken2
CC=golang-dev
https://golang.org/cl/4629042
»»»

R=rsc
CC=golang-dev
https://golang.org/cl/4662063

src/cmd/5g/gsubr.c
src/cmd/6g/gsubr.c
src/cmd/8g/gsubr.c
src/cmd/gc/dcl.c
src/cmd/gc/gen.c
src/cmd/gc/go.h
test/fixedbugs/bug344.go [new file with mode: 0644]

index bc39912ea3e192e7b0fab8e570ec3ba8e8c1a3a5..caaa3e246f1ecb006eedb43864a6c722130b36ad 100644 (file)
@@ -124,6 +124,64 @@ newplist(void)
        return pl;
 }
 
+void
+clearstk(void)
+{
+       Plist *pl;
+       Prog *p, *p1, *p2, *p3;
+       Node dst, end, zero, con;
+
+       if(plast->firstpc->to.offset <= 0)
+               return;
+
+       // reestablish context for inserting code
+       // at beginning of function.
+       pl = plast;
+       p1 = pl->firstpc;
+       p2 = p1->link;
+       pc = mal(sizeof(*pc));
+       clearp(pc);
+       p1->link = pc;
+       
+       // zero stack frame
+
+       // MOVW $4(SP), R1
+       nodreg(&dst, types[tptr], 1);
+       p = gins(AMOVW, N, &dst);
+       p->from.type = D_CONST;
+       p->from.reg = REGSP;
+       p->from.offset = 4;
+
+       // MOVW $n(R1), R2
+       nodreg(&end, types[tptr], 2);
+       p = gins(AMOVW, N, &end);
+       p->from.type = D_CONST;
+       p->from.reg = 1;
+       p->from.offset = p1->to.offset;
+       
+       // MOVW $0, R3
+       nodreg(&zero, types[TUINT32], 3);
+       nodconst(&con, types[TUINT32], 0);
+       gmove(&con, &zero);
+
+       // L:
+       //      MOVW.P R3, 0(R1) +4
+       //      CMP R1, R2
+       //      BNE L
+       p = gins(AMOVW, &zero, &dst);
+       p->to.type = D_OREG;
+       p->to.offset = 4;
+       p->scond |= C_PBIT;
+       p3 = p;
+       p = gins(ACMP, &dst, N);
+       raddr(&end, p);
+       patch(gbranch(ABNE, T), p3);
+
+       // continue with original code.
+       gins(ANOP, N, N)->link = p2;
+       pc = P;
+}      
+
 void
 gused(Node *n)
 {
index ae6ae57651a26b74fbc676547bc1d521c2905e63..66dac11859b5acd0841877a1e389846e774304d7 100644 (file)
@@ -120,6 +120,41 @@ newplist(void)
        return pl;
 }
 
+void
+clearstk(void)
+{
+       Plist *pl;
+       Prog *p1, *p2;
+       Node sp, di, cx, con;
+
+       if((uint32)plast->firstpc->to.offset <= 0)
+               return;
+
+       // reestablish context for inserting code
+       // at beginning of function.
+       pl = plast;
+       p1 = pl->firstpc;
+       p2 = p1->link;
+       pc = mal(sizeof(*pc));
+       clearp(pc);
+       p1->link = pc;
+       
+       // zero stack frame
+       nodreg(&sp, types[tptr], D_SP);
+       nodreg(&di, types[tptr], D_DI);
+       nodreg(&cx, types[TUINT64], D_CX);
+       nodconst(&con, types[TUINT64], (uint32)p1->to.offset / widthptr);
+       gins(ACLD, N, N);
+       gins(AMOVQ, &sp, &di);
+       gins(AMOVQ, &con, &cx);
+       gins(AREP, N, N);
+       gins(ASTOSQ, N, N);
+
+       // continue with original code.
+       gins(ANOP, N, N)->link = p2;
+       pc = P;
+}      
+
 void
 gused(Node *n)
 {
index 6bcc3eed840aa3fb82886f1fb80cebc2c5b2eae4..d0c7310251b88908efb2eaf3fa9657e3522978b3 100644 (file)
@@ -122,6 +122,41 @@ newplist(void)
        return pl;
 }
 
+void
+clearstk(void)
+{
+       Plist *pl;
+       Prog *p1, *p2;
+       Node sp, di, cx, con;
+
+       if(plast->firstpc->to.offset <= 0)
+               return;
+
+       // reestablish context for inserting code
+       // at beginning of function.
+       pl = plast;
+       p1 = pl->firstpc;
+       p2 = p1->link;
+       pc = mal(sizeof(*pc));
+       clearp(pc);
+       p1->link = pc;
+       
+       // zero stack frame
+       nodreg(&sp, types[tptr], D_SP);
+       nodreg(&di, types[tptr], D_DI);
+       nodreg(&cx, types[TUINT32], D_CX);
+       nodconst(&con, types[TUINT32], p1->to.offset / widthptr);
+       gins(ACLD, N, N);
+       gins(AMOVL, &sp, &di);
+       gins(AMOVL, &con, &cx);
+       gins(AREP, N, N);
+       gins(ASTOSL, N, N);
+
+       // continue with original code.
+       gins(ANOP, N, N)->link = p2;
+       pc = P;
+}      
+
 void
 gused(Node *n)
 {
index 83be82f92fe5e47697582b399eb3df46b6528930..335d056a06c43b77b6265a3c805fa1d2a910b471 100644 (file)
@@ -1241,9 +1241,14 @@ funccompile(Node *n, int isclosure)
        stksize = 0;
        dclcontext = PAUTO;
        funcdepth = n->funcdepth + 1;
+       hasgoto = 0;
        compile(n);
+       if(hasgoto)
+               clearstk();
        curfn = nil;
        funcdepth = 0;
        dclcontext = PEXTERN;
 }
 
+
+
index feb55e90513cbad0e1cac999c313afd2f43ef11b..ad7b65b306dee9725ae3ff0aece900312a1e5768 100644 (file)
@@ -209,6 +209,7 @@ gen(Node *n)
                break;
 
        case OGOTO:
+               hasgoto = 1;
                newlab(OGOTO, n, N);
                gjmp(P);
                break;
index 86db48391faca3f8c9023a7e0c7e5a86b1b3d40c..c16903e77667a8fc24a6252d93df1173752594f4 100644 (file)
@@ -1255,3 +1255,6 @@ void      zhist(Biobuf *b, int line, vlong offset);
 void   zname(Biobuf *b, Sym *s, int t);
 void   data(void);
 void   text(void);
+
+EXTERN int     hasgoto;
+void   clearstk(void);
diff --git a/test/fixedbugs/bug344.go b/test/fixedbugs/bug344.go
new file mode 100644 (file)
index 0000000..2a20dcf
--- /dev/null
@@ -0,0 +1,22 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug344
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "fmt"
+
+func main() {
+       // invalid use of goto.
+       // do whatever you like, just don't crash.
+       i := 42
+       a := []*int{&i, &i, &i, &i}
+       x := a[0]
+       goto start
+       for _, x = range a {
+       start:
+               fmt.Sprint(*x)
+       }
+}