mirror of
https://github.com/golang/go
synced 2024-11-13 14:40:21 -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:
parent
51a7f1c9d6
commit
4408659e81
@ -348,7 +348,6 @@ enum
|
|||||||
OADD, OSUB, OOR, OXOR, OADDSTR,
|
OADD, OSUB, OOR, OXOR, OADDSTR,
|
||||||
OADDR,
|
OADDR,
|
||||||
OANDAND,
|
OANDAND,
|
||||||
OAPPENDSTR,
|
|
||||||
OARRAY,
|
OARRAY,
|
||||||
OARRAYBYTESTR, OARRAYRUNESTR,
|
OARRAYBYTESTR, OARRAYRUNESTR,
|
||||||
OSTRARRAYBYTE, OSTRARRAYRUNE,
|
OSTRARRAYBYTE, OSTRARRAYRUNE,
|
||||||
@ -1066,7 +1065,6 @@ Node* ascompatee1(int, Node*, Node*, NodeList**);
|
|||||||
NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**);
|
NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**);
|
||||||
NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**);
|
NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**);
|
||||||
NodeList* ascompatte(int, Type**, NodeList*, int, NodeList**);
|
NodeList* ascompatte(int, Type**, NodeList*, int, NodeList**);
|
||||||
Node* mapop(Node*, NodeList**);
|
|
||||||
Type* fixchan(Type*);
|
Type* fixchan(Type*);
|
||||||
Node* ifacecvt(Type*, Node*, int, NodeList**);
|
Node* ifacecvt(Type*, Node*, int, NodeList**);
|
||||||
int ifaceas(Type*, Type*, int);
|
int ifaceas(Type*, Type*, int);
|
||||||
|
@ -80,8 +80,10 @@ typecheck(Node **np, int top)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n->typecheck == 2)
|
if(n->typecheck == 2) {
|
||||||
fatal("typecheck loop");
|
yyerror("typechecking loop");
|
||||||
|
return n;
|
||||||
|
}
|
||||||
n->typecheck = 2;
|
n->typecheck = 2;
|
||||||
|
|
||||||
redo:
|
redo:
|
||||||
@ -355,9 +357,7 @@ reswitch:
|
|||||||
if(iscmp[n->op]) {
|
if(iscmp[n->op]) {
|
||||||
n->etype = n->op;
|
n->etype = n->op;
|
||||||
n->op = OCMPSTR;
|
n->op = OCMPSTR;
|
||||||
} else if(n->op == OASOP)
|
} else if(n->op == OADD)
|
||||||
n->op = OAPPENDSTR;
|
|
||||||
else if(n->op == OADD)
|
|
||||||
n->op = OADDSTR;
|
n->op = OADDSTR;
|
||||||
}
|
}
|
||||||
if(et == TINTER) {
|
if(et == TINTER) {
|
||||||
|
@ -354,7 +354,6 @@ walkstmt(Node **np)
|
|||||||
dump("nottop", n);
|
dump("nottop", n);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OAPPENDSTR:
|
|
||||||
case OASOP:
|
case OASOP:
|
||||||
case OAS:
|
case OAS:
|
||||||
case OAS2:
|
case OAS2:
|
||||||
@ -522,8 +521,8 @@ walkexprlistsafe(NodeList *l, NodeList **init)
|
|||||||
void
|
void
|
||||||
walkexpr(Node **np, NodeList **init)
|
walkexpr(Node **np, NodeList **init)
|
||||||
{
|
{
|
||||||
Node *r, *l;
|
Node *r, *l, *var, *a;
|
||||||
NodeList *ll, *lr;
|
NodeList *ll, *lr, *lpost;
|
||||||
Type *t;
|
Type *t;
|
||||||
int et;
|
int et;
|
||||||
int32 lno;
|
int32 lno;
|
||||||
@ -707,8 +706,35 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
r = n->rlist->n;
|
r = n->rlist->n;
|
||||||
walkexprlistsafe(n->list, init);
|
walkexprlistsafe(n->list, init);
|
||||||
walkexpr(&r, 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);
|
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;
|
goto ret;
|
||||||
|
|
||||||
case OAS2RECV:
|
case OAS2RECV:
|
||||||
@ -815,26 +841,35 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
n->left = safeexpr(n->left, init);
|
n->left = safeexpr(n->left, init);
|
||||||
walkexpr(&n->left, init);
|
walkexpr(&n->left, init);
|
||||||
l = n->left;
|
l = n->left;
|
||||||
if(l->op == OINDEXMAP)
|
|
||||||
n = mapop(n, init);
|
|
||||||
walkexpr(&n->right, init);
|
walkexpr(&n->right, init);
|
||||||
if(n->etype == OANDNOT) {
|
if(n->etype == OANDNOT) {
|
||||||
n->etype = OAND;
|
n->etype = OAND;
|
||||||
n->right = nod(OCOM, n->right, N);
|
n->right = nod(OCOM, n->right, N);
|
||||||
typecheck(&n->right, Erv);
|
typecheck(&n->right, Erv);
|
||||||
goto ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* on 32-bit arch, rewrite 64-bit ops into l = l op r.
|
* on 32-bit arch, rewrite 64-bit ops into l = l op r.
|
||||||
* on 386, rewrite float 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?
|
* TODO(rsc): Maybe this rewrite should be done always?
|
||||||
*/
|
*/
|
||||||
et = n->left->type->etype;
|
et = n->left->type->etype;
|
||||||
if((widthptr == 4 && (et == TUINT64 || et == TINT64)) ||
|
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);
|
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);
|
typecheck(&r, Etop);
|
||||||
walkexpr(&r, init);
|
walkexpr(&r, init);
|
||||||
n = r;
|
n = r;
|
||||||
@ -1016,17 +1051,6 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
conv(n->right, types[TSTRING]));
|
conv(n->right, types[TSTRING]));
|
||||||
goto ret;
|
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:
|
case OSLICESTR:
|
||||||
// sys_slicestring(s, lb, hb)
|
// sys_slicestring(s, lb, hb)
|
||||||
if(n->right->right) {
|
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",
|
yyerror("assignment count mismatch: %d = %d",
|
||||||
count(nl), structcount(*nr));
|
count(nl), structcount(*nr));
|
||||||
if(ucount)
|
if(ucount)
|
||||||
yyerror("reorder2: too many function calls evaluating parameters");
|
fatal("reorder2: too many function calls evaluating parameters");
|
||||||
return concat(nn, mm);
|
return concat(nn, mm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1862,35 +1886,6 @@ bad:
|
|||||||
return T;
|
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?
|
* assigning src to dst involving interfaces?
|
||||||
* return op to use.
|
* return op to use.
|
||||||
|
@ -159,7 +159,7 @@ do break
|
|||||||
broke
|
broke
|
||||||
|
|
||||||
=========== fixedbugs/bug081.go
|
=========== fixedbugs/bug081.go
|
||||||
fixedbugs/bug081.go:9: fatal error: typecheck loop
|
fixedbugs/bug081.go:9: typechecking loop
|
||||||
|
|
||||||
=========== fixedbugs/bug093.go
|
=========== fixedbugs/bug093.go
|
||||||
M
|
M
|
||||||
|
Loading…
Reference in New Issue
Block a user