]> Cypherpunks repositories - gostls13.git/commitdiff
checkpoint; still plenty to clean up
authorRuss Cox <rsc@golang.org>
Fri, 31 Jul 2009 16:29:28 +0000 (09:29 -0700)
committerRuss Cox <rsc@golang.org>
Fri, 31 Jul 2009 16:29:28 +0000 (09:29 -0700)
R=ken
OCL=32576
CL=32580

src/cmd/gc/Makefile
src/cmd/gc/builtin.c.boot
src/cmd/gc/dcl.c
src/cmd/gc/go.h
src/cmd/gc/mkbuiltin
src/cmd/gc/mkbuiltin1.c
src/cmd/gc/subr.c
src/cmd/gc/swt.c
src/cmd/gc/sys.go
src/cmd/gc/typecheck.c
src/cmd/gc/walk.c

index 2338163ac986a92826a28d3ffffe5832fd56b2d2..9273e3a0feffb62ac991dd68d543ed958e96ef38 100644 (file)
@@ -52,6 +52,11 @@ builtin.c:   sys.go unsafe.go mkbuiltin1.c mkbuiltin
        ./mkbuiltin >builtin.c || \
        (echo 'mkbuiltin failed; using bootstrap copy of builtin.c'; cp builtin.c.boot builtin.c)
 
+subr.$O: opnames.h
+
+opnames.h:     mkopnames go.h
+       ./mkopnames go.h >opnames.h
+
 clean:
        rm -f $(OFILES) *.6 enam.c 6.out a.out y.tab.h y.tab.c $(LIB) mkbuiltin1 builtin.c _builtin.c
 
index 47ee8835369dbceb4d9149f952736634415c1917..3cbb87e1ed803a6b203cb5d368a994a4b6161ab0 100644 (file)
@@ -4,7 +4,7 @@ char *sysimport =
        "func sys.throwindex ()\n"
        "func sys.throwreturn ()\n"
        "func sys.throwinit ()\n"
-       "func sys.panicl (? int32)\n"
+       "func sys.panicl ()\n"
        "func sys.printbool (? bool)\n"
        "func sys.printfloat (? float64)\n"
        "func sys.printint (? int64)\n"
index 3440de692b4b93c4597b7b42eb1583865d436595..978d05026733d4fcb804409d70c6fcf60d5daa45 100644 (file)
@@ -1670,7 +1670,7 @@ variter(NodeList *vl, Node *nt, NodeList *el)
                v = vl->n;
                tv = t;
                if(t == T) {
-                       gettype(&e, &r);
+                       typecheck(&e, Erv);
                        defaultlit(&e, T);
                        tv = e->type;
                }
index 778162d9c1da4e5ac9d25658da921b8ff93c0da8..33969ec8a2c7d2e90d82135d710aad23e54e0050 100644 (file)
@@ -320,43 +320,75 @@ enum
 {
        OXXX,
 
-       ONAME, ONONAME, OTYPE, OPACK, OLITERAL,
-       ODCL,
-       ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
-       ODCLFUNC, ODCLFIELD, ODCLARG,
-       OCMP, OPTR, OARRAY, ORANGE,
-       ORETURN, OFOR, OIF, OSWITCH, ODEFER,
-       OAS, OAS2, OASOP, OCASE, OXCASE, OFALL, OXFALL,
-       OGOTO, OPROC, OMAKE, ONEW, OEMPTY, OSELECT,
-       OLEN, OCAP, OPANIC, OPANICN, OPRINT, OPRINTN, OTYPEOF,
-       OCLOSE, OCLOSED, OBLOCK,
-
-       OOROR,
+       // names
+       ONAME,
+       ONONAME,
+       OTYPE,
+       OPACK,
+       OLITERAL,
+
+       // exprs
+       OADD, OSUB, OOR, OXOR,
+       OADDR,
        OANDAND,
+       OARRAY,
+       OAS, OAS2, OASOP,
+       OBAD,
+       OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
+       OCAP,
+       OCLOSE,
+       OCLOSED,
+       OCOMPOS, OCOMPSLICE, OCOMPMAP,
+       OCONV, OCONVNOP, OCONVRUNE, OCONVSTRB, OCONVSTRI, OCONVA2S,
+       ODCL, ODCLFUNC, ODCLFIELD, ODCLARG,
+       ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
+       ODOTTYPE,
        OEQ, ONE, OLT, OLE, OGE, OGT,
-       OADD, OSUB, OOR, OXOR,
-       OMUL, ODIV, OMOD, OLSH, ORSH, OAND, OANDNOT,
-       OINC, ODEC,
        OFUNC,
-       OLABEL,
-       OBREAK,
-       OCONTINUE,
-       OADDR,
        OIND,
-       OCALL, OCALLFUNC, OCALLMETH, OCALLINTER,
-       OINDEX, OSLICE,
-       ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
-       OREGISTER, OINDREG,
+       OINDEX, OINDEXSTR, OINDEXMAP, OINDEXARR,
        OKEY, OPARAM,
-       OCOMPOS, OCOMPSLICE, OCOMPMAP,
-       OCONV, OCONVNOP, OCONVRUNE, OCONVSTRB, OCONVSTRI,
-       OCONVA2S,
-       ODOTTYPE, OTYPESW, OTYPECASE,
-       OBAD,
-
-       OTCHAN, OTMAP, OTSTRUCT, OTINTER, OTFUNC, OTARRAY,
+       OLEN,
+       OMAKE,
+       OMUL, ODIV, OMOD, OLSH, ORSH, OAND, OANDNOT,
+       ONEW,
+       ONOT, OCOM, OPLUS, OMINUS,
+       OOROR,
+       OPANIC, OPANICN, OPRINT, OPRINTN,
+       OSEND,
+       OSLICE, OSLICESTR, OSLICEARR,
+       ORECV,
 
-       OEXTEND,        // 6g internal
+       // stmts
+       OBLOCK,
+       OBREAK,
+       OCASE, OXCASE,
+       OCONTINUE,
+       ODEFER,
+       OEMPTY,
+       OFALL, OXFALL,
+       OFOR,
+       OGOTO,
+       OIF,
+       OLABEL,
+       OPROC,
+       ORANGE,
+       ORETURN,
+       OSELECT,
+       OSWITCH,
+       OTYPECASE,
+       OTYPESW,
+
+       // types
+       OTCHAN,
+       OTMAP,
+       OTSTRUCT,
+       OTINTER,
+       OTFUNC,
+       OTARRAY,
+
+       // for back ends
+       OCMP, ODEC, OEXTEND, OINC, OREGISTER, OINDREG,
 
        OEND,
 };
@@ -936,12 +968,10 @@ Type*     pkgtype(Sym*);
 /*
  *     walk.c
  */
-void   gettype(Node**, NodeList**);
 void   walk(Node*);
 void   walkstmt(Node**);
 void   walkstmtlist(NodeList*);
-void   walkexpr(Node**, int, NodeList**);
-void   walkexprlist(NodeList*, int, NodeList**);
+void   walkexprlist(NodeList*, NodeList**);
 void   walkconv(Node**, NodeList**);
 void   walkdottype(Node*, NodeList**);
 void   walkas(Node*);
@@ -949,21 +979,20 @@ void      walkbool(Node**);
 void   walkswitch(Node*);
 void   walkselect(Node*);
 void   walkdot(Node*, NodeList**);
+void   walkexpr(Node**, NodeList**);
 Node*  ascompatee1(int, Node*, Node*, NodeList**);
 NodeList*      ascompatee(int, NodeList*, NodeList*, NodeList**);
 NodeList*      ascompatet(int, NodeList*, Type**, int, NodeList**);
 NodeList*      ascompatte(int, Type**, NodeList*, int, NodeList**);
 int    ascompat(Type*, Type*);
-Node*  prcompat(NodeList*, int, int);
-Node*  nodpanic(int32);
 Node*  newcompat(Node*);
 Node*  makecompat(Node*);
-Node*  stringop(Node*, int, NodeList**);
+Node*  stringop(Node*, NodeList**);
 Type*  fixmap(Type*);
-Node*  mapop(Node*, int, NodeList**);
+Node*  mapop(Node*, NodeList**);
 Type*  fixchan(Type*);
-Node*  chanop(Node*, int, NodeList**);
-Node*  arrayop(Node*, int);
+Node*  chanop(Node*, NodeList**);
+Node*  arrayop(Node*);
 Node*  ifacecvt(Type*, Node*, int);
 Node*  ifaceop(Node*);
 int    ifaceas(Type*, Type*, int);
index b99752cc91b2bc1d7771ded4b4d31d42e2b64b7a..4e7e9144112b20130b34387445f806b86401dc8b 100755 (executable)
@@ -16,7 +16,7 @@ rm -f _builtin.c
 for i in sys unsafe
 do
        $GC -A $i.go
-       ./mkbuiltin1 $i >>_builtin.c
+       O=$O ./mkbuiltin1 $i >>_builtin.c
 done
 
 # If _builtin.c has changed vs builtin.c.boot,
index 22ef468f311b4ebad1fe0a3385439dbbea48ccc0..80bccf4896d5cce03352e242b2a8f65a37655230 100644 (file)
@@ -26,7 +26,7 @@ main(int argc, char **argv)
        name = argv[1];
        snprintf(initfunc, sizeof(initfunc), "init_%s_function", name);
 
-       snprintf(buf, sizeof(buf), "%s.6", name);
+       snprintf(buf, sizeof(buf), "%s.%s", name, getenv("O"));
        if((fin = fopen(buf, "r")) == NULL) {
                fprintf(stderr, "open %s: %s\n", buf, strerror(errno));
                exit(1);
index 20b3113e44b0798c092821c5aedfde0dc90396e7..d05830bce41e01b7acd5299d5deea1254d223a01 100644 (file)
@@ -4,6 +4,7 @@
 
 #include       "go.h"
 #include       "y.tab.h"
+#include       "opnames.h"
 
 void
 errorexit(void)
@@ -612,127 +613,6 @@ dump(char *s, Node *n)
        dodump(n, 1);
 }
 
-/*
-s%,%,\n%g
-s%\n+%\n%g
-s%^[   ]*O%%g
-s%,.*%%g
-s%.+%  [O&]            = "&",%g
-s%^    ........*\]%&~%g
-s%~    %%g
-|sort
-*/
-
-static char*
-opnames[] =
-{
-       [OADDR]         = "ADDR",
-       [OADD]          = "ADD",
-       [OANDAND]       = "ANDAND",
-       [OANDNOT]       = "ANDNOT",
-       [OAND]          = "AND",
-       [OARRAY]        = "ARRAY",
-       [OASOP]         = "ASOP",
-       [OAS]           = "AS",
-       [OAS2]          = "AS2",
-       [OBAD]          = "BAD",
-       [OBLOCK]                = "BLOCK",
-       [OBREAK]        = "BREAK",
-       [OCALLFUNC]     = "CALLFUNC",
-       [OCALLINTER]    = "CALLINTER",
-       [OCALLMETH]     = "CALLMETH",
-       [OCALL]         = "CALL",
-       [OCAP]          = "CAP",
-       [OCASE]         = "CASE",
-       [OCLOSED]       = "CLOSED",
-       [OCLOSE]        = "CLOSE",
-       [OCMP]          = "CMP",
-       [OCOMPMAP]      = "COMPMAP",
-       [OCOMPOS]       = "COMPOS",
-       [OCOMPSLICE]    = "COMPSLICE",
-       [OCOM]          = "COM",
-       [OCONTINUE]     = "CONTINUE",
-       [OCONV]         = "CONV",
-       [OCONVNOP]              = "CONVNOP",
-       [ODCLARG]       = "DCLARG",
-       [ODCLFIELD]     = "DCLFIELD",
-       [ODCLFUNC]      = "DCLFUNC",
-       [ODCL]          = "DCL",
-       [ODEC]          = "DEC",
-       [ODEFER]        = "DEFER",
-       [ODIV]          = "DIV",
-       [ODOTINTER]     = "DOTINTER",
-       [ODOTMETH]      = "DOTMETH",
-       [ODOTPTR]       = "DOTPTR",
-       [ODOTTYPE]      = "DOTTYPE",
-       [ODOT]          = "DOT",
-       [OEMPTY]        = "EMPTY",
-       [OEND]          = "END",
-       [OEQ]           = "EQ",
-       [OEXTEND]       = "EXTEND",
-       [OFALL]         = "FALL",
-       [OFOR]          = "FOR",
-       [OFUNC]         = "FUNC",
-       [OGE]           = "GE",
-       [OGOTO]         = "GOTO",
-       [OGT]           = "GT",
-       [OIF]           = "IF",
-       [OINC]          = "INC",
-       [OINDEX]        = "INDEX",
-       [OINDREG]       = "INDREG",
-       [OIND]          = "IND",
-       [OKEY]          = "KEY",
-       [OLABEL]        = "LABEL",
-       [OLEN]          = "LEN",
-       [OLE]           = "LE",
-       [OLITERAL]      = "LITERAL",
-       [OLSH]          = "LSH",
-       [OLT]           = "LT",
-       [OMAKE]         = "MAKE",
-       [OMINUS]        = "MINUS",
-       [OMOD]          = "MOD",
-       [OMUL]          = "MUL",
-       [ONAME]         = "NAME",
-       [ONEW]          = "NEW",
-       [ONE]           = "NE",
-       [ONONAME]       = "NONAME",
-       [ONOT]          = "NOT",
-       [OOROR]         = "OROR",
-       [OOR]           = "OR",
-       [OPANICN]       = "PANICN",
-       [OPANIC]        = "PANIC",
-       [OPACK]         = "PACK",
-       [OPARAM]        = "PARAM",
-       [OPLUS]         = "PLUS",
-       [OPRINTN]       = "PRINTN",
-       [OPRINT]        = "PRINT",
-       [OPROC]         = "PROC",
-       [OPTR]          = "PTR",
-       [ORANGE]        = "RANGE",
-       [ORECV]         = "RECV",
-       [OREGISTER]     = "REGISTER",
-       [ORETURN]       = "RETURN",
-       [ORSH]          = "RSH",
-       [OSELECT]       = "SELECT",
-       [OSEND]         = "SEND",
-       [OSLICE]        = "SLICE",
-       [OSUB]          = "SUB",
-       [OSWITCH]       = "SWITCH",
-       [OTCHAN]        = "TCHAN",
-       [OTMAP] = "TMAP",
-       [OTSTRUCT]      = "TSTRUCT",
-       [OTINTER]       = "TINTER",
-       [OTFUNC]        = "TFUNC",
-       [OTARRAY]       = "TARRAY",
-       [OTYPEOF]       = "TYPEOF",
-       [OTYPESW]       = "TYPESW",
-       [OTYPE]         = "TYPE",
-       [OXCASE]        = "XCASE",
-       [OXFALL]        = "XFALL",
-       [OXOR]          = "XOR",
-       [OXXX]          = "XXX",
-};
-
 static char*
 goopnames[] =
 {
@@ -2395,7 +2275,7 @@ saferef(Node *n, NodeList **init)
                *r = *n;
                r->left = l;
                typecheck(&r, Elv);
-               walkexpr(&r, Elv, init);
+               walkexpr(&r, init);
                return r;
 
        case OINDEX:
@@ -2405,11 +2285,11 @@ saferef(Node *n, NodeList **init)
                tempname(l, ptrto(n->type));
                a = nod(OAS, l, nod(OADDR, n, N));
                typecheck(&a, Etop);
-               walkexpr(&a, Etop, init);
+               walkexpr(&a, init);
                *init = list(*init, a);
                r = nod(OIND, l, N);
                typecheck(&r, Elv);
-               walkexpr(&r, Elv, init);
+               walkexpr(&r, init);
                return r;
        }
        fatal("saferef %N", n);
index aa8fa81a142cb20e51bc4b4b66a6bd94808e1967..a885bb371f1a69d0a42de948efc0bc373c11e191 100644 (file)
@@ -250,7 +250,7 @@ sw0(Node **cp, Type *place, int arg)
                        yyerror("expression case in a type switch");
                        return T;
                }
-               walkexpr(cp, Erv, nil);
+               walkexpr(cp, nil);
                break;
        case OTYPESW:
        case OTYPECASE:
@@ -596,7 +596,7 @@ exprswitch(Node *sw)
                if(sw->ntest->val.u.bval == 0)
                        arg = Sfalse;
        }
-       walkexpr(&sw->ntest, Erv, &sw->ninit);
+       walkexpr(&sw->ntest, &sw->ninit);
 
        /*
         * pass 0,1,2,3
@@ -780,7 +780,7 @@ typeswitch(Node *sw)
                yyerror("type switch must have an assignment");
                return;
        }
-       walkexpr(&sw->ntest->right, Erv, &sw->ninit);
+       walkexpr(&sw->ntest->right, &sw->ninit);
        if(!istype(sw->ntest->right->type, TINTER)) {
                yyerror("type switch must be on an interface");
                return;
index de060b6c2afc5becb4de8e5f9032dbea662ecf85..2144e7c324f74f5aa852e36e9714f1129aca8fa7 100644 (file)
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-
 package PACKAGE
 
 // emitted by compiler, not referred to by go programs
@@ -11,7 +10,7 @@ func  mal(int32) *any;
 func   throwindex();
 func   throwreturn();
 func   throwinit();
-func   panicl(int32);
+func   panicl();
 
 func   printbool(bool);
 func   printfloat(float64);
index eeadbf2896249d17cc3b875d5bada9535c39998d..ac83ca85521a9b7be9467bbbea9993290cbbdeba 100644 (file)
@@ -315,7 +315,9 @@ reswitch:
         * exprs
         */
        case OADDR:
-               l = typecheck(&n->left, Elv);
+               typecheck(&n->left, Elv);
+               defaultlit(&n->left, T);
+               l = n->left;
                if((t = l->type) == T)
                        goto error;
                n->type = ptrto(t);
@@ -452,6 +454,9 @@ reswitch:
                        break;
 
                case TMAP:
+                       n->etype = 0;
+                       if(top & Elv)
+                               n->etype = 1;   // clumsy hack
                        ok |= Erv | Elv;
                        defaultlit(&n->right, t->down);
                        n->type = t->type;
@@ -499,6 +504,9 @@ reswitch:
                if((t = r->type) == T)
                        goto error;
                // TODO: more aggressive
+               n->etype = 0;
+               if(top & Erv)
+                       n->etype = 1;   // clumsy hack
                ok |= Etop | Erv;
                n->type = types[TBOOL];
                goto ret;
@@ -539,12 +547,15 @@ reswitch:
                        goto error;
 
                case TARRAY:
-                       ok |= Elv;
-                       n = arrayop(n, Erv);
+                       n->type = typ(TARRAY);
+                       n->type->type = t;
+                       n->type->bound = -1;
+                       n = arrayop(n);
                        break;
 
                case TSTRING:
-                       n = stringop(n, Erv, nil);
+                       n->type = t;
+                       n = stringop(n, nil);
                        break;
                }
                goto ret;
index 6e203a964461584fcd5a298cf9162e6f98f8cb55..91f1ea875ae75eb4d05451825667a11c38ff9bbd 100644 (file)
@@ -6,6 +6,13 @@
 
 static Node*   curfn;
 
+static Node*   prcompat(Node*);
+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*);
+
 enum
 {
        Inone,
@@ -72,6 +79,7 @@ void
 walk(Node *fn)
 {
        char s[50];
+       // int nerr;
 
        curfn = fn;
        if(debug['W']) {
@@ -81,7 +89,12 @@ 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)
+               return;
+       */
        walkstmtlist(curfn->nbody);
        if(debug['W']) {
                snprint(s, sizeof(s), "after walk %S", curfn->nname->sym);
@@ -228,7 +241,7 @@ walkstmt(Node **np)
        case OEMPTY:
                init = n->ninit;
                n->ninit = nil;
-               walkexpr(&n, Etop, &init);
+               walkexpr(&n, &init);
                n->ninit = concat(init, n->ninit);
                break;
 
@@ -253,7 +266,7 @@ walkstmt(Node **np)
 
        case ODEFER:
                hasdefer = 1;
-               walkexpr(&n->left, Etop, &n->ninit);
+               walkexpr(&n->left, &n->ninit);
                break;
 
        case OFOR:
@@ -271,11 +284,11 @@ walkstmt(Node **np)
                break;
 
        case OPROC:
-               walkexpr(&n->left, Etop, &n->ninit);
+               walkexpr(&n->left, &n->ninit);
                break;
 
        case ORETURN:
-               walkexprlist(n->list, Erv, &n->ninit);
+               walkexprlist(n->list, &n->ninit);
                if(curfn->type->outnamed && n->list == nil) {
                        // print("special return\n");
                        break;
@@ -311,20 +324,20 @@ walkstmt(Node **np)
  */
 
 void
-walkexprlist(NodeList *l, int top, NodeList **init)
+walkexprlist(NodeList *l, NodeList **init)
 {
        for(; l; l=l->next)
-               walkexpr(&l->n, top, init);
+               walkexpr(&l->n, init);
 }
 
 void
-walkexpr(Node **np, int top, NodeList **init)
+walkexpr(Node **np, NodeList **init)
 {
        Node *r, *l;
        NodeList *ll, *lr;
        Type *t;
        Sym *s;
-       int et, cl, cr, typeok, op;
+       int et, cl, cr;
        int32 lno;
        Node *n;
 
@@ -334,10 +347,8 @@ walkexpr(Node **np, int top, NodeList **init)
                return;
 
        lno = setlineno(n);
-       typeok = top & Etype;
-       top &= ~Etype;
 
-       if(debug['w'] > 1 && top == Etop)
+       if(debug['w'] > 1)
                dump("walk-before", n);
 
        if(n->typecheck != 1) {
@@ -377,51 +388,36 @@ reswitch:
        case ODOTPTR:
        case ODOTMETH:
        case ODOTINTER:
-               walkexpr(&n->left, Erv, init);
-               goto ret;
-
        case OIND:
-               walkexpr(&n->left, Erv | Etype, init);
+               walkexpr(&n->left, init);
                goto ret;
 
-       case OPRINT:
-               if(top != Etop)
-                       goto nottop;
-               walkexprlist(n->list, Erv, init);
-               n = prcompat(n->list, 0, 0);
-//dump("prcompat", n);
+       case OLSH:
+       case ORSH:
+       case OAND:
+       case OOR:
+       case OXOR:
+       case OANDAND:
+       case OOROR:
+       case OSUB:
+       case OMUL:
+               walkexpr(&n->left, init);
+               walkexpr(&n->right, init);
                goto ret;
 
+       case OPRINT:
        case OPRINTN:
-               if(top != Etop)
-                       goto nottop;
-               walkexprlist(n->list, Erv, init);
-               n = prcompat(n->list, 1, 0);
-               goto ret;
-
        case OPANIC:
-               if(top != Etop)
-                       goto nottop;
-               walkexprlist(n->list, Erv, init);
-               n = prcompat(n->list, 0, 1);
-               goto ret;
-
        case OPANICN:
-               if(top != Etop)
-                       goto nottop;
-               walkexprlist(n->list, Erv, init);
-               n = prcompat(n->list, 2, 1);
+               walkexprlist(n->list, init);
+               n = prcompat(n);
                goto ret;
 
        case OLITERAL:
-               if(!(top & Erv))
-                       goto nottop;
                n->addable = 1;
                goto ret;
 
        case ONAME:
-               if(top == Etop)
-                       goto nottop;
                if(!(n->class & PHEAP) && n->class != PPARAMREF)
                        n->addable = 1;
                if(n->type == T) {
@@ -437,9 +433,6 @@ reswitch:
                goto ret;
 
        case OCALL:
-               if(top == Elv)
-                       goto nottop;
-
                if(n->left == N)
                        goto ret;
 
@@ -450,7 +443,7 @@ reswitch:
                        goto reswitch;
                }
 
-               walkexpr(&n->left, Erv | Etype | Ecall, init);
+               walkexpr(&n->left, init);
                defaultlit(&n->left, T);
 
                t = n->left->type;
@@ -466,8 +459,6 @@ reswitch:
                        break;
                case OTYPE:
                        n->op = OCONV;
-                       if(!(top & Erv))
-                               goto nottop;
                        // turn CALL(type, arg) into CONV(arg) w/ type.
                        n->type = n->left->type;
                        if(n->list == nil) {
@@ -492,22 +483,7 @@ reswitch:
                }
 
                dowidth(t);
-               n->type = *getoutarg(t);
-               switch(t->outtuple) {
-               case 0:
-                       if(top == Erv) {
-                               yyerror("function requires a return type");
-                               n->type = types[TINT];
-                       }
-                       break;
-
-               case 1:
-                       if(n->type != T && n->type->type != T && n->type->type->type != T)
-                               n->type = n->type->type->type;
-                       break;
-               }
-
-               walkexprlist(n->list, Erv, init);
+               walkexprlist(n->list, init);
 
                switch(n->op) {
                default:
@@ -545,12 +521,10 @@ reswitch:
                goto ret;
 
        case OAS:
-               if(top != Etop)
-                       goto nottop;
                *init = concat(*init, n->ninit);
                n->ninit = nil;
-               walkexpr(&n->left, Elv, init);
-               walkexpr(&n->right, Erv, init);
+               walkexpr(&n->left, init);
+               walkexpr(&n->right, init);
                l = n->left;
                r = n->right;
                if(l == N || r == N)
@@ -561,18 +535,16 @@ reswitch:
                goto ret;
 
        case OAS2:
-               if(top != Etop)
-                       goto nottop;
                *init = concat(*init, n->ninit);
                n->ninit = nil;
 
-               walkexprlist(n->list, Elv, init);
+               walkexprlist(n->list, init);
 
                cl = count(n->list);
                cr = count(n->rlist);
                if(cl == cr) {
                multias:
-                       walkexprlist(n->rlist, Erv, init);
+                       walkexprlist(n->rlist, init);
                        ll = ascompatee(OAS, n->list, n->rlist, init);
                        ll = reorder3(ll);
                        n = liststmt(ll);
@@ -590,7 +562,7 @@ reswitch:
                case OCALL:
                        if(cr == 1) {
                                // a,b,... = fn()
-                               walkexpr(&r, Erv, init);
+                               walkexpr(&r, init);
                                if(r->type == T || r->type->etype != TSTRUCT)
                                        break;
                                ll = ascompatet(n->op, n->list, &r->type, 0, init);
@@ -602,10 +574,10 @@ reswitch:
                case OINDEX:
                        if(cl == 2 && cr == 1) {
                                // a,b = map[] - mapaccess2
-                               walkexpr(&r->left, Erv, init);
+                               walkexpr(&r->left, init);
                                if(!istype(r->left->type, TMAP))
                                        break;
-                               l = mapop(n, top, init);
+                               l = mapop(n, init);
                                if(l == N)
                                        break;
                                n = l;
@@ -616,10 +588,10 @@ reswitch:
                case ORECV:
                        if(cl == 2 && cr == 1) {
                                // a,b = <chan - chanrecv2
-                               walkexpr(&r->left, Erv, init);
+                               walkexpr(&r->left, init);
                                if(!istype(r->left->type, TCHAN))
                                        break;
-                               l = chanop(n, top, init);
+                               l = chanop(n, init);
                                if(l == N)
                                        break;
                                n = l;
@@ -676,7 +648,7 @@ reswitch:
                                // map[] = a,b - mapassign2
                                if(!istype(l->left->type, TMAP))
                                        break;
-                               l = mapop(n, top, init);
+                               l = mapop(n, init);
                                if(l == N)
                                        break;
                                n = l;
@@ -694,13 +666,11 @@ reswitch:
                walkdottype(n, init);
                // fall through
        case OCONV:
-               if(!(top & Erv))
-                       goto nottop;
                walkconv(&n, init);
                goto ret;
 
        case OCOMPOS:
-               walkexpr(&n->right, Etype, init);
+               walkexpr(&n->right, init);
                t = n->right->type;
                n->type = t;
                if(t == T)
@@ -727,47 +697,43 @@ reswitch:
                goto ret;
 
        case OASOP:
-               if(top != Etop)
-                       goto nottop;
-               walkexpr(&n->left, Elv, init);
+               walkexpr(&n->left, init);
                l = n->left;
                if(l->op == OINDEX && istype(l->left->type, TMAP))
-                       n = mapop(n, top, init);
-               if(n->etype == OLSH || n->etype == ORSH)
-                       goto shft;
-               goto com;
-
-       case OLSH:
-       case ORSH:
-               if(!(top & Erv))
-                       goto nottop;
-               walkexpr(&n->left, Erv, init);
-
-       shft:
-               walkexpr(&n->right, Erv, init);
-               if(n->left == N || n->right == N)
-                       goto ret;
-               evconst(n);
-               if(n->op == OLITERAL)
+                       n = mapop(n, init);
+               walkexpr(&n->right, init);
+               if(n->etype == OANDNOT) {
+                       n->etype = OAND;
+                       n->right = nod(OCOM, n->right, N);
+                       n->right->type = n->right->left->type;
                        goto ret;
-               // do NOT defaultlit n->left.
-               // let parent defaultlit or convlit instead.
-               defaultlit(&n->right, types[TUINT]);
-               if(n->left->type == T || n->right->type == T)
+               }
+               if(istype(n->left->type, TSTRING)) {
+                       n = stringop(n, init);
                        goto ret;
-               et = n->right->type->etype;
-               if(issigned[et] || !isint[et])
-                       goto badt;
-               // check of n->left->type happens in second switch.
+               }
+               
+               /*
+                * on 32-bit arch, rewrite 64-bit ops into l = l op r
+                */
+               et = n->left->type->etype;
+               if(widthptr == 4 && (et == TUINT64 || et == TINT64)) {
+                       l = saferef(n->left, init);
+                       r = nod(OAS, l, nod(n->etype, l, n->right));
+                       typecheck(&r, Etop);
+                       walkexpr(&r, init);
+                       n = r;
+               }
                goto ret;
 
-       case OMOD:
-       case OAND:
        case OANDNOT:
-       case OOR:
-       case OXOR:
-       case OANDAND:
-       case OOROR:
+               walkexpr(&n->left, init);
+               walkexpr(&n->right, init);
+               n->op = OAND;
+               n->right = nod(OCOM, n->right, N);
+               n->right->type = n->right->left->type;
+               goto ret;
+
        case OEQ:
        case ONE:
        case OLT:
@@ -775,233 +741,93 @@ reswitch:
        case OGE:
        case OGT:
        case OADD:
-       case OSUB:
-       case OMUL:
-       case ODIV:
-               if(!(top & Erv))
-                       goto nottop;
-               walkexpr(&n->left, Erv, init);
-
-       com:
-               walkexpr(&n->right, Erv, init);
-               if(n->left == N || n->right == N)
+               walkexpr(&n->left, init);
+               walkexpr(&n->right, init);
+               if(istype(n->left->type, TSTRING)) {
+                       n = stringop(n, nil);
                        goto ret;
-               if(n->left->type == T || n->right->type == T)
-                       goto ret;
-
-               switch(n->op) {
-               case OANDNOT:
-                       n->op = OAND;
-                       n->right = nod(OCOM, n->right, N);
-                       n->right->type = n->right->left->type;
-                       break;
-
-               case OASOP:
-                       if(n->etype == OANDNOT) {
-                               n->etype = OAND;
-                               n->right = nod(OCOM, n->right, N);
-                               n->right->type = n->right->left->type;
-                               break;
-                       }
-                       if(istype(n->left->type, TSTRING)) {
-                               n = stringop(n, top, init);
-                               goto ret;
-                       }
-                       break;
-
-               case OEQ:
-               case ONE:
-               case OLT:
-               case OLE:
-               case OGE:
-               case OGT:
-               case OADD:
-                       if(istype(n->left->type, TSTRING)) {
-                               n = stringop(n, top, nil);
-                               goto ret;
-                       }
-                       break;
                }
-               
-               switch(n->op) {
-               case OEQ:
-               case ONE:
-                       if(isinter(n->left->type)) {
-                               n = ifaceop(n);
-                               goto ret;
-                       }
-                       break;
+               if(isinter(n->left->type)) {
+                       n = ifaceop(n);
+                       goto ret;
                }
-               
+               goto ret;
+
+       case ODIV:
+       case OMOD:
                /*
                 * rewrite div and mod into function calls
                 * on 32-bit architectures.
                 */
-               switch(n->op) {
-               case ODIV:
-               case OMOD:
-                       et = n->left->type->etype;
-                       if(widthptr > 4 || (et != TUINT64 && et != TINT64))
-                               break;
-                       if(et == TINT64)
-                               strcpy(namebuf, "int64");
-                       else
-                               strcpy(namebuf, "uint64");
-                       if(n->op == ODIV)
-                               strcat(namebuf, "div");
-                       else
-                               strcat(namebuf, "mod");
-                       l = syslook(namebuf, 0);
-                       n->left = nod(OCONV, n->left, N);
-                       n->left->type = types[et];
-                       n->right = nod(OCONV, n->right, N);
-                       n->right->type = types[et];
-                       r = nod(OCALL, l, N);
-                       r->list = list(list1(n->left), n->right);
-                       r = nod(OCONV, r, N);
-                       r->type = n->left->left->type;
-                       typecheck(&r, Erv);
-                       walkexpr(&r, Erv, init);
-                       n = r;
-                       break;
-       
-               case OASOP:
-                       et = n->left->type->etype;
-                       if(widthptr > 4 || (et != TUINT64 && et != TINT64))
-                               break;
-                       l = saferef(n->left, init);
-                       r = nod(OAS, l, nod(n->etype, l, n->right));
-                       typecheck(&r, Etop);
-                       walkexpr(&r, Etop, init);
-                       n = r;
-                       break;
-               }
+               walkexpr(&n->left, init);
+               walkexpr(&n->right, init);
+               et = n->left->type->etype;
+               if(widthptr > 4 || (et != TUINT64 && et != TINT64))
+                       goto ret;
+               if(et == TINT64)
+                       strcpy(namebuf, "int64");
+               else
+                       strcpy(namebuf, "uint64");
+               if(n->op == ODIV)
+                       strcat(namebuf, "div");
+               else
+                       strcat(namebuf, "mod");
+               n = mkcall(namebuf, n->type, init,
+                       conv(n->left, types[et]), conv(n->right, types[et]));
                goto ret;
 
        case OINDEX:
-               if(top == Etop)
-                       goto nottop;
-
-               walkexpr(&n->left, Erv, init);
-               walkexpr(&n->right, Erv, init);
-
+               walkexpr(&n->left, init);
+               walkexpr(&n->right, init);
                if(n->left == N || n->right == N)
                        goto ret;
-
-               defaultlit(&n->left, T);
-
                t = n->left->type;
                if(t == T)
                        goto ret;
 
                switch(t->etype) {
-               default:
-                       defaultlit(&n->right, T);
-                       goto badt;
-
                case TSTRING:
-                       // right side must be an int
-                       if(!(top & Erv))
-                               goto nottop;
-                       defaultlit(&n->right, types[TINT]);
-                       if(n->right->type == T)
-                               break;
-                       if(!isint[n->right->type->etype])
-                               goto badt;
-                       n = stringop(n, top, nil);
+                       n = stringop(n, nil);
                        break;
 
                case TMAP:
-                       // right side must be map type
-                       defaultlit(&n->right, t->down);
-                       if(n->right->type == T)
-                               break;
-                       if(!eqtype(n->right->type, t->down))
-                               goto badt;
-                       n->type = t->type;
-                       if(top == Erv)
-                               n = mapop(n, top, nil);
-                       break;
-
-               case TARRAY:
-                       // right side must be an int
-                       defaultlit(&n->right, types[TINT]);
-                       if(n->right->type == T)
-                               break;
-                       if(!isint[n->right->type->etype])
-                               goto badt;
-                       n->type = t->type;
+                       if(n->etype != 1)       // clumsy hack
+                               n = mapop(n, nil);
                        break;
                }
                goto ret;
 
        case OCLOSE:
-               if(top != Etop)
-                       goto nottop;
-               walkexpr(&n->left, Erv, init);          // chan
-               n = chanop(n, top, nil);
-               goto ret;
-
        case OCLOSED:
-               if(top == Elv)
-                       goto nottop;
-               walkexpr(&n->left, Erv, init);          // chan
-               n = chanop(n, top, nil);
-               goto ret;
-
        case OSEND:
-               if(top == Elv)
-                       goto nottop;
-               walkexpr(&n->left, Erv, init);  // chan
-               walkexpr(&n->right, Erv, init); // e
-               n = chanop(n, top, nil);
-               goto ret;
-
        case ORECV:
-               if(top == Elv)
-                       goto nottop;
-               if(n->right == N) {
-                       walkexpr(&n->left, Erv, init);          // chan
-                       n = chanop(n, top, init);       // returns e blocking
-                       goto ret;
-               }
-               walkexpr(&n->left, Elv, init);          // e
-               walkexpr(&n->right, Erv, init); // chan
-               n = chanop(n, top, nil);        // returns bool non-blocking
+               walkexpr(&n->left, init);
+               walkexpr(&n->right, init);
+               n = chanop(n, init);
                goto ret;
 
        case OSLICE:
-               if(top == Etop)
-                       goto nottop;
-
-               walkexpr(&n->left, top, init);
-               walkexpr(&n->right->left, Erv, init);
-               walkexpr(&n->right->right, Erv, init);
+               walkexpr(&n->left, init);
+               walkexpr(&n->right->left, init);
+               walkexpr(&n->right->right, init);
                if(n->left == N || n->right == N)
                        goto ret;
-               defaultlit(&n->left, T);
-               defaultlit(&n->right->left, types[TUINT]);
-               defaultlit(&n->right->right, types[TUINT]);
                t = n->left->type;
                if(t == T)
                        goto ret;
                if(t->etype == TSTRING) {
-                       n = stringop(n, top, nil);
+                       n = stringop(n, nil);
                        goto ret;
                }
                if(t->etype == TARRAY) {
-                       n = arrayop(n, top);
+                       n = arrayop(n);
                        goto ret;
                }
-               badtype(OSLICE, n->left->type, T);
                goto ret;
 
        case OADDR:
-               if(!(top & Erv))
-                       goto nottop;
-               defaultlit(&n->left, T);
                if(n->left->op == OCOMPOS) {
-                       walkexpr(&n->left->right, Etype, init);
+                       walkexpr(&n->left->right, init);
                        n->left->type = n->left->right->type;
                        if(n->left->type == T)
                                goto ret;
@@ -1019,7 +845,7 @@ reswitch:
 
                        nas = nod(OAS, nvar, callnew(n->left->type));
                        typecheck(&nas, Etop);
-                       walkexpr(&nas, Etop, init);
+                       walkexpr(&nas, init);
                        *init = list(*init, nas);
 
                        nstar = nod(OIND, nvar, N);
@@ -1039,7 +865,7 @@ reswitch:
                                goto badlit;
                        }
 
-//                     walkexpr(&n->left->left, Erv, init);
+//                     walkexpr(&n->left->left, init);
                        n = nvar;
                        goto ret;
                }
@@ -1053,7 +879,7 @@ reswitch:
                }
                if(n->left == N)
                        goto ret;
-               walkexpr(&n->left, Elv, init);
+               walkexpr(&n->left, init);
                t = n->left->type;
                if(t == T)
                        goto ret;
@@ -1062,21 +888,17 @@ reswitch:
                goto ret;
 
        case OMAKE:
-               if(!(top & Erv))
-                       goto nottop;
                n = makecompat(n);
                goto ret;
 
        case ONEW:
-               if(!(top & Erv))
-                       goto nottop;
                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, Etype, init);
+               walkexpr(&n->list->n, init);
                l = n->list->n;
                if((t = l->type) == T)
                        ;
@@ -1084,69 +906,12 @@ reswitch:
                        n = callnew(t);
                goto ret;
        }
-       fatal("missing switch %#O", n->op);
-
-nottop:
-       if(n->diag)
-               goto ret;
-       n->diag = 1;
-       switch(top | typeok) {
-       default:
-               yyerror("didn't expect %O here [top=%d]", n->op, top);
-               break;
-       case Etype:
-               yyerror("operation %O not allowed in type context", n->op);
-               break;
-       case Etop:
-               yyerror("operation %O not allowed in statement context", n->op);
-               break;
-       case Elv:
-               yyerror("operation %O not allowed in assignment context", n->op);
-               break;
-       case Erv:
-       case Erv | Etype:
-               yyerror("operation %O not allowed in expression context", n->op);
-               break;
-       }
-       goto ret;
-
-badt:
-       if(n->diag)
-               goto ret;
-       n->diag = 1;
-       if(n->right == N) {
-               if(n->left == N) {
-                       badtype(n->op, T, T);
-                       goto ret;
-               }
-               badtype(n->op, n->left->type, T);
-               goto ret;
-       }
-       op = n->op;
-       if(op == OASOP)
-               op = n->etype;
-       badtype(op, n->left->type, n->right->type);
-       goto ret;
+       fatal("missing switch %O", n->op);
 
 ret:
-       if(debug['w'] && top == Etop && n != N)
+       if(debug['w'] && n != N)
                dump("walk", n);
 
-       if(typeok && top == 0) {        // must be type
-               if(n->op != OTYPE) {
-                       if(n->sym) {
-                               if(!n->sym->undef)
-                                       yyerror("%S is not a type", n->sym);
-                       } else {
-                               yyerror("expr %O is not type", n->op);
-                               n->op = OTYPE;  // leads to fewer errors later
-                               n->type = T;
-                       }
-               }
-       }
-       if(!typeok && n->op == OTYPE)
-               yyerror("cannot use type %T as expr", n->type);
-
        ullmancalc(n);
        lineno = lno;
        *np = n;
@@ -1160,7 +925,7 @@ walkbool(Node **np)
        n = *np;
        if(n == N)
                return;
-       walkexpr(np, Erv, &n->ninit);
+       walkexpr(np, &n->ninit);
        defaultlit(np, T);
        n = *np;
        if(n->type != T && !eqtype(n->type, types[TBOOL]))
@@ -1170,14 +935,11 @@ walkbool(Node **np)
 void
 walkdottype(Node *n, NodeList **init)
 {
-       walkexpr(&n->left, Erv, init);
+       walkexpr(&n->left, init);
        if(n->left == N)
                return;
-       defaultlit(&n->left, T);
-       if(!isinter(n->left->type))
-               yyerror("type assertion requires interface on left, have %T", n->left->type);
        if(n->right != N) {
-               walkexpr(&n->right, Etype, init);
+               walkexpr(&n->right, init);
                n->type = n->right->type;
                n->right = N;
        }
@@ -1197,7 +959,7 @@ walkconv(Node **np, NodeList **init)
        if(t == T)
                return;
        typecheck(&n->left, Erv);
-       walkexpr(&n->left, Erv, init);
+       walkexpr(&n->left, init);
        l = n->left;
        if(l == N)
                return;
@@ -1259,7 +1021,7 @@ walkconv(Node **np, NodeList **init)
        if(istype(t, TSTRING)) {
                et = l->type->etype;
                if(isint[et]) {
-                       n = stringop(n, Erv, nil);
+                       n = stringop(n, nil);
                        *np = n;
                        return;
                }
@@ -1268,7 +1030,7 @@ walkconv(Node **np, NodeList **init)
                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, Erv, nil);
+                       n = stringop(n, nil);
                        *np = n;
                        return;
                }
@@ -1277,7 +1039,7 @@ walkconv(Node **np, NodeList **init)
                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, Erv, nil);
+                       n = stringop(n, nil);
                        *np = n;
                        return;
                }
@@ -1290,7 +1052,7 @@ walkconv(Node **np, NodeList **init)
        // 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, Erv);
+                       n = arrayop(n);
                        *np = n;
                        return;
                }
@@ -1327,9 +1089,8 @@ bad:
 Node*
 selcase(Node *n, Node *var, NodeList **init)
 {
-       Node *a, *r, *on, *c;
+       Node *a, *r, *c;
        Type *t;
-       NodeList *args;
 
        if(n->list == nil)
                goto dflt;
@@ -1337,8 +1098,8 @@ selcase(Node *n, Node *var, NodeList **init)
        if(c->op == ORECV)
                goto recv;
 
-       walkexpr(&c->left, Erv, init);          // chan
-       walkexpr(&c->right, Erv, init); // elem
+       walkexpr(&c->left, init);               // chan
+       walkexpr(&c->right, init);      // elem
 
        t = fixchan(c->left->type);
        if(t == T)
@@ -1356,23 +1117,14 @@ selcase(Node *n, Node *var, NodeList **init)
        }
 
        // selectsend(sel *byte, hchan *chan any, elem any) (selected bool);
-       on = syslook("selectsend", 1);
-       argtype(on, t->type);
-       argtype(on, t->type);
-
-       a = var;                        // sel-var
-       args = list1(a);
-       a = c->left;                    // chan
-       args = list(args, a);
-       a = c->right;                   // elem
-       args = list(args, a);
+       a = mkcall1(chanfn("selectsend", 2, t), types[TBOOL], init, var, c->left, c->right);
        goto out;
 
 recv:
        if(c->right != N)
                goto recv2;
 
-       walkexpr(&c->left, Erv, init);          // chan
+       walkexpr(&c->left, init);               // chan
 
        t = fixchan(c->left->type);
        if(t == T)
@@ -1384,25 +1136,11 @@ recv:
        }
 
        // selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
-       on = syslook("selectrecv", 1);
-       argtype(on, t->type);
-       argtype(on, t->type);
-
-       a = var;                        // sel-var
-       args = list1(a);
-
-       a = c->left;                    // chan
-       args = list(args, a);
-
-       a = c->left;                    // nil elem
-       a = nod(OLITERAL, N, N);
-       a->val.ctype = CTNIL;
-       a->type = types[TNIL];
-       args = list(args, a);
+       a = mkcall1(chanfn("selectrecv", 2, t), types[TBOOL], init, var, c->left, nodnil());
        goto out;
 
 recv2:
-       walkexpr(&c->right, Erv, init); // chan
+       walkexpr(&c->right, init);      // chan
 
        t = fixchan(c->right->type);
        if(t == T)
@@ -1413,39 +1151,18 @@ recv2:
                return N;
        }
 
-       walkexpr(&c->left, Elv, init);  // check elem
-       convlit(&c->left, t->type);
-       if(!ascompat(t->type, c->left->type)) {
-               badtype(c->op, t->type, c->left->type);
-               return N;
-       }
+       walkexpr(&c->left, init);
 
        // selectrecv(sel *byte, hchan *chan any, elem *any) (selected bool);
-       on = syslook("selectrecv", 1);
-       argtype(on, t->type);
-       argtype(on, t->type);
-
-       a = var;                        // sel-var
-       args = list1(a);
-
-       a = c->right;                   // chan
-       args = list(args, a);
-
-       a = c->left;                    // elem
-       a = nod(OADDR, a, N);
-       args = list(args, a);
+       a = mkcall1(chanfn("selectrecv", 2, t), types[TBOOL], init, var, c->right, nod(OADDR, c->left, N));
        goto out;
 
 dflt:
        // selectdefault(sel *byte);
-       on = syslook("selectdefault", 0);
-       a = var;
-       args = list1(a);
+       a = mkcall("selectdefault", types[TBOOL], init, var);
        goto out;
 
 out:
-       a = nod(OCALL, on, N);
-       a->list = args;
        r = nod(OIF, N, N);
        r->ntest = a;
 
@@ -1465,7 +1182,7 @@ selectas(Node *name, Node *expr, NodeList **init)
        if(expr == N || expr->op != ORECV)
                goto bad;
 
-       walkexpr(&expr->left, Erv, init);
+       walkexpr(&expr->left, init);
        t = expr->left->type;
        if(t == T)
                goto bad;
@@ -1483,7 +1200,7 @@ walkselect(Node *sel)
 {
        Node *n, *l, *oc, *on, *r;
        Node *var, *def;
-       NodeList *args, *res, *bod, *nbod, *init, *ln;
+       NodeList *res, *bod, *nbod, *init, *ln;
        int count, op;
        int32 lno;
 
@@ -1579,20 +1296,10 @@ walkselect(Node *sel)
        setlineno(sel);
 
        // selectgo(sel *byte);
-       on = syslook("selectgo", 0);
-       r = nod(OCALL, on, N);
-       r->list = list1(var);           // sel-var
-       res = list(res, r);
+       res = list(res, mkcall("selectgo", T, nil, var));
 
        // newselect(size uint32) (sel *byte);
-       on = syslook("newselect", 0);
-
-       r = nod(OXXX, N, N);
-       nodconst(r, types[TINT], count);        // count
-       args = list1(r);
-       r = nod(OCALL, on, N);
-       r->list = args;
-       r = nod(OAS, var, r);
+       r = nod(OAS, var, mkcall("newselect", var->type, nil, nodintconst(count)));
        typecheck(&r, Etop);
        typechecklist(res, Etop);
 
@@ -1813,7 +1520,7 @@ mkdotargs(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init)
                r->left->type = r->right->type;
                r->left->xoffset += t->width;
                typecheck(&r, Etop);
-               walkexpr(&r, Etop, init);
+               walkexpr(&r, init);
                lr->n = r;
                t = t->down;
        }
@@ -2067,28 +1774,26 @@ ascompat(Type *dst, Type *src)
 }
 
 // generate code for print
-//     fmt = 0: print
-//     fmt = 1: println
-Node*
-prcompat(NodeList *all, int fmt, int dopanic)
+static Node*
+prcompat(Node *nn)
 {
        Node *r;
        Node *n;
-       NodeList *l;
+       NodeList *l, *all;
        Node *on;
        Type *t;
-       int notfirst, et;
+       int notfirst, et, op;
        NodeList *calls;
 
+       op = nn->op;
+       all = nn->list;
        calls = nil;
        notfirst = 0;
 
        for(l=all; l; l=l->next) {
-               if(notfirst) {
-                       on = syslook("printsp", 0);
-                       calls = list(calls, nod(OCALL, on, N));
-               }
-               notfirst = fmt;
+               if(notfirst)
+                       calls = list(calls, mkcall("printsp", T, nil));
+               notfirst = op == OPRINTN || op == OPANICN;
 
                typecheck(&l->n, Erv);
                n = l->n;
@@ -2153,39 +1858,21 @@ prcompat(NodeList *all, int fmt, int dopanic)
                calls = list(calls, r);
        }
 
-       if(fmt == 1 && !dopanic) {
-               on = syslook("printnl", 0);
-               calls = list(calls, nod(OCALL, on, N));
-       }
+       if(op == OPRINTN)
+               calls = list(calls, mkcall("printnl", T, nil));
        typechecklist(calls, Etop);
-       walkexprlist(calls, Etop, nil);
+       walkexprlist(calls, nil);
 
-       if(dopanic)
-               r = nodpanic(0);
+       if(op == OPANIC || op == OPANICN)
+               r = mkcall("panicl", T, nil);
        else
                r = nod(OEMPTY, N, N);
        typecheck(&r, Etop);
-       walkexpr(&r, Etop, nil);
+       walkexpr(&r, nil);
        r->ninit = calls;
        return r;
 }
 
-Node*
-nodpanic(int32 lineno)
-{
-       Node *n, *on;
-       NodeList *args;
-
-       on = syslook("panicl", 0);
-       n = nodintconst(lineno);
-       args = list1(n);
-       n = nod(OCALL, on, N);
-       n->list = args;
-       typecheck(&n, Etop);
-       walkexpr(&n, Etop, nil);
-       return n;
-}
-
 Node*
 makecompat(Node *n)
 {
@@ -2203,7 +1890,7 @@ makecompat(Node *n)
        l = args->n;
        args = args->next;
        init = nil;
-       walkexpr(&l, Etype, &init);
+       walkexpr(&l, &init);
        if(l->op != OTYPE) {
                yyerror("cannot make(expr)");
                return n;
@@ -2217,11 +1904,11 @@ makecompat(Node *n)
        case TARRAY:
                if(!isslice(t))
                        goto bad;
-               return arrayop(n, Erv);
+               return arrayop(n);
        case TMAP:
-               return mapop(n, Erv, nil);
+               return mapop(n, nil);
        case TCHAN:
-               return chanop(n, Erv, nil);
+               return chanop(n, nil);
        }
 
 bad:
@@ -2235,26 +1922,18 @@ bad:
 Node*
 callnew(Type *t)
 {
-       Node *r, *on;
-       NodeList *args;
+       Node *fn;
 
        dowidth(t);
-       on = syslook("mal", 1);
-       argtype(on, t);
-       r = nodintconst(t->width);
-       args = list1(r);
-       r = nod(OCALL, on, N);
-       r->list = args;
-       typecheck(&r, Erv);
-       walkexpr(&r, Erv, nil);
-       return r;
+       fn = syslook("mal", 1);
+       argtype(fn, t);
+       return mkcall1(fn, ptrto(t), nil, nodintconst(t->width));
 }
 
 Node*
-stringop(Node *n, int top, NodeList **init)
+stringop(Node *n, NodeList **init)
 {
-       Node *r, *c, *on;
-       NodeList *args;
+       Node *r, *fn;
 
        switch(n->op) {
        default:
@@ -2267,30 +1946,18 @@ stringop(Node *n, int top, NodeList **init)
        case OLE:
        case OLT:
                // sys_cmpstring(s1, s2) :: 0
-               on = syslook("cmpstring", 0);
-               r = nod(OCONV, n->left, N);
-               r->type = types[TSTRING];
-               args = list1(r);
-               c = nod(OCONV, n->right, N);
-               c->type = types[TSTRING];
-               args = list(args, c);
-               r = nod(OCALL, on, N);
-               r->list = args;
-               c = nodintconst(0);
-               r = nod(n->op, r, c);
+               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)
-               on = syslook("catstring", 0);
-               r = nod(OCONV, n->left, N);
-               r->type = types[TSTRING];
-               args = list1(r);
-               c = nod(OCONV, n->right, N);
-               c->type = types[TSTRING];
-               args = list(args, c);
-               r = nod(OCALL, on, N);
-               r->list = args;
+               r = mkcall("catstring", n->type, init,
+                       conv(n->left, types[TSTRING]),
+                       conv(n->right, types[TSTRING]));
                break;
 
        case OASOP:
@@ -2303,82 +1970,50 @@ stringop(Node *n, int top, NodeList **init)
                        // s1 = sys_catstring(s1, s2)
                        if(n->etype != OADD)
                                fatal("stringop: not cat");
-                       on = syslook("catstring", 0);
-                       r = nod(OCONV, n->left, N);
-                       r->type = types[TSTRING];
-                       args = list1(r);
-                       c = nod(OCONV, n->right, N);
-                       c->type = types[TSTRING];
-                       args = list(args, c);
-                       r = nod(OCALL, on, N);
-                       r->list = args;
+                       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:
-               r = nod(OCONV, n->left, N);
-               r->type = types[TSTRING];
-               args = list1(r);
 
+       case OSLICE:
                // sys_slicestring(s, lb, hb)
-               r = nod(OCONV, n->right->left, N);
-               r->type = types[TINT];
-               args = list(args, r);
-
-               c = nod(OCONV, n->right->right, N);
-               c->type = types[TINT];
-               args = list(args, c);
-
-               on = syslook("slicestring", 0);
-               r = nod(OCALL, on, N);
-               r->list = args;
+               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 = nod(OCONV, n->left, N);
-               r->type = types[TSTRING];
-               args = list1(r);
-
-               r = nod(OCONV, n->right, N);
-               r->type = types[TINT];
-               args = list(args, r);
-               on = syslook("indexstring", 0);
-               r = nod(OCALL, on, N);
-               r->list = args;
+               r = mkcall("indexstring", n->type, init,
+                       conv(n->left, types[TSTRING]),
+                       conv(n->right, types[TINT]));
                break;
 
        case OCONV:
                // sys_intstring(v)
-               r = nod(OCONV, n->left, N);
-               r->type = types[TINT64];
-               args = list1(r);
-               on = syslook("intstring", 0);
-               r = nod(OCALL, on, N);
-               r->list = args;
+               r = mkcall("intstring", n->type, init,
+                       conv(n->left, types[TINT64]));  // TODO(rsc): int64?!
                break;
 
        case OARRAY:
                // arraystring([]byte) string;
-               on = syslook("arraystring", 0);
                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;
-                               on = syslook("arraystringi", 0);
+                               fn = syslook("arraystringi", 0);
                        }
                }
-               args = list1(r);
-               r = nod(OCALL, on, N);
-               r->list = args;
+               r = mkcall1(fn, n->type, init, r);
                break;
        }
-
-       typecheck(&r, top);
-       walkexpr(&r, top, init);
        return r;
 }
 
@@ -2422,11 +2057,11 @@ bad:
 }
 
 Node*
-mapop(Node *n, int top, NodeList **init)
+mapop(Node *n, NodeList **init)
 {
        Node *r, *a, *l;
        Type *t;
-       Node *on;
+       Node *fn, *hint;
        int cl, cr;
        NodeList *args;
 
@@ -2440,9 +2075,6 @@ mapop(Node *n, int top, NodeList **init)
                if(cl > 1)
                        yyerror("too many arguments to make map");
 
-               if(!(top & Erv))
-                       goto nottop;
-
                // newmap(keysize int, valsize int,
                //      keyalg int, valalg int,
                //      hint int) (hmap map[any-1]any-2);
@@ -2451,66 +2083,31 @@ mapop(Node *n, int top, NodeList **init)
                if(t == T)
                        break;
 
-               a = nodintconst(t->down->width);        // key width
-               args = list1(a);
-               a = nodintconst(t->type->width);        // val width
-               args = list(args, a);
-               a = nodintconst(algtype(t->down));      // key algorithm
-               args = list(args, a);
-               a = nodintconst(algtype(t->type));      // val algorithm
-               args = list(args, a);
-
+               fn = syslook("newmap", 1);
+               argtype(fn, t->down);   // any-1
+               argtype(fn, t->type);   // any-2
+               
                if(cl == 1)
-                       a = n->list->n;                         // hint
+                       hint = n->list->n;
                else
-                       a = nodintconst(0);
-               args = list(args, a);
-
-               on = syslook("newmap", 1);
-
-               argtype(on, t->down);   // any-1
-               argtype(on, t->type);   // any-2
-
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Erv);
-               walkexpr(&r, top, nil);
-               r->type = n->type;
+                       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:
-               if(!(top & Erv))
-                       goto nottop;
                // mapaccess1(hmap map[any]any, key any) (val any);
 
                t = fixmap(n->left->type);
                if(t == T)
                        break;
 
-               convlit(&n->right, t->down);
-
-               if(!eqtype(n->right->type, t->down)) {
-                       badtype(n->op, n->right->type, t->down);
-                       break;
-               }
-
-               a = n->left;                            // map
-               args = list1(a);
-               a = n->right;                           // key
-               args = list(args, a);
-
-               on = syslook("mapaccess1", 1);
-
-               argtype(on, t->down);   // any-1
-               argtype(on, t->type);   // any-2
-               argtype(on, t->down);   // any-3
-               argtype(on, t->type);   // any-4
-
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Erv);
-               walkexpr(&r, Erv, nil);
-               r->type = t->type;
+               r = mkcall1(mapfn("mapaccess1", t), t->type, init, n->left, n->right);
                break;
 
        case OAS:
@@ -2522,24 +2119,7 @@ mapop(Node *n, int top, NodeList **init)
                if(t == T)
                        break;
 
-               a = n->left->left;                      // map
-               args = list1(a);
-               a = n->left->right;                     // key
-               args = list(args, a);
-               a = n->right;                           // val
-               args = list(args, a);
-
-               on = syslook("mapassign1", 1);
-
-               argtype(on, t->down);   // any-1
-               argtype(on, t->type);   // any-2
-               argtype(on, t->down);   // any-3
-               argtype(on, t->type);   // any-4
-
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Etop);
-               walkexpr(&r, Etop, init);
+               r = mkcall1(mapfn("mapassign1", t), T, init, n->left->left, n->left->right, n->right);
                break;
 
        case OAS2:
@@ -2562,22 +2142,7 @@ mapop(Node *n, int top, NodeList **init)
                if(t == T)
                        break;
 
-               args = list1(l->left);                  // map
-               args = list(args, l->right);            // key
-               args = list(args, n->rlist->n);         // val
-               args = list(args, n->rlist->next->n);   // pres
-
-               on = syslook("mapassign2", 1);
-
-               argtype(on, t->down);   // any-1
-               argtype(on, t->type);   // any-2
-               argtype(on, t->down);   // any-3
-               argtype(on, t->type);   // any-4
-
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Etop);
-               walkexpr(&r, Etop, init);
+               r = mkcall1(mapfn("mapassign2", t), T, init, l->left, l->right, n->rlist->n, n->rlist->next->n);
                break;
 
        access2:
@@ -2595,19 +2160,11 @@ mapop(Node *n, int top, NodeList **init)
                args = list1(r->left);          // map
                args = list(args, r->right);            // key
 
-               on = syslook("mapaccess2", 1);
-
-               argtype(on, t->down);   // any-1
-               argtype(on, t->type);   // any-2
-               argtype(on, t->down);   // any-3
-               argtype(on, t->type);   // any-4
-
-               a = nod(OCALL, on, N);
-               a->list = args;
-               typecheck(&a, Erv);
+               fn = mapfn("mapaccess2", t);
+               a = mkcall1(fn, getoutargx(fn->type), init, r->left, r->right);
                n->rlist = list1(a);
                typecheck(&n, Etop);
-               walkexpr(&n, Etop, init);
+               walkexpr(&n, init);
                r = n;
                break;
 
@@ -2622,34 +2179,31 @@ mapop(Node *n, int top, NodeList **init)
                r = nod(OAS, a, n->left->right);        // tmpi := index
                n->left->right = a;                     // m[tmpi]
                typecheck(&r, Etop);
-               walkexpr(&r, Etop, init);
+               walkexpr(&r, init);
                *init = list(*init, r);
 
                a = nod(OXXX, N, N);
                *a = *n->left;          // copy of map[tmpi]
+               a->typecheck = 0;
+               a->type = T;
                a = nod(n->etype, a, n->right);         // m[tmpi] op right
                r = nod(OAS, n->left, a);               // map[tmpi] = map[tmpi] op right
                typecheck(&r, Etop);
-               walkexpr(&r, Etop, init);
+               walkexpr(&r, init);
                break;
        }
        return r;
 
 shape:
        dump("shape", n);
-       fatal("mapop: cl=%d cr=%d, %O", top, n->op);
-       return N;
-
-nottop:
-       yyerror("didn't expect %O here", n->op);
+       fatal("mapop: %O", n->op);
        return N;
 }
 
 Node*
-chanop(Node *n, int top, NodeList **init)
+chanop(Node *n, NodeList **init)
 {
-       Node *r, *a, *on;
-       NodeList *args;
+       Node *r, *a, *fn;
        Type *t;
        int cl, cr;
 
@@ -2663,18 +2217,9 @@ chanop(Node *n, int top, NodeList **init)
                t = fixchan(n->left->type);
                if(t == T)
                        break;
-
-               a = n->left;                    // chan
-               args = list1(a);
-
-               on = syslook("closechan", 1);
-               argtype(on, t); // any-1
-
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Etop);
-               walkexpr(&r, top, nil);
-               r->type = n->type;
+               fn = syslook("closechan", 1);
+               argtype(fn, t);
+               r = mkcall1(fn, T, init, n->left);
                break;
 
        case OCLOSED:
@@ -2682,18 +2227,9 @@ chanop(Node *n, int top, NodeList **init)
                t = fixchan(n->left->type);
                if(t == T)
                        break;
-
-               a = n->left;                    // chan
-               args = list1(a);
-
-               on = syslook("closedchan", 1);
-               argtype(on, t); // any-1
-
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Erv);
-               walkexpr(&r, top, nil);
-               n->type = r->type;
+               fn = syslook("closedchan", 1);
+               argtype(fn, t);
+               r = mkcall1(fn, n->type, init, n->left);
                break;
 
        case OMAKE:
@@ -2708,26 +2244,14 @@ chanop(Node *n, int top, NodeList **init)
                if(t == T)
                        break;
 
-               a = nodintconst(t->type->width);        // elem width
-               args = list1(a);
-               a = nodintconst(algtype(t->type));      // elem algorithm
-               args = list(args, a);
-               a = nodintconst(0);
-               if(cl == 1) {
-                       // async buf size
-                       a = nod(OCONV, n->list->n, N);
-                       a->type = types[TINT];
-               }
-               args = list(args, a);
-
-               on = syslook("newchan", 1);
-               argtype(on, t->type);   // any-1
-
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Erv);
-               walkexpr(&r, top, nil);
-               r->type = n->type;
+               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:
@@ -2743,25 +2267,16 @@ chanop(Node *n, int top, NodeList **init)
                t = fixchan(r->left->type);
                if(t == T)
                        break;
-
                if(!(t->chan & Crecv)) {
                        yyerror("cannot receive from %T", t);
                        break;
                }
 
-               a = r->left;                    // chan
-               args = list1(a);
-
-               on = syslook("chanrecv2", 1);
-
-               argtype(on, t->type);   // any-1
-               argtype(on, t->type);   // any-2
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Etop);
+               fn = chanfn("chanrecv2", 2, t);
+               r = mkcall1(fn, getoutargx(fn->type), init, r->left);
                n->rlist->n = r;
                r = n;
-               walkexpr(&r, Etop, init);
+               walkexpr(&r, init);
                break;
 
        case ORECV:
@@ -2772,27 +2287,15 @@ chanop(Node *n, int top, NodeList **init)
                }
 
                // chanrecv1(hchan *chan any) (elem any);
-               defaultlit(&n->left, T);
                t = fixchan(n->left->type);
                if(t == T)
                        break;
-
                if(!(t->chan & Crecv)) {
                        yyerror("cannot receive from %T", t);
                        break;
                }
 
-               a = n->left;                    // chan
-               args = list1(a);
-
-               on = syslook("chanrecv1", 1);
-
-               argtype(on, t->type);   // any-1
-               argtype(on, t->type);   // any-2
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Erv);
-               walkexpr(&r, Erv, nil);
+               r = mkcall1(chanfn("chanrecv1", 2, t), n->type, init, n->left);
                break;
 
        case OSEND:
@@ -2803,39 +2306,16 @@ chanop(Node *n, int top, NodeList **init)
                        yyerror("cannot send to %T", t);
                        break;
                }
-
-               if(top != Etop)
+               if(n->etype == 1)       // clumsy hack
                        goto send2;
 
                // chansend1(hchan *chan any, elem any);
-               a = n->left;                    // chan
-               args = list1(a);
-               a = n->right;                   // e
-               args = list(args, a);
-
-               on = syslook("chansend1", 1);
-               argtype(on, t->type);   // any-1
-               argtype(on, t->type);   // any-2
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Etop);
-               walkexpr(&r, Etop, nil);
+               r = mkcall1(chanfn("chansend1", 2, t), T, init, n->left, n->right);
                break;
 
        send2:
                // chansend2(hchan *chan any, val any) (pres bool);
-               a = n->left;                    // chan
-               args = list1(a);
-               a = n->right;                   // e
-               args = list(args, a);
-
-               on = syslook("chansend2", 1);
-               argtype(on, t->type);   // any-1
-               argtype(on, t->type);   // any-2
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Etop);
-               walkexpr(&r, Etop, nil);
+               r = mkcall1(chanfn("chansend2", 2, t), n->type, init, n->left, n->right);
                break;
        }
        return r;
@@ -2865,12 +2345,12 @@ bad:
 }
 
 Node*
-arrayop(Node *n, int top)
+arrayop(Node *n)
 {
-       Node *r, *a;
+       Node *r, *nel, *max;
        NodeList *args;
        Type *t, *tl;
-       Node *on;
+       Node *fn;
        int cl;
 
        r = n;
@@ -2878,6 +2358,9 @@ arrayop(Node *n, int top)
        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])
@@ -2887,27 +2370,17 @@ arrayop(Node *n, int top)
                if(t == T || tl == T)
                        break;
 
-               args = list1(n->left);  // old
-
-               a = nodintconst(t->bound);              // nel
-               a = nod(OCONV, a, N);
-               a->type = types[TINT];
-               args = list(args, a);
+               fn = syslook("arrays2d", 1);
+               argtype(fn, t);                         // any-1
+               argtype(fn, tl->type);                  // any-2
 
-               on = syslook("arrays2d", 1);
-               argtype(on, t);                         // any-1
-               argtype(on, tl->type);                  // any-2
-               r = nod(OCALL, on, N);
-               r->list = args;
-               n->left = r;
+               n->left = mkcall1(fn, n->type, nil, n->left, nodintconst(t->bound));
                typecheck(&n, Erv);
-               walkexpr(&n, top, nil);
+               walkexpr(&n, nil);
                return n;
 
        case OAS:
-               r = nod(OCONV, n->right, N);
-               r->type = n->left->type;
-               n->right = arrayop(r, Erv);
+               n->right = arrayop(conv(n->right, n->left->type));
                return n;
 
        case OMAKE:
@@ -2919,39 +2392,16 @@ arrayop(Node *n, int top)
                t = fixarray(n->type);
                if(t == T)
                        break;
+               fn = syslook("newarray", 1);
+               argtype(fn, t->type);                   // any-1
 
-               // nel
-               a = n->list->n;
-               if(a == N) {
-                       yyerror("new slice must have size");
-                       a = nodintconst(1);
-               }
-               a = nod(OCONV, a, N);
-               a->type = types[TINT];
-               args = list1(a);
-
-               // max
+               nel = conv(n->list->n, types[TINT]);
                if(cl < 2)
-                       a = nodintconst(0);
+                       max = nodintconst(0);
                else
-                       a = n->list->next->n;
-               a = nod(OCONV, a, N);
-               a->type = types[TINT];
-               args = list(args, a);
-
-               // width
-               a = nodintconst(t->type->width);        // width
-               a = nod(OCONV, a, N);
-               a->type = types[TINT];
-               args = list(args, a);
-
-               on = syslook("newarray", 1);
-               argtype(on, t->type);                   // any-1
-               r = nod(OCALL, on, N);
-               r->list = args;
-               typecheck(&r, Erv);
-               walkexpr(&r, top, nil);
-               r->type = t;    // if t had a name, going through newarray lost it
+                       max = conv(n->list->next->n, types[TINT]);
+               r = mkcall1(fn, n->type, nil,
+                       nel, max, nodintconst(t->type->width));
                break;
 
        case OSLICE:
@@ -2964,43 +2414,29 @@ arrayop(Node *n, int top)
 
                if(t->bound >= 0) {
                        // static slice
-                       a = nod(OADDR, n->left, N);             // old
-                       args = list1(a);
-
-                       a = nodintconst(t->bound);              // nel
-                       a = nod(OCONV, a, N);
-                       a->type = types[TINT];
-                       args = list(args, a);
+                       args = list1(nod(OADDR, n->left, N));           // old
+                       args = list(args, nodintconst(t->bound));               // nel
 
-                       on = syslook("arrayslices", 1);
-                       argtype(on, t);                         // any-1
-                       argtype(on, t->type);                   // any-2
+                       fn = syslook("arrayslices", 1);
+                       argtype(fn, t);                         // any-1
+                       argtype(fn, t->type);                   // any-2
                } else {
                        // dynamic slice
-                       a = n->left;                            // old
-                       args = list1(a);
+                       args = list1(n->left);                          // old
 
-                       on = syslook("arraysliced", 1);
-                       argtype(on, t->type);                   // any-1
-                       argtype(on, t->type);                   // any-2
+                       fn = syslook("arraysliced", 1);
+                       argtype(fn, t->type);                   // any-1
+                       argtype(fn, t->type);                   // any-2
                }
 
-               a = nod(OCONV, n->right->left, N);      // lb
-               a->type = types[TINT];
-               args = list(args, a);
+               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
 
-               a = nod(OCONV, n->right->right, N);     // hb
-               a->type = types[TINT];
-               args = list(args, a);
-
-               a = nodintconst(t->type->width);        // width
-               a = nod(OCONV, a, N);
-               a->type = types[TINT];
-               args = list(args, a);
-
-               r = nod(OCALL, on, N);
+               r = nod(OCALL, fn, N);
                r->list = args;
                typecheck(&r, Erv);
+               walkexpr(&r, nil);
                break;
        }
        return r;
@@ -3150,7 +2586,7 @@ ifacecvt(Type *tl, Node *n, int et)
        r = nod(OCALL, on, N);
        r->list = args;
        typecheck(&r, Erv);
-       walkexpr(&r, Erv, nil);
+       walkexpr(&r, nil);
        return r;
 }
 
@@ -3184,7 +2620,7 @@ ifaceop(Node *n)
                if(n->op == ONE)
                        r = nod(ONOT, r, N);
                typecheck(&r, Erv);
-               walkexpr(&r, Erv, nil);
+               walkexpr(&r, nil);
                return r;
        }
 }
@@ -3214,13 +2650,13 @@ convas(Node *n, NodeList **init)
 
        if(n->left->op == OINDEX)
        if(istype(n->left->left->type, TMAP)) {
-               n = mapop(n, Elv, init);
+               n = mapop(n, init);
                goto out;
        }
 
        if(n->left->op == OSEND)
        if(n->left->type != T) {
-               n = chanop(n, Elv, init);
+               n = chanop(n, init);
                goto out;
        }
 
@@ -3236,7 +2672,7 @@ convas(Node *n, NodeList **init)
        if(isslice(lt) && isptr[rt->etype] && isfixedarray(rt->type)) {
                if(!eqtype(lt->type->type, rt->type->type->type))
                        goto bad;
-               n = arrayop(n, Etop);
+               n = arrayop(n);
                goto out;
        }
 
@@ -3389,14 +2825,14 @@ colas(NodeList *ll, NodeList *lr)
                        if(nr->left->op == ONAME && nr->left->etype != 0)
                                break;
                        typecheck(&nr->left, Erv | Etype | Ecall);
-                       walkexpr(&nr->left, Erv | Etype | Ecall, &init);
+                       walkexpr(&nr->left, &init);
                        if(nr->left->op == OTYPE)
                                break;
                        goto call;
                case OCALLMETH:
                case OCALLINTER:
                        typecheck(&nr->left, Erv);
-                       walkexpr(&nr->left, Erv, &init);
+                       walkexpr(&nr->left, &init);
                call:
                        convlit(&nr->left, types[TFUNC]);
                        t = nr->left->type;
@@ -3466,7 +2902,7 @@ multi:
                // if so, types are valuetype,bool
                if(cl != 2)
                        goto badt;
-               walkexpr(&nr->left, Erv, &init);
+               walkexpr(&nr->left, &init);
                t = nr->left->type;
                if(!istype(t, TMAP))
                        goto badt;
@@ -3493,7 +2929,7 @@ multi:
        case ORECV:
                if(cl != 2)
                        goto badt;
-               walkexpr(&nr->left, Erv, &init);
+               walkexpr(&nr->left, &init);
                t = nr->left->type;
                if(!istype(t, TCHAN))
                        goto badt;
@@ -4011,7 +3447,7 @@ structlit(Node *n, Node *var, NodeList **init)
                a = nod(ODOT, var, newname(l->sym));
                a = nod(OAS, a, r);
                typecheck(&a, Etop);
-               walkexpr(&a, Etop, init);
+               walkexpr(&a, init);
                if(nerr != nerrors)
                        return var;
                *init = list(*init, a);
@@ -4028,7 +3464,7 @@ keyval:
        memset(hash, 0, sizeof(hash));
        a = nod(OAS, var, N);
        typecheck(&a, Etop);
-       walkexpr(&a, Etop, init);
+       walkexpr(&a, init);
        *init = list(*init, a);
 
        for(; nl; nl=nl->next) {
@@ -4048,7 +3484,7 @@ keyval:
 
                a = nod(OAS, a, r->right);
                typecheck(&a, Etop);
-               walkexpr(&a, Etop, init);
+               walkexpr(&a, init);
                if(nerr != nerrors)
                        break;
 
@@ -4130,7 +3566,7 @@ arraylit(Node *n, Node *var, NodeList **init)
                a->list = list(list1(typenod(t)), nodintconst(ninit));
                a = nod(OAS, var, a);
                typecheck(&a, Etop);
-               walkexpr(&a, Etop, init);
+               walkexpr(&a, init);
                *init = list(*init, a);
        } else {
                // if entire array isnt initialized,
@@ -4138,7 +3574,7 @@ arraylit(Node *n, Node *var, NodeList **init)
                if(ninit < b) {
                        a = nod(OAS, var, N);
                        typecheck(&a, Etop);
-                       walkexpr(&a, Etop, init);
+                       walkexpr(&a, init);
                        *init = list(*init, a);
                }
        }
@@ -4170,7 +3606,7 @@ arraylit(Node *n, Node *var, NodeList **init)
                a = nod(OINDEX, var, a);
                a = nod(OAS, a, r);
                typecheck(&a, Etop);
-               walkexpr(&a, Etop, init);       // add any assignments in r to top
+               walkexpr(&a, init);     // add any assignments in r to top
                if(nerr != nerrors)
                        break;
 
@@ -4258,7 +3694,7 @@ maplit(Node *n, Node *var, NodeList **init)
        a->list = list1(typenod(t));
        a = nod(OAS, var, a);
        typecheck(&a, Etop);
-       walkexpr(&a, Etop, init);
+       walkexpr(&a, init);
        *init = list(*init, a);
 
        memset(hash, 0, sizeof(hash));
@@ -4277,7 +3713,7 @@ maplit(Node *n, Node *var, NodeList **init)
                a = nod(OINDEX, var, r->left);
                a = nod(OAS, a, r->right);
                typecheck(&a, Etop);
-               walkexpr(&a, Etop, init);
+               walkexpr(&a, init);
                if(nerr != nerrors)
                        break;
 
@@ -4392,3 +3828,94 @@ heapmoves(void)
        nn = concat(nn, paramstoheap(getinarg(curfn->type)));
        curfn->enter = concat(curfn->enter, nn);
 }
+
+static Node*
+vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
+{
+       int i, n;
+       Node *r;
+       NodeList *args;
+
+       if(fn->type == T || fn->type->etype != TFUNC)
+               fatal("mkcall %#N %T", fn, fn->type);
+
+       args = nil;
+       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)
+               typecheck(&r, Erv);
+       else
+               typecheck(&r, Etop);
+       walkexpr(&r, init);
+       r->type = t;
+       return r;
+}
+
+static Node*
+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);
+       return r;
+}
+
+static Node*
+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);
+       return r;
+}
+
+static Node*
+conv(Node *n, Type *t)
+{
+       if(eqtype(n->type, t))
+               return n;
+       n = nod(OCONV, n, N);
+       n->type = t;
+       typecheck(&n, Erv);
+       walkexpr(&n, nil);
+       return n;
+}
+
+static Node*
+chanfn(char *name, int n, Type *t)
+{
+       Node *fn;
+       int i;
+
+       if(t->etype != TCHAN)
+               fatal("chanfn %T", t);
+       fn = syslook(name, 1);
+       for(i=0; i<n; i++)
+               argtype(fn, t->type);
+       return fn;
+}
+
+static Node*
+mapfn(char *name, Type *t)
+{
+       Node *fn;
+
+       if(t->etype != TMAP)
+               fatal("mapfn %T", t);
+       fn = syslook(name, 1);
+       argtype(fn, t->down);
+       argtype(fn, t->type);
+       argtype(fn, t->down);
+       argtype(fn, t->type);
+       return fn;
+}