diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index f889cf606e..64a4735ae1 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -17,8 +17,12 @@ dflag(void) return 1; } +/* + * declare (possible list) n of type t. + * append ODCL nodes to *init + */ void -dodclvar(Node *n, Type *t) +dodclvar(Node *n, Type *t, Node **init) { if(n == N) return; @@ -26,7 +30,7 @@ dodclvar(Node *n, Type *t) if(t != T && (t->etype == TIDEAL || t->etype == TNIL)) fatal("dodclvar %T", t); for(; n->op == OLIST; n = n->right) - dodclvar(n->left, t); + dodclvar(n->left, t, init); dowidth(t); @@ -39,7 +43,7 @@ dodclvar(Node *n, Type *t) addvar(n, t, dclcontext); autoexport(n->sym); if(funcdepth > 0) - addtop = list(addtop, nod(ODCL, n, N)); + *init = list(*init, nod(ODCL, n, N)); } void @@ -1665,13 +1669,14 @@ embedded(Sym *s) /* * declare variables from grammar - * new_name_list [type] = expr_list + * new_name_list (type | [type] = expr_list) */ Node* variter(Node *vv, Type *t, Node *ee) { Iter viter, eiter; Node *v, *e, *r, *a; + Type *tv; vv = rev(vv); ee = rev(ee); @@ -1680,29 +1685,31 @@ variter(Node *vv, Type *t, Node *ee) e = listfirst(&eiter, &ee); r = N; -loop: - if(v == N && e == N) - return rev(r); + while(v != N) { + if(ee != N && e == N) { + yyerror("missing expr in var dcl"); + break; + } - if(v == N || e == N) { - yyerror("shape error in var dcl"); - return rev(r); + a = N; + if(e != N || funcdepth > 0) + a = nod(OAS, v, e); + tv = t; + if(t == T) { + gettype(e, &r); + defaultlit(e, T); + tv = e->type; + } + dodclvar(v, tv, &r); + r = list(r, a); + + v = listnext(&viter); + if(ee != N) + e = listnext(&eiter); } - - a = nod(OAS, v, N); - if(t == T) { - gettype(e, a); - defaultlit(e, T); - dodclvar(v, e->type); - } else - dodclvar(v, t); - a->right = e; - - r = list(r, a); - - v = listnext(&viter); - e = listnext(&eiter); - goto loop; + if(e != N) + yyerror("extra expr in var dcl"); + return rev(r); } /* @@ -1713,7 +1720,7 @@ void constiter(Node *vv, Type *t, Node *cc) { Iter viter, citer; - Node *v, *c, n1; + Node *v, *c, *init; if(cc == N) { if(t != T) @@ -1741,9 +1748,9 @@ loop: return; } - memset(&n1, 0, sizeof n1); - gettype(c, &n1); - if(n1.ninit != nil) { + init = N; + gettype(c, &init); + if(init != N) { // the expression had extra code to run. // dodclconst is going to print an error // because the expression isn't constant, @@ -1771,7 +1778,7 @@ loop: Node* unsafenmagic(Node *l, Node *r) { - Node *n; + Node *n, *init; Sym *s; Type *t, *tr; long v; @@ -1787,8 +1794,9 @@ unsafenmagic(Node *l, Node *r) if(strcmp(s->package, "unsafe") != 0) goto no; + init = N; if(strcmp(s->name, "Sizeof") == 0) { - walktype(r, Erv); + walkexpr(r, Erv, &init); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; @@ -1800,12 +1808,12 @@ unsafenmagic(Node *l, Node *r) if(strcmp(s->name, "Offsetof") == 0) { if(r->op != ODOT && r->op != ODOTPTR) goto no; - walktype(r, Erv); + walkexpr(r, Erv, &init); v = r->xoffset; goto yes; } if(strcmp(s->name, "Alignof") == 0) { - walktype(r, Erv); + walkexpr(r, Erv, &init); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; @@ -1830,7 +1838,7 @@ no: return N; yes: - addtop = N; // any side effects disappear + // any side effects disappear; ignore init val.ctype = CTINT; val.u.xval = mal(sizeof(*n->val.u.xval)); mpmovecfix(val.u.xval, v); diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 1bcfd420c6..011d6dc957 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -601,7 +601,6 @@ EXTERN int widthptr; EXTERN Node* retnil; EXTERN Node* fskel; -EXTERN Node* addtop; EXTERN Node* typeswvar; EXTERN char* structpkg; @@ -765,7 +764,7 @@ void tempname(Node*, Type*); Node* staticname(Type*); int iscomposite(Type*); Node* callnew(Type*); -Node* saferef(Node*); +Node* saferef(Node*, Node**); int is64(Type*); int noconv(Type*, Type*); @@ -812,7 +811,7 @@ int simsimtype(Type*); /* * dcl.c */ -void dodclvar(Node*, Type*); +void dodclvar(Node*, Type*, Node**); Type* dodcltype(Type*); void updatetype(Type*, Type*); void dodclconst(Node*, Node*); @@ -907,30 +906,29 @@ Type* pkgtype(Sym*); /* * walk.c */ -void addtotop(Node*); -void gettype(Node*, Node*); +void gettype(Node*, Node**); void walk(Node*); -void walkstate(Node*); -void walktype(Node*, int); -void walkconv(Node*); +void walkstmt(Node*); +void walkexpr(Node*, int, Node**); +void walkconv(Node*, Node**); void walkas(Node*); void walkbool(Node*); void walkswitch(Node*); void walkselect(Node*); -void walkdot(Node*); -Node* ascompatee(int, Node**, Node**); -Node* ascompatet(int, Node**, Type**, int); -Node* ascompatte(int, Type**, Node**, int); +void walkdot(Node*, Node**); +Node* ascompatee(int, Node**, Node**, Node**); +Node* ascompatet(int, Node**, Type**, int, Node**); +Node* ascompatte(int, Type**, Node**, int, Node**); int ascompat(Type*, Type*); Node* prcompat(Node*, int); Node* nodpanic(int32); Node* newcompat(Node*); Node* makecompat(Node*); -Node* stringop(Node*, int); +Node* stringop(Node*, int, Node**); Type* fixmap(Type*); -Node* mapop(Node*, int); +Node* mapop(Node*, int, Node**); Type* fixchan(Type*); -Node* chanop(Node*, int); +Node* chanop(Node*, int, Node**); Node* arrayop(Node*, int); Node* ifacecvt(Type*, Node*, int); Node* ifaceop(Node*); @@ -938,18 +936,18 @@ int ifaceas(Type*, Type*, int); int ifaceas1(Type*, Type*, int); void ifacecheck(Type*, Type*, int, int); void runifacechecks(void); -Node* convas(Node*); +Node* convas(Node*, Node**); void arrayconv(Type*, Node*); -Node* colas(Node*, Node*); +Node* colas(Node*, Node*, Node**); Node* dorange(Node*); Node* reorder1(Node*); Node* reorder3(Node*); Node* reorder4(Node*); -Node* structlit(Node*, Node*); -Node* arraylit(Node*, Node*); -Node* maplit(Node*, Node*); -Node* selectas(Node*, Node*); -Node* old2new(Node*, Type*); +Node* structlit(Node*, Node*, Node**); +Node* arraylit(Node*, Node*, Node**); +Node* maplit(Node*, Node*, Node**); +Node* selectas(Node*, Node*, Node**); +Node* old2new(Node*, Type*, Node**); void addrescapes(Node*); void heapmoves(void); diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 046db1d914..263b6bf07f 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -351,30 +351,15 @@ varoptsemi: vardcl: name_list type varoptsemi { - dodclvar($$, $2); - - if(funcdepth == 0) { - $$ = N; - } else { - $$ = nod(OAS, $$, N); - addtotop($$); - } + $$ = variter($1, $2, N); } | name_list type varoptsemi '=' expr_list { - if(addtop != N) - fatal("new_name_list_r type '=' expr_list"); - $$ = variter($1, $2, $5); - addtotop($$); } | name_list '=' expr_list { - if(addtop != N) - fatal("new_name_list_r '=' expr_list"); - $$ = variter($1, T, $3); - addtotop($$); } constdcl: @@ -438,16 +423,17 @@ simple_stmt: } | expr_list LCOLAS expr_list { - if(addtop != N) - fatal("expr_list LCOLAS expr_list"); + Node *top; + if($3->op == OTYPESW) { $$ = nod(OTYPESW, $1, $3->left); break; } - $$ = colas($$, $3); + top = N; + $$ = colas($$, $3, &top); $$ = nod(OAS, $$, $3); $$->colas = 1; - addtotop($$); + $$->ninit = top; } | expr LINC { @@ -463,9 +449,12 @@ simple_stmt: case: LCASE expr_list ':' { + Node *top; + // will be converted to OCASE // right will point to next case // done in casebody() + top = N; poptodcl(); if(typeswvar != N && typeswvar->right != N) { int e; @@ -476,14 +465,14 @@ case: break; } if($2->op == OTYPE) { - $$ = old2new(typeswvar->right, $2->type); + $$ = old2new(typeswvar->right, $2->type, &top); $$ = nod(OTYPESW, $$, N); $$ = nod(OXCASE, $$, N); - addtotop($$); + $$->ninit = top; break; } e = nerrors; - gettype($2, N); + gettype($2, nil); // maybe gettype found problems that keep // e from being valid even outside a type switch. // only complain if gettype didn't print new errors. @@ -497,15 +486,18 @@ case: } | LCASE type ':' { + Node *top; + + top = N; poptodcl(); if(typeswvar == N || typeswvar->right == N) { yyerror("type case not in a type switch"); $$ = N; } else - $$ = old2new(typeswvar->right, $2); + $$ = old2new(typeswvar->right, $2, &top); $$ = nod(OTYPESW, $$, N); $$ = nod(OXCASE, $$, N); - addtotop($$); + $$->ninit = top; } | LCASE name '=' expr ':' { @@ -518,13 +510,16 @@ case: } | LCASE name LCOLAS expr ':' { + Node *top; + // will be converted to OCASE // right will point to next case // done in casebody() poptodcl(); - $$ = nod(OAS, selectas($2,$4), $4); + top = N; + $$ = nod(OAS, selectas($2, $4, &top), $4); $$ = nod(OXCASE, $$, N); - addtotop($$); + $$->ninit = top; } | LDEFAULT ':' { @@ -621,7 +616,6 @@ for_header: | range_stmt { $$ = dorange($1); - addtotop($$); } for_body: diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c index 021b030146..fa7aabdabd 100644 --- a/src/cmd/gc/sinit.c +++ b/src/cmd/gc/sinit.c @@ -249,7 +249,7 @@ mapindex(Node *n) b = nod(OAS, b, val); a = nod(OLIST, a, b); - walktype(a, Etop); + walkexpr(a, Etop, nil); return a; } diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 9c5d2c1264..06790c8568 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -517,11 +517,13 @@ appendr(Node *na, Node *nb) Type* aindex(Node *b, Type *t) { + Node *top; Type *r; int bound; bound = -1; // open bound - walktype(b, Erv); + top = N; + walkexpr(b, Erv, &top); if(b != nil) { switch(consttype(b)) { default: @@ -2452,25 +2454,26 @@ staticname(Type *t) } /* - * return side effect-free n, moving side effects to top. + * return side effect-free n, appending side effects to init. */ Node* -saferef(Node *n) +saferef(Node *n, Node **init) { Node *l; Node *r; + Node *a; switch(n->op) { case ONAME: return n; case ODOT: - l = saferef(n->left); + l = saferef(n->left, init); if(l == n->left) return n; r = nod(OXXX, N, N); *r = *n; r->left = l; - walktype(r, Elv); + walkexpr(r, Elv, init); return r; case OINDEX: @@ -2478,9 +2481,11 @@ saferef(Node *n) case OIND: l = nod(OXXX, N, N); tempname(l, ptrto(n->type)); - addtop = list(addtop, nod(OAS, l, nod(OADDR, n, N))); + a = nod(OAS, l, nod(OADDR, n, N)); + walkexpr(a, Etop, init); + *init = list(*init, a); r = nod(OIND, l, N); - walktype(r, Elv); + walkexpr(r, Elv, init); return r; } fatal("saferef %N", n); @@ -2634,11 +2639,13 @@ out: Node* adddot(Node *n) { + Node *top; Type *t; Sym *s; int c, d; - walktype(n->left, Erv); + top = N; + walkexpr(n->left, Erv, &top); t = n->left->type; if(t == T) goto ret; @@ -2666,8 +2673,8 @@ out: n->left->right = newname(dotlist[c].field->sym); } ret: - n->ninit = list(addtop, n->ninit); - addtop = N; + if(top != N) + n->ninit = list(top, n->ninit); return n; } diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c index 4347eeac95..282e5d157b 100644 --- a/src/cmd/gc/swt.c +++ b/src/cmd/gc/swt.c @@ -247,7 +247,7 @@ sw0(Node *c, Type *place, int arg) yyerror("inappropriate case for a type switch"); return T; } - walktype(c, Erv); + walkexpr(c, Erv, nil); break; case OTYPESW: if(arg != Stype) @@ -298,7 +298,7 @@ sw3(Node *c, Type *place, int arg) } /* - * over all cases, call paramenter function. + * over all cases, call parameter function. * four passes of these are used to allocate * types to cases and switch */ @@ -335,7 +335,7 @@ loop: } Node* -newlabel() +newlabel(void) { static int label; @@ -598,7 +598,7 @@ exprswitch(Node *sw) if(sw->ntest->val.u.bval == 0) arg = Sfalse; } - walktype(sw->ntest, Erv); + walkexpr(sw->ntest, Erv, &sw->ninit); /* * pass 0,1,2,3 @@ -639,7 +639,7 @@ loop: if(c0 == C) { cas = list(cas, def); sw->nbody->left = rev(cas); - walkstate(sw->nbody); + walkstmt(sw->nbody); return; } @@ -773,7 +773,7 @@ typeswitch(Node *sw) yyerror("type switch must have an assignment"); return; } - walktype(sw->ntest->right, Erv); + walkexpr(sw->ntest->right, Erv, &sw->ninit); if(!istype(sw->ntest->right->type, TINTER)) { yyerror("type switch must be on an interface"); return; @@ -818,7 +818,7 @@ loop: if(c0 == C) { cas = list(cas, def); sw->nbody->left = rev(cas); - walkstate(sw->nbody); + walkstmt(sw->nbody); return; } @@ -860,7 +860,7 @@ walkswitch(Node *sw) * cases have OGOTO into statements. * both have inserted OBREAK statements */ - walkstate(sw->ninit); + walkstmt(sw->ninit); if(sw->ntest == N) sw->ntest = nodbool(1); casebody(sw); diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 65313bcbce..21f19773ba 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -72,11 +72,7 @@ walk(Node *fn) if(curfn->type->outtuple) if(walkret(curfn->nbody)) yyerror("function ends without a return statement"); - if(addtop != N) { - dump("addtop", addtop); - fatal("addtop in walk"); - } - walkstate(curfn->nbody); + walkstmt(curfn->nbody); if(debug['W']) { snprint(s, sizeof(s), "after walk %S", curfn->nname->sym); dump(s, curfn->nbody); @@ -89,55 +85,37 @@ walk(Node *fn) } void -addtotop(Node *n) -{ - Node *l; - - while(addtop != N) { - l = addtop; - addtop = N; - walktype(l, Etop); - n->ninit = list(n->ninit, l); - } -} - -void -gettype(Node *n, Node *a) +gettype(Node *n, Node **init) { if(debug['W']) dump("\nbefore gettype", n); - walktype(n, Erv); - if(a == N && addtop != N) - fatal("gettype: addtop"); - addtotop(a); + walkexpr(n, Erv, init); if(debug['W']) dump("after gettype", n); } void -walkstate(Node *n) +walkstmt(Node *n) { - Node *more; + Node *init, *l; + int lno; -loop: + while(n != N && n->op == OLIST) { + walkstmt(n->left); + n = n->right; + } if(n == N) return; - more = N; + lno = lineno; setlineno(n); switch(n->op) { - - case OLIST: - walkstate(n->left); - more = n->right; - break; - default: if(n->op == ONAME) - yyerror("walkstate: %S not a top level statement", n->sym); + yyerror("walkstmt: %S not a top level statement", n->sym); else - yyerror("walkstate: %O not a top level statement", n->op); + yyerror("walkstmt: %O not a top level statement", n->op); break; case OASOP: @@ -147,38 +125,79 @@ loop: case OCALLMETH: case OCALLINTER: case OCALL: - case ODCL: case OSEND: case ORECV: case OPRINT: case OPRINTN: case OPANIC: case OPANICN: - case OFOR: - case OIF: - case OSWITCH: - case OSELECT: case OEMPTY: + init = N; + walkexpr(n, Etop, &init); + n->ninit = list(n->ninit, init); + break; + case OBREAK: + case ODCL: case OCONTINUE: + case OFALL: case OGOTO: case OLABEL: - case OFALL: - case OXCASE: - case OCASE: - case OXFALL: - case ORETURN: - case OPROC: - case ODEFER: - walktype(n, Etop); break; - } - addtotop(n); + case OXCASE: + yyerror("case statement out of place"); + n->op = OCASE; + case OCASE: + walkstmt(n->right); + break; - if(more != N) { - n = more; - goto loop; + case ODEFER: + hasdefer = 1; + walkexpr(n->left, Etop, &n->ninit); + break; + + case OFOR: + walkstmt(n->ninit); + walkbool(n->ntest); + walkstmt(n->nincr); + walkstmt(n->nbody); + break; + + case OIF: + walkstmt(n->ninit); + walkbool(n->ntest); + walkstmt(n->nbody); + walkstmt(n->nelse); + break; + + case OPROC: + walkexpr(n->left, Etop, &n->ninit); + break; + + case ORETURN: + walkexpr(n->left, Erv, &n->ninit); + if(curfn->type->outnamed && n->left == N) { + // print("special return\n"); + break; + } + l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1, &n->ninit); + if(l != N) + n->left = reorder4(l); + break; + + case OSELECT: + walkselect(n); + break; + + case OSWITCH: + walkswitch(n); + break; + + case OXFALL: + yyerror("fallthrough statement out of place"); + n->op = OFALL; + break; } } @@ -206,12 +225,19 @@ implicitstar(Node **nn) if(!isfixedarray(t)) return; n = nod(OIND, n, N); - walktype(n, Elv); + walkexpr(n, Elv, nil); *nn = n; } +/* + * walk the whole tree of the body of an + * expression or simple statement. + * the types expressions are calculated. + * compile-time constants are evaluated. + * complex side effects like statements are appended to init + */ void -walktype(Node *n, int top) +walkexpr(Node *n, int top, Node **init) { Node *r, *l; Type *t; @@ -223,12 +249,6 @@ walktype(Node *n, int top) return; lno = setlineno(n); - /* - * walk the whole tree of the body of a function. - * the types expressions are calculated. - * compile-time constants are evaluated. - */ - loop: if(n == N) goto ret; @@ -244,7 +264,7 @@ loop: switch(n->op) { default: dump("walk", n); - fatal("walktype: switch 1 unknown op %N", n); + fatal("walkexpr: switch 1 unknown op %N", n); goto ret; case OTYPE: @@ -254,40 +274,37 @@ loop: } goto ret; - case ODCL: - goto ret; - case OLIST: case OKEY: - walktype(n->left, top); + walkexpr(n->left, top, init); n = n->right; goto loop; case OPRINT: if(top != Etop) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); indir(n, prcompat(n->left, 0)); goto ret; case OPRINTN: if(top != Etop) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); indir(n, prcompat(n->left, 1)); goto ret; case OPANIC: if(top != Etop) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); indir(n, list(prcompat(n->left, 0), nodpanic(n->lineno))); goto ret; case OPANICN: if(top != Etop) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); indir(n, list(prcompat(n->left, 2), nodpanic(n->lineno))); goto ret; @@ -317,53 +334,14 @@ loop: s = n->sym; if(s->undef == 0) { if(n->etype != 0) - yyerror("walktype: %S must be called", s); + yyerror("walkexpr: %S must be called", s, init); else - yyerror("walktype: %S undeclared", s); + yyerror("walkexpr: %S undeclared", s, init); s->undef = 1; } } goto ret; - case OFOR: - if(top != Etop) - goto nottop; - walkstate(n->ninit); - walkbool(n->ntest); - walkstate(n->nincr); - walkstate(n->nbody); - goto ret; - - case OSWITCH: - if(top != Etop) - goto nottop; - - walkswitch(n); - goto ret; - - case OSELECT: - if(top != Etop) - goto nottop; - walkselect(n); - goto ret; - - case OIF: - if(top != Etop) - goto nottop; - walkstate(n->ninit); - walkbool(n->ntest); - walkstate(n->nbody); - walkstate(n->nelse); - goto ret; - - case ODEFER: - hasdefer = 1; - case OPROC: - if(top != Etop) - goto nottop; - walktype(n->left, Etop); - goto ret; - case OCALLMETH: case OCALLINTER: case OCALL: @@ -376,7 +354,7 @@ loop: if(n->left == N) goto ret; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); defaultlit(n->left, T); t = n->left->type; @@ -409,32 +387,32 @@ loop: break; } - walktype(n->right, Erv); + walkexpr(n->right, Erv, init); switch(n->op) { default: fatal("walk: op: %O", n->op); case OCALLINTER: - l = ascompatte(n->op, getinarg(t), &n->right, 0); + l = ascompatte(n->op, getinarg(t), &n->right, 0, init); n->right = reorder1(l); break; case OCALL: - l = ascompatte(n->op, getinarg(t), &n->right, 0); + l = ascompatte(n->op, getinarg(t), &n->right, 0, init); n->right = reorder1(l); if(isselect(n)) { // clear output bool - special prob with selectsend Node *b; b = nodbool(0); - r = ascompatte(n->op, getoutarg(t), &b, 0); + r = ascompatte(n->op, getoutarg(t), &b, 0, init); n->right = list(n->right, r); } break; case OCALLMETH: - l = ascompatte(n->op, getinarg(t), &n->right, 0); - r = ascompatte(n->op, getthis(t), &n->left->left, 0); + l = ascompatte(n->op, getinarg(t), &n->right, 0, init); + r = ascompatte(n->op, getthis(t), &n->left->left, 0, init); l = list(r, l); n->left->left = N; ullmancalc(n->left); @@ -447,12 +425,12 @@ loop: if(top != Etop) goto nottop; - addtop = list(addtop, n->ninit); + *init = list(*init, n->ninit); n->ninit = N; l = n->left; r = n->right; - walktype(l, Elv); + walkexpr(l, Elv, init); if(l == N || r == N) goto ret; @@ -461,8 +439,8 @@ loop: if(cl == cr) { simpleas: - walktype(r, Erv); - l = ascompatee(n->op, &n->left, &n->right); + walkexpr(r, Erv, init); + l = ascompatee(n->op, &n->left, &n->right, init); if(l != N) indir(n, reorder3(l)); goto ret; @@ -475,10 +453,10 @@ loop: case OCALL: if(cr == 1) { // a,b,... = fn() - walktype(r, Erv); + walkexpr(r, Erv, init); if(r->type == T || r->type->etype != TSTRUCT) break; - l = ascompatet(n->op, &n->left, &r->type, 0); + l = ascompatet(n->op, &n->left, &r->type, 0, init); if(l != N) indir(n, list(r, l)); goto ret; @@ -488,11 +466,11 @@ loop: case OINDEX: if(cl == 2 && cr == 1) { // a,b = map[] - mapaccess2 - walktype(r->left, Erv); + walkexpr(r->left, Erv, init); implicitstar(&r->left); if(!istype(r->left->type, TMAP)) break; - l = mapop(n, top); + l = mapop(n, top, init); if(l == N) break; indir(n, l); @@ -503,10 +481,10 @@ loop: case ORECV: if(cl == 2 && cr == 1) { // a,b = left, Erv); + walkexpr(r->left, Erv, init); if(!istype(r->left->type, TCHAN)) break; - l = chanop(n, top); + l = chanop(n, top, init); if(l == N) break; indir(n, l); @@ -517,7 +495,7 @@ loop: case ODOTTYPE: if(cl == 2 && cr == 1) { // a,b = i.(T) - walktype(r->left, Erv); + walkexpr(r->left, Erv, init); if(r->left == N) break; et = ifaceas1(r->type, r->left->type, 1); @@ -548,7 +526,7 @@ loop: if(et == Inone) break; r = ifacecvt(r->type, r->left, et); - l = ascompatet(n->op, &n->left, &r->type, 0); + l = ascompatet(n->op, &n->left, &r->type, 0, init); if(l != N) indir(n, list(r, l)); goto ret; @@ -562,7 +540,7 @@ loop: // map[] = a,b - mapassign2 if(!istype(l->left->type, TMAP)) break; - l = mapop(n, top); + l = mapop(n, top, init); if(l == N) break; indir(n, l); @@ -576,33 +554,6 @@ loop: } goto ret; - case OBREAK: - case OCONTINUE: - case OGOTO: - case OLABEL: - if(top != Etop) - goto nottop; - goto ret; - - case OXCASE: - if(top != Etop) - goto nottop; - yyerror("case statement out of place"); - n->op = OCASE; - - case OCASE: - if(top != Etop) - goto nottop; - walkstate(n->right); - goto ret; - - case OXFALL: - if(top != Etop) - goto nottop; - yyerror("fallthrough statement out of place"); - n->op = OFALL; - - case OFALL: case OINDREG: case OEMPTY: goto ret; @@ -611,7 +562,7 @@ loop: case ODOTTYPE: if(top != Erv) goto nottop; - walkconv(n); + walkconv(n, init); goto ret; case OCONVNOP: @@ -635,32 +586,18 @@ loop: goto ret; case TSTRUCT: - r = structlit(n, N); + r = structlit(n, N, init); break; case TARRAY: - r = arraylit(n, N); + r = arraylit(n, N, init); break; case TMAP: - r = maplit(n, N); + r = maplit(n, N, init); break; } indir(n, r); -// walktype(l, Erv); - goto ret; - - case ORETURN: - if(top != Etop) - goto nottop; - walktype(n->left, Erv); - if(curfn->type->outnamed && n->left == N) { - // print("special return\n"); - goto ret; - } - l = ascompatte(n->op, getoutarg(curfn->type), &n->left, 1); - if(l != N) - n->left = reorder4(l); goto ret; case ONOT: @@ -669,7 +606,7 @@ loop: evconst(n); if(n->op == OLITERAL) goto ret; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); if(n->left == N || n->left->type == T) goto ret; et = n->left->type->etype; @@ -678,10 +615,10 @@ loop: case OASOP: if(top != Etop) goto nottop; - walktype(n->left, Elv); + walkexpr(n->left, Elv, init); l = n->left; if(l->op == OINDEX && istype(l->left->type, TMAP)) - indir(n, mapop(n, top)); + indir(n, mapop(n, top, init)); if(n->etype == OLSH || n->etype == ORSH) goto shft; goto com; @@ -690,10 +627,10 @@ loop: case ORSH: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); shft: - walktype(n->right, Erv); + walkexpr(n->right, Erv, init); if(n->left == N || n->right == N) goto ret; evconst(n); @@ -728,10 +665,10 @@ loop: case ODIV: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); com: - walktype(n->right, Erv); + walkexpr(n->right, Erv, init); if(n->left == N || n->right == N) goto ret; evconst(n); @@ -757,6 +694,11 @@ loop: n->right->type = n->right->left->type; break; } + if(istype(n->left->type, TSTRING)) { + indir(n, stringop(n, top, init)); + goto ret; + } + break; case OEQ: case ONE: @@ -766,7 +708,7 @@ loop: case OGT: case OADD: if(istype(n->left->type, TSTRING)) { - indir(n, stringop(n, top)); + indir(n, stringop(n, top, nil)); goto ret; } break; @@ -778,7 +720,7 @@ loop: case OCOM: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); if(n->left == N) goto ret; evconst(n); @@ -789,7 +731,7 @@ loop: case OLEN: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); if(n->left == N) { yyerror("missing argument to len"); goto ret; @@ -819,7 +761,7 @@ loop: case OCAP: if(top != Erv) goto nottop; - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); defaultlit(n->left, T); implicitstar(&n->left); t = n->left->type; @@ -840,8 +782,8 @@ loop: if(top == Etop) goto nottop; - walktype(n->left, Erv); - walktype(n->right, Erv); + walkexpr(n->left, Erv, init); + walkexpr(n->right, Erv, init); if(n->left == N || n->right == N) goto ret; @@ -867,7 +809,7 @@ loop: break; if(!isint[n->right->type->etype]) goto badt; - indir(n, stringop(n, top)); + indir(n, stringop(n, top, nil)); break; case TMAP: @@ -879,7 +821,7 @@ loop: goto badt; n->type = t->type; if(top == Erv) - indir(n, mapop(n, top)); + indir(n, mapop(n, top, nil)); break; case TARRAY: @@ -897,44 +839,44 @@ loop: case OCLOSE: if(top != Etop) goto nottop; - walktype(n->left, Erv); // chan - indir(n, chanop(n, top)); + walkexpr(n->left, Erv, init); // chan + indir(n, chanop(n, top, nil)); goto ret; case OCLOSED: if(top == Elv) goto nottop; - walktype(n->left, Erv); // chan - indir(n, chanop(n, top)); + walkexpr(n->left, Erv, init); // chan + indir(n, chanop(n, top, nil)); goto ret; case OSEND: if(top == Elv) goto nottop; - walktype(n->left, Erv); // chan - walktype(n->right, Erv); // e - indir(n, chanop(n, top)); + walkexpr(n->left, Erv, init); // chan + walkexpr(n->right, Erv, init); // e + indir(n, chanop(n, top, nil)); goto ret; case ORECV: if(top == Elv) goto nottop; if(n->right == N) { - walktype(n->left, Erv); // chan - indir(n, chanop(n, top)); // returns e blocking + walkexpr(n->left, Erv, init); // chan + indir(n, chanop(n, top, init)); // returns e blocking goto ret; } - walktype(n->left, Elv); // e - walktype(n->right, Erv); // chan - indir(n, chanop(n, top)); // returns bool non-blocking + walkexpr(n->left, Elv, init); // e + walkexpr(n->right, Erv, init); // chan + indir(n, chanop(n, top, nil)); // returns bool non-blocking goto ret; case OSLICE: if(top == Etop) goto nottop; - walktype(n->left, top); - walktype(n->right, Erv); + walkexpr(n->left, top, init); + walkexpr(n->right, Erv, init); if(n->left == N || n->right == N) goto ret; defaultlit(n->left, T); @@ -945,7 +887,7 @@ loop: if(t == T) goto ret; if(t->etype == TSTRING) { - indir(n, stringop(n, top)); + indir(n, stringop(n, top, nil)); goto ret; } if(t->etype == TARRAY) { @@ -962,7 +904,7 @@ loop: if(top == Etop) goto nottop; defaultlit(n->left, T); - walkdot(n); + walkdot(n, init); goto ret; case OADDR: @@ -982,27 +924,27 @@ loop: tempname(nvar, ptrto(n->left->type)); nas = nod(OAS, nvar, callnew(n->left->type)); - walktype(nas, Etop); - addtop = list(addtop, nas); + walkexpr(nas, Etop, init); + *init = list(*init, nas); nstar = nod(OIND, nvar, N); nstar->type = n->left->type; switch(n->left->type->etype) { case TSTRUCT: - structlit(n->left, nstar); + structlit(n->left, nstar, init); break; case TARRAY: - arraylit(n->left, nstar); + arraylit(n->left, nstar, init); break; case TMAP: - maplit(n->left, nstar); + maplit(n->left, nstar, init); break; default: goto badlit; } -// walktype(n->left->left, Erv); +// walkexpr(n->left->left, Erv, init); indir(n, nvar); goto ret; } @@ -1016,7 +958,7 @@ loop: } if(n->left == N) goto ret; - walktype(n->left, Elv); + walkexpr(n->left, Elv, init); t = n->left->type; if(t == T) goto ret; @@ -1029,7 +971,7 @@ loop: goto nottop; if(top == Elv) // even if n is lvalue, n->left is rvalue top = Erv; - walktype(n->left, top); + walkexpr(n->left, top, init); defaultlit(n->left, T); if(n->left == N) goto ret; @@ -1075,7 +1017,7 @@ loop: switch(n->op) { default: - fatal("walktype: switch 2 unknown op %N", n); + fatal("walkexpr: switch 2 unknown op %N", n, init); goto ret; case OASOP: @@ -1140,7 +1082,7 @@ loop: // TODO(rsc): Can do this more efficiently, // but OSUB is wrong. Should be in back end anyway. indir(n, nod(OMUL, n->left, nodintconst(-1))); - walktype(n, Erv); + walkexpr(n, Erv, init); goto ret; } break; @@ -1187,7 +1129,7 @@ loop: r = nod(OCALL, l, list(n->left, n->right)); r = nod(OCONV, r, N); r->type = n->left->left->type; - walktype(r, Erv); + walkexpr(r, Erv, init); indir(n, r); goto ret; @@ -1195,9 +1137,9 @@ loop: et = n->left->type->etype; if(widthptr > 4 || (et != TUINT64 && et != TINT64)) break; - l = saferef(n->left); + l = saferef(n->left, init); r = nod(OAS, l, nod(n->etype, l, n->right)); - walktype(r, Etop); + walkexpr(r, Etop, init); indir(n, r); goto ret; } @@ -1253,16 +1195,16 @@ ret: void walkbool(Node *n) { - walktype(n, Erv); + if(n == N) + return; + walkexpr(n, Erv, &n->ninit); defaultlit(n, T); - addtotop(n); - if(n != N && n->type != T) - if(!eqtype(n->type, types[TBOOL])) - yyerror("IF and FOR require a boolean type"); + if(n->type != T && !eqtype(n->type, types[TBOOL])) + yyerror("IF and FOR require a boolean type"); } void -walkconv(Node *n) +walkconv(Node *n, Node **init) { int et; char *what; @@ -1275,7 +1217,7 @@ walkconv(Node *n) l = n->left; if(l == N) return; - walktype(l, Erv); + walkexpr(l, Erv, init); if(l->type == T) return; @@ -1334,7 +1276,7 @@ walkconv(Node *n) if(istype(t, TSTRING)) { et = l->type->etype; if(isint[et]) { - indir(n, stringop(n, Erv)); + indir(n, stringop(n, Erv, nil)); return; } @@ -1342,7 +1284,7 @@ walkconv(Node *n) if((isptr[et] && isfixedarray(l->type->type) && istype(l->type->type->type, TUINT8)) || (isslice(l->type) && istype(l->type->type, TUINT8))) { n->op = OARRAY; - indir(n, stringop(n, Erv)); + indir(n, stringop(n, Erv, nil)); return; } @@ -1350,7 +1292,7 @@ walkconv(Node *n) if((isptr[et] && isfixedarray(l->type->type) && istype(l->type->type->type, TINT)) || (isslice(l->type) && istype(l->type->type, TINT))) { n->op = OARRAY; - indir(n, stringop(n, Erv)); + indir(n, stringop(n, Erv, nil)); return; } } @@ -1399,7 +1341,7 @@ bad: } Node* -selcase(Node *n, Node *var) +selcase(Node *n, Node *var, Node **init) { Node *a, *r, *on, *c; Type *t; @@ -1410,8 +1352,8 @@ selcase(Node *n, Node *var) if(c->op == ORECV) goto recv; - walktype(c->left, Erv); // chan - walktype(c->right, Erv); // elem + walkexpr(c->left, Erv, init); // chan + walkexpr(c->right, Erv, init); // elem t = fixchan(c->left->type); if(t == T) @@ -1446,7 +1388,7 @@ recv: if(c->right != N) goto recv2; - walktype(c->left, Erv); // chan + walkexpr(c->left, Erv, init); // chan t = fixchan(c->left->type); if(t == T) @@ -1475,7 +1417,7 @@ recv: goto out; recv2: - walktype(c->right, Erv); // chan + walkexpr(c->right, Erv, init); // chan t = fixchan(c->right->type); if(t == T) @@ -1486,7 +1428,7 @@ recv2: return N; } - walktype(c->left, Elv); // elem + walkexpr(c->left, Elv, init); // elem convlit(c->left, t->type); if(!ascompat(t->type, c->left->type)) { badtype(c->op, t->type, c->left->type); @@ -1526,55 +1468,23 @@ out: * enumerate the special cases * of the case statement: * case v := <-chan // select and switch - * case v := map[] // switch - * case v := interface.(TYPE) // switch */ Node* -selectas(Node *name, Node *expr) +selectas(Node *name, Node *expr, Node **init) { - Node *a; Type *t; - if(expr == N) - goto bad; - switch(expr->op) { - default: -//dump("case", expr); + if(expr == N || expr->op != ORECV) goto bad; - case ORECV: - walktype(expr->left, Erv); - t = expr->left->type; - if(t == T) - goto bad; - if(t->etype != TCHAN) - goto bad; - t = t->type; - break; - - case OINDEX: - walktype(expr->left, Erv); - walktype(expr->right, Erv); - t = expr->left->type; - if(t == T) - goto bad; - if(t->etype != TMAP) - goto bad; - t = t->type; - break; - - case ODOTTYPE: - walktype(expr->left, Erv); - t = expr->left->type; - if(t == T) - goto bad; - if(t->etype != TINTER) - goto bad; - t = expr->type; - break; - } - a = old2new(name, t); - return a; + walkexpr(expr->left, Erv, init); + t = expr->left->type; + if(t == T) + goto bad; + if(t->etype != TCHAN) + goto bad; + t = t->type; + return old2new(name, t, init); bad: return name; @@ -1584,13 +1494,15 @@ void walkselect(Node *sel) { Iter iter, iter1; - Node *n, *n1, *l, *oc, *on, *r; + Node *n, *n1, *l, *oc, *on, *r, *init; Node *var, *bod, *nbod, *res, *def; int count, op; int32 lno; lno = setlineno(sel); + init = N; + // generate sel-struct var = nod(OXXX, N, N); tempname(var, ptrto(types[TUINT8])); @@ -1665,7 +1577,7 @@ walkselect(Node *sel) nbod = list(nbod, nod(OBREAK, N, N)); n->nbody = N; - oc = selcase(n, var); + oc = selcase(n, var, &init); if(oc != N) { oc->nbody = rev(nbod); res = list(res, oc); @@ -1690,11 +1602,11 @@ walkselect(Node *sel) sel->nbody = rev(res); sel->left = N; - walkstate(sel->ninit); - walkstate(sel->nbody); - + walkstmt(sel->ninit); + walkstmt(sel->nbody); //dump("sel", sel); + sel->ninit = list(sel->ninit, init); lineno = lno; } @@ -1741,7 +1653,7 @@ lookdot(Node *n, Type *t) if(t->etype == TINTER) { if(isptr[n->left->type->etype]) { n->left = nod(OIND, n->left, N); // implicitstar - walktype(n->left, Elv); + walkexpr(n->left, Elv, nil); } n->op = ODOTINTER; } @@ -1753,7 +1665,7 @@ lookdot(Node *n, Type *t) rcvr = getthisx(f2->type)->type->type; if(!eqtype(rcvr, tt)) { if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) { - walktype(n->left, Elv); + walkexpr(n->left, Elv, nil); addrescapes(n->left); n->left = nod(OADDR, n->left, N); n->left->type = ptrto(tt); @@ -1776,12 +1688,15 @@ lookdot(Node *n, Type *t) } void -walkdot(Node *n) +walkdot(Node *n, Node **init) { Type *t; - addtop = list(addtop, n->ninit); - n->ninit = N; + walkexpr(n->ninit, Etop, init); + if(n->ninit != N) { + *init = list(*init, n->ninit); + n->ninit = N; + } if(n->left == N || n->right == N) return; @@ -1791,7 +1706,7 @@ walkdot(Node *n) return; // already done } - walktype(n->left, Erv); + walkexpr(n->left, Erv, init); if(n->right->op != ONAME) { yyerror("rhs of . must be a name"); return; @@ -1818,7 +1733,7 @@ walkdot(Node *n) } Node* -ascompatee(int op, Node **nl, Node **nr) +ascompatee(int op, Node **nl, Node **nr, Node **init) { Node *l, *r, *nn, *a; Iter savel, saver; @@ -1849,7 +1764,7 @@ loop: yyerror("cannot assign to function"); a = nod(OAS, l, r); - a = convas(a); + a = convas(a, init); nn = list(a, nn); l = listnext(&savel); @@ -1874,7 +1789,7 @@ fncall(Node *l, Type *rt) } Node* -ascompatet(int op, Node **nl, Type **nr, int fp) +ascompatet(int op, Node **nl, Type **nr, int fp, Node **init) { Node *l, *nn, *mm, *tmp, *a; Type *r; @@ -1919,13 +1834,13 @@ loop: tmp = nod(OXXX, N, N); tempname(tmp, r->type); a = nod(OAS, l, tmp); - a = convas(a); + a = convas(a, init); mm = list(mm, a); l = tmp; } a = nod(OAS, l, nodarg(r, fp)); - a = convas(a); + a = convas(a, init); ullmancalc(a); if(a->ullman >= UINF) ucount++; @@ -1968,7 +1883,7 @@ sigtype(Type *st) * with a pointer to the structure. */ Node* -mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) +mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp, Node **init) { Type *t, *st, *ft; Node *a, *n, *var; @@ -2017,7 +1932,7 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) var->sym = lookup(".ddd"); // assign the fields to the struct. - // use addtop so that reorder1 doesn't reorder + // use the init list so that reorder1 doesn't reorder // these assignments after the interface conversion // below. n = rev(n); @@ -2028,7 +1943,8 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) *r->left = *var; r->left->type = r->right->type; r->left->xoffset += t->width; - addtop = list(addtop, r); + walkexpr(r, Etop, init); + *init = list(*init, r); r = listnext(&saven); t = t->down; } @@ -2036,7 +1952,7 @@ mkdotargs(Node *r, Node *rr, Iter *saver, Node *nn, Type *l, int fp) // last thing is to put assignment // of the structure to the DDD parameter a = nod(OAS, nodarg(l, fp), var); - nn = list(convas(a), nn); + nn = list(convas(a, init), nn); return nn; } @@ -2094,7 +2010,7 @@ dumpnodetypes(Node **nr, char *what) * func(expr-list) */ Node* -ascompatte(int op, Type **nl, Node **nr, int fp) +ascompatte(int op, Type **nl, Node **nr, int fp, Node **init) { Type *l, *ll; Node *r, *rr, *nn, *a; @@ -2118,7 +2034,7 @@ ascompatte(int op, Type **nl, Node **nr, int fp) fatal("misaligned multiple return\n\t%T\n\t%T", r->type, *nl); a = nodarg(*nl, fp); a->type = r->type; - return convas(nod(OAS, a, r)); + return convas(nod(OAS, a, r), init); } loop: @@ -2135,7 +2051,7 @@ loop: rr = listnext(&saver); if(r != N && rr == N && isddd(r->type)) { a = nod(OAS, nodarg(l, fp), r); - a = convas(a); + a = convas(a, init); nn = list(a, nn); return rev(nn); } @@ -2143,7 +2059,7 @@ loop: // normal case -- make a structure of all // remaining arguments and pass a pointer to // it to the ddd parameter (empty interface) - nn = mkdotargs(r, rr, &saver, nn, l, fp); + nn = mkdotargs(r, rr, &saver, nn, l, fp, init); return rev(nn); } @@ -2167,7 +2083,7 @@ loop: a = nod(OAS, nodarg(l, fp), r); - a = convas(a); + a = convas(a, init); nn = list(a, nn); l = structnext(&savel); @@ -2296,7 +2212,7 @@ loop: on = syslook("printnl", 0); r = list(r, nod(OCALL, on, N)); } - walktype(r, Etop); + walkexpr(r, Etop, nil); return r; } @@ -2305,7 +2221,7 @@ loop: r = list(r, nod(OCALL, on, N)); } - walktype(l, Erv); + walkexpr(l, Erv, nil); if(l->op == OLITERAL) { switch(l->val.ctype) { case CTINT: @@ -2376,7 +2292,7 @@ nodpanic(int32 lineno) on = syslook("panicl", 0); n = nodintconst(lineno); n = nod(OCALL, on, n); - walktype(n, Etop); + walkexpr(n, Etop, nil); return n; } @@ -2408,9 +2324,9 @@ makecompat(Node *n) goto bad; return arrayop(n, Erv); case TMAP: - return mapop(n, Erv); + return mapop(n, Erv, nil); case TCHAN: - return chanop(n, Erv); + return chanop(n, Erv, nil); } bad: @@ -2431,12 +2347,12 @@ callnew(Type *t) argtype(on, t); r = nodintconst(t->width); r = nod(OCALL, on, r); - walktype(r, Erv); + walkexpr(r, Erv, nil); return r; } Node* -stringop(Node *n, int top) +stringop(Node *n, int top, Node **init) { Node *r, *c, *on; @@ -2540,7 +2456,7 @@ stringop(Node *n, int top) break; } - walktype(r, top); + walkexpr(r, top, init); return r; } @@ -2584,7 +2500,7 @@ bad: } Node* -mapop(Node *n, int top) +mapop(Node *n, int top, Node **init) { Node *r, *a; Type *t; @@ -2632,7 +2548,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-2 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); r->type = n->type; break; @@ -2665,7 +2581,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-4 r = nod(OCALL, on, r); - walktype(r, Erv); + walkexpr(r, Erv, nil); r->type = t->type; break; @@ -2703,7 +2619,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-4 r = nod(OCALL, on, r); - walktype(r, Etop); + walkexpr(r, Etop, init); break; assign2: @@ -2732,7 +2648,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-4 r = nod(OCALL, on, r); - walktype(r, Etop); + walkexpr(r, Etop, init); break; access2: @@ -2759,7 +2675,7 @@ mapop(Node *n, int top) argtype(on, t->type); // any-4 n->right = nod(OCALL, on, r); - walktype(n, Etop); + walkexpr(n, Etop, init); r = n; break; @@ -2778,7 +2694,7 @@ mapop(Node *n, int top) a = nod(n->etype, a, n->right); // m[tmpi] op right a = nod(OAS, n->left, a); // map[tmpi] = map[tmpi] op right r = nod(OLIST, r, a); - walktype(r, Etop); + walkexpr(r, Etop, init); break; } return r; @@ -2794,15 +2710,13 @@ nottop: } Node* -chanop(Node *n, int top) +chanop(Node *n, int top, Node **init) { Node *r, *a; Type *t; Node *on; int cl, cr; -//dump("chanop", n); - r = n; switch(n->op) { default: @@ -2821,7 +2735,7 @@ chanop(Node *n, int top) argtype(on, t); // any-1 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); r->type = n->type; break; @@ -2838,7 +2752,7 @@ chanop(Node *n, int top) argtype(on, t); // any-1 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); n->type = r->type; break; @@ -2871,7 +2785,7 @@ chanop(Node *n, int top) argtype(on, t->type); // any-1 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); r->type = n->type; break; @@ -2903,7 +2817,7 @@ chanop(Node *n, int top) r = nod(OCALL, on, r); n->right = r; r = n; - walktype(r, Etop); + walkexpr(r, Etop, init); break; case ORECV: @@ -2929,7 +2843,7 @@ chanop(Node *n, int top) argtype(on, t->type); // any-1 argtype(on, t->type); // any-2 r = nod(OCALL, on, r); - walktype(r, Erv); + walkexpr(r, Erv, nil); break; recv2: @@ -2956,7 +2870,7 @@ chanop(Node *n, int top) r = nod(OCALL, on, r); n->right = r; r = n; - walktype(r, Etop); + walkexpr(r, Etop, nil); break; case OSEND: @@ -2981,7 +2895,7 @@ chanop(Node *n, int top) argtype(on, t->type); // any-1 argtype(on, t->type); // any-2 r = nod(OCALL, on, r); - walktype(r, Etop); + walkexpr(r, Etop, nil); break; send2: @@ -2995,7 +2909,7 @@ chanop(Node *n, int top) argtype(on, t->type); // any-1 argtype(on, t->type); // any-2 r = nod(OCALL, on, r); - walktype(r, Etop); + walkexpr(r, Etop, nil); break; } return r; @@ -3059,7 +2973,7 @@ arrayop(Node *n, int top) argtype(on, tl->type); // any-2 r = nod(OCALL, on, r); n->left = r; - walktype(n, top); + walkexpr(n, top, nil); return n; case OAS: @@ -3104,7 +3018,7 @@ arrayop(Node *n, int top) argtype(on, t->type); // any-1 r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); r->type = t; // if t had a name, going through newarray lost it break; @@ -3152,7 +3066,7 @@ arrayop(Node *n, int top) argtype(on, t->type); // any-2 } r = nod(OCALL, on, r); - walktype(r, top); + walkexpr(r, top, nil); break; } return r; @@ -3311,7 +3225,7 @@ ifacecvt(Type *tl, Node *n, int et) } r = nod(OCALL, on, r); - walktype(r, Erv); + walkexpr(r, Erv, nil); return r; } @@ -3345,18 +3259,13 @@ ifaceop(Node *n) r = nod(OCALL, on, r); if(n->op == ONE) r = nod(ONOT, r, N); - - walktype(r, Erv); + walkexpr(r, Erv, nil); return r; } - - r = nod(OCALL, on, r); - walktype(r, Erv); - return r; } Node* -convas(Node *n) +convas(Node *n, Node **init) { Node *l, *r; Type *lt, *rt; @@ -3380,13 +3289,13 @@ convas(Node *n) if(n->left->op == OINDEX) if(istype(n->left->left->type, TMAP)) { - indir(n, mapop(n, Elv)); + indir(n, mapop(n, Elv, init)); goto out; } if(n->left->op == OSEND) if(n->left->type != T) { - indir(n, chanop(n, Elv)); + indir(n, chanop(n, Elv, init)); goto out; } @@ -3437,7 +3346,7 @@ colasname(Node *n) } Node* -old2new(Node *n, Type *t) +old2new(Node *n, Type *t, Node **init) { Node *l; @@ -3446,7 +3355,7 @@ old2new(Node *n, Type *t) return n; } l = newname(n->sym); - dodclvar(l, t); + dodclvar(l, t, init); return l; } @@ -3459,7 +3368,7 @@ mixedoldnew(Node *n, Type *t) } static Node* -checkmixed(Node *nl) +checkmixed(Node *nl, Node **init) { Iter save; Node *l, *n, *a; @@ -3504,7 +3413,7 @@ checkmixed(Node *nl) a = l; if(l->sym->block != block) - a = old2new(l, t); + a = old2new(l, t, init); n = list(n, a); l = listnext(&save); @@ -3519,7 +3428,7 @@ allnew: t = l->type; l = l->left; - a = old2new(l, t); + a = old2new(l, t, init); n = list(n, a); l = listnext(&save); } @@ -3527,7 +3436,7 @@ allnew: } Node* -colas(Node *nl, Node *nr) +colas(Node *nl, Node *nr, Node **init) { Iter savel, saver; Node *l, *r, *a, *n; @@ -3549,16 +3458,16 @@ colas(Node *nl, Node *nr) case OCALLMETH: case OCALLINTER: case OCALL: - walktype(nr->left, Erv); + walkexpr(nr->left, Erv, init); convlit(nr->left, types[TFUNC]); t = nr->left->type; if(t == T) - return nl; // error already printed + goto outl; // error already printed if(t->etype == tptr) t = t->type; if(t == T || t->etype != TFUNC) { yyerror("cannot call %T", t); - return nl; + goto outl; } if(t->outtuple != cl) { cr = t->outtuple; @@ -3568,15 +3477,15 @@ colas(Node *nl, Node *nr) l = listfirst(&savel, &nl); t = structfirst(&saver, getoutarg(t)); if(t == T) - return N; + goto outl; while(l != N) { a = mixedoldnew(l, t->type); n = list(n, a); l = listnext(&savel); t = structnext(&saver); } - n = checkmixed(n); - return n; + n = checkmixed(n, init); + goto out; } } if(cl != cr) { @@ -3589,7 +3498,7 @@ colas(Node *nl, Node *nr) r = listfirst(&saver, &nr); while(l != N) { - walktype(r, Erv); + walkexpr(r, Erv, init); defaultlit(r, T); a = mixedoldnew(l, r->type); n = list(n, a); @@ -3597,8 +3506,8 @@ colas(Node *nl, Node *nr) l = listnext(&savel); r = listnext(&saver); } - n = checkmixed(n); - return n; + n = checkmixed(n, init); + goto out; multi: /* @@ -3616,7 +3525,7 @@ multi: // if so, types are valuetype,bool if(cl != 2) goto badt; - walktype(nr->left, Erv); + walkexpr(nr->left, Erv, init); implicitstar(&nr->left); t = nr->left->type; if(!istype(t, TMAP)) @@ -3625,14 +3534,14 @@ multi: n = a; a = mixedoldnew(nl->right, types[TBOOL]); n = list(n, a); - n = checkmixed(n); + n = checkmixed(n, init); break; case ODOTTYPE: // a,b := i.(T) if(cl != 2) goto badt; - walktype(nr->left, Erv); + walkexpr(nr->left, Erv, init); if(!isinter(nr->left->type)) goto badt; // a,b = iface @@ -3640,13 +3549,13 @@ multi: n = a; a = mixedoldnew(nl->right, types[TBOOL]); n = list(n, a); - n = checkmixed(n); + n = checkmixed(n, init); break; case ORECV: if(cl != 2) goto badt; - walktype(nr->left, Erv); + walkexpr(nr->left, Erv, init); t = nr->left->type; if(!istype(t, TCHAN)) goto badt; @@ -3654,10 +3563,11 @@ multi: n = a; a = mixedoldnew(nl->right, types[TBOOL]); n = list(n, a); - n = checkmixed(n); + n = checkmixed(n, init); break; } n = rev(n); +out: return n; badt: @@ -3665,6 +3575,7 @@ badt: nl->diag = 1; yyerror("assignment count mismatch: %d = %d", cl, cr); } +outl: return nl; } @@ -3695,7 +3606,7 @@ dorange(Node *nn) n = nod(OFOR, N, N); init = N; - walktype(nn->right, Erv); + walkexpr(nn->right, Erv, &init); implicitstar(&nn->right); m = nn->right; local = nn->etype; @@ -3733,16 +3644,15 @@ ary: n->nincr->etype = OADD; if(local) - k = old2new(k, hk->type); + k = old2new(k, hk->type, &init); n->nbody = nod(OAS, k, hk); if(v != N) { if(local) - v = old2new(v, t->type); + v = old2new(v, t->type, &init); n->nbody = list(n->nbody, nod(OAS, v, nod(OINDEX, ha, hk)) ); } - addtotop(n); goto out; map: @@ -3777,7 +3687,7 @@ map: n->nincr = r; if(local) - k = old2new(k, t->down); + k = old2new(k, t->down, &init); if(v == N) { on = syslook("mapiter1", 1); argtype(on, th); @@ -3788,7 +3698,7 @@ map: goto out; } if(local) - v = old2new(v, t->type); + v = old2new(v, t->type, &init); on = syslook("mapiter2", 1); argtype(on, th); argtype(on, t->down); @@ -3819,9 +3729,9 @@ chan: n->nincr = nod(OAS, hv, nod(ORECV, hc, N)); if(local) - k = old2new(k, hv->type); + k = old2new(k, hv->type, &init); n->nbody = nod(OAS, k, hv); - addtotop(n); + goto out; strng: @@ -3841,9 +3751,9 @@ strng: } if(local) { - k = old2new(k, types[TINT]); + k = old2new(k, types[TINT], &init); if(v != N) - v = old2new(v, types[TINT]); + v = old2new(v, types[TINT], &init); } // ha = s @@ -3900,9 +3810,6 @@ strng: n->nbody = list(n->nbody, a); } - addtotop(n); - goto out; - out: n->ninit = list(n->ninit, init); return n; @@ -4124,7 +4031,7 @@ fielddup(Node *n, Node *hash[], ulong nhash) } Node* -structlit(Node *n, Node *var) +structlit(Node *n, Node *var, Node **init) { Iter savel, saver; Type *l, *t; @@ -4164,10 +4071,10 @@ structlit(Node *n, Node *var) // build list of var.field = expr a = nod(ODOT, var, newname(l->sym)); a = nod(OAS, a, r); - walktype(a, Etop); + walkexpr(a, Etop, init); if(nerr != nerrors) return var; - addtop = list(addtop, a); + *init = list(*init, a); l = structnext(&savel); r = listnext(&saver); @@ -4181,7 +4088,8 @@ structlit(Node *n, Node *var) keyval: memset(hash, 0, sizeof(hash)); a = nod(OAS, var, N); - addtop = list(addtop, a); + walkexpr(a, Etop, init); + *init = list(*init, a); while(r != N) { // assignment to field:value elements @@ -4197,11 +4105,11 @@ keyval: break; a = nod(OAS, a, r->right); - walktype(a, Etop); + walkexpr(a, Etop, init); if(nerr != nerrors) break; - addtop = list(addtop, a); + *init = list(*init, a); r = listnext(&saver); } @@ -4232,7 +4140,7 @@ indexdup(Node *n, Node *hash[], ulong nhash) } Node* -arraylit(Node *n, Node *var) +arraylit(Node *n, Node *var, Node **init) { Iter saver; Type *t; @@ -4283,13 +4191,15 @@ arraylit(Node *n, Node *var) // slice a = nod(OMAKE, nod(OLIST, typenod(t), nodintconst(ninit)), N); a = nod(OAS, var, a); - addtop = list(addtop, a); + walkexpr(a, Etop, init); + *init = list(*init, a); } else { // if entire array isnt initialized, // then clear the array if(ninit < b) { a = nod(OAS, var, N); - addtop = list(addtop, a); + walkexpr(a, Etop, init); + *init = list(*init, a); } } @@ -4322,11 +4232,11 @@ arraylit(Node *n, Node *var) a = nod(OINDEX, var, a); a = nod(OAS, a, r); - walktype(a, Etop); // add any assignments in r to addtop + walkexpr(a, Etop, init); // add any assignments in r to top if(nerr != nerrors) break; - addtop = list(addtop, a); + *init = list(*init, a); b++; r = listnext(&saver); @@ -4390,7 +4300,7 @@ keydup(Node *n, Node *hash[], ulong nhash) } Node* -maplit(Node *n, Node *var) +maplit(Node *n, Node *var, Node **init) { Iter saver; Type *t; @@ -4410,7 +4320,8 @@ maplit(Node *n, Node *var) a = nod(OMAKE, typenod(t), N); a = nod(OAS, var, a); - addtop = list(addtop, a); + walkexpr(a, Etop, init); + *init = list(*init, a); r = listfirst(&saver, &n->left); if(r != N && r->op == OEMPTY) @@ -4433,11 +4344,11 @@ maplit(Node *n, Node *var) a = nod(OINDEX, var, r->left); a = nod(OAS, a, r->right); - walktype(a, Etop); + walkexpr(a, Etop, init); if(nerr != nerrors) break; - addtop = list(addtop, a); + *init = list(*init, a); r = listnext(&saver); }