summaryrefslogtreecommitdiff
path: root/src/cmd/gc/walk.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/walk.c')
-rw-r--r--src/cmd/gc/walk.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 49c1ef4bc..3952ad2e6 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -1301,7 +1301,7 @@ Node*
reorder1(Node *n)
{
Iter save;
- Node *l, *r, *f;
+ Node *l, *r, *f, *a, *g;
int c, t;
/*
@@ -1321,10 +1321,6 @@ loop1:
if(l == N) {
if(c == 0 || t == 1)
return n;
- if(c > 1) {
- yyerror("reorder1: too many function calls evaluating parameters");
- return n;
- }
goto pass2;
}
if(l->op == OLIST)
@@ -1338,23 +1334,50 @@ loop1:
pass2:
l = listfirst(&save, &n);
- r = N; // rest
- f = N; // fncall
+ g = N; // fncalls assigned to tempnames
+ f = N; // one fncall assigned to stack
+ r = N; // non fncalls and tempnames assigned to stack
loop2:
if(l == N) {
- r = nod(OLIST, f, r);
r = rev(r);
+ g = rev(g);
+ if(g != N)
+ f = nod(OLIST, g, f);
+ r = nod(OLIST, f, r);
return r;
}
- if(l->ullman >= UINF)
+ if(l->ullman < UINF) {
+ if(r == N)
+ r = l;
+ else
+ r = nod(OLIST, l, r);
+ goto more;
+ }
+ if(f == N) {
f = l;
+ goto more;
+ }
+
+ // make assignment of fncall to tempname
+ a = nod(OXXX, N, N);
+ tempname(a, l->right->type);
+ a = nod(OAS, a, l->right);
+
+ if(g == N)
+ g = a;
else
+ g = nod(OLIST, a, g);
+
+ // put normal arg assignment on list
+ // with fncall replaced by tempname
+ l->right = a->left;
if(r == N)
r = l;
else
r = nod(OLIST, l, r);
+more:
l = listnext(&save);
goto loop2;
}