]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.r57] gc: work around goto bug
authorRuss Cox <rsc@golang.org>
Thu, 16 Jun 2011 05:04:43 +0000 (01:04 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 16 Jun 2011 05:04:43 +0000 (01:04 -0400)
««« CL 4629042 / ec3b60d1fe6e
gc: work around goto bug

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

R=adg
CC=golang-dev
https://golang.org/cl/4631041

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 83a9949d6c87ba57e4e5eee2887a9969becb79ba..57cb56a649a93f7a57d47dcd20e3de0fa2b1ce16 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 c3dac1fdcdc606afa6bfff458601ca8b63b52293..f224dfd9f21cfab579134305eb51fe40bd251ed4 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 8ed7e55645751eeceda6cb74f10e6635caf60052..de1d323f83c8f0fd79af8cb799b51c378fa47a8a 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 99af18d9f11d5c2b336a523a74989b43efa06aa7..8e790ef08ab3f8f26856a7397ef329367599527c 100644 (file)
@@ -1233,9 +1233,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 8ad6c437de99122540a1902450e89ce92ff56edb..857fcbef9df717da20197b371ef1158766bf1999 100644 (file)
@@ -205,6 +205,7 @@ gen(Node *n)
                break;
 
        case OGOTO:
+               hasgoto = 1;
                newlab(OGOTO, n, N);
                gjmp(P);
                break;
index f58b7678916468fac848b4d0c6b97d895884d091..4b4e8fcd1307e881dfa945fa2d82726e20c010c0 100644 (file)
@@ -1246,3 +1246,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)
+       }
+}