Commit 4408659e authored by Russ Cox's avatar Russ Cox

gc: various map-related bug fixes

Fixes #687.

R=ken2
CC=golang-dev
https://golang.org/cl/680042
parent 51a7f1c9
...@@ -348,7 +348,6 @@ enum ...@@ -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**); ...@@ -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) ...@@ -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: ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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: ...@@ -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 ...@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment