mirror of
https://github.com/golang/go
synced 2024-11-21 11:24:39 -07:00
gc: work around goto bug
R=ken2 CC=golang-dev https://golang.org/cl/4629042
This commit is contained in:
parent
f011bd378f
commit
5d9dbe19a7
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -209,6 +209,7 @@ gen(Node *n)
|
||||
break;
|
||||
|
||||
case OGOTO:
|
||||
hasgoto = 1;
|
||||
newlab(OGOTO, n, N);
|
||||
gjmp(P);
|
||||
break;
|
||||
|
@ -1257,3 +1257,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);
|
||||
|
22
test/fixedbugs/bug344.go
Normal file
22
test/fixedbugs/bug344.go
Normal file
@ -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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user