Commit b648716e authored by Russ Cox's avatar Russ Cox

forward declarations not necessary.

still to do:
	* initializer cycle detection
	* nicer error for type checking cycles

R=ken
OCL=32855
CL=32880
parent e98dde27
......@@ -18,7 +18,7 @@ OFILES=\
align.$O\
bits.$O\
builtin.$O\
compat.$O\
closure.$O\
const.$O\
dcl.$O\
export.$O\
......
......@@ -61,10 +61,23 @@ widstruct(Type *t, uint32 o, int flag)
if(f->etype != TFIELD)
fatal("widstruct: not TFIELD: %lT", f);
dowidth(f->type);
if(f->type->width < 0 || f->type->width > 100000000)
fatal("invalid width %lld", f->type->width);
w = f->type->width;
m = arrayelemwidth(f->type);
o = rnd(o, m);
f->width = o; // really offset for TFIELD
if(f->nname != N) {
// this same stackparam logic is in addrescapes
// in typecheck.c. usually addrescapes runs after
// widstruct, in which case we could drop this,
// but function closure functions are the exception.
if(f->nname->stackparam) {
f->nname->stackparam->xoffset = o;
f->nname->xoffset = 0;
} else
f->nname->xoffset = o;
}
o += w;
}
// final width is rounded
......@@ -91,6 +104,9 @@ dowidth(Type *t)
if(t == T)
return;
if(t->width > 0)
return;
if(t->width == -2) {
yyerror("invalid recursive type %T", t);
t->width = 0;
......@@ -99,7 +115,6 @@ dowidth(Type *t)
t->width = -2;
et = t->etype;
switch(et) {
case TFUNC:
......@@ -165,13 +180,16 @@ dowidth(Type *t)
break;
case TFORW: // should have been filled in
case TFORWSTRUCT:
yyerror("incomplete type %T", t);
yyerror("undefined type %T", t);
w = widthptr;
break;
case TANY: // implemented as pointer
w = widthptr;
case TANY:
// dummy type; should be replaced before use.
fatal("dowidth any");
break;
case TSTRING:
if(sizeof_String == 0)
fatal("early dowidth string");
w = sizeof_String;
break;
case TARRAY:
......@@ -413,6 +431,9 @@ typeinit(void)
// string is same as slice wo the cap
sizeof_String = rnd(Array_nel+types[TUINT32]->width, maxround);
dowidth(types[TSTRING]);
dowidth(idealstring);
}
/*
......
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
/*
* function literals aka closures
*/
#include "go.h"
void
closurehdr(Node *ntype)
{
Node *n, *name;
NodeList *l;
n = nod(OCLOSURE, N, N);
n->ntype = ntype;
n->funcdepth = funcdepth;
funchdr(n);
// steal ntype's argument names and
// leave a fresh copy in their place.
// references to these variables need to
// refer to the variables in the external
// function declared below; see walkclosure.
n->list = ntype->list;
n->rlist = ntype->rlist;
ntype->list = nil;
ntype->rlist = nil;
for(l=n->list; l; l=l->next) {
name = l->n->left;
if(name)
name = newname(name->sym);
ntype->list = list(ntype->list, nod(ODCLFIELD, name, l->n->right));
}
for(l=n->rlist; l; l=l->next) {
name = l->n->left;
if(name)
name = newname(name->sym);
ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, name, l->n->right));
}
}
Node*
closurebody(NodeList *body)
{
Node *func, *v;
NodeList *l;
if(body == nil)
body = list1(nod(OEMPTY, N, N));
func = curfn;
l = func->dcl;
func->nbody = body;
funcbody(func);
// closure-specific variables are hanging off the
// ordinary ones in the symbol table; see oldname.
// unhook them.
// make the list of pointers for the closure call.
for(l=func->cvars; l; l=l->next) {
v = l->n;
v->closure->closure = v->outer;
v->heapaddr = nod(OADDR, oldname(v->sym), N);
}
return func;
}
void
typecheckclosure(Node *func)
{
Node *oldfn;
NodeList *l;
Node *v;
oldfn = curfn;
typecheck(&func->ntype, Etype);
func->type = func->ntype->type;
if(func->type != T) {
curfn = func;
typechecklist(func->nbody, Etop);
curfn = oldfn;
}
// type check the & of closed variables outside the closure,
// so that the outer frame also grabs them and knows they
// escape.
func->enter = nil;
for(l=func->cvars; l; l=l->next) {
v = l->n;
if(v->type == T) {
// if v->type is nil, it means v looked like it was
// going to be used in the closure but wasn't.
// this happens because when parsing a, b, c := f()
// the a, b, c gets parsed as references to older
// a, b, c before the parser figures out this is a
// declaration.
v->op = 0;
continue;
}
typecheck(&v->heapaddr, Erv);
func->enter = list(func->enter, v->heapaddr);
v->heapaddr = N;
}
}
Node*
walkclosure(Node *func, NodeList **init)
{
int narg;
Node *xtype, *v, *addr, *xfunc, *call, *clos;
NodeList *l, *in;
static int closgen;
/*
* wrap body in external function
* with extra closure parameters.
*/
xtype = nod(OTFUNC, N, N);
// each closure variable has a corresponding
// address parameter.
narg = 0;
for(l=func->cvars; l; l=l->next) {
v = l->n;
if(v->op == 0)
continue;
addr = nod(ONAME, N, N);
snprint(namebuf, sizeof namebuf, "&%s", v->sym->name);
addr->sym = lookup(namebuf);
addr->ntype = nod(OIND, typenod(v->type), N);
addr->class = PPARAM;
addr->addable = 1;
addr->ullman = 1;
narg++;
v->heapaddr = addr;
xtype->list = list(xtype->list, nod(ODCLFIELD, addr, addr->ntype));
}
// then a dummy arg where the closure's caller pc sits
xtype->list = list(xtype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
// then the function arguments
xtype->list = concat(xtype->list, func->list);
xtype->rlist = concat(xtype->rlist, func->rlist);
// create the function
xfunc = nod(ODCLFUNC, N, N);
snprint(namebuf, sizeof namebuf, "_f%.3ld·%s", ++closgen, filename);
xfunc->nname = newname(lookup(namebuf));
xfunc->nname->ntype = xtype;
declare(xfunc->nname, PFUNC);
xfunc->nname->funcdepth = func->funcdepth;
xfunc->funcdepth = func->funcdepth;
xfunc->nbody = func->nbody;
xfunc->dcl = func->dcl;
if(xfunc->nbody == nil)
fatal("empty body - won't generate any code");
typecheck(&xfunc, Etop);
closures = list(closures, xfunc);
// prepare call of sys.closure that turns external func into func literal value.
clos = syslook("closure", 1);
clos->type = T;
clos->ntype = nod(OTFUNC, N, N);
in = list1(nod(ODCLFIELD, N, typenod(types[TINT]))); // siz
in = list(in, nod(ODCLFIELD, N, xtype));
for(l=func->cvars; l; l=l->next) {
if(l->n->op == 0)
continue;
in = list(in, nod(ODCLFIELD, N, l->n->heapaddr->ntype));
}
clos->ntype->list = in;
clos->ntype->rlist = list1(nod(ODCLFIELD, N, typenod(func->type)));
typecheck(&clos, Erv);
call = nod(OCALL, clos, N);
if(narg*widthptr > 100)
yyerror("closure needs too many variables; runtime will reject it");
in = list1(nodintconst(narg*widthptr));
in = list(in, xfunc->nname);
in = concat(in, func->enter);
call->list = in;
typecheck(&call, Erv);
walkexpr(&call, init);
return call;
}
......@@ -337,6 +337,7 @@ evconst(Node *n)
case OMAKEMAP:
case OMAKESLICE:
case OMAKECHAN:
case ODCLCONST:
return;
}
......
This diff is collapsed.
......@@ -61,6 +61,8 @@ autoexport(Node *n, int ctxt)
return;
if((ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN)
return;
if(n->ntype && n->ntype->op == OTFUNC && n->ntype->left) // method
return;
if(exportname(n->sym->name) || strcmp(n->sym->name, "init") == 0)
exportsym(n);
else
......@@ -347,7 +349,6 @@ importvar(Sym *s, Type *t, int ctxt)
warn("redeclare import var %S from %T to %T",
s, s->def->type, t);
}
checkwidth(t);
n = newname(s);
n->type = t;
declare(n, ctxt);
......@@ -357,56 +358,19 @@ importvar(Sym *s, Type *t, int ctxt)
}
void
importtype(Sym *s, Type *t)
importtype(Type *pt, Type *t)
{
Node *n;
Type *tt;
importsym(s, OTYPE);
n = s->def;
if(n != N && n->op == OTYPE) {
if(cvttype(t, n->type))
return;
if(t->etype == TFORWSTRUCT && n->type->etype == TSTRUCT)
return;
if(t->etype == TFORWINTER && n->type->etype == TINTER)
return;
if(n->type->etype != TFORW && n->type->etype != TFORWSTRUCT && n->type->etype != TFORWINTER) {
yyerror("redeclare import type %S from %lT to %lT", s, n->type, t);
n = s->def = typenod(typ(0));
}
}
if(n == N || n->op != OTYPE) {
tt = typ(0);
tt->sym = s;
n = typenod(tt);
s->def = n;
}
if(n->type == T)
n->type = typ(0);
*n->type = *t;
n->type->sym = s;
n->type->nod = n;
switch(n->type->etype) {
case TFORWINTER:
case TFORWSTRUCT:
// allow re-export in case it gets defined
s->flags &= ~(SymExport|SymPackage);
s->flags &= ~SymImported;
break;
default:
checkwidth(n->type);
}
typedcl2(pt, t);
if(debug['E'])
print("import type %S %lT\n", s, t);
print("import type %T %lT\n", pt, t);
}
void
importmethod(Sym *s, Type *t)
{
checkwidth(t);
addmethod(newname(s), t, 0);
addmethod(s, t, 0);
}
/*
......
......@@ -25,14 +25,25 @@ allocparams(void)
NodeList *l;
Node *n;
uint32 w;
Sym *s;
if(stksize < 0)
fatal("allocparams not during code generation");
/*
* allocate (set xoffset) the stack
* slots for all automatics.
* allocated starting at -w down.
*/
for(l=autodcl; l; l=l->next) {
for(l=curfn->dcl; l; l=l->next) {
n = l->n;
if(n->op == ONAME && n->class == PHEAP-1) {
// heap address variable; finish the job
// started in addrescapes.
s = n->sym;
tempname(n, n->type);
n->sym = s;
}
if(n->op != ONAME || n->class != PAUTO)
continue;
typecheck(&n, Erv); // only needed for unused variables
......@@ -42,9 +53,10 @@ allocparams(void)
w = n->type->width;
if(n->class & PHEAP)
w = widthptr;
if(w >= 100000000)
fatal("bad width");
stksize += w;
stksize = rnd(stksize, w);
n->xoffset = -stksize;
}
}
......@@ -161,6 +173,9 @@ gen(Node *n)
case OFALL:
case OXCASE:
case OXFALL:
case ODCLCONST:
case ODCLFUNC:
case ODCLTYPE:
break;
case OEMPTY:
......@@ -511,3 +526,90 @@ cgen_as(Node *nl, Node *nr)
ret:
;
}
/*
* gather series of offsets
* >=0 is direct addressed field
* <0 is pointer to next field (+1)
*/
int
dotoffset(Node *n, int *oary, Node **nn)
{
int i;
switch(n->op) {
case ODOT:
if(n->xoffset == BADWIDTH) {
dump("bad width in dotoffset", n);
fatal("bad width in dotoffset");
}
i = dotoffset(n->left, oary, nn);
if(i > 0) {
if(oary[i-1] >= 0)
oary[i-1] += n->xoffset;
else
oary[i-1] -= n->xoffset;
break;
}
if(i < 10)
oary[i++] = n->xoffset;
break;
case ODOTPTR:
if(n->xoffset == BADWIDTH) {
dump("bad width in dotoffset", n);
fatal("bad width in dotoffset");
}
i = dotoffset(n->left, oary, nn);
if(i < 10)
oary[i++] = -(n->xoffset+1);
break;
default:
*nn = n;
return 0;
}
if(i >= 10)
*nn = N;
return i;
}
/*
* make a new off the books
*/
void
tempname(Node *n, Type *t)
{
Sym *s;
uint32 w;
if(stksize < 0)
fatal("tempname not during code generation");
if(t == T) {
yyerror("tempname called with nil type");
t = types[TINT32];
}
// give each tmp a different name so that there
// a chance to registerizer them
snprint(namebuf, sizeof(namebuf), "autotmp_%.4d", statuniqgen);
statuniqgen++;
s = lookup(namebuf);
memset(n, 0, sizeof(*n));
n->op = ONAME;
n->sym = s;
n->type = t;
n->class = PAUTO;
n->addable = 1;
n->ullman = 1;
n->noescape = 1;
dowidth(t);
w = t->width;
stksize += w;
stksize = rnd(stksize, w);
n->xoffset = -stksize;
}
......@@ -144,6 +144,7 @@ struct Type
uchar funarg;
uchar copyany;
uchar local; // created in this file
uchar deferwidth;
Node* nod; // canonical OTYPE node
......@@ -195,6 +196,7 @@ struct Node
uchar builtin; // built-in name, like len or close
uchar walkdef;
uchar typecheck;
uchar local;
// most nodes
Node* left;
......@@ -217,17 +219,15 @@ struct Node
// func
Node* nname;
Node* shortname;
NodeList* enter;
NodeList* exit;
NodeList* cvars; // closure params
NodeList* dcl; // outer autodcl
NodeList* dcl; // autodcl for this func/closure
// OLITERAL/OREGISTER
Val val;
// OTFUNC
Node* rcvr;
// ONAME
Node* ntype;
Node* defn;
......@@ -250,7 +250,7 @@ struct Node
};
#define N ((Node*)0)
struct NodeList
struct NodeList
{
Node* n;
NodeList* next;
......@@ -327,11 +327,12 @@ enum
OCAP,
OCLOSE,
OCLOSED,
OCLOSURE,
OCMPIFACE, OCMPSTR,
OCOMPLIT, OMAPLIT, OSTRUCTLIT, OARRAYLIT,
OCOMPSLICE, OCOMPMAP,
OCONV, OCONVNOP, OCONVA2S, OCONVIFACE, OCONVSLICE,
ODCL, ODCLFUNC, ODCLFIELD, ODCLARG,
ODCL, ODCLFUNC, ODCLFIELD, ODCLCONST, ODCLTYPE,
ODOT, ODOTPTR, ODOTMETH, ODOTINTER, OXDOT,
ODOTTYPE,
OEQ, ONE, OLT, OLE, OGE, OGT,
......@@ -624,8 +625,8 @@ EXTERN Mpint* maxintval[NTYPE];
EXTERN Mpflt* minfltval[NTYPE];
EXTERN Mpflt* maxfltval[NTYPE];
EXTERN NodeList* autodcl;
EXTERN NodeList* externdcl;
EXTERN NodeList* closures;
EXTERN NodeList* exportlist;
EXTERN NodeList* typelist;
EXTERN int dclcontext; // PEXTERN/PAUTO
......@@ -639,7 +640,6 @@ EXTERN NodeList* lastconst;
EXTERN Node* lasttype;
EXTERN int32 maxarg;
EXTERN int32 stksize; // stack size for current frame
EXTERN int32 initstksize; // stack size for init function
EXTERN int32 blockgen; // max block number
EXTERN int32 block; // current block number
EXTERN int hasdefer; // flag that curfn has defer statetment
......@@ -662,8 +662,8 @@ EXTERN int exporting;
EXTERN int noargnames;
EXTERN int funcdepth;
EXTERN int typecheckok;
EXTERN Node* funclit;
/*
* y.tab.c
......@@ -859,21 +859,20 @@ int simsimtype(Type*);
* dcl.c
*/
void declare(Node*, int);
void dodclvar(Node*, Type*, NodeList**);
Type* dodcltype(Type*);
void updatetype(Type*, Type*);
void defaultlit(Node**, Type*);
void defaultlit2(Node**, Node**, int);
int structcount(Type*);
void addmethod(Node*, Type*, int);
void addmethod(Sym*, Type*, int);
Node* methodname(Node*, Type*);
Node* methodname1(Node*, Node*);
Sym* methodsym(Sym*, Type*);
Type* functype(Node*, NodeList*, NodeList*);
char* thistypenam(Node*);
void funcnam(Type*, char*);
Node* renameinit(Node*);
void funchdr(Node*);
void funcargs(Type*);
void funcbody(Node*);
Node* typenod(Type*);
Type* dostruct(NodeList*, int);
......@@ -906,10 +905,23 @@ Node* embedded(Sym*);
NodeList* variter(NodeList*, Node*, NodeList*);
NodeList* constiter(NodeList*, Node*, NodeList*);
Node* funclit0(Node*);
Node* funclit1(Node*, NodeList*);
Node* unsafenmagic(Node*, NodeList*);
void dclchecks(void);
void funccompile(Node*);
Node* typedcl0(Sym*);
Node* typedcl1(Node*, Node*, int);
Node* fwdtype(Node*, int);
void typedcl2(Type*, Type*);
/*
* closure.c
*/
void closurehdr(Node*);
Node* closurebody(NodeList*);
void typecheckclosure(Node*);
Node* walkclosure(Node*, NodeList**);
/*
* sinit.c
......@@ -932,10 +944,11 @@ void dumpexportvar(Sym*);
void dumpexportconst(Sym*);
void importconst(Sym *s, Type *t, Node *v);
void importmethod(Sym *s, Type *t);
void importtype(Sym *s, Type *t);
void importtype(Type *s, Type *t);
void importvar(Sym *s, Type *t, int ctxt);
void checkimports(void);
Type* pkgtype(Sym*);
Sym* importsym(Sym*, int);
/*
* walk.c
......
......@@ -56,7 +56,7 @@
%type <node> for_body for_header for_stmt if_header if_stmt
%type <node> keyval labelname name
%type <node> name_or_type non_expr_type
%type <node> new_name dcl_name oexpr
%type <node> new_name dcl_name oexpr typedclname
%type <node> onew_name
%type <node> osimple_stmt pexpr
%type <node> pseudocall range_stmt select_stmt
......@@ -72,8 +72,7 @@
%type <node> convtype dotdotdot
%type <node> indcl interfacetype structtype ptrtype
%type <type> new_type typedclname
%type <node> chantype non_chan_type othertype non_fn_type fntype fnlitdcl
%type <node> chantype non_chan_type othertype non_fn_type fntype
%type <sym> hidden_importsym hidden_pkg_importsym
......@@ -85,7 +84,7 @@
%type <list> hidden_interfacedcl_list ohidden_interfacedcl_list
%type <list> hidden_structdcl_list ohidden_structdcl_list
%type <type> hidden_type hidden_type1 hidden_type2
%type <type> hidden_type hidden_type1 hidden_type2 hidden_pkgtype
%left LOROR
%left LANDAND
......@@ -121,13 +120,28 @@ file:
imports
xdcl_list
{
NodeList *l;
if(nsyntaxerrors == 0)
testdclstack();
typecheckok = 1;
if(debug['f'])
frame(1);
defercheckwidth();
typechecklist($4, Etop);
resumecheckwidth();
for(l=$4; l; l=l->next)
if(l->n->op == ODCLFUNC)
funccompile(l->n);
if(nerrors == 0)
fninit($4);
if(nsyntaxerrors == 0)
testdclstack();
while(closures) {
l = closures;
closures = nil;
for(; l; l=l->next)
funccompile(l->n);
}
dclchecks();
}
......@@ -266,16 +280,10 @@ import_done:
* declarations
*/
xdcl:
{ stksize = initstksize; } common_dcl
{
$$ = $2;
initstksize = stksize;
}
common_dcl
| xfndcl
{
if($1 != N && $1->nname != N && $1->type->thistuple == 0)
autoexport($1->nname, dclcontext);
$$ = nil;
$$ = list1($1);
}
| ';'
{
......@@ -305,26 +313,23 @@ common_dcl:
}
| LCONST constdcl
{
$$ = nil;
$$ = $2;
iota = 0;
lastconst = nil;
walkdeflist($2);
}
| LCONST '(' constdcl osemi ')'
{
$$ = nil;
$$ = $3;
iota = 0;
lastconst = nil;
yyoptsemi(0);
walkdeflist($3);
}
| LCONST '(' constdcl ';' constdcl_list osemi ')'
{
$$ = nil;
$$ = concat($3, $5);
iota = 0;
lastconst = nil;
yyoptsemi(0);
walkdeflist(concat($3, $5));
}
| LCONST '(' ')'
{
......@@ -333,15 +338,13 @@ common_dcl:
}
| LTYPE typedcl
{
$$ = nil;
// $$ = list1($2);
$$ = list1($2);
if(yylast == LSEMIBRACE)
yyoptsemi(0);
}
| LTYPE '(' typedcl_list osemi ')'
{
$$ = nil;
// $$ = $3;
$$ = $3;
yyoptsemi(0);
}
| LTYPE '(' ')'
......@@ -392,28 +395,29 @@ constdcl1:
}
typedclname:
new_type
sym
{
$$ = dodcltype($1);
defercheckwidth();
// different from dclname because the name
// becomes visible right here, not at the end
// of the declaration.
$$ = typedcl0($1);
}
typedcl:
typedclname ntype
{
typecheck(&$2, Etype);
updatetype($1, $2->type);
resumecheckwidth();
$$ = typedcl1($1, $2, 1);
}
// TODO(rsc): delete
| typedclname LSTRUCT
{
updatetype($1, typ(TFORWSTRUCT));
resumecheckwidth();
$$ = fwdtype($1, TFORWSTRUCT);
}
// TODO(rsc): delete
| typedclname LINTERFACE
{
updatetype($1, typ(TFORWINTER));
resumecheckwidth();
$$ = fwdtype($1, TFORWINTER);
}
simple_stmt:
......@@ -814,9 +818,6 @@ uexpr:
pseudocall:
pexpr '(' oexpr_or_type_list ')'
{
$$ = unsafenmagic($1, $3);
if($$)
break;
$$ = nod(OCALL, $1, N);
$$->list = $3;
}
......@@ -918,12 +919,6 @@ dcl_name:
$$ = dclname($1);
}
new_type:
sym
{
$$ = newtype($1);
}
onew_name:
{
$$ = N;
......@@ -940,7 +935,7 @@ name:
}
labelname:
name
new_name
convtype:
'[' oexpr ']' ntype
......@@ -1104,14 +1099,10 @@ keyval:
* all in one place to show how crappy it all is
*/
xfndcl:
LFUNC
{
maxarg = 0;
stksize = 0;
} fndcl fnbody
LFUNC fndcl fnbody
{
$$ = $3;
$$->nbody = $4;
$$ = $2;
$$->nbody = $3;
funcbody($$);
}
......@@ -1127,13 +1118,13 @@ fndcl:
n = nod(OTFUNC, N, N);
n->list = $3;
n->rlist = $5;
typecheck(&n, Etype);
$$->type = n->type;
// TODO: check if nname already has an ntype
$$->nname->ntype = n;
funchdr($$);
}
| '(' oarg_type_list ')' new_name '(' oarg_type_list ')' fnres
{
Node *rcvr;
Node *rcvr, *t;
rcvr = $2->n;
if($2->next != nil || $2->n->op != ODCLFIELD) {
......@@ -1142,12 +1133,13 @@ fndcl:
}
$$ = nod(ODCLFUNC, N, N);
$$->nname = $4;
$$->nname = methodname($4, rcvr->type);
$$->type = functype(rcvr, $6, $8);
$$->nname = methodname1($4, rcvr->right);
t = nod(OTFUNC, rcvr, N);
t->list = $6;
t->rlist = $8;
$$->nname->ntype = t;
$$->shortname = $4;
funchdr($$);
if(rcvr != N)
addmethod($4, $$->type, 1);
}
fntype:
......@@ -1158,19 +1150,6 @@ fntype:
$$->rlist = $5;
}
fnlitdcl:
fntype
{
markdcl();
$$ = funclit0($$);
}
fnliteral:
fnlitdcl '{' stmt_list '}'
{
$$ = funclit1($1, $3);
}
fnbody:
{
$$ = nil;
......@@ -1197,6 +1176,19 @@ fnres:
$$ = $2;
}
fnlitdcl:
fntype
{
closurehdr($1);
}
fnliteral:
fnlitdcl '{' stmt_list '}'
{
$$ = closurebody($3);
}
/*
* lists of things
* note that they are left recursive
......@@ -1590,15 +1582,16 @@ hidden_import:
{
importconst($2, $3, $5);
}
| LTYPE hidden_pkg_importsym hidden_type
| LTYPE hidden_pkgtype hidden_type
{
importtype($2, $3);
}
| LTYPE hidden_pkg_importsym LSTRUCT
// TODO(rsc): delete
| LTYPE hidden_pkgtype LSTRUCT
{
importtype($2, typ(TFORWSTRUCT));
}
| LTYPE hidden_pkg_importsym LINTERFACE
| LTYPE hidden_pkgtype LINTERFACE
{
importtype($2, typ(TFORWINTER));
}
......@@ -1615,6 +1608,13 @@ hidden_import:
importmethod($5, functype($3->n, $7, $9));
}
hidden_pkgtype:
hidden_pkg_importsym
{
$$ = pkgtype($1);
importsym($1, OTYPE);
}
hidden_type:
hidden_type1
| hidden_type2
......@@ -1690,13 +1690,11 @@ hidden_type2:
hidden_dcl:
sym hidden_type
{
$$ = nod(ODCLFIELD, newname($1), N);
$$->type = $2;
$$ = nod(ODCLFIELD, newname($1), typenod($2));
}
| '?' hidden_type
{
$$ = nod(ODCLFIELD, N, N);
$$->type = $2;
$$ = nod(ODCLFIELD, N, typenod($2));
}
hidden_structdcl:
......@@ -1734,11 +1732,7 @@ hidden_funres:
}
| hidden_type1
{
Node *n;
n = nod(ODCLFIELD, N, N);
n->type = $1;
$$ = list1(n);
$$ = list1(nod(ODCLFIELD, N, typenod($1)));
}
hidden_constant:
......
......@@ -50,10 +50,20 @@ anyinit(NodeList *n)
{
uint32 h;
Sym *s;
// are there any init statements
if(n != nil)
return 1;
NodeList *l;
// are there any interesting init statements
for(l=n; l; l=l->next) {
switch(l->n->op) {
case ODCLFUNC:
case ODCLCONST:
case ODCLTYPE:
case OEMPTY:
break;
default:
return 1;
}
}
// is this main
if(strcmp(package, "main") == 0)
......@@ -93,6 +103,7 @@ fninit(NodeList *n)
return;
}
n = initfix(n);
if(!anyinit(n))
return;
......@@ -106,7 +117,6 @@ fninit(NodeList *n)
// (2)
maxarg = 0;
stksize = initstksize;
snprint(namebuf, sizeof(namebuf), "Init·%s", filename);
......@@ -118,7 +128,7 @@ fninit(NodeList *n)
fn = nod(ODCLFUNC, N, N);
initsym = lookup(namebuf);
fn->nname = newname(initsym);
fn->type = functype(N, nil, nil);
fn->nname->ntype = nod(OTFUNC, N, N);
funchdr(fn);
// (3)
......@@ -181,12 +191,14 @@ fninit(NodeList *n)
exportsym(fn->nname);
fn->nbody = r;
//dump("b", fn);
//dump("r", fn->nbody);
popdcl();
initflag = 1; // flag for loader static initialization
compile(fn);
funcbody(fn);
typecheck(&fn, Etop);
funccompile(fn);
initflag = 0;
}
......
......@@ -310,6 +310,7 @@ importfile(Val *f)
curio.peekc = 0;
curio.peekc1 = 0;
curio.infile = file;
typecheckok = 1;
for(;;) {
c = getc();
if(c == EOF)
......@@ -343,6 +344,7 @@ unimportfile(void)
curio = pushedio;
pushedio.bin = nil;
inimportsys = 0;
typecheckok = 0;
}
void
......@@ -362,6 +364,7 @@ cannedimports(char *file, char *cp)
curio.cp = cp;
pkgmyname = S;
typecheckok = 1;
inimportsys = 1;
}
......@@ -1308,7 +1311,8 @@ lexinit(void)
t = typ(etype);
t->sym = s;
dowidth(t);
if(etype != TANY && etype != TSTRING)
dowidth(t);
types[etype] = t;
}
s->def = typenod(t);
......
......@@ -389,6 +389,7 @@ dcommontype(Sym *s, int ot, Type *t)
Type *elem;
char *p;
dowidth(t);
s1 = dextratype(t);
// empty interface pointing at this type.
......
......@@ -69,6 +69,12 @@ initlin(NodeList *l)
for(; l; l=l->next) {
n = l->n;
switch(n->op) {
case ODCLFUNC:
case ODCLCONST:
case ODCLTYPE:
continue;
}
initlin(n->ninit);
n->ninit = nil;
xxx.list = list(xxx.list, n);
......
......@@ -380,6 +380,7 @@ typ(int et)
t = mal(sizeof(*t));
t->etype = et;
t->width = BADWIDTH;
return t;
}
......@@ -471,7 +472,6 @@ aindex(Node *b, Type *t)
r = typ(TARRAY);
r->type = t;
r->bound = bound;
checkwidth(r);
return r;
}
......@@ -517,7 +517,12 @@ dodump(Node *n, int dep)
break;
case OTYPE:
print("%O %T\n", n->op, n->type);
print("%O %S type=%T\n", n->op, n->sym, n->type);
if(n->type == T && n->ntype) {
indent(dep);
print("%O-ntype\n", n->op);
dodump(n->ntype, dep+1);
}
break;
case OIF:
......@@ -577,7 +582,7 @@ dodump(Node *n, int dep)
break;
}
if(n->ntype != nil) {
if(0 && n->ntype != nil) {
indent(dep);
print("%O-ntype\n", n->op);
dodump(n->ntype, dep+1);
......@@ -1930,7 +1935,9 @@ frame(int context)
int flag;
p = "stack";
l = autodcl;
l = nil;
if(curfn)
l = curfn->dcl;
if(context) {
p = "external";
l = externdcl;
......@@ -2202,42 +2209,6 @@ brrev(int a)
return a;
}
/*
* make a new off the books
*/
void
tempname(Node *n, Type *t)
{
Sym *s;
uint32 w;
if(t == T) {
yyerror("tempname called with nil type");
t = types[TINT32];
}
// give each tmp a different name so that there
// a chance to registerizer them
snprint(namebuf, sizeof(namebuf), "autotmp_%.4d", statuniqgen);
statuniqgen++;
s = lookup(namebuf);
memset(n, 0, sizeof(*n));
n->op = ONAME;
n->sym = s;
n->type = t;
n->class = PAUTO;
n->addable = 1;
n->ullman = 1;
n->noescape = 1;
dowidth(t);
w = t->width;
stksize += w;
stksize = rnd(stksize, w);
n->xoffset = -stksize;
}
Node*
staticname(Type *t)
{
......@@ -2297,58 +2268,14 @@ setmaxarg(Type *t)
{
int32 w;
dowidth(t);
w = t->argwid;
if(t->argwid >= 100000000)
fatal("bad argwid %T", t);
if(w > maxarg)
maxarg = w;
}
/*
* gather series of offsets
* >=0 is direct addressed field
* <0 is pointer to next field (+1)
*/
int
dotoffset(Node *n, int *oary, Node **nn)
{
int i;
switch(n->op) {
case ODOT:
if(n->xoffset == BADWIDTH) {
dump("bad width in dotoffset", n);
fatal("bad width in dotoffset");
}
i = dotoffset(n->left, oary, nn);
if(i > 0) {
if(oary[i-1] >= 0)
oary[i-1] += n->xoffset;
else
oary[i-1] -= n->xoffset;
break;
}
if(i < 10)
oary[i++] = n->xoffset;
break;
case ODOTPTR:
if(n->xoffset == BADWIDTH) {
dump("bad width in dotoffset", n);
fatal("bad width in dotoffset");
}
i = dotoffset(n->left, oary, nn);
if(i < 10)
oary[i++] = -(n->xoffset+1);
break;
default:
*nn = n;
return 0;
}
if(i >= 10)
*nn = N;
return i;
}
/*
* code to resolve elided DOTs
* in embedded types
......@@ -2644,8 +2571,7 @@ structargs(Type **tl, int mustname)
snprint(buf, sizeof buf, ".anon%d", gen++);
n = newname(lookup(buf));
}
a = nod(ODCLFIELD, n, N);
a->type = t->type;
a = nod(ODCLFIELD, n, typenod(t->type));
args = list(args, a);
}
return args;
......@@ -2677,7 +2603,7 @@ structargs(Type **tl, int mustname)
void
genwrapper(Type *rcvr, Type *method, Sym *newnam)
{
Node *this, *fn, *call, *n;
Node *this, *fn, *call, *n, *t;
NodeList *l, *args, *in, *out;
if(debug['r'])
......@@ -2687,14 +2613,17 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam)
dclcontext = PEXTERN;
markdcl();
this = nod(ODCLFIELD, newname(lookup(".this")), N);
this->type = rcvr;
this = nod(ODCLFIELD, newname(lookup(".this")), typenod(rcvr));
this->left->ntype = this->right;
in = structargs(getinarg(method->type), 1);
out = structargs(getoutarg(method->type), 0);
fn = nod(ODCLFUNC, N, N);
fn->nname = newname(newnam);
fn->type = functype(this, in, out);
t = nod(OTFUNC, this, N);
t->list = in;
t->rlist = out;
fn->nname->ntype = t;
funchdr(fn);
// arg list
......@@ -2716,6 +2645,8 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam)
dumplist("genwrapper body", fn->nbody);
funcbody(fn);
typecheck(&fn, Etop);
funccompile(fn);
}
/*
......@@ -3044,6 +2975,9 @@ checkwidth(Type *t)
dowidth(t);
return;
}
if(t->deferwidth)
return;
t->deferwidth = 1;
l = tlfree;
if(l != nil)
......@@ -3075,6 +3009,7 @@ resumecheckwidth(void)
defercalc = 0;
for(l = tlq; l != nil; l = tlq) {
l->t->deferwidth = 0;
dowidth(l->t);
tlq = l->next;
l->next = tlfree;
......
......@@ -27,9 +27,10 @@ static void typecheckcomplit(Node**);
static void addrescapes(Node*);
static void typecheckas2(Node*);
static void typecheckas(Node*);
static void typecheckfunc(Node*);
static void checklvalue(Node*, char*);
static void checkassign(Node*);
static void checkassignlist(NodeList*);
static void checkassign(Node*);
static void checkassignlist(NodeList*);
static int islvalue(Node*);
void
......@@ -53,6 +54,10 @@ typecheck(Node **np, int top)
int lno, ok;
Type *t;
// cannot type check until all the source has been parsed
if(!typecheckok)
fatal("early typecheck");
n = *np;
if(n == N)
return N;
......@@ -392,9 +397,10 @@ reswitch:
if(t == T)
goto error;
n->op = ODOTPTR;
checkwidth(t);
}
if(!lookdot(n, t)) {
yyerror("%#N undefined (type %T has no field %S)", n, t, n->right->sym);
yyerror("%#N undefined (type %p %T has no field %S)", n, t, t, n->right->sym);
goto error;
}
switch(n->op) {
......@@ -566,6 +572,10 @@ reswitch:
n->right = N;
goto reswitch;
}
if(l->op == ONAME && (r = unsafenmagic(l, n->list)) != N) {
n = r;
goto reswitch;
}
typecheck(&n->left, Erv | Etype | Ecall);
defaultlit(&n->left, T);
l = n->left;
......@@ -575,7 +585,7 @@ reswitch:
typechecklist(n->list, Erv);
if((t = l->type) == T)
goto error;
dowidth(t);
checkwidth(t);
switch(l->op) {
case OTYPE:
......@@ -818,6 +828,13 @@ reswitch:
typechecklist(n->list, Erv);
goto ret;
case OCLOSURE:
ok |= Erv;
typecheckclosure(n);
if(n->type == T)
goto error;
goto ret;
/*
* statements
*/
......@@ -905,9 +922,40 @@ reswitch:
typechecklist(n->list, Erv);
typechecklist(n->nbody, Etop);
goto ret;
case ODCLFUNC:
ok |= Etop;
typecheckfunc(n);
goto ret;
case ODCLCONST:
ok |= Etop;
typecheck(&n->left, Erv);
goto ret;
case ODCLTYPE:
ok |= Etop;
typecheck(&n->left, Etype);
goto ret;
}
ret:
t = n->type;
if(t && !t->funarg && n->op != OTYPE) {
switch(t->etype) {
case TFUNC: // might have TANY; wait until its called
case TANY:
case TFORW:
case TFORWINTER:
case TFORWSTRUCT:
case TIDEAL:
case TNIL:
break;
default:
checkwidth(t);
}
}
evconst(n);
if(n->op == OTYPE && !(top & Etype)) {
yyerror("type %T is not an expression", n->type);
......@@ -921,11 +969,12 @@ ret:
yyerror("must call %#N", n);
goto error;
}
if((top & (Ecall|Erv|Etype)) && !(ok & (Erv|Etype|Ecall))) {
// TODO(rsc): simplify
if((top & (Ecall|Erv|Etype)) && !(top & Etop) && !(ok & (Erv|Etype|Ecall))) {
yyerror("%#N used as value", n);
goto error;
}
if((top & Etop) && !(ok & Etop)) {
if((top & Etop) && !(top & (Ecall|Erv|Etype)) && !(ok & Etop)) {
yyerror("%#N not used", n);
goto error;
}
......@@ -1016,6 +1065,7 @@ lookdot(Node *n, Type *t)
s = n->right->sym;
dowidth(t);
f1 = T;
if(t->etype == TSTRUCT || t->etype == TINTER)
f1 = lookdot1(s, t, t->type);
......@@ -1042,6 +1092,7 @@ lookdot(Node *n, Type *t)
if(f2 != T) {
tt = n->left->type;
dowidth(tt);
rcvr = getthisx(f2->type)->type->type;
if(!eqtype(rcvr, tt)) {
if(rcvr->etype == tptr && eqtype(rcvr->type, tt)) {
......@@ -1609,12 +1660,18 @@ addrescapes(Node *n)
case PPARAM:
// if func param, need separate temporary
// to hold heap pointer.
// the function type has already been checked
// (we're in the function body)
// so the param already has a valid xoffset.
if(n->class == PPARAM) {
// expression to refer to stack copy
n->stackparam = nod(OPARAM, n, N);
n->stackparam->type = n->type;
n->stackparam->addable = 1;
if(n->xoffset == BADWIDTH)
fatal("addrescapes before param assignment");
n->stackparam->xoffset = n->xoffset;
n->xoffset = 0;
}
n->class |= PHEAP;
......@@ -1624,10 +1681,12 @@ addrescapes(Node *n)
n->xoffset = 0;
// create stack variable to hold pointer to heap
n->heapaddr = nod(0, N, N);
tempname(n->heapaddr, ptrto(n->type));
n->heapaddr = nod(ONAME, N, N);
n->heapaddr->type = ptrto(n->type);
snprint(buf, sizeof buf, "&%S", n->sym);
n->heapaddr->sym = lookup(buf);
n->heapaddr->class = PHEAP-1; // defer tempname to allocparams
curfn->dcl = list(curfn->dcl, n->heapaddr);
break;
}
break;
......@@ -1846,3 +1905,21 @@ out:
if(ll->n->typecheck == 0)
typecheck(&ll->n, Erv);
}
/*
* type check function definition
*/
static void
typecheckfunc(Node *n)
{
Type *t, *rcvr;
typecheck(&n->nname, Erv);
if((t = n->nname->type) == T)
return;
n->type = t;
rcvr = getthisx(t)->type;
if(rcvr != nil && n->shortname != N)
addmethod(n->shortname->sym, t, 1);
}
......@@ -52,16 +52,9 @@ loop:
case OGOTO:
case ORETURN:
case OPANIC:
case OPANICN:
return 0;
case OCALL:
if(n->left->op == ONAME) {
switch(n->left->etype) {
case OPANIC:
case OPANICN:
return 0;
}
}
break;
}
......@@ -118,7 +111,7 @@ walkdeflist(NodeList *l)
void
walkdef(Node *n)
{
int lno;
int lno, maplineno;
NodeList *init;
Node *e;
Type *t;
......@@ -147,6 +140,9 @@ walkdef(Node *n)
init = nil;
switch(n->op) {
default:
fatal("walkdef %O", n->op);
case OLITERAL:
if(n->ntype != N) {
typecheck(&n->ntype, Etype);
......@@ -189,8 +185,48 @@ walkdef(Node *n)
break;
if(n->defn == N)
fatal("var without type, init: %S", n->sym);
if(n->defn->op == ONAME) {
typecheck(&n->defn, Erv);
n->type = n->defn->type;
break;
}
typecheck(&n->defn, Etop); // fills in n->type
break;
case OTYPE:
n->walkdef = 1;
if(n->nincr != N) // fwd decl hack
n->type = n->nincr->type;
else
n->type = typ(TFORW);
n->type->sym = n->sym;
n->typecheck = 1;
typecheck(&n->ntype, Etype);
if((t = n->ntype->type) == T) {
n->diag = 1;
goto ret;
}
// copy new type and clear fields
// that don't come along
maplineno = n->type->maplineno;
*n->type = *t;
t = n->type;
t->sym = n->sym;
t->local = n->local;
t->vargen = n->vargen;
t->siggen = 0;
t->printed = 0;
t->method = nil;
t->nod = N;
// double-check use of type as map key
// TODO(rsc): also use of type as receiver?
if(maplineno) {
lineno = maplineno;
maptype(n->type, types[TBOOL]);
}
break;
}
ret:
......@@ -265,6 +301,8 @@ walkstmt(Node **np)
case OFALL:
case OGOTO:
case OLABEL:
case ODCLCONST:
case ODCLTYPE:
break;
case OBLOCK:
......@@ -919,6 +957,10 @@ walkexpr(Node **np, NodeList **init)
argtype(fn, n->type->type); // any-2
n = mkcall1(fn, n->type, init, n->left, nodintconst(n->left->type->type->bound));
goto ret;
case OCLOSURE:
n = walkclosure(n, init);
goto ret;
}
fatal("missing switch %O", n->op);
......@@ -1658,6 +1700,7 @@ ifacecvt(Type *tl, Node *n, int et, NodeList **init)
break;
}
dowidth(on->type);
r = nod(OCALL, on, N);
r->list = args;
typecheck(&r, Erv | Efnstruct);
......
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