Commit a2b8e387 authored by Russ Cox's avatar Russ Cox

checkpoint; still plenty to clean up

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