From: Russ Cox Date: Fri, 31 Jul 2009 16:29:28 +0000 (-0700) Subject: checkpoint; still plenty to clean up X-Git-Tag: weekly.2009-11-06~1004 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a2b8e387665c1298f2b8ded29cec56e85cfd29a4;p=gostls13.git checkpoint; still plenty to clean up R=ken OCL=32576 CL=32580 --- diff --git a/src/cmd/gc/Makefile b/src/cmd/gc/Makefile index 2338163ac9..9273e3a0fe 100644 --- a/src/cmd/gc/Makefile +++ b/src/cmd/gc/Makefile @@ -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 diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot index 47ee883536..3cbb87e1ed 100644 --- a/src/cmd/gc/builtin.c.boot +++ b/src/cmd/gc/builtin.c.boot @@ -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" diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index 3440de692b..978d050267 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -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; } diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index 778162d9c1..33969ec8a2 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -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); diff --git a/src/cmd/gc/mkbuiltin b/src/cmd/gc/mkbuiltin index b99752cc91..4e7e914411 100755 --- a/src/cmd/gc/mkbuiltin +++ b/src/cmd/gc/mkbuiltin @@ -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, diff --git a/src/cmd/gc/mkbuiltin1.c b/src/cmd/gc/mkbuiltin1.c index 22ef468f31..80bccf4896 100644 --- a/src/cmd/gc/mkbuiltin1.c +++ b/src/cmd/gc/mkbuiltin1.c @@ -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); diff --git a/src/cmd/gc/subr.c b/src/cmd/gc/subr.c index 20b3113e44..d05830bce4 100644 --- a/src/cmd/gc/subr.c +++ b/src/cmd/gc/subr.c @@ -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); diff --git a/src/cmd/gc/swt.c b/src/cmd/gc/swt.c index aa8fa81a14..a885bb371f 100644 --- a/src/cmd/gc/swt.c +++ b/src/cmd/gc/swt.c @@ -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; diff --git a/src/cmd/gc/sys.go b/src/cmd/gc/sys.go index de060b6c2a..2144e7c324 100644 --- a/src/cmd/gc/sys.go +++ b/src/cmd/gc/sys.go @@ -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); diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index eeadbf2896..ac83ca8552 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -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; diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c index 6e203a9644..91f1ea875a 100644 --- a/src/cmd/gc/walk.c +++ b/src/cmd/gc/walk.c @@ -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 = 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; ilist = 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; itype); + 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; +}