diff options
Diffstat (limited to 'src/cmd/gc/walk.c')
-rw-r--r-- | src/cmd/gc/walk.c | 1450 |
1 files changed, 334 insertions, 1116 deletions
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 91f1ea875..d9f2a9092 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -4,15 +4,13 @@ #include "go.h" -static Node* curfn; - -static Node* prcompat(Node*); +static Node* walkprint(Node*, NodeList**); static Node* mkcall(char*, Type*, NodeList**, ...); static Node* mkcall1(Node*, Type*, NodeList**, ...); static Node* conv(Node*, Type*); static Node* chanfn(char*, int, Type*); static Node* mapfn(char*, Type*); - +static Node* makenewvar(Type*, NodeList**, Node**); enum { Inone, @@ -79,7 +77,6 @@ void walk(Node *fn) { char s[50]; - // int nerr; curfn = fn; if(debug['W']) { @@ -89,12 +86,9 @@ walk(Node *fn) if(curfn->type->outtuple) if(walkret(curfn->nbody)) yyerror("function ends without a return statement"); - // nerr = nerrors; typechecklist(curfn->nbody, Etop); - /* TODO(rsc) - if(nerrors != nerr) + if(nerrors != 0) return; - */ walkstmtlist(curfn->nbody); if(debug['W']) { snprint(s, sizeof(s), "after walk %S", curfn->nname->sym); @@ -223,6 +217,7 @@ walkstmt(Node **np) dump("nottop", n); break; + case OAPPENDSTR: case OASOP: case OAS: case OAS2: @@ -336,16 +331,22 @@ walkexpr(Node **np, NodeList **init) Node *r, *l; NodeList *ll, *lr; Type *t; - Sym *s; int et, cl, cr; int32 lno; - Node *n; + Node *n, *fn; n = *np; if(n == N) return; + // annoying case - not typechecked + if(n->op == OKEY) { + walkexpr(&n->left, init); + walkexpr(&n->right, init); + return; + } + lno = setlineno(n); if(debug['w'] > 1) @@ -356,7 +357,6 @@ walkexpr(Node **np, NodeList **init) fatal("missed typecheck"); } -reswitch: t = T; et = Txxx; @@ -367,15 +367,9 @@ reswitch: goto ret; case OTYPE: - case OCALLMETH: - case OCALLINTER: - case OCALLFUNC: case ONONAME: case OINDREG: case OEMPTY: - case OCONVNOP: - case OCOMPMAP: - case OCOMPSLICE: goto ret; case ONOT: @@ -401,6 +395,13 @@ reswitch: case OOROR: case OSUB: case OMUL: + case OEQ: + case ONE: + case OLT: + case OLE: + case OGE: + case OGT: + case OADD: walkexpr(&n->left, init); walkexpr(&n->right, init); goto ret; @@ -410,7 +411,7 @@ reswitch: case OPANIC: case OPANICN: walkexprlist(n->list, init); - n = prcompat(n); + n = walkprint(n, init); goto ret; case OLITERAL: @@ -420,104 +421,50 @@ reswitch: case ONAME: if(!(n->class & PHEAP) && n->class != PPARAMREF) n->addable = 1; - if(n->type == T) { - s = n->sym; - if(s->undef == 0) { - if(n->etype != 0) - yyerror("walkexpr: %S must be called", s, init); - else - yyerror("walkexpr: %S undeclared", s, init); - s->undef = 1; - } - } goto ret; - case OCALL: - if(n->left == N) + case OCALLINTER: + t = n->left->type; + if(n->list && n->list->n->op == OAS) goto ret; - - if(n->left->op == ONAME && n->left->etype != 0) { - // builtin OLEN, OCAP, etc. - n->op = n->left->etype; - n->left = N; - goto reswitch; - } - walkexpr(&n->left, init); - defaultlit(&n->left, T); + walkexprlist(n->list, init); + ll = ascompatte(n->op, getinarg(t), n->list, 0, init); + n->list = reorder1(ll); + goto ret; + case OCALLFUNC: t = n->left->type; - if(t == T) + if(n->list && n->list->n->op == OAS) goto ret; - - switch(n->left->op) { - case ODOTMETH: - n->op = OCALLMETH; - break; - case ODOTINTER: - n->op = OCALLINTER; - break; - case OTYPE: - n->op = OCONV; - // turn CALL(type, arg) into CONV(arg) w/ type. - n->type = n->left->type; - if(n->list == nil) { - yyerror("missing argument in type conversion"); - goto ret; - } - if(n->list->next != nil) { - yyerror("too many arguments in type conversion"); - goto ret; - } - n->left = n->list->n; - n->list = nil; - goto reswitch; - default: - n->op = OCALLFUNC; - break; + walkexpr(&n->left, init); + walkexprlist(n->list, init); + ll = ascompatte(n->op, getinarg(t), n->list, 0, init); + n->list = reorder1(ll); + if(isselect(n)) { + // special prob with selectsend and selectrecv: + // if chan is nil, they don't know big the channel + // element is and therefore don't know how to find + // the output bool, so we clear it before the call. + Node *b; + b = nodbool(0); + lr = ascompatte(n->op, getoutarg(t), list1(b), 0, init); + n->list = concat(n->list, lr); } + goto ret; - if(t->etype != TFUNC) { - yyerror("call of a non-function: %T", t); + case OCALLMETH: + t = n->left->type; + if(n->list && n->list->n->op == OAS) goto ret; - } - - dowidth(t); + walkexpr(&n->left, init); walkexprlist(n->list, init); - - switch(n->op) { - default: - fatal("walk: op: %O", n->op); - - case OCALLINTER: - ll = ascompatte(n->op, getinarg(t), n->list, 0, init); - n->list = reorder1(ll); - break; - - case OCALLFUNC: - ll = ascompatte(n->op, getinarg(t), n->list, 0, init); - n->list = reorder1(ll); - if(isselect(n)) { - // special prob with selectsend and selectrecv: - // if chan is nil, they don't know big the channel - // element is and therefore don't know how to find - // the output bool, so we clear it before the call. - Node *b; - b = nodbool(0); - lr = ascompatte(n->op, getoutarg(t), list1(b), 0, init); - n->list = concat(n->list, lr); - } - break; - - case OCALLMETH: - ll = ascompatte(n->op, getinarg(t), n->list, 0, init); - lr = ascompatte(n->op, getthis(t), list1(n->left->left), 0, init); - ll = concat(ll, lr); - n->left->left = N; - ullmancalc(n->left); - n->list = reorder1(ll); - break; - } + ll = ascompatte(n->op, getinarg(t), n->list, 0, init); + lr = ascompatte(n->op, getthis(t), list1(n->left->left), 0, init); + ll = concat(ll, lr); + n->left->left = N; + ullmancalc(n->left); + n->list = reorder1(ll); goto ret; case OAS: @@ -571,12 +518,10 @@ reswitch: } break; - case OINDEX: + case OINDEXMAP: if(cl == 2 && cr == 1) { // a,b = map[] - mapaccess2 walkexpr(&r->left, init); - if(!istype(r->left->type, TMAP)) - break; l = mapop(n, init); if(l == N) break; @@ -634,7 +579,7 @@ reswitch: } if(et == Inone) break; - r = ifacecvt(r->type, r->left, et); + r = ifacecvt(r->type, r->left, et, init); ll = ascompatet(n->op, n->list, &r->type, 0, init); n = liststmt(concat(list1(r), ll)); goto ret; @@ -643,11 +588,9 @@ reswitch: } switch(l->op) { - case OINDEX: + case OINDEXMAP: if(cl == 1 && cr == 2) { // map[] = a,b - mapassign2 - if(!istype(l->left->type, TMAP)) - break; l = mapop(n, init); if(l == N) break; @@ -664,42 +607,18 @@ reswitch: case ODOTTYPE: walkdottype(n, init); - // fall through - case OCONV: walkconv(&n, init); goto ret; - case OCOMPOS: - walkexpr(&n->right, init); - t = n->right->type; - n->type = t; - if(t == T) - goto ret; - - switch(t->etype) { - default: - yyerror("invalid type for composite literal: %T", t); - goto ret; - - case TSTRUCT: - r = structlit(n, N, init); - break; - - case TARRAY: - r = arraylit(n, N, init); - break; - - case TMAP: - r = maplit(n, N, init); - break; - } - n = r; + case OCONV: + case OCONVNOP: + walkexpr(&n->left, init); goto ret; case OASOP: walkexpr(&n->left, init); l = n->left; - if(l->op == OINDEX && istype(l->left->type, TMAP)) + if(l->op == OINDEXMAP) n = mapop(n, init); walkexpr(&n->right, init); if(n->etype == OANDNOT) { @@ -708,11 +627,7 @@ reswitch: n->right->type = n->right->left->type; goto ret; } - if(istype(n->left->type, TSTRING)) { - n = stringop(n, init); - goto ret; - } - + /* * on 32-bit arch, rewrite 64-bit ops into l = l op r */ @@ -734,25 +649,6 @@ reswitch: n->right->type = n->right->left->type; goto ret; - case OEQ: - case ONE: - case OLT: - case OLE: - case OGE: - case OGT: - case OADD: - walkexpr(&n->left, init); - walkexpr(&n->right, init); - if(istype(n->left->type, TSTRING)) { - n = stringop(n, nil); - goto ret; - } - if(isinter(n->left->type)) { - n = ifaceop(n); - goto ret; - } - goto ret; - case ODIV: case OMOD: /* @@ -779,131 +675,246 @@ reswitch: case OINDEX: walkexpr(&n->left, init); walkexpr(&n->right, init); - if(n->left == N || n->right == N) + goto ret; + + case OINDEXMAP: + if(n->etype == 1) goto ret; t = n->left->type; - if(t == T) - goto ret; - - switch(t->etype) { - case TSTRING: - n = stringop(n, nil); - break; - - case TMAP: - if(n->etype != 1) // clumsy hack - n = mapop(n, nil); - break; - } + n = mkcall1(mapfn("mapaccess1", t), t->type, init, n->left, n->right); goto ret; - case OCLOSE: - case OCLOSED: - case OSEND: case ORECV: walkexpr(&n->left, init); walkexpr(&n->right, init); - n = chanop(n, init); + n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, n->left); goto ret; case OSLICE: walkexpr(&n->left, init); walkexpr(&n->right->left, init); walkexpr(&n->right->right, init); - if(n->left == N || n->right == N) - goto ret; - t = n->left->type; - if(t == T) + // dynamic slice + // arraysliced(old []any, lb int, hb int, width int) (ary []any) + t = n->type; + fn = syslook("arraysliced", 1); + argtype(fn, t->type); // any-1 + argtype(fn, t->type); // any-2 + n = mkcall1(fn, t, init, + n->left, + conv(n->right->left, types[TINT]), + conv(n->right->right, types[TINT]), + nodintconst(t->type->width)); + goto ret; + + case OSLICEARR: + walkexpr(&n->left, init); + walkexpr(&n->right->left, init); + walkexpr(&n->right->right, init); + // static slice + // arrayslices(old *any, nel int, lb int, hb int, width int) (ary []any) + t = n->type; + fn = syslook("arrayslices", 1); + argtype(fn, n->left->type); // any-1 + argtype(fn, t->type); // any-2 + n = mkcall1(fn, t, init, + nod(OADDR, n->left, N), nodintconst(t->bound), + conv(n->right->left, types[TINT]), + conv(n->right->right, types[TINT]), + nodintconst(t->type->width)); + goto ret; + + case OADDR:; + Node *nvar, *nstar; + + // turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation. + // initialize with + // nvar := new(*Point); + // *nvar = Point(1, 2); + // and replace expression with nvar + switch(n->left->op) { + case OARRAYLIT: + nvar = makenewvar(n->type, init, &nstar); + arraylit(n->left, nstar, init); + n = nvar; goto ret; - if(t->etype == TSTRING) { - n = stringop(n, nil); + + case OMAPLIT: + nvar = makenewvar(n->type, init, &nstar); + maplit(n->left, nstar, init); + n = nvar; goto ret; - } - if(t->etype == TARRAY) { - n = arrayop(n); + + + case OSTRUCTLIT: + nvar = makenewvar(n->type, init, &nstar); + structlit(n->left, nstar, init); + n = nvar; goto ret; } + + walkexpr(&n->left, init); goto ret; - case OADDR: - if(n->left->op == OCOMPOS) { - walkexpr(&n->left->right, init); - n->left->type = n->left->right->type; - if(n->left->type == T) - goto ret; + case ONEW: + n = callnew(n->type->type); + goto ret; - Node *nvar, *nas, *nstar; + case OCMPSTR: + // sys_cmpstring(s1, s2) :: 0 + r = mkcall("cmpstring", types[TINT], init, + conv(n->left, types[TSTRING]), + conv(n->right, types[TSTRING])); + r = nod(n->etype, r, nodintconst(0)); + typecheck(&r, Erv); + n = r; + goto ret; - // turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation. - // initialize with - // nvar := new(*Point); - // *nvar = Point(1, 2); - // and replace expression with nvar + case OADDSTR: + // sys_catstring(s1, s2) + n = mkcall("catstring", n->type, init, + conv(n->left, types[TSTRING]), + conv(n->right, types[TSTRING])); + goto ret; - nvar = nod(OXXX, N, N); - tempname(nvar, ptrto(n->left->type)); + 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; - nas = nod(OAS, nvar, callnew(n->left->type)); - typecheck(&nas, Etop); - walkexpr(&nas, init); - *init = list(*init, nas); + case OSLICESTR: + // sys_slicestring(s, lb, hb) + n = mkcall("slicestring", n->type, init, + conv(n->left, types[TSTRING]), + conv(n->right->left, types[TINT]), + conv(n->right->right, types[TINT])); + goto ret; - nstar = nod(OIND, nvar, N); - nstar->type = n->left->type; + case OINDEXSTR: + // TODO(rsc): should be done in back end + // sys_indexstring(s, i) + n = mkcall("indexstring", n->type, init, + conv(n->left, types[TSTRING]), + conv(n->right, types[TINT])); + goto ret; - switch(n->left->type->etype) { - case TSTRUCT: - structlit(n->left, nstar, init); - break; - case TARRAY: - arraylit(n->left, nstar, init); - break; - case TMAP: - maplit(n->left, nstar, init); - break; - default: - goto badlit; - } + case OCLOSE: + // cannot use chanfn - closechan takes any, not chan any + fn = syslook("closechan", 1); + argtype(fn, n->left->type); + n = mkcall1(fn, T, init, n->left); + goto ret; -// walkexpr(&n->left->left, init); - n = nvar; - goto ret; - } + case OCLOSED: + // cannot use chanfn - closechan takes any, not chan any + fn = syslook("closedchan", 1); + argtype(fn, n->left->type); + n = mkcall1(fn, n->type, init, n->left); + goto ret; - badlit: - if(istype(n->left->type, TFUNC) && n->left->class == PFUNC) { - if(!n->diag) { - n->diag = 1; - yyerror("cannot take address of function"); - } - } - if(n->left == N) - goto ret; - walkexpr(&n->left, init); - t = n->left->type; - if(t == T) - goto ret; - addrescapes(n->left); - n->type = ptrto(t); + case OMAKECHAN: + n = mkcall1(chanfn("newchan", 1, n->type), n->type, init, + nodintconst(n->type->type->width), + nodintconst(algtype(n->type->type)), + conv(n->left, types[TINT])); + goto ret; + + case OMAKEMAP: + t = n->type; + + fn = syslook("newmap", 1); + argtype(fn, t->down); // any-1 + argtype(fn, t->type); // any-2 + + n = mkcall1(fn, n->type, init, + nodintconst(t->down->width), // key width + nodintconst(t->type->width), // val width + nodintconst(algtype(t->down)), // key algorithm + nodintconst(algtype(t->type)), // val algorithm + conv(n->left, types[TINT])); goto ret; - case OMAKE: - n = makecompat(n); + case OMAKESLICE: + // newarray(nel int, max int, width int) (ary []any) + t = n->type; + fn = syslook("newarray", 1); + argtype(fn, t->type); // any-1 + n = mkcall1(fn, n->type, nil, + conv(n->left, types[TINT]), + conv(n->right, types[TINT]), + nodintconst(t->type->width)); goto ret; - case ONEW: - if(n->list == nil) { - yyerror("missing argument to new"); - goto ret; - } - if(n->list->next) - yyerror("too many arguments to new"); - walkexpr(&n->list->n, init); - l = n->list->n; - if((t = l->type) == T) - ; + case ORUNESTR: + // sys_intstring(v) + n = mkcall("intstring", n->type, init, conv(n->left, types[TINT64])); // TODO(rsc): int64?! + goto ret; + + case OARRAYBYTESTR: + // arraystring([]byte) string; + n = mkcall("arraystring", n->type, init, n->left); + goto ret; + + case OARRAYRUNESTR: + // arraystring([]byte) string; + n = mkcall("arraystringi", n->type, init, n->left); + goto ret; + + case OCMPIFACE: + // ifaceeq(i1 any-1, i2 any-2) (ret bool); + if(!eqtype(n->left->type, n->right->type)) + fatal("ifaceeq %O %T %T", n->op, n->left->type, n->right->type); + if(isnilinter(n->left->type)) + fn = syslook("efaceeq", 1); else - n = callnew(t); + fn = syslook("ifaceeq", 1); + argtype(fn, n->right->type); + argtype(fn, n->left->type); + r = mkcall1(fn, n->type, init, n->left, n->right); + if(n->etype == ONE) { + r = nod(ONOT, r, N); + typecheck(&r, Erv); + } + n = r; + goto ret; + + case OARRAYLIT: + n = arraylit(n, N, init); + goto ret; + + case OMAPLIT: + n = maplit(n, N, init); + goto ret; + + case OSTRUCTLIT: + n = structlit(n, N, init); + goto ret; + + case OSEND: + n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, n->left, n->right); + goto ret; + + case OSENDNB: + n = mkcall1(chanfn("chansend2", 2, n->left->type), n->type, init, n->left, n->right); + goto ret; + + case OCONVIFACE: + walkexpr(&n->left, init); + n = ifacecvt(n->type, n->left, n->etype, init); + goto ret; + + case OCONVSLICE: + // arrays2d(old *any, nel int) (ary []any) + fn = syslook("arrays2d", 1); + argtype(fn, n->left->type->type); // any-1 + argtype(fn, n->type->type); // any-2 + n = mkcall1(fn, n->type, init, n->left, nodintconst(n->left->type->type->bound)); goto ret; } fatal("missing switch %O", n->op); @@ -917,6 +928,23 @@ ret: *np = n; } +Node* +makenewvar(Type *t, NodeList **init, Node **nstar) +{ + Node *nvar, *nas; + + nvar = nod(OXXX, N, N); + tempname(nvar, t); + nas = nod(OAS, nvar, callnew(t->type)); + typecheck(&nas, Etop); + walkexpr(&nas, init); + *init = list(*init, nas); + + *nstar = nod(OIND, nvar, N); + typecheck(nstar, Erv); + return nvar; +} + void walkbool(Node **np) { @@ -958,7 +986,6 @@ walkconv(Node **np, NodeList **init) t = n->type; if(t == T) return; - typecheck(&n->left, Erv); walkexpr(&n->left, init); l = n->left; if(l == N) @@ -969,110 +996,19 @@ walkconv(Node **np, NodeList **init) // if using .(T), interface assertion. if(n->op == ODOTTYPE) { et = ifaceas1(t, l->type, 1); - if(et == I2Isame || et == E2Esame) - goto nop; - if(et != Inone) { - n = ifacecvt(t, l, et); - *np = n; - return; - } - goto bad; - } - - // otherwise, conversion. - convlit1(&n->left, t, 1); - l = n->left; - if(l->type == T) - return; - - // no-op conversion - if(cvttype(t, l->type) == 1) { - nop: - if(l->op == OLITERAL) { - *n = *l; - n->type = t; + if(et == I2Isame || et == E2Esame) { + n->op = OCONVNOP; return; } - // leave OCONV node in place - // in case tree gets walked again. - // back end will ignore. - n->op = OCONVNOP; - return; - } - - // to/from interface. - // ifaceas1 will generate a good error - // if the conversion is invalid. - if(t->etype == TINTER || l->type->etype == TINTER) { - n = ifacecvt(t, l, ifaceas1(t, l->type, 0)); - *np = n; - return; - } - - // simple fix-float - if(isint[l->type->etype] || isfloat[l->type->etype]) - if(isint[t->etype] || isfloat[t->etype]) { - evconst(n); - return; - } - - // to string - if(l->type != T) - if(istype(t, TSTRING)) { - et = l->type->etype; - if(isint[et]) { - n = stringop(n, nil); - *np = n; - return; - } - - // can convert []byte and *[10]byte - if((isptr[et] && isfixedarray(l->type->type) && istype(l->type->type->type, TUINT8)) - || (isslice(l->type) && istype(l->type->type, TUINT8))) { - n->op = OARRAY; - n = stringop(n, nil); - *np = n; - return; - } - - // can convert []int and *[10]int - if((isptr[et] && isfixedarray(l->type->type) && istype(l->type->type->type, TINT)) - || (isslice(l->type) && istype(l->type->type, TINT))) { - n->op = OARRAY; - n = stringop(n, nil); - *np = n; - return; - } - } - - // convert dynamic to static generated by ONEW/OMAKE - if(isfixedarray(t) && isslice(l->type)) - return; - - // convert static array to dynamic array - if(isslice(t) && isptr[l->type->etype] && isfixedarray(l->type->type)) { - if(eqtype(t->type->type, l->type->type->type->type)) { - n = arrayop(n); + if(et != Inone) { + n = ifacecvt(t, l, et, init); *np = n; return; } + goto bad; } - // convert to unsafe.pointer - if(isptrto(n->type, TANY)) { - if(isptr[l->type->etype]) - return; - if(l->type->etype == TUINTPTR) - return; - } - - // convert from unsafe.pointer - if(isptrto(l->type, TANY)) { - if(isptr[t->etype]) - return; - if(t->etype == TUINTPTR) - return; - } + fatal("walkconv"); bad: if(n->diag) @@ -1279,6 +1215,7 @@ walkselect(Node *sel) break; case OSEND: + case OSENDNB: case ORECV: break; } @@ -1325,14 +1262,15 @@ ascompatee1(int op, Node *l, Node *r, NodeList **init) * a expression. called in * expr = expr */ + if(l->type != T && l->type->etype == TFORW) + return N; + if(r->type != T && r->type->etype ==TFORW) + return N; convlit(&r, l->type); if(!ascompat(l->type, r->type)) { badtype(op, l->type, r->type); return N; } - if(l->op == ONAME && l->class == PFUNC) - yyerror("cannot assign to function"); - a = nod(OAS, l, r); a = convas(a, init); return a; @@ -1653,7 +1591,7 @@ loop: } goto ret; } - convlit(&r, l->type); + if(!ascompat(l->type, r->type)) { badtype(op, l->type, r->type); return nil; @@ -1677,59 +1615,14 @@ ret: } /* - * do the export rules allow writing to this type? - * cannot be implicitly assigning to any type with - * an unavailable field. - */ -int -exportasok(Type *t) -{ - Type *f; - Sym *s; - - if(t == T) - return 1; - switch(t->etype) { - default: - // most types can't contain others; they're all fine. - break; - case TSTRUCT: - for(f=t->type; f; f=f->down) { - if(f->etype != TFIELD) - fatal("structas: not field"); - s = f->sym; - // s == nil doesn't happen for embedded fields (they get the type symbol). - // it only happens for fields in a ... struct. - if(s != nil && !exportname(s->name) && strcmp(package, s->package) != 0) { - yyerror("implicit assignment of %T field '%s'", t, s->name); - return 0; - } - if(!exportasok(f->type)) - return 0; - } - break; - - case TARRAY: - if(t->bound < 0) // slices are pointers; that's fine - break; - if(!exportasok(t->type)) - return 0; - break; - } - return 1; -} - -/* * can we assign var of type src to var of type dst? * return 0 if not, 1 if conversion is trivial, 2 if conversion is non-trivial. */ int ascompat(Type *dst, Type *src) { - if(eqtype(dst, src)) { - exportasok(src); + if(eqtype(dst, src)) return 1; - } if(dst == T || src == T) return 0; @@ -1775,7 +1668,7 @@ ascompat(Type *dst, Type *src) // generate code for print static Node* -prcompat(Node *nn) +walkprint(Node *nn, NodeList **init) { Node *r; Node *n; @@ -1792,10 +1685,9 @@ prcompat(Node *nn) for(l=all; l; l=l->next) { if(notfirst) - calls = list(calls, mkcall("printsp", T, nil)); + calls = list(calls, mkcall("printsp", T, init)); notfirst = op == OPRINTN || op == OPANICN; - typecheck(&l->n, Erv); n = l->n; if(n->op == OLITERAL) { switch(n->val.ctype) { @@ -1811,7 +1703,7 @@ prcompat(Node *nn) defaultlit(&n, types[TINT64]); defaultlit(&n, nil); l->n = n; - if(n->type == T) + if(n->type == T || n->type->etype == TFORW) continue; et = n->type->etype; @@ -1861,65 +1753,19 @@ prcompat(Node *nn) if(op == OPRINTN) calls = list(calls, mkcall("printnl", T, nil)); typechecklist(calls, Etop); - walkexprlist(calls, nil); + walkexprlist(calls, init); if(op == OPANIC || op == OPANICN) r = mkcall("panicl", T, nil); else r = nod(OEMPTY, N, N); typecheck(&r, Etop); - walkexpr(&r, nil); + walkexpr(&r, init); r->ninit = calls; return r; } Node* -makecompat(Node *n) -{ - Type *t; - Node *l, *r; - NodeList *args, *init; - -//dump("makecompat", n); - args = n->list; - if(args == nil) { - yyerror("make requires type argument"); - return n; - } - r = N; - l = args->n; - args = args->next; - init = nil; - walkexpr(&l, &init); - if(l->op != OTYPE) { - yyerror("cannot make(expr)"); - return n; - } - t = l->type; - n->type = t; - n->list = args; - - if(t != T) - switch(t->etype) { - case TARRAY: - if(!isslice(t)) - goto bad; - return arrayop(n); - case TMAP: - return mapop(n, nil); - case TCHAN: - return chanop(n, nil); - } - -bad: - if(!n->diag) { - n->diag = 1; - yyerror("cannot make(%T)", t); - } - return n; -} - -Node* callnew(Type *t) { Node *fn; @@ -1930,93 +1776,6 @@ callnew(Type *t) return mkcall1(fn, ptrto(t), nil, nodintconst(t->width)); } -Node* -stringop(Node *n, NodeList **init) -{ - Node *r, *fn; - - switch(n->op) { - default: - fatal("stringop: unknown op %O", n->op); - - case OEQ: - case ONE: - case OGE: - case OGT: - case OLE: - case OLT: - // sys_cmpstring(s1, s2) :: 0 - r = mkcall("cmpstring", types[TINT], init, - conv(n->left, types[TSTRING]), - conv(n->right, types[TSTRING])); - r = nod(n->op, r, nodintconst(0)); - typecheck(&r, Erv); - break; - - case OADD: - // sys_catstring(s1, s2) - r = mkcall("catstring", n->type, init, - conv(n->left, types[TSTRING]), - conv(n->right, types[TSTRING])); - break; - - case OASOP: - // sys_catstring(s1, s2) - switch(n->etype) { - default: - fatal("stringop: unknown op %O-%O", n->op, n->etype); - - case OADD: - // s1 = sys_catstring(s1, s2) - if(n->etype != OADD) - fatal("stringop: not cat"); - r = mkcall("catstring", n->left->type, init, - conv(n->left, types[TSTRING]), - conv(n->right, types[TSTRING])); - r = nod(OAS, n->left, r); - break; - } - break; - - - case OSLICE: - // sys_slicestring(s, lb, hb) - r = mkcall("slicestring", n->type, init, - conv(n->left, types[TSTRING]), - conv(n->right->left, types[TINT]), - conv(n->right->right, types[TINT])); - break; - - case OINDEX: - // TODO(rsc): should be done in back end - // sys_indexstring(s, i) - r = mkcall("indexstring", n->type, init, - conv(n->left, types[TSTRING]), - conv(n->right, types[TINT])); - break; - - case OCONV: - // sys_intstring(v) - r = mkcall("intstring", n->type, init, - conv(n->left, types[TINT64])); // TODO(rsc): int64?! - break; - - case OARRAY: - // arraystring([]byte) string; - r = n->left; - fn = syslook("arraystring", 0); - if(r->type != T && r->type->type != T) { - if(istype(r->type->type, TINT) || istype(r->type->type->type, TINT)) { - // arraystring([]byte) string; - fn = syslook("arraystringi", 0); - } - } - r = mkcall1(fn, n->type, init, r); - break; - } - return r; -} - Type* fixmap(Type *t) { @@ -2061,7 +1820,7 @@ mapop(Node *n, NodeList **init) { Node *r, *a, *l; Type *t; - Node *fn, *hint; + Node *fn; int cl, cr; NodeList *args; @@ -2070,49 +1829,9 @@ mapop(Node *n, NodeList **init) default: fatal("mapop: unknown op %O", n->op); - case OMAKE: - cl = count(n->list); - if(cl > 1) - yyerror("too many arguments to make map"); - - // newmap(keysize int, valsize int, - // keyalg int, valalg int, - // hint int) (hmap map[any-1]any-2); - - t = fixmap(n->type); - if(t == T) - break; - - fn = syslook("newmap", 1); - argtype(fn, t->down); // any-1 - argtype(fn, t->type); // any-2 - - if(cl == 1) - hint = n->list->n; - else - hint = nodintconst(0); - - r = mkcall1(fn, n->type, init, - nodintconst(t->down->width), // key width - nodintconst(t->type->width), // val width - nodintconst(algtype(t->down)), // key algorithm - nodintconst(algtype(t->type)), // val algorithm - hint); - break; - - case OINDEX: - // mapaccess1(hmap map[any]any, key any) (val any); - - t = fixmap(n->left->type); - if(t == T) - break; - - r = mkcall1(mapfn("mapaccess1", t), t->type, init, n->left, n->right); - break; - case OAS: // mapassign1(hmap map[any-1]any-2, key any-3, val any-4); - if(n->left->op != OINDEX) + if(n->left->op != OINDEXMAP) goto shape; t = fixmap(n->left->left->type); @@ -2135,7 +1854,7 @@ mapop(Node *n, NodeList **init) assign2: // mapassign2(hmap map[any]any, key any, val any, pres bool); l = n->list->n; - if(l->op != OINDEX) + if(l->op != OINDEXMAP) goto shape; t = fixmap(l->left->type); @@ -2150,7 +1869,7 @@ mapop(Node *n, NodeList **init) //dump("access2", n); r = n->rlist->n; - if(r->op != OINDEX) + if(r->op != OINDEXMAP) goto shape; t = fixmap(r->left->type); @@ -2184,8 +1903,7 @@ mapop(Node *n, NodeList **init) a = nod(OXXX, N, N); *a = *n->left; // copy of map[tmpi] - a->typecheck = 0; - a->type = T; + 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); @@ -2203,7 +1921,7 @@ shape: Node* chanop(Node *n, NodeList **init) { - Node *r, *a, *fn; + Node *r, *fn; Type *t; int cl, cr; @@ -2212,48 +1930,6 @@ chanop(Node *n, NodeList **init) default: fatal("chanop: unknown op %O", n->op); - case OCLOSE: - // closechan(hchan *chan any); - t = fixchan(n->left->type); - if(t == T) - break; - fn = syslook("closechan", 1); - argtype(fn, t); - r = mkcall1(fn, T, init, n->left); - break; - - case OCLOSED: - // closedchan(hchan *chan any) bool; - t = fixchan(n->left->type); - if(t == T) - break; - fn = syslook("closedchan", 1); - argtype(fn, t); - r = mkcall1(fn, n->type, init, n->left); - break; - - case OMAKE: - cl = count(n->list); - if(cl > 1) - yyerror("too many arguments to make chan"); - - // newchan(elemsize int, elemalg int, - // hint int) (hmap *chan[any-1]); - - t = fixchan(n->type); - if(t == T) - break; - - if(cl == 1) - a = conv(n->list->n, types[TINT]); - else - a = nodintconst(0); - r = mkcall1(chanfn("newchan", 1, t), n->type, init, - nodintconst(t->type->width), - nodintconst(algtype(t->type)), - a); - break; - case OAS2: cl = count(n->list); cr = count(n->rlist); @@ -2278,45 +1954,6 @@ chanop(Node *n, NodeList **init) r = n; walkexpr(&r, init); break; - - case ORECV: - // should not happen - nonblocking is OAS w/ ORECV now. - if(n->right != N) { - dump("recv2", n); - fatal("chanop recv2"); - } - - // chanrecv1(hchan *chan any) (elem any); - t = fixchan(n->left->type); - if(t == T) - break; - if(!(t->chan & Crecv)) { - yyerror("cannot receive from %T", t); - break; - } - - r = mkcall1(chanfn("chanrecv1", 2, t), n->type, init, n->left); - break; - - case OSEND: - t = fixchan(n->left->type); - if(t == T) - break; - if(!(t->chan & Csend)) { - yyerror("cannot send to %T", t); - break; - } - if(n->etype == 1) // clumsy hack - goto send2; - - // chansend1(hchan *chan any, elem any); - r = mkcall1(chanfn("chansend1", 2, t), T, init, n->left, n->right); - break; - - send2: - // chansend2(hchan *chan any, val any) (pres bool); - r = mkcall1(chanfn("chansend2", 2, t), n->type, init, n->left, n->right); - break; } return r; @@ -2325,6 +1962,7 @@ shape: return N; } + Type* fixarray(Type *t) { @@ -2344,104 +1982,6 @@ bad: } -Node* -arrayop(Node *n) -{ - Node *r, *nel, *max; - NodeList *args; - Type *t, *tl; - Node *fn; - int cl; - - r = n; - switch(n->op) { - default: - fatal("darrayop: unknown op %O", n->op); - - case OCONVNOP: - return n; - - case OCONV: - // arrays2d(old *any, nel int) (ary []any) - if(n->left->type == T || !isptr[n->left->type->etype]) - break; - t = fixarray(n->left->type->type); - tl = fixarray(n->type); - if(t == T || tl == T) - break; - - fn = syslook("arrays2d", 1); - argtype(fn, t); // any-1 - argtype(fn, tl->type); // any-2 - - n->left = mkcall1(fn, n->type, nil, n->left, nodintconst(t->bound)); - typecheck(&n, Erv); - walkexpr(&n, nil); - return n; - - case OAS: - n->right = arrayop(conv(n->right, n->left->type)); - return n; - - case OMAKE: - cl = count(n->list); - if(cl > 2) - yyerror("too many arguments to make array"); - - // newarray(nel int, max int, width int) (ary []any) - t = fixarray(n->type); - if(t == T) - break; - fn = syslook("newarray", 1); - argtype(fn, t->type); // any-1 - - nel = conv(n->list->n, types[TINT]); - if(cl < 2) - max = nodintconst(0); - else - max = conv(n->list->next->n, types[TINT]); - r = mkcall1(fn, n->type, nil, - nel, max, nodintconst(t->type->width)); - break; - - case OSLICE: - // arrayslices(old any, nel int, lb int, hb int, width int) (ary []any) - // arraysliced(old []any, lb int, hb int, width int) (ary []any) - - t = fixarray(n->left->type); - if(t == T) - break; - - if(t->bound >= 0) { - // static slice - args = list1(nod(OADDR, n->left, N)); // old - args = list(args, nodintconst(t->bound)); // nel - - fn = syslook("arrayslices", 1); - argtype(fn, t); // any-1 - argtype(fn, t->type); // any-2 - } else { - // dynamic slice - args = list1(n->left); // old - - fn = syslook("arraysliced", 1); - argtype(fn, t->type); // any-1 - argtype(fn, t->type); // any-2 - } - - args = list(args, conv(n->right->left, types[TINT])); // lb - args = list(args, conv(n->right->right, types[TINT])); // hb - args = list(args, nodintconst(t->type->width)); // width - - r = nod(OCALL, fn, N); - r->list = args; - typecheck(&r, Erv); - walkexpr(&r, nil); - break; - } - return r; -} - /* * assigning src to dst involving interfaces? * return op to use. @@ -2520,7 +2060,7 @@ ifacename[] = }; Node* -ifacecvt(Type *tl, Node *n, int et) +ifacecvt(Type *tl, Node *n, int et, NodeList **init) { Type *tr; Node *r, *on; @@ -2532,6 +2072,10 @@ ifacecvt(Type *tl, Node *n, int et) default: fatal("ifacecvt: unknown op %d\n", et); + case I2Isame: + case E2Esame: + return n; + case T2I: // ifaceT2I(sigi *byte, sigt *byte, elem any) (ret any); args = list1(typename(tl)); // sigi @@ -2541,6 +2085,7 @@ ifacecvt(Type *tl, Node *n, int et) on = syslook("ifaceT2I", 1); argtype(on, tr); argtype(on, tl); + dowidth(on->type); break; case I2T: @@ -2586,46 +2131,11 @@ ifacecvt(Type *tl, Node *n, int et) r = nod(OCALL, on, N); r->list = args; typecheck(&r, Erv); - walkexpr(&r, nil); + walkexpr(&r, init); return r; } Node* -ifaceop(Node *n) -{ - Node *r, *on; - NodeList *args; - - switch(n->op) { - default: - fatal("ifaceop %O", n->op); - - case OEQ: - case ONE: - // ifaceeq(i1 any-1, i2 any-2) (ret bool); - args = list1(n->left); // i1 - args = list(args, n->right); // i2 - - if(!eqtype(n->left->type, n->right->type)) - fatal("ifaceop %O %T %T", n->op, n->left->type, n->right->type); - if(isnilinter(n->left->type)) - on = syslook("efaceeq", 1); - else - on = syslook("ifaceeq", 1); - argtype(on, n->right->type); - argtype(on, n->left->type); - - r = nod(OCALL, on, N); - r->list = args; - if(n->op == ONE) - r = nod(ONOT, r, N); - typecheck(&r, Erv); - walkexpr(&r, nil); - return r; - } -} - -Node* convas(Node *n, NodeList **init) { Node *l, *r; @@ -2634,6 +2144,7 @@ convas(Node *n, NodeList **init) if(n->op != OAS) fatal("convas: not OAS %O", n->op); + n->typecheck = 1; lt = T; rt = T; @@ -2648,38 +2159,23 @@ convas(Node *n, NodeList **init) if(lt == T || rt == T) goto out; - if(n->left->op == OINDEX) - if(istype(n->left->left->type, TMAP)) { + if(n->left->op == OINDEXMAP) { n = mapop(n, init); goto out; } - if(n->left->op == OSEND) - if(n->left->type != T) { - n = chanop(n, init); - goto out; - } - if(eqtype(lt, rt)) goto out; et = ifaceas(lt, rt, 0); if(et != Inone) { - n->right = ifacecvt(lt, r, et); - goto out; - } - - if(isslice(lt) && isptr[rt->etype] && isfixedarray(rt->type)) { - if(!eqtype(lt->type->type, rt->type->type->type)) - goto bad; - n = arrayop(n); + n->right = ifacecvt(lt, r, et, init); goto out; } if(ascompat(lt, rt)) goto out; -bad: badtype(n->op, lt, rt); out: @@ -2897,15 +2393,13 @@ multi: default: goto badt; - case OINDEX: + case OINDEXMAP: // check if rhs is a map index. // if so, types are valuetype,bool if(cl != 2) goto badt; walkexpr(&nr->left, &init); t = nr->left->type; - if(!istype(t, TMAP)) - goto badt; a = mixedoldnew(ll->n, t->type); n = list1(a); a = mixedoldnew(ll->next->n, types[TBOOL]); @@ -3387,38 +2881,13 @@ reorder4(NodeList *ll) return ll; } -static void -fielddup(Node *n, Node *hash[], ulong nhash) -{ - uint h; - char *s; - Node *a; - - if(n->op != ONAME) - fatal("fielddup: not ONAME"); - s = n->sym->name; - h = stringhash(s)%nhash; - for(a=hash[h]; a!=N; a=a->ntest) { - if(strcmp(a->sym->name, s) == 0) { - yyerror("duplicate field name in struct literal: %s", s); - return; - } - } - n->ntest = hash[h]; - hash[h] = n; -} - Node* structlit(Node *n, Node *var, NodeList **init) { - Iter savel; - Type *l, *t; + Type *t; Node *r, *a; - Node* hash[101]; NodeList *nl; - int nerr; - nerr = nerrors; t = n->type; if(t->etype != TSTRUCT) fatal("structlit: not struct"); @@ -3429,141 +2898,45 @@ structlit(Node *n, Node *var, NodeList **init) } nl = n->list; - if(nl == nil || nl->n->op == OKEY) - goto keyval; - l = structfirst(&savel, &n->type); - for(; nl; nl=nl->next) { - r = nl->n; - // assignment to every field - if(l == T) - break; - if(r->op == OKEY) { - yyerror("mixture of value and field:value initializers"); - return var; - } - - // build list of var.field = expr - a = nod(ODOT, var, newname(l->sym)); - a = nod(OAS, a, r); + if(count(n->list) < structcount(t)) { + a = nod(OAS, var, N); typecheck(&a, Etop); walkexpr(&a, init); - if(nerr != nerrors) - return var; *init = list(*init, a); - - l = structnext(&savel); } - if(l != T) - yyerror("struct literal expect expr of type %T", l); - if(nl != nil) - yyerror("struct literal too many expressions"); - return var; - -keyval: - memset(hash, 0, sizeof(hash)); - a = nod(OAS, var, N); - typecheck(&a, Etop); - walkexpr(&a, init); - *init = list(*init, a); for(; nl; nl=nl->next) { r = nl->n; - // assignment to field:value elements - if(r->op != OKEY) { - yyerror("mixture of field:value and value initializers"); - break; - } - // build list of var.field = expr a = nod(ODOT, var, newname(r->left->sym)); - fielddup(a->right, hash, nelem(hash)); - if(nerr != nerrors) - break; - a = nod(OAS, a, r->right); typecheck(&a, Etop); walkexpr(&a, init); - if(nerr != nerrors) - break; - *init = list(*init, a); } return var; } -static void -indexdup(Node *n, Node *hash[], ulong nhash) -{ - uint h; - Node *a; - ulong b, c; - - if(n->op != OLITERAL) - fatal("indexdup: not OLITERAL"); - - b = mpgetfix(n->val.u.xval); - h = b%nhash; - for(a=hash[h]; a!=N; a=a->ntest) { - c = mpgetfix(a->val.u.xval); - if(b == c) { - yyerror("duplicate index in array literal: %ld", b); - return; - } - } - n->ntest = hash[h]; - hash[h] = n; -} - Node* arraylit(Node *n, Node *var, NodeList **init) { Type *t; Node *r, *a; NodeList *l; - long ninit, b; - Node* hash[101]; - int nerr; - nerr = nerrors; t = n->type; - if(t->etype != TARRAY) - fatal("arraylit: not array"); - - // find max index - ninit = 0; - b = 0; - - for(l=n->list; l; l=l->next) { - r = l->n; - if(r->op == OKEY) { - evconst(r->left); - b = nonnegconst(r->left); - } - b++; - if(b > ninit) - ninit = b; - } - - b = t->bound; - if(b == -100) { - // flag for [...] - b = ninit; - if(var == N) - t = shallow(t); - t->bound = b; - } if(var == N) { var = nod(OXXX, N, N); tempname(var, t); } - if(b < 0) { + if(t->bound < 0) { // slice a = nod(OMAKE, N, N); - a->list = list(list1(typenod(t)), nodintconst(ninit)); + a->list = list(list1(typenod(t)), n->right); a = nod(OAS, var, a); typecheck(&a, Etop); walkexpr(&a, init); @@ -3571,7 +2944,7 @@ arraylit(Node *n, Node *var, NodeList **init) } else { // if entire array isnt initialized, // then clear the array - if(ninit < b) { + if(count(n->list) < t->bound) { a = nod(OAS, var, N); typecheck(&a, Etop); walkexpr(&a, init); @@ -3579,96 +2952,17 @@ arraylit(Node *n, Node *var, NodeList **init) } } - b = 0; - memset(hash, 0, sizeof(hash)); for(l=n->list; l; l=l->next) { r = l->n; // build list of var[c] = expr - if(r->op == OKEY) { - b = nonnegconst(r->left); - if(b < 0) { - yyerror("array index must be non-negative constant"); - break; - } - r = r->right; - } - - if(t->bound >= 0 && b > t->bound) { - yyerror("array index out of bounds"); - break; - } - - a = nodintconst(b); - indexdup(a, hash, nelem(hash)); - if(nerr != nerrors) - break; - - a = nod(OINDEX, var, a); - a = nod(OAS, a, r); + a = nod(OINDEX, var, r->left); + a = nod(OAS, a, r->right); typecheck(&a, Etop); walkexpr(&a, init); // add any assignments in r to top - if(nerr != nerrors) - break; - *init = list(*init, a); - b++; - } - return var; -} - -static void -keydup(Node *n, Node *hash[], ulong nhash) -{ - uint h; - ulong b; - double d; - int i; - Node *a; - Node cmp; - char *s; - - evconst(n); - if(n->op != OLITERAL) - return; // we dont check variables - - switch(n->val.ctype) { - default: // unknown, bool, nil - b = 23; - break; - case CTINT: - b = mpgetfix(n->val.u.xval); - break; - case CTFLT: - d = mpgetflt(n->val.u.fval); - s = (char*)&d; - b = 0; - for(i=sizeof(d); i>0; i--) - b = b*PRIME1 + *s++; - break; - case CTSTR: - b = 0; - s = n->val.u.sval->s; - for(i=n->val.u.sval->len; i>0; i--) - b = b*PRIME1 + *s++; - break; } - h = b%nhash; - memset(&cmp, 0, sizeof(cmp)); - for(a=hash[h]; a!=N; a=a->ntest) { - cmp.op = OEQ; - cmp.left = n; - cmp.right = a; - evconst(&cmp); - b = cmp.val.u.bval; - if(b) { - // too lazy to print the literal - yyerror("duplicate key in map literal"); - return; - } - } - n->ntest = hash[h]; - hash[h] = n; + return var; } Node* @@ -3700,16 +2994,7 @@ maplit(Node *n, Node *var, NodeList **init) memset(hash, 0, sizeof(hash)); for(l=n->list; l; l=l->next) { r = l->n; - if(r->op != OKEY) { - yyerror("map literal must have key:value pairs"); - break; - } - // build list of var[c] = expr - keydup(r->left, hash, nelem(hash)); - if(nerr != nerrors) - break; - a = nod(OINDEX, var, r->left); a = nod(OAS, a, r->right); typecheck(&a, Etop); @@ -3723,72 +3008,6 @@ maplit(Node *n, Node *var, NodeList **init) } /* - * the address of n has been taken and might be used after - * the current function returns. mark any local vars - * as needing to move to the heap. - */ -void -addrescapes(Node *n) -{ - char buf[100]; - switch(n->op) { - default: - // probably a type error already. - // dump("addrescapes", n); - break; - - case ONAME: - if(n->noescape) - break; - switch(n->class) { - case PPARAMOUT: - yyerror("cannot take address of out parameter %s", n->sym->name); - break; - case PAUTO: - case PPARAM: - // if func param, need separate temporary - // to hold heap pointer. - if(n->class == PPARAM) { - // expression to refer to stack copy - n->stackparam = nod(OPARAM, n, N); - n->stackparam->type = n->type; - n->stackparam->addable = 1; - n->stackparam->xoffset = n->xoffset; - } - - n->class |= PHEAP; - n->addable = 0; - n->ullman = 2; - n->alloc = callnew(n->type); - n->xoffset = 0; - - // create stack variable to hold pointer to heap - n->heapaddr = nod(0, N, N); - tempname(n->heapaddr, ptrto(n->type)); - snprint(buf, sizeof buf, "&%S", n->sym); - n->heapaddr->sym = lookup(buf); - break; - } - break; - - case OIND: - case ODOTPTR: - break; - - case ODOT: - case OINDEX: - // ODOTPTR has already been introduced, - // so these are the non-pointer ODOT and OINDEX. - // In &x[0], if x is a slice, then x does not - // escape--the pointer inside x does, but that - // is always a heap pointer anyway. - if(!isslice(n->left->type)) - addrescapes(n->left); - break; - } -} - -/* * walk through argin parameters. * generate and return code to allocate * copies of escaped parameters to the heap. @@ -3843,7 +3062,7 @@ vmkcall(Node *fn, Type *t, NodeList **init, va_list va) n = fn->type->intuple; for(i=0; i<n; i++) args = list(args, va_arg(va, Node*)); - + r = nod(OCALL, fn, N); r->list = args; if(fn->type->outtuple > 0) @@ -3860,7 +3079,7 @@ mkcall(char *name, Type *t, NodeList **init, ...) { Node *r; va_list va; - + va_start(va, init); r = vmkcall(syslook(name, 0), t, init, va); va_end(va); @@ -3872,7 +3091,7 @@ mkcall1(Node *fn, Type *t, NodeList **init, ...) { Node *r; va_list va; - + va_start(va, init); r = vmkcall(fn, t, init, va); va_end(va); @@ -3887,7 +3106,6 @@ conv(Node *n, Type *t) n = nod(OCONV, n, N); n->type = t; typecheck(&n, Erv); - walkexpr(&n, nil); return n; } |