}
/*
- * return side effect-free, assignable n, appending side effects to init.
+ * return side effect-free appending side effects to init.
+ * result is assignable if n is.
*/
Node*
-saferef(Node *n, NodeList **init)
+safeexpr(Node *n, NodeList **init)
{
Node *l;
Node *r;
switch(n->op) {
case ONAME:
+ case OLITERAL:
return n;
+
case ODOT:
- l = saferef(n->left, init);
+ l = safeexpr(n->left, init);
if(l == n->left)
return n;
r = nod(OXXX, N, N);
walkexpr(&r, init);
return r;
- case OINDEX:
case ODOTPTR:
case OIND:
- l = nod(OXXX, N, N);
- tempname(l, ptrto(n->type));
- a = nod(OAS, l, nod(OADDR, n, N));
- typecheck(&a, Etop);
+ l = safeexpr(n->left, init);
+ if(l == n->left)
+ return n;
+ a = nod(OXXX, N, N);
+ *a = *n;
+ a->left = l;
walkexpr(&a, init);
- *init = list(*init, a);
- r = nod(OIND, l, N);
- typecheck(&r, Erv);
- walkexpr(&r, init);
- return r;
- }
- fatal("saferef %N", n);
- return N;
-}
-
-/*
- * return side effect-free n, appending side effects to init.
- */
-Node*
-safeval(Node *n, NodeList **init)
-{
- Node *l;
- Node *a;
+ return a;
- // is this a local variable or a dot of a local variable?
- for(l=n; l->op == ODOT; l=l->left)
- if(l->left->type != T && isptr[l->left->type->etype])
- goto copy;
- if(l->op == ONAME && (l->class == PAUTO || l->class == PPARAM))
- return n;
+ case OINDEX:
+ case OINDEXMAP:
+ l = safeexpr(n->left, init);
+ r = safeexpr(n->right, init);
+ if(l == n->left && r == n->right)
+ return n;
+ a = nod(OXXX, N, N);
+ *a = *n;
+ a->left = l;
+ a->right = r;
+ walkexpr(&a, init);
+ return a;
+ }
-copy:
+ // make a copy; must not be used as an lvalue
+ if(islvalue(n))
+ fatal("missing lvalue case in safeexpr: %N", n);
l = nod(OXXX, N, N);
tempname(l, n->type);
a = nod(OAS, l, n);
walkexpr(&l->n, init);
}
+void
+walkexprlistsafe(NodeList *l, NodeList **init)
+{
+ for(; l; l=l->next) {
+ l->n = safeexpr(l->n, init);
+ walkexpr(&l->n, init);
+ }
+}
+
void
walkexpr(Node **np, NodeList **init)
{
*init = concat(*init, n->ninit);
n->ninit = nil;
walkexpr(&n->left, init);
+ n->left = safeexpr(n->left, init);
if(oaslit(n, init))
goto ret;
walkexpr(&n->right, init);
as2:
*init = concat(*init, n->ninit);
n->ninit = nil;
- walkexprlist(n->list, init);
- walkexprlist(n->rlist, init);
+ walkexprlistsafe(n->list, init);
+ walkexprlistsafe(n->rlist, init);
ll = ascompatee(OAS, n->list, n->rlist, init);
ll = reorder3(ll);
n = liststmt(ll);
*init = concat(*init, n->ninit);
n->ninit = nil;
r = n->rlist->n;
- walkexprlist(n->list, init);
+ walkexprlistsafe(n->list, init);
walkexpr(&r, init);
ll = ascompatet(n->op, n->list, &r->type, 0, init);
n = liststmt(concat(list1(r), ll));
*init = concat(*init, n->ninit);
n->ninit = nil;
r = n->rlist->n;
- walkexprlist(n->list, init);
+ walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
fn = chanfn("chanrecv2", 2, r->left->type);
r = mkcall1(fn, getoutargx(fn->type), init, r->left);
*init = concat(*init, n->ninit);
n->ninit = nil;
r = n->rlist->n;
- walkexprlist(n->list, init);
+ walkexprlistsafe(n->list, init);
walkexpr(&r->left, init);
fn = mapfn("mapaccess2", r->left->type);
r = mkcall1(fn, getoutargx(fn->type), init, r->left, r->right);
// a,b = m[i];
*init = concat(*init, n->ninit);
n->ninit = nil;
- walkexprlist(n->list, init);
+ walkexprlistsafe(n->list, init);
l = n->list->n;
t = l->left->type;
n = mkcall1(mapfn("mapassign2", t), T, init, l->left, l->right, n->rlist->n, n->rlist->next->n);
*init = concat(*init, n->ninit);
n->ninit = nil;
r = n->rlist->n;
- walkexprlist(n->list, init);
+ walkexprlistsafe(n->list, init);
walkdottype(r, init);
et = ifaceas1(r->type, r->left->type, 1);
switch(et) {
goto ret;
case OASOP:
+ n->left = safeexpr(n->left, init);
walkexpr(&n->left, init);
l = n->left;
if(l->op == OINDEXMAP)
*/
et = n->left->type->etype;
if(widthptr == 4 && (et == TUINT64 || et == TINT64)) {
- l = saferef(n->left, init);
+ l = safeexpr(n->left, init);
r = nod(OAS, l, nod(n->etype, l, n->right));
typecheck(&r, Etop);
walkexpr(&r, init);
* a expression list. called in
* expr-list = expr-list
*/
+
+ // ensure order of evaluation for function calls
+ for(ll=nl; ll; ll=ll->next)
+ ll->n = safeexpr(ll->n, init);
+ for(lr=nr; lr; lr=lr->next)
+ lr->n = safeexpr(lr->n, init);
+
nn = nil;
for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next)
nn = list(nn, ascompatee1(op, ll->n, lr->n, init));
// into tmpi := index; map[tmpi] = map[tmpi] op right
// make it ok to double-evaluate map[tmpi]
- n->left->left = safeval(n->left->left, init);
- n->left->right = safeval(n->left->right, init);
+ 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]