Commit 4a431983 authored by Russ Cox's avatar Russ Cox

update compiler to new func rules

R=ken
OCL=23958
CL=23961
parent 4cf77115
...@@ -75,6 +75,7 @@ widstruct(Type *t, uint32 o, int flag) ...@@ -75,6 +75,7 @@ widstruct(Type *t, uint32 o, int flag)
void void
dowidth(Type *t) dowidth(Type *t)
{ {
int32 et;
uint32 w; uint32 w;
if(t == T) if(t == T)
...@@ -88,8 +89,22 @@ dowidth(Type *t) ...@@ -88,8 +89,22 @@ dowidth(Type *t)
t->width = -2; t->width = -2;
et = t->etype;
switch(et) {
case TFUNC:
case TCHAN:
case TMAP:
case TSTRING:
break;
default:
et = simtype[t->etype];
break;
}
w = 0; w = 0;
switch(simtype[t->etype]) { switch(et) {
default: default:
fatal("dowidth: unknown type: %E", t->etype); fatal("dowidth: unknown type: %E", t->etype);
break; break;
...@@ -162,16 +177,18 @@ dowidth(Type *t) ...@@ -162,16 +177,18 @@ dowidth(Type *t)
w = widstruct(t, 0, 1); w = widstruct(t, 0, 1);
if(w == 0) if(w == 0)
w = maxround; w = maxround;
offmod(t);
break; break;
case TFUNC: case TFUNC:
// function is 3 cated structures // function is 3 cated structures;
// compute their widths as side-effect.
w = widstruct(*getthis(t), 0, 1); w = widstruct(*getthis(t), 0, 1);
w = widstruct(*getinarg(t), w, 0); w = widstruct(*getinarg(t), w, 0);
w = widstruct(*getoutarg(t), w, 1); w = widstruct(*getoutarg(t), w, 1);
t->argwid = w; t->argwid = w;
w = 0;
// but width of func type is pointer
w = wptr;
break; break;
} }
t->width = w; t->width = w;
...@@ -222,6 +239,7 @@ belexinit(int lextype) ...@@ -222,6 +239,7 @@ belexinit(int lextype)
simtype[TMAP] = tptr; simtype[TMAP] = tptr;
simtype[TCHAN] = tptr; simtype[TCHAN] = tptr;
simtype[TSTRING] = tptr; simtype[TSTRING] = tptr;
simtype[TFUNC] = tptr;
zprog.link = P; zprog.link = P;
zprog.as = AGOK; zprog.as = AGOK;
......
...@@ -19,8 +19,8 @@ cgen(Node *n, Node *res) ...@@ -19,8 +19,8 @@ cgen(Node *n, Node *res)
Addr addr; Addr addr;
if(debug['g']) { if(debug['g']) {
dump("\ncgen-res", res); dump("\ncgen-n", n);
dump("cgen-r", n); dump("cgen-res", res);
} }
if(n == N || n->type == T) if(n == N || n->type == T)
return; return;
...@@ -82,6 +82,8 @@ cgen(Node *n, Node *res) ...@@ -82,6 +82,8 @@ cgen(Node *n, Node *res)
} else } else
p1 = gins(a, n, N); p1 = gins(a, n, N);
p1->to = addr; p1->to = addr;
if(debug['g'])
print("%P [ignore previous line]\n", p1);
sudoclean(); sudoclean();
goto ret; goto ret;
} }
...@@ -448,7 +450,7 @@ agen(Node *n, Node *res) ...@@ -448,7 +450,7 @@ agen(Node *n, Node *res)
nodconst(&n2, types[TUINT64], v); nodconst(&n2, types[TUINT64], v);
gins(optoas(OCMP, types[TUINT32]), &n1, &n2); gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
p1 = gbranch(optoas(OGT, types[TUINT32]), T); p1 = gbranch(optoas(OGT, types[TUINT32]), T);
gins(ACALL, N, throwindex); ginscall(throwindex, 0);
patch(p1, pc); patch(p1, pc);
} }
...@@ -494,7 +496,7 @@ agen(Node *n, Node *res) ...@@ -494,7 +496,7 @@ agen(Node *n, Node *res)
nodconst(&n1, types[TUINT64], nl->type->bound); nodconst(&n1, types[TUINT64], nl->type->bound);
gins(optoas(OCMP, types[TUINT32]), &n2, &n1); gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
p1 = gbranch(optoas(OLT, types[TUINT32]), T); p1 = gbranch(optoas(OLT, types[TUINT32]), T);
gins(ACALL, N, throwindex); ginscall(throwindex, 0);
patch(p1, pc); patch(p1, pc);
} }
......
...@@ -8,6 +8,17 @@ ...@@ -8,6 +8,17 @@
#include "gg.h" #include "gg.h"
#include "opt.h" #include "opt.h"
static Node*
sysfunc(char *name)
{
Node *n;
n = newname(pkglookup(name, "sys"));
n->class = PFUNC;
return n;
}
void void
compile(Node *fn) compile(Node *fn)
{ {
...@@ -18,45 +29,16 @@ compile(Node *fn) ...@@ -18,45 +29,16 @@ compile(Node *fn)
Type *t; Type *t;
Iter save; Iter save;
if(newproc == N) { if(newproc == N)
newproc = nod(ONAME, N, N); newproc = sysfunc("newproc");
newproc->sym = pkglookup("newproc", "sys"); if(deferproc == N)
newproc->class = PEXTERN; deferproc = sysfunc("deferproc");
newproc->addable = 1; if(deferreturn == N)
newproc->ullman = 1; deferreturn = sysfunc("deferreturn");
} if(throwindex == N)
throwindex = sysfunc("throwindex");
if(deferproc == N) { if(throwreturn == N)
deferproc = nod(ONAME, N, N); throwreturn = sysfunc("throwreturn");
deferproc->sym = pkglookup("deferproc", "sys");
deferproc->class = PEXTERN;
deferproc->addable = 1;
deferproc->ullman = 1;
}
if(deferreturn == N) {
deferreturn = nod(ONAME, N, N);
deferreturn->sym = pkglookup("deferreturn", "sys");
deferreturn->class = PEXTERN;
deferreturn->addable = 1;
deferreturn->ullman = 1;
}
if(throwindex == N) {
throwindex = nod(ONAME, N, N);
throwindex->sym = pkglookup("throwindex", "sys");
throwindex->class = PEXTERN;
throwindex->addable = 1;
throwindex->ullman = 1;
}
if(throwreturn == N) {
throwreturn = nod(ONAME, N, N);
throwreturn->sym = pkglookup("throwreturn", "sys");
throwreturn->class = PEXTERN;
throwreturn->addable = 1;
throwreturn->ullman = 1;
}
if(fn->nbody == N) if(fn->nbody == N)
return; return;
...@@ -95,6 +77,7 @@ if(throwreturn == N) { ...@@ -95,6 +77,7 @@ if(throwreturn == N) {
nodconst(&nod1, types[TINT32], 0); nodconst(&nod1, types[TINT32], 0);
ptxt = gins(ATEXT, curfn->nname, &nod1); ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from);
// inarggen(); // inarggen();
...@@ -104,12 +87,11 @@ if(throwreturn == N) { ...@@ -104,12 +87,11 @@ if(throwreturn == N) {
gclean(); gclean();
checklabels(); checklabels();
if(curfn->type->outtuple != 0) { if(curfn->type->outtuple != 0)
gins(ACALL, N, throwreturn); ginscall(throwreturn, 0);
}
if(hasdefer) if(hasdefer)
gins(ACALL, N, deferreturn); ginscall(deferreturn, 0);
pc->as = ARET; // overwrite AEND pc->as = ARET; // overwrite AEND
pc->lineno = lineno; pc->lineno = lineno;
...@@ -720,6 +702,7 @@ argsize(Type *t) ...@@ -720,6 +702,7 @@ argsize(Type *t)
void void
ginscall(Node *f, int proc) ginscall(Node *f, int proc)
{ {
Prog *p;
Node reg, con; Node reg, con;
switch(proc) { switch(proc) {
...@@ -728,23 +711,20 @@ ginscall(Node *f, int proc) ...@@ -728,23 +711,20 @@ ginscall(Node *f, int proc)
break; break;
case 0: // normal call case 0: // normal call
gins(ACALL, N, f); p = gins(ACALL, N, f);
afunclit(&p->to);
break; break;
case 1: // call in new proc (go) case 1: // call in new proc (go)
case 2: // defered call (defer) case 2: // defered call (defer)
nodreg(&reg, types[TINT64], D_AX); nodreg(&reg, types[TINT64], D_AX);
if(f->op != OREGISTER) { gins(APUSHQ, f, N);
gins(ALEAQ, f, &reg);
gins(APUSHQ, &reg, N);
} else
gins(APUSHQ, f, N);
nodconst(&con, types[TINT32], argsize(f->type)); nodconst(&con, types[TINT32], argsize(f->type));
gins(APUSHQ, &con, N); gins(APUSHQ, &con, N);
if(proc == 1) if(proc == 1)
gins(ACALL, N, newproc); ginscall(newproc, 0);
else else
gins(ACALL, N, deferproc); ginscall(deferproc, 0);
gins(APOPQ, N, &reg); gins(APOPQ, N, &reg);
gins(APOPQ, N, &reg); gins(APOPQ, N, &reg);
break; break;
...@@ -827,7 +807,7 @@ cgen_callmeth(Node *n, int proc) ...@@ -827,7 +807,7 @@ cgen_callmeth(Node *n, int proc)
n->left->type = l->type; n->left->type = l->type;
if(n->left->op == ONAME) if(n->left->op == ONAME)
n->left->class = PEXTERN; n->left->class = PFUNC;
cgen_call(n, proc); cgen_call(n, proc);
} }
...@@ -850,16 +830,11 @@ cgen_call(Node *n, int proc) ...@@ -850,16 +830,11 @@ cgen_call(Node *n, int proc)
// if name involves a fn call // if name involves a fn call
// precompute the address of the fn // precompute the address of the fn
tempname(&afun, types[tptr]); tempname(&afun, types[tptr]);
if(isptr[n->left->type->etype]) cgen(n->left, &afun);
cgen(n->left, &afun);
else
agen(n->left, &afun);
} }
gen(n->right, L); // assign the args gen(n->right, L); // assign the args
t = n->left->type; t = n->left->type;
if(isptr[t->etype])
t = t->type;
setmaxarg(t); setmaxarg(t);
...@@ -874,7 +849,7 @@ cgen_call(Node *n, int proc) ...@@ -874,7 +849,7 @@ cgen_call(Node *n, int proc)
} }
// call pointer // call pointer
if(isptr[n->left->type->etype]) { if(n->left->op != ONAME || n->left->class != PFUNC) {
regalloc(&nod, types[tptr], N); regalloc(&nod, types[tptr], N);
cgen_as(&nod, n->left); cgen_as(&nod, n->left);
nod.type = t; nod.type = t;
...@@ -887,6 +862,7 @@ cgen_call(Node *n, int proc) ...@@ -887,6 +862,7 @@ cgen_call(Node *n, int proc)
n->left->method = 1; n->left->method = 1;
ginscall(n->left, proc); ginscall(n->left, proc);
ret: ret:
; ;
} }
...@@ -992,7 +968,7 @@ cgen_ret(Node *n) ...@@ -992,7 +968,7 @@ cgen_ret(Node *n)
{ {
gen(n->left, L); // copy out args gen(n->left, L); // copy out args
if(hasdefer) if(hasdefer)
gins(ACALL, N, deferreturn); ginscall(deferreturn, 0);
gins(ARET, N, N); gins(ARET, N, N);
} }
......
...@@ -164,6 +164,7 @@ int needconvert(Type*, Type*); ...@@ -164,6 +164,7 @@ int needconvert(Type*, Type*);
void genconv(Type*, Type*); void genconv(Type*, Type*);
void allocparams(void); void allocparams(void);
void checklabels(); void checklabels();
void ginscall(Node*, int);
/* /*
* cgen * cgen
...@@ -219,6 +220,7 @@ int isfat(Type*); ...@@ -219,6 +220,7 @@ int isfat(Type*);
void setmaxarg(Type*); void setmaxarg(Type*);
void sudoclean(void); void sudoclean(void);
int sudoaddable(Node*, Addr*); int sudoaddable(Node*, Addr*);
void afunclit(Addr*);
/* /*
* list.c * list.c
......
...@@ -1084,6 +1084,10 @@ naddr(Node *n, Addr *a) ...@@ -1084,6 +1084,10 @@ naddr(Node *n, Addr *a)
case PPARAMOUT: case PPARAMOUT:
a->type = D_PARAM; a->type = D_PARAM;
break; break;
case PFUNC:
a->index = D_EXTERN;
a->type = D_ADDR;
break;
} }
break; break;
...@@ -1155,6 +1159,20 @@ naddr(Node *n, Addr *a) ...@@ -1155,6 +1159,20 @@ naddr(Node *n, Addr *a)
} }
} }
/*
* naddr of func generates code for address of func.
* if using opcode that can take address implicitly,
* call afunclit to fix up the argument.
*/
void
afunclit(Addr *a)
{
if(a->type == D_ADDR && a->index == D_EXTERN) {
a->type = D_EXTERN;
a->index = D_NONE;
}
}
/* /*
* return Axxx for Oxxx on type t. * return Axxx for Oxxx on type t.
*/ */
...@@ -1889,6 +1907,10 @@ dotoffset(Node *n, int *oary, Node **nn) ...@@ -1889,6 +1907,10 @@ dotoffset(Node *n, int *oary, Node **nn)
switch(n->op) { switch(n->op) {
case ODOT: case ODOT:
if(n->xoffset == BADWIDTH) {
dump("bad width in dotoffset", n);
fatal("bad width in dotoffset");
}
i = dotoffset(n->left, oary, nn); i = dotoffset(n->left, oary, nn);
if(i > 0) { if(i > 0) {
if(oary[i-1] >= 0) if(oary[i-1] >= 0)
...@@ -1902,6 +1924,10 @@ dotoffset(Node *n, int *oary, Node **nn) ...@@ -1902,6 +1924,10 @@ dotoffset(Node *n, int *oary, Node **nn)
break; break;
case ODOTPTR: case ODOTPTR:
if(n->xoffset == BADWIDTH) {
dump("bad width in dotoffset", n);
fatal("bad width in dotoffset");
}
i = dotoffset(n->left, oary, nn); i = dotoffset(n->left, oary, nn);
if(i < 10) if(i < 10)
oary[i++] = -(n->xoffset+1); oary[i++] = -(n->xoffset+1);
...@@ -2084,7 +2110,7 @@ oindex: ...@@ -2084,7 +2110,7 @@ oindex:
} }
gins(optoas(OCMP, types[TUINT32]), reg1, &n2); gins(optoas(OCMP, types[TUINT32]), reg1, &n2);
p1 = gbranch(optoas(OLT, types[TUINT32]), T); p1 = gbranch(optoas(OLT, types[TUINT32]), T);
gins(ACALL, N, throwindex); ginscall(throwindex, 0);
patch(p1, pc); patch(p1, pc);
} }
...@@ -2126,7 +2152,7 @@ oindex_const: ...@@ -2126,7 +2152,7 @@ oindex_const:
nodconst(&n2, types[TUINT64], v); nodconst(&n2, types[TUINT64], v);
gins(optoas(OCMP, types[TUINT32]), &n1, &n2); gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
p1 = gbranch(optoas(OGT, types[TUINT32]), T); p1 = gbranch(optoas(OGT, types[TUINT32]), T);
gins(ACALL, N, throwindex); ginscall(throwindex, 0);
patch(p1, pc); patch(p1, pc);
} }
......
...@@ -70,7 +70,7 @@ dumpobj(void) ...@@ -70,7 +70,7 @@ dumpobj(void)
if(n == N || n->type == T) if(n == N || n->type == T)
fatal("external %S nil\n", s); fatal("external %S nil\n", s);
if(n->type->etype == TFUNC) if(n->class == PFUNC)
continue; continue;
dowidth(n->type); dowidth(n->type);
...@@ -664,7 +664,7 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s) ...@@ -664,7 +664,7 @@ dumpsigt(Type *progt, Type *ifacet, Type *rcvrt, Type *methodt, Sym *s)
a->hash += PRIME10*stringhash(package); a->hash += PRIME10*stringhash(package);
a->perm = o; a->perm = o;
a->sym = methodsym(method, rcvrt); a->sym = methodsym(method, rcvrt);
sighash = sighash*100003 + a->hash; sighash = sighash*100003 + a->hash;
if(!a->sym->siggen) { if(!a->sym->siggen) {
...@@ -803,7 +803,7 @@ dumpsigi(Type *t, Sym *s) ...@@ -803,7 +803,7 @@ dumpsigi(Type *t, Sym *s)
a->perm = o; a->perm = o;
a->sym = methodsym(f->sym, t); a->sym = methodsym(f->sym, t);
a->offset = 0; a->offset = 0;
sighash = sighash*100003 + a->hash; sighash = sighash*100003 + a->hash;
o++; o++;
......
...@@ -71,6 +71,7 @@ convlit1(Node *n, Type *t, int conv) ...@@ -71,6 +71,7 @@ convlit1(Node *n, Type *t, int conv)
case TARRAY: case TARRAY:
case TMAP: case TMAP:
case TCHAN: case TCHAN:
case TFUNC:
break; break;
} }
break; break;
......
...@@ -384,9 +384,9 @@ funchdr(Node *n) ...@@ -384,9 +384,9 @@ funchdr(Node *n)
// declare fun name, argument types and argument names // declare fun name, argument types and argument names
n->nname->type = n->type; n->nname->type = n->type;
if(n->type->thistuple == 0) if(n->type->thistuple == 0)
addvar(n->nname, n->type, PEXTERN); addvar(n->nname, n->type, PFUNC);
else else
n->nname->class = PEXTERN; n->nname->class = PFUNC;
} else { } else {
// identical redeclaration // identical redeclaration
// steal previous names // steal previous names
...@@ -501,9 +501,6 @@ loop: ...@@ -501,9 +501,6 @@ loop:
if(n->op != ODCLFIELD || n->type == T) if(n->op != ODCLFIELD || n->type == T)
fatal("stotype: oops %N\n", n); fatal("stotype: oops %N\n", n);
if(et == TSTRUCT && n->type->etype == TFUNC)
yyerror("bad structure field type: %T", n->type);
switch(n->val.ctype) { switch(n->val.ctype) {
case CTSTR: case CTSTR:
note = n->val.u.sval; note = n->val.u.sval;
...@@ -742,7 +739,7 @@ addvar(Node *n, Type *t, int ctxt) ...@@ -742,7 +739,7 @@ addvar(Node *n, Type *t, int ctxt)
s = n->sym; s = n->sym;
if(ctxt == PEXTERN) { if(ctxt == PEXTERN || ctxt == PFUNC) {
r = externdcl; r = externdcl;
gen = 0; gen = 0;
} else { } else {
...@@ -773,6 +770,8 @@ addvar(Node *n, Type *t, int ctxt) ...@@ -773,6 +770,8 @@ addvar(Node *n, Type *t, int ctxt)
if(dflag()) { if(dflag()) {
if(ctxt == PEXTERN) if(ctxt == PEXTERN)
print("extern var-dcl %S G%ld %T\n", s, s->vargen, t); print("extern var-dcl %S G%ld %T\n", s, s->vargen, t);
else if(ctxt == PFUNC)
print("extern func-dcl %S G%ld %T\n", s, s->vargen, t);
else else
print("auto var-dcl %S G%ld %T\n", s, s->vargen, t); print("auto var-dcl %S G%ld %T\n", s, s->vargen, t);
} }
...@@ -896,6 +895,7 @@ newname(Sym *s) ...@@ -896,6 +895,7 @@ newname(Sym *s)
n->type = T; n->type = T;
n->addable = 1; n->addable = 1;
n->ullman = 1; n->ullman = 1;
n->xoffset = 0;
return n; return n;
} }
......
...@@ -153,11 +153,11 @@ dumpexportvar(Sym *s) ...@@ -153,11 +153,11 @@ dumpexportvar(Sym *s)
dumpprereq(t); dumpprereq(t);
Bprint(bout, "\t"); Bprint(bout, "\t");
if(t->etype == TFUNC) if(t->etype == TFUNC && n->class == PFUNC)
Bprint(bout, "func "); Bprint(bout, "func %lS %#hhT", s, t);
else else
Bprint(bout, "var "); Bprint(bout, "var %lS %#T", s, t);
Bprint(bout, "%lS %#T\n", s, t); Bprint(bout, "\n");
} }
void void
...@@ -199,7 +199,7 @@ dumpsym(Sym *s) ...@@ -199,7 +199,7 @@ dumpsym(Sym *s)
dumpexporttype(s); dumpexporttype(s);
for(f=s->otype->method; f!=T; f=f->down) for(f=s->otype->method; f!=T; f=f->down)
Bprint(bout, "\tfunc (%#T) %hS %#hT\n", Bprint(bout, "\tfunc (%#T) %hS %#hhT\n",
f->type->type->type, f->sym, f->type); f->type->type->type, f->sym, f->type);
break; break;
case LNAME: case LNAME:
...@@ -368,7 +368,7 @@ importconst(Node *ss, Type *t, Val *v) ...@@ -368,7 +368,7 @@ importconst(Node *ss, Type *t, Val *v)
} }
void void
importvar(Node *ss, Type *t) importvar(Node *ss, Type *t, int ctxt)
{ {
Sym *s; Sym *s;
...@@ -383,7 +383,7 @@ importvar(Node *ss, Type *t) ...@@ -383,7 +383,7 @@ importvar(Node *ss, Type *t)
s, s->oname->type, t); s, s->oname->type, t);
} }
checkwidth(t); checkwidth(t);
addvar(newname(s), t, PEXTERN); addvar(newname(s), t, ctxt);
if(debug['e']) if(debug['e'])
print("import var %S %lT\n", s, t); print("import var %S %lT\n", s, t);
......
...@@ -414,6 +414,7 @@ enum ...@@ -414,6 +414,7 @@ enum
PAUTO, PAUTO,
PPARAM, PPARAM,
PPARAMOUT, PPARAMOUT,
PFUNC,
PHEAP = 1<<7, PHEAP = 1<<7,
}; };
...@@ -778,7 +779,7 @@ void doimport9(Sym*, Node*); ...@@ -778,7 +779,7 @@ void doimport9(Sym*, Node*);
void importconst(Node *ss, Type *t, Val *v); void importconst(Node *ss, Type *t, Val *v);
void importmethod(Sym *s, Type *t); void importmethod(Sym *s, Type *t);
void importtype(Node *ss, Type *t); void importtype(Node *ss, Type *t);
void importvar(Node *ss, Type *t); void importvar(Node *ss, Type *t, int ctxt);
void checkimports(void); void checkimports(void);
Type* pkgtype(char*, char*); Type* pkgtype(char*, char*);
......
...@@ -1231,15 +1231,15 @@ fntype: ...@@ -1231,15 +1231,15 @@ fntype:
| Bfntype | Bfntype
Afntype: Afntype:
'(' oarg_type_list ')' Afnres LFUNC '(' oarg_type_list ')' Afnres
{ {
$$ = functype(N, $2, $4); $$ = functype(N, $3, $5);
} }
Bfntype: Bfntype:
'(' oarg_type_list ')' Bfnres LFUNC '(' oarg_type_list ')' Bfnres
{ {
$$ = functype(N, $2, $4); $$ = functype(N, $3, $5);
} }
fnlitdcl: fnlitdcl:
...@@ -1251,7 +1251,7 @@ fnlitdcl: ...@@ -1251,7 +1251,7 @@ fnlitdcl:
} }
fnliteral: fnliteral:
LFUNC fnlitdcl '{' ostmt_list '}' fnlitdcl '{' ostmt_list '}'
{ {
popdcl(); popdcl();
...@@ -1259,21 +1259,19 @@ fnliteral: ...@@ -1259,21 +1259,19 @@ fnliteral:
snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen); snprint(namebuf, sizeof(namebuf), "_f%.3ld", vargen);
$$ = newname(lookup(namebuf)); $$ = newname(lookup(namebuf));
addvar($$, $2, PEXTERN); addvar($$, $1, PFUNC);
{ {
Node *n; Node *n;
n = nod(ODCLFUNC, N, N); n = nod(ODCLFUNC, N, N);
n->nname = $$; n->nname = $$;
n->type = $2; n->type = $1;
n->nbody = $4; n->nbody = $3;
if(n->nbody == N) if(n->nbody == N)
n->nbody = nod(ORETURN, N, N); n->nbody = nod(ORETURN, N, N);
compile(n); compile(n);
} }
$$ = nod(OADDR, $$, N);
} }
fnbody: fnbody:
...@@ -1417,12 +1415,6 @@ indcl: ...@@ -1417,12 +1415,6 @@ indcl:
// without func keyword // without func keyword
$$ = functype(fakethis(), $2, $4); $$ = functype(fakethis(), $2, $4);
} }
| latype
{
$$ = oldtype($1);
if($$ == T || $$->etype != TFUNC)
yyerror("illegal type for function literal");
}
/* /*
* function arguments. * function arguments.
...@@ -1733,7 +1725,7 @@ hidden_import: ...@@ -1733,7 +1725,7 @@ hidden_import:
/* variables */ /* variables */
| LVAR hidden_pkg_importsym hidden_type | LVAR hidden_pkg_importsym hidden_type
{ {
importvar($2, $3); importvar($2, $3, PEXTERN);
} }
| LCONST hidden_pkg_importsym '=' hidden_constant | LCONST hidden_pkg_importsym '=' hidden_constant
{ {
...@@ -1749,7 +1741,7 @@ hidden_import: ...@@ -1749,7 +1741,7 @@ hidden_import:
} }
| LFUNC hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres | LFUNC hidden_pkg_importsym '(' ohidden_funarg_list ')' ohidden_funres
{ {
importvar($2, functype(N, $4, $6)); importvar($2, functype(N, $4, $6), PFUNC);
} }
| LFUNC '(' hidden_funarg_list ')' sym1 '(' ohidden_funarg_list ')' ohidden_funres | LFUNC '(' hidden_funarg_list ')' sym1 '(' ohidden_funarg_list ')' ohidden_funres
{ {
...@@ -1829,9 +1821,9 @@ hidden_type2: ...@@ -1829,9 +1821,9 @@ hidden_type2:
$$->type = $2; $$->type = $2;
$$->chan = Cboth; $$->chan = Cboth;
} }
| '(' ohidden_funarg_list ')' ohidden_funres | LFUNC '(' ohidden_funarg_list ')' ohidden_funres
{ {
$$ = functype(N, $2, $4); $$ = functype(N, $3, $5);
} }
hidden_dcl: hidden_dcl:
...@@ -1980,11 +1972,6 @@ latype: ...@@ -1980,11 +1972,6 @@ latype:
yyerror("no type %s", $1->name); yyerror("no type %s", $1->name);
YYERROR; YYERROR;
} }
| lpack '.' LNAME
{
yyerror("no type %s.%s", context, $3->name);
YYERROR;
}
nametype: nametype:
LNAME LNAME
......
...@@ -1154,6 +1154,7 @@ lexinit(void) ...@@ -1154,6 +1154,7 @@ lexinit(void)
case TINTER: case TINTER:
case TMAP: case TMAP:
case TCHAN: case TCHAN:
case TFUNC:
okforeq[i] = 1; okforeq[i] = 1;
break; break;
} }
......
...@@ -283,6 +283,7 @@ nod(int op, Node *nleft, Node *nright) ...@@ -283,6 +283,7 @@ nod(int op, Node *nleft, Node *nright)
n->lineno = lineno; n->lineno = lineno;
else else
n->lineno = prevlineno; n->lineno = prevlineno;
n->xoffset = BADWIDTH;
return n; return n;
} }
...@@ -291,7 +292,7 @@ algtype(Type *t) ...@@ -291,7 +292,7 @@ algtype(Type *t)
{ {
int a; int a;
if(issimple[t->etype] || isptr[t->etype] || t->etype == TCHAN) if(issimple[t->etype] || isptr[t->etype] || t->etype == TCHAN || t->etype == TFUNC)
a = AMEM; // just bytes (int, ptr, etc) a = AMEM; // just bytes (int, ptr, etc)
else else
if(t->etype == TSTRING) if(t->etype == TSTRING)
...@@ -1040,6 +1041,8 @@ Tpretty(Fmt *fp, Type *t) ...@@ -1040,6 +1041,8 @@ Tpretty(Fmt *fp, Type *t)
fmtprint(fp, ")"); fmtprint(fp, ")");
} }
if(!(fp->flags&FmtByte))
fmtprint(fp, "func");
fmtprint(fp, "("); fmtprint(fp, "(");
for(t1=getinargx(t)->type; t1; t1=t1->down) { for(t1=getinargx(t)->type; t1; t1=t1->down) {
fmtprint(fp, "%T", t1); fmtprint(fp, "%T", t1);
...@@ -1052,7 +1055,7 @@ Tpretty(Fmt *fp, Type *t) ...@@ -1052,7 +1055,7 @@ Tpretty(Fmt *fp, Type *t)
break; break;
case 1: case 1:
t1 = getoutargx(t)->type; t1 = getoutargx(t)->type;
if(t1->etype != TFIELD) { if(t1->etype != TFIELD && t1->etype != TFUNC) {
fmtprint(fp, " %T", t1); fmtprint(fp, " %T", t1);
break; break;
} }
...@@ -1077,7 +1080,7 @@ Tpretty(Fmt *fp, Type *t) ...@@ -1077,7 +1080,7 @@ Tpretty(Fmt *fp, Type *t)
case TINTER: case TINTER:
fmtprint(fp, "interface {"); fmtprint(fp, "interface {");
for(t1=t->type; t1!=T; t1=t1->down) { for(t1=t->type; t1!=T; t1=t1->down) {
fmtprint(fp, " %hS %hT", t1->sym, t1->type); fmtprint(fp, " %hS %hhT", t1->sym, t1->type);
if(t1->down) if(t1->down)
fmtprint(fp, ";"); fmtprint(fp, ";");
} }
......
...@@ -1020,6 +1020,12 @@ loop: ...@@ -1020,6 +1020,12 @@ loop:
indir(n, nvar); indir(n, nvar);
goto ret; goto ret;
} }
if(istype(n->left->type, TFUNC) && n->left->class == PFUNC) {
if(!n->diag) {
n->diag = 1;
yyerror("cannot take address of function");
}
}
walktype(n->left, Elv); walktype(n->left, Elv);
addrescapes(n->left); addrescapes(n->left);
if(n->left == N) if(n->left == N)
...@@ -1060,10 +1066,8 @@ loop: ...@@ -1060,10 +1066,8 @@ loop:
goto ret; goto ret;
} }
t = n->type; t = n->type;
if(t == T || t->etype == TFUNC) { if(t == T)
yyerror("cannot new(%T)", t);
goto ret; goto ret;
}
indir(n, callnew(t)); indir(n, callnew(t));
goto ret; goto ret;
} }
...@@ -1721,6 +1725,8 @@ loop: ...@@ -1721,6 +1725,8 @@ loop:
badtype(op, l->type, r->type); badtype(op, l->type, r->type);
return N; return N;
} }
if(l->op == ONAME && l->class == PFUNC)
yyerror("cannot assign to function");
a = nod(OAS, l, r); a = nod(OAS, l, r);
a = convas(a); a = convas(a);
......
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