aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Gerrand <adg@golang.org>2011-06-29 15:32:06 +1000
committerAndrew Gerrand <adg@golang.org>2011-06-29 15:32:06 +1000
commit3b32b3eb3d38706aec35aa4bb66088f3a4e3899c (patch)
tree3a687b13cfbaebbb24a1db1f7977ad81ecedbc07
parentf70c7b2b6306fa674c495865e4f772dfde15cc29 (diff)
downloadgo-3b32b3eb3d38706aec35aa4bb66088f3a4e3899c.tar.gz
go-3b32b3eb3d38706aec35aa4bb66088f3a4e3899c.zip
[release-branch.r58] gc: work around goto bug
««« 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
-rw-r--r--src/cmd/5g/gsubr.c58
-rw-r--r--src/cmd/6g/gsubr.c35
-rw-r--r--src/cmd/8g/gsubr.c35
-rw-r--r--src/cmd/gc/dcl.c5
-rw-r--r--src/cmd/gc/gen.c1
-rw-r--r--src/cmd/gc/go.h3
-rw-r--r--test/fixedbugs/bug344.go22
7 files changed, 159 insertions, 0 deletions
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index bc39912ea3..caaa3e246f 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -125,6 +125,64 @@ newplist(void)
}
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)
{
gins(ANOP, n, N); // used
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index ae6ae57651..66dac11859 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -121,6 +121,41 @@ newplist(void)
}
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)
{
gins(ANOP, n, N); // used
diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c
index 6bcc3eed84..d0c7310251 100644
--- a/src/cmd/8g/gsubr.c
+++ b/src/cmd/8g/gsubr.c
@@ -123,6 +123,41 @@ newplist(void)
}
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)
{
gins(ANOP, n, N); // used
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 83be82f92f..335d056a06 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -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;
}
+
+
diff --git a/src/cmd/gc/gen.c b/src/cmd/gc/gen.c
index feb55e9051..ad7b65b306 100644
--- a/src/cmd/gc/gen.c
+++ b/src/cmd/gc/gen.c
@@ -209,6 +209,7 @@ gen(Node *n)
break;
case OGOTO:
+ hasgoto = 1;
newlab(OGOTO, n, N);
gjmp(P);
break;
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 86db48391f..c16903e776 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -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
index 0000000000..2a20dcf6ff
--- /dev/null
+++ b/test/fixedbugs/bug344.go
@@ -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)
+ }
+}