Commit 66bb399f authored by Russ Cox's avatar Russ Cox

whole-package compilation

R=ken
OCL=33063
CL=33095
parent 866b2723
...@@ -649,16 +649,9 @@ funchdr(Node *n) ...@@ -649,16 +649,9 @@ funchdr(Node *n)
Node *nt; Node *nt;
if(n->nname != N) { if(n->nname != N) {
// TODO(rsc): remove once forward declarations are gone n->nname->op = ONAME;
if(n->nname->sym->def && n->nname->sym->def->class == PFUNC) { declare(n->nname, PFUNC);
nt = n->nname->ntype; n->nname->defn = n;
n->nname = n->nname->sym->def;
n->nname->ntype = nt;
n->nname->type = T;
} else {
n->nname->op = ONAME;
declare(n->nname, PFUNC);
}
} }
// change the declaration context from extern to auto // change the declaration context from extern to auto
......
...@@ -299,6 +299,8 @@ pkgtype(Sym *s) ...@@ -299,6 +299,8 @@ pkgtype(Sym *s)
t->sym = s; t->sym = s;
s->def = typenod(t); s->def = typenod(t);
} }
if(s->def->type == T)
yyerror("pkgtype %lS", s);
return s->def->type; return s->def->type;
} }
...@@ -314,6 +316,8 @@ mypackage(Sym *s) ...@@ -314,6 +316,8 @@ mypackage(Sym *s)
void void
importconst(Sym *s, Type *t, Node *n) importconst(Sym *s, Type *t, Node *n)
{ {
Node *n1;
if(!exportname(s->name) && !mypackage(s)) if(!exportname(s->name) && !mypackage(s))
return; return;
importsym(s, OLITERAL); importsym(s, OLITERAL);
...@@ -327,6 +331,11 @@ importconst(Sym *s, Type *t, Node *n) ...@@ -327,6 +331,11 @@ importconst(Sym *s, Type *t, Node *n)
yyerror("expression must be a constant"); yyerror("expression must be a constant");
return; return;
} }
if(n->sym != S) {
n1 = nod(OXXX, N, N);
*n1 = *n;
n = n1;
}
n->sym = s; n->sym = s;
declare(n, PEXTERN); declare(n, PEXTERN);
...@@ -360,7 +369,8 @@ importvar(Sym *s, Type *t, int ctxt) ...@@ -360,7 +369,8 @@ importvar(Sym *s, Type *t, int ctxt)
void void
importtype(Type *pt, Type *t) importtype(Type *pt, Type *t)
{ {
typedcl2(pt, t); if(pt != T && t != T)
typedcl2(pt, t);
if(debug['E']) if(debug['E'])
print("import type %T %lT\n", pt, t); print("import type %T %lT\n", pt, t);
......
...@@ -198,6 +198,7 @@ struct Node ...@@ -198,6 +198,7 @@ struct Node
uchar walkdef; uchar walkdef;
uchar typecheck; uchar typecheck;
uchar local; uchar local;
uchar initorder;
// most nodes // most nodes
Node* left; Node* left;
...@@ -649,6 +650,7 @@ EXTERN Mpint* maxintval[NTYPE]; ...@@ -649,6 +650,7 @@ EXTERN Mpint* maxintval[NTYPE];
EXTERN Mpflt* minfltval[NTYPE]; EXTERN Mpflt* minfltval[NTYPE];
EXTERN Mpflt* maxfltval[NTYPE]; EXTERN Mpflt* maxfltval[NTYPE];
EXTERN NodeList* xtop;
EXTERN NodeList* externdcl; EXTERN NodeList* externdcl;
EXTERN NodeList* closures; EXTERN NodeList* closures;
EXTERN NodeList* exportlist; EXTERN NodeList* exportlist;
......
...@@ -120,29 +120,7 @@ file: ...@@ -120,29 +120,7 @@ file:
imports imports
xdcl_list xdcl_list
{ {
NodeList *l; xtop = concat(xtop, $4);
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);
while(closures) {
l = closures;
closures = nil;
for(; l; l=l->next)
funccompile(l->n);
}
dclchecks();
} }
package: package:
...@@ -262,15 +240,17 @@ import_done: ...@@ -262,15 +240,17 @@ import_done:
if(my == import && strcmp(import->name, package) == 0) if(my == import && strcmp(import->name, package) == 0)
break; break;
if(my->def != N) { // TODO(rsc): this line is needed for a package
// TODO(rsc): this line is only needed because of the // which does bytes := in a function, which creates
// package net // an ONONAME for bytes, but then a different file
// import "net" // imports "bytes". more generally we need to figure out
// convention; if we get rid of it, the check can go away // what it means if one file imports "bytes" and another
// and we can just always print the error // declares a top-level name.
if(my->def->op != OPACK || strcmp(my->name, import->name) != 0) if(my->def && my->def->op == ONONAME)
yyerror("redeclaration of %S by import", my); my->def = N;
}
if(my->def)
yyerror("redeclaration of %S by import\n\t%N", my, my->def);
my->def = nod(OPACK, N, N); my->def = nod(OPACK, N, N);
my->def->sym = import; my->def->sym = import;
import->block = -1; // above top level import->block = -1; // above top level
......
...@@ -15,6 +15,7 @@ Node* ...@@ -15,6 +15,7 @@ Node*
renameinit(Node *n) renameinit(Node *n)
{ {
Sym *s; Sym *s;
static int initgen;
s = n->sym; s = n->sym;
if(s == S) if(s == S)
...@@ -22,7 +23,7 @@ renameinit(Node *n) ...@@ -22,7 +23,7 @@ renameinit(Node *n)
if(strcmp(s->name, "init") != 0) if(strcmp(s->name, "init") != 0)
return n; return n;
snprint(namebuf, sizeof(namebuf), "init·%s", filename); snprint(namebuf, sizeof(namebuf), "init·%d", ++initgen);
s = lookup(namebuf); s = lookup(namebuf);
return newname(s); return newname(s);
} }
...@@ -70,7 +71,7 @@ anyinit(NodeList *n) ...@@ -70,7 +71,7 @@ anyinit(NodeList *n)
return 1; return 1;
// is there an explicit init function // is there an explicit init function
snprint(namebuf, sizeof(namebuf), "init·%s", filename); snprint(namebuf, sizeof(namebuf), "init·1");
s = lookup(namebuf); s = lookup(namebuf);
if(s->def != N) if(s->def != N)
return 1; return 1;
...@@ -92,6 +93,7 @@ anyinit(NodeList *n) ...@@ -92,6 +93,7 @@ anyinit(NodeList *n)
void void
fninit(NodeList *n) fninit(NodeList *n)
{ {
int i;
Node *gatevar; Node *gatevar;
Node *a, *b, *fn; Node *a, *b, *fn;
NodeList *r; NodeList *r;
...@@ -110,7 +112,7 @@ fninit(NodeList *n) ...@@ -110,7 +112,7 @@ fninit(NodeList *n)
r = nil; r = nil;
// (1) // (1)
snprint(namebuf, sizeof(namebuf), "initdone·%s", filename); snprint(namebuf, sizeof(namebuf), "initdone·");
gatevar = newname(lookup(namebuf)); gatevar = newname(lookup(namebuf));
addvar(gatevar, types[TUINT8], PEXTERN); addvar(gatevar, types[TUINT8], PEXTERN);
...@@ -118,7 +120,7 @@ fninit(NodeList *n) ...@@ -118,7 +120,7 @@ fninit(NodeList *n)
maxarg = 0; maxarg = 0;
snprint(namebuf, sizeof(namebuf), "Init·%s", filename); snprint(namebuf, sizeof(namebuf), "Init·");
// this is a botch since we need a known name to // this is a botch since we need a known name to
// call the top level init function out of rt0 // call the top level init function out of rt0
...@@ -168,13 +170,15 @@ fninit(NodeList *n) ...@@ -168,13 +170,15 @@ fninit(NodeList *n)
} }
// (8) // (8)
r = concat(r, initfix(n)); r = concat(r, n);
// (9) // (9)
// could check that it is fn of no args/returns // could check that it is fn of no args/returns
snprint(namebuf, sizeof(namebuf), "init·%s", filename); for(i=1;; i++) {
s = lookup(namebuf); snprint(namebuf, sizeof(namebuf), "init·%d", i);
if(s->def != N) { s = lookup(namebuf);
if(s->def == N)
break;
a = nod(OCALL, s->def, N); a = nod(OCALL, s->def, N);
r = list(r, a); r = list(r, a);
} }
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
extern int yychar; extern int yychar;
Sym *anysym; Sym *anysym;
char nopackage[] = "____";
#define DBG if(!debug['x']);else print #define DBG if(!debug['x']);else print
enum enum
...@@ -20,10 +21,11 @@ enum ...@@ -20,10 +21,11 @@ enum
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int c; int i, c;
NodeList *l;
outfile = nil; outfile = nil;
package = "____"; package = nopackage;
ARGBEGIN { ARGBEGIN {
default: default:
c = ARGC(); c = ARGC();
...@@ -44,7 +46,7 @@ main(int argc, char *argv[]) ...@@ -44,7 +46,7 @@ main(int argc, char *argv[])
break; break;
} ARGEND } ARGEND
if(argc != 1) if(argc < 1)
goto usage; goto usage;
pathname = mal(100); pathname = mal(100);
...@@ -69,31 +71,57 @@ main(int argc, char *argv[]) ...@@ -69,31 +71,57 @@ main(int argc, char *argv[])
lexinit(); lexinit();
typeinit(); typeinit();
lineno = 1;
block = 1;
blockgen = 1; blockgen = 1;
dclcontext = PEXTERN;
nerrors = 0;
lineno = 1;
setfilename(argv[0]); for(i=0; i<argc; i++) {
infile = argv[0]; if(i == 0)
linehist(infile, 0, 0); setfilename(argv[i]);
infile = argv[i];
linehist(infile, 0, 0);
curio.infile = infile;
curio.bin = Bopen(infile, OREAD);
if(curio.bin == nil)
fatal("open%s: %r", infile);
curio.peekc = 0;
curio.peekc1 = 0;
curio.infile = infile; block = 1;
curio.bin = Bopen(infile, OREAD);
if(curio.bin == nil)
fatal("cant open: %s", infile);
curio.peekc = 0;
curio.peekc1 = 0;
dclcontext = PEXTERN; yyparse();
if(nsyntaxerrors != 0)
errorexit();
nerrors = 0; linehist(nil, 0, 0);
yyparse(); if(curio.bin != nil)
runifacechecks(); Bterm(curio.bin);
}
linehist(nil, 0, 0); testdclstack();
if(curio.bin != nil)
Bterm(curio.bin); typecheckok = 1;
if(debug['f'])
frame(1);
defercheckwidth();
typechecklist(xtop, Etop);
resumecheckwidth();
for(l=xtop; l; l=l->next)
if(l->n->op == ODCLFUNC)
funccompile(l->n);
if(nerrors == 0)
fninit(xtop);
while(closures) {
l = closures;
closures = nil;
for(; l; l=l->next)
funccompile(l->n);
}
dclchecks();
runifacechecks();
if(nerrors) if(nerrors)
errorexit(); errorexit();
...@@ -264,6 +292,8 @@ importfile(Val *f) ...@@ -264,6 +292,8 @@ importfile(Val *f)
int32 c; int32 c;
int len; int len;
// TODO: don't bother reloading imports more than once
if(f->ctype != CTSTR) { if(f->ctype != CTSTR) {
yyerror("import statement not a string"); yyerror("import statement not a string");
return; return;
...@@ -1427,6 +1457,16 @@ lexname(int lex) ...@@ -1427,6 +1457,16 @@ lexname(int lex)
return buf; return buf;
} }
int
specialsym(Sym *s)
{
if(strcmp(s->name, "byte") == 0 && s->def->sym == lookup("uint8"))
return 1;
if(strcmp(s->name, "iota") == 0 && s->def->sym == S)
return 1;
return 0;
}
void void
mkpackage(char* pkg) mkpackage(char* pkg)
{ {
...@@ -1434,23 +1474,43 @@ mkpackage(char* pkg) ...@@ -1434,23 +1474,43 @@ mkpackage(char* pkg)
int32 h; int32 h;
char *p; char *p;
if(bout != nil) { if(package == nopackage) {
yyerror("mkpackage: called again %s %s", pkg, package); // redefine all names to be this package.
return; for(h=0; h<NHASH; h++)
for(s = hash[h]; s != S; s = s->link)
if(s->package == nopackage)
s->package = pkg;
package = pkg;
} else {
if(strcmp(pkg, package) != 0)
yyerror("package %s; expected %s", pkg, package);
for(h=0; h<NHASH; h++) {
for(s = hash[h]; s != S; s = s->link) {
if(s->def == N || s->package != package)
continue;
if(s->def->op == OPACK) {
// throw away top-level package name leftover
// from previous file.
s->def = N;
continue;
}
if(s->def->sym != s && !specialsym(s)) {
// throw away top-level name left over
// from previous import . "x"
s->def = N;
continue;
}
}
}
} }
// redefine all names to be this package /*
for(h=0; h<NHASH; h++)
for(s = hash[h]; s != S; s = s->link)
if(s->package == package)
s->package = pkg;
package = pkg;
// declare this name as a package // declare this name as a package
s = lookup(package); s = lookup(package);
s->def = nod(OPACK, N, N); s->def = nod(OPACK, N, N);
s->def->sym = s; s->def->sym = s;
s->block = -1; // above top level s->block = -1; // above top level
*/
if(outfile == nil) { if(outfile == nil) {
p = strrchr(infile, '/'); p = strrchr(infile, '/');
......
...@@ -457,13 +457,85 @@ return; ...@@ -457,13 +457,85 @@ return;
} }
static void
init1(Node *n, NodeList **out)
{
NodeList *l;
if(n == N)
return;
init1(n->left, out);
init1(n->right, out);
for(l=n->list; l; l=l->next)
init1(l->n, out);
if(n->op != ONAME)
return;
switch(n->class) {
case PEXTERN:
case PFUNC:
break;
default:
return;
}
if(n->initorder == 1)
return;
if(n->initorder == 2)
fatal("init loop");
// make sure that everything n depends on is initialized.
// n->defn is an assignment to n
n->initorder = 2;
if(n->defn != N) {
switch(n->defn->op) {
case ODCLFUNC:
for(l=n->defn->nbody; l; l=l->next)
init1(l->n, out);
break;
case OAS:
if(n->defn->left != n) {
default:
dump("defn", n->defn);
fatal("bad defn");
}
init1(n->defn->right, out);
if(debug['j'])
print("%S\n", n->sym);
*out = list(*out, n->defn);
break;
}
}
n->initorder = 1;
return;
}
static void
initreorder(NodeList *l, NodeList **out)
{
Node *n;
for(; l; l=l->next) {
n = l->n;
switch(n->op) {
case ODCLFUNC:
case ODCLCONST:
case ODCLTYPE:
continue;
}
initreorder(n->ninit, out);
n->ninit = nil;
init1(n, out);
}
}
NodeList* NodeList*
initfix(NodeList *l) initfix(NodeList *l)
{ {
Node *r; Node *r;
xxx.list = nil; xxx.list = nil;
initlin(l); initreorder(l, &xxx.list);
if(0) if(0)
return xxx.list; return xxx.list;
......
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