1
0
mirror of https://github.com/golang/go synced 2024-11-21 14:24:44 -07:00

gc: various map-related bug fixes

Fixes #687.

R=ken2
CC=golang-dev
https://golang.org/cl/680042
This commit is contained in:
Russ Cox 2010-03-22 18:51:14 -07:00
parent 51a7f1c9d6
commit 4408659e81
4 changed files with 51 additions and 58 deletions

View File

@ -348,7 +348,6 @@ enum
OADD, OSUB, OOR, OXOR, OADDSTR,
OADDR,
OANDAND,
OAPPENDSTR,
OARRAY,
OARRAYBYTESTR, OARRAYRUNESTR,
OSTRARRAYBYTE, OSTRARRAYRUNE,
@ -1066,7 +1065,6 @@ Node* ascompatee1(int, Node*, Node*, NodeList**);
NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**);
NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**);
NodeList* ascompatte(int, Type**, NodeList*, int, NodeList**);
Node* mapop(Node*, NodeList**);
Type* fixchan(Type*);
Node* ifacecvt(Type*, Node*, int, NodeList**);
int ifaceas(Type*, Type*, int);

View File

@ -80,8 +80,10 @@ typecheck(Node **np, int top)
}
}
if(n->typecheck == 2)
fatal("typecheck loop");
if(n->typecheck == 2) {
yyerror("typechecking loop");
return n;
}
n->typecheck = 2;
redo:
@ -355,9 +357,7 @@ reswitch:
if(iscmp[n->op]) {
n->etype = n->op;
n->op = OCMPSTR;
} else if(n->op == OASOP)
n->op = OAPPENDSTR;
else if(n->op == OADD)
} else if(n->op == OADD)
n->op = OADDSTR;
}
if(et == TINTER) {

View File

@ -354,7 +354,6 @@ walkstmt(Node **np)
dump("nottop", n);
break;
case OAPPENDSTR:
case OASOP:
case OAS:
case OAS2:
@ -522,8 +521,8 @@ walkexprlistsafe(NodeList *l, NodeList **init)
void
walkexpr(Node **np, NodeList **init)
{
Node *r, *l;
NodeList *ll, *lr;
Node *r, *l, *var, *a;
NodeList *ll, *lr, *lpost;
Type *t;
int et;
int32 lno;
@ -707,8 +706,35 @@ walkexpr(Node **np, NodeList **init)
r = n->rlist->n;
walkexprlistsafe(n->list, init);
walkexpr(&r, init);
l = n->list->n;
// all the really hard stuff - explicit function calls and so on -
// is gone, but map assignments remain.
// if there are map assignments here, assign via
// temporaries, because ascompatet assumes
// the targets can be addressed without function calls
// and map index has an implicit one.
lpost = nil;
if(l->op == OINDEXMAP) {
var = nod(OXXX, N, N);
tempname(var, l->type);
n->list->n = var;
a = nod(OAS, l, var);
typecheck(&a, Etop);
lpost = list(lpost, a);
}
l = n->list->next->n;
if(l->op == OINDEXMAP) {
var = nod(OXXX, N, N);
tempname(var, l->type);
n->list->next->n = var;
a = nod(OAS, l, var);
typecheck(&a, Etop);
lpost = list(lpost, a);
}
ll = ascompatet(n->op, n->list, &r->type, 0, init);
n = liststmt(concat(list1(r), ll));
walkexprlist(lpost, init);
n = liststmt(concat(concat(list1(r), ll), lpost));
goto ret;
case OAS2RECV:
@ -815,26 +841,35 @@ walkexpr(Node **np, NodeList **init)
n->left = safeexpr(n->left, init);
walkexpr(&n->left, init);
l = n->left;
if(l->op == OINDEXMAP)
n = mapop(n, init);
walkexpr(&n->right, init);
if(n->etype == OANDNOT) {
n->etype = OAND;
n->right = nod(OCOM, n->right, N);
typecheck(&n->right, Erv);
goto ret;
}
/*
* on 32-bit arch, rewrite 64-bit ops into l = l op r.
* on 386, rewrite float ops into l = l op r.
* everywhere, rewrite map ops into l = l op r.
* everywhere, rewrite string += into l = l op r.
* TODO(rsc): Maybe this rewrite should be done always?
*/
et = n->left->type->etype;
if((widthptr == 4 && (et == TUINT64 || et == TINT64)) ||
(thechar == '8' && isfloat[et])) {
(thechar == '8' && isfloat[et]) ||
l->op == OINDEXMAP ||
et == TSTRING) {
l = safeexpr(n->left, init);
r = nod(OAS, l, nod(n->etype, l, n->right));
a = l;
if(a->op == OINDEXMAP) {
// map index has "lhs" bit set in a->etype.
// make a copy so we can clear it on the rhs.
a = nod(OXXX, N, N);
*a = *l;
a->etype = 0;
}
r = nod(OAS, l, nod(n->etype, a, n->right));
typecheck(&r, Etop);
walkexpr(&r, init);
n = r;
@ -1016,17 +1051,6 @@ walkexpr(Node **np, NodeList **init)
conv(n->right, types[TSTRING]));
goto ret;
case OAPPENDSTR:
// s1 = sys_catstring(s1, s2)
if(n->etype != OADD)
fatal("walkasopstring: not add");
r = mkcall("catstring", n->left->type, init,
conv(n->left, types[TSTRING]),
conv(n->right, types[TSTRING]));
r = nod(OAS, n->left, r);
n = r;
goto ret;
case OSLICESTR:
// sys_slicestring(s, lb, hb)
if(n->right->right) {
@ -1366,7 +1390,7 @@ ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
yyerror("assignment count mismatch: %d = %d",
count(nl), structcount(*nr));
if(ucount)
yyerror("reorder2: too many function calls evaluating parameters");
fatal("reorder2: too many function calls evaluating parameters");
return concat(nn, mm);
}
@ -1862,35 +1886,6 @@ bad:
return T;
}
Node*
mapop(Node *n, NodeList **init)
{
Node *r, *a;
r = n;
switch(n->op) {
default:
fatal("mapop: unknown op %O", n->op);
case OASOP:
// rewrite map[index] op= right
// into tmpi := index; map[tmpi] = map[tmpi] op right
// make it ok to double-evaluate map[tmpi]
n->left->left = safeexpr(n->left->left, init);
n->left->right = safeexpr(n->left->right, init);
a = nod(OXXX, N, N);
*a = *n->left; // copy of map[tmpi]
a->etype = 0;
a = nod(n->etype, a, n->right); // m[tmpi] op right
r = nod(OAS, n->left, a); // map[tmpi] = map[tmpi] op right
typecheck(&r, Etop);
walkexpr(&r, init);
break;
}
return r;
}
/*
* assigning src to dst involving interfaces?
* return op to use.

View File

@ -159,7 +159,7 @@ do break
broke
=========== fixedbugs/bug081.go
fixedbugs/bug081.go:9: fatal error: typecheck loop
fixedbugs/bug081.go:9: typechecking loop
=========== fixedbugs/bug093.go
M