summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2009-08-12 13:18:19 -0700
committerRuss Cox <rsc@golang.org>2009-08-12 13:18:19 -0700
commita66d62a16800f6628d1372ee87aa67eb1766ec30 (patch)
tree0df44983afca9b1eeef9b0d8408acbb4dcfa921f /src
parent32652606d49e99c4e9555ed0ab0cb8ccaf599780 (diff)
downloadgolang-a66d62a16800f6628d1372ee87aa67eb1766ec30.tar.gz
whole-package compilation
R=ken OCL=33063 CL=33095
Diffstat (limited to 'src')
-rw-r--r--src/cmd/gc/dcl.c13
-rw-r--r--src/cmd/gc/export.c12
-rw-r--r--src/cmd/gc/go.h2
-rw-r--r--src/cmd/gc/go.y44
-rw-r--r--src/cmd/gc/init.c20
-rw-r--r--src/cmd/gc/lex.c122
-rw-r--r--src/cmd/gc/sinit.c74
7 files changed, 204 insertions, 83 deletions
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index fe64ee08d..d19c0a4d2 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -649,16 +649,9 @@ funchdr(Node *n)
Node *nt;
if(n->nname != N) {
- // TODO(rsc): remove once forward declarations are gone
- if(n->nname->sym->def && n->nname->sym->def->class == PFUNC) {
- nt = n->nname->ntype;
- n->nname = n->nname->sym->def;
- n->nname->ntype = nt;
- n->nname->type = T;
- } else {
- n->nname->op = ONAME;
- declare(n->nname, PFUNC);
- }
+ n->nname->op = ONAME;
+ declare(n->nname, PFUNC);
+ n->nname->defn = n;
}
// change the declaration context from extern to auto
diff --git a/src/cmd/gc/export.c b/src/cmd/gc/export.c
index 20831d161..b5abec3cc 100644
--- a/src/cmd/gc/export.c
+++ b/src/cmd/gc/export.c
@@ -299,6 +299,8 @@ pkgtype(Sym *s)
t->sym = s;
s->def = typenod(t);
}
+ if(s->def->type == T)
+ yyerror("pkgtype %lS", s);
return s->def->type;
}
@@ -314,6 +316,8 @@ mypackage(Sym *s)
void
importconst(Sym *s, Type *t, Node *n)
{
+ Node *n1;
+
if(!exportname(s->name) && !mypackage(s))
return;
importsym(s, OLITERAL);
@@ -327,6 +331,11 @@ importconst(Sym *s, Type *t, Node *n)
yyerror("expression must be a constant");
return;
}
+ if(n->sym != S) {
+ n1 = nod(OXXX, N, N);
+ *n1 = *n;
+ n = n1;
+ }
n->sym = s;
declare(n, PEXTERN);
@@ -360,7 +369,8 @@ importvar(Sym *s, Type *t, int ctxt)
void
importtype(Type *pt, Type *t)
{
- typedcl2(pt, t);
+ if(pt != T && t != T)
+ typedcl2(pt, t);
if(debug['E'])
print("import type %T %lT\n", pt, t);
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 72c6b745d..e5cdadbb7 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -198,6 +198,7 @@ struct Node
uchar walkdef;
uchar typecheck;
uchar local;
+ uchar initorder;
// most nodes
Node* left;
@@ -649,6 +650,7 @@ EXTERN Mpint* maxintval[NTYPE];
EXTERN Mpflt* minfltval[NTYPE];
EXTERN Mpflt* maxfltval[NTYPE];
+EXTERN NodeList* xtop;
EXTERN NodeList* externdcl;
EXTERN NodeList* closures;
EXTERN NodeList* exportlist;
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 4b59dfc3f..439340cab 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -120,29 +120,7 @@ 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);
- while(closures) {
- l = closures;
- closures = nil;
- for(; l; l=l->next)
- funccompile(l->n);
- }
- dclchecks();
+ xtop = concat(xtop, $4);
}
package:
@@ -262,15 +240,17 @@ import_done:
if(my == import && strcmp(import->name, package) == 0)
break;
- if(my->def != N) {
- // TODO(rsc): this line is only needed because of the
- // package net
- // import "net"
- // convention; if we get rid of it, the check can go away
- // and we can just always print the error
- if(my->def->op != OPACK || strcmp(my->name, import->name) != 0)
- yyerror("redeclaration of %S by import", my);
- }
+ // TODO(rsc): this line is needed for a package
+ // which does bytes := in a function, which creates
+ // an ONONAME for bytes, but then a different file
+ // imports "bytes". more generally we need to figure out
+ // what it means if one file imports "bytes" and another
+ // declares a top-level name.
+ if(my->def && my->def->op == ONONAME)
+ 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->sym = import;
import->block = -1; // above top level
diff --git a/src/cmd/gc/init.c b/src/cmd/gc/init.c
index ca6b1eb37..dd641de96 100644
--- a/src/cmd/gc/init.c
+++ b/src/cmd/gc/init.c
@@ -15,6 +15,7 @@ Node*
renameinit(Node *n)
{
Sym *s;
+ static int initgen;
s = n->sym;
if(s == S)
@@ -22,7 +23,7 @@ renameinit(Node *n)
if(strcmp(s->name, "init") != 0)
return n;
- snprint(namebuf, sizeof(namebuf), "init·%s", filename);
+ snprint(namebuf, sizeof(namebuf), "init·%d", ++initgen);
s = lookup(namebuf);
return newname(s);
}
@@ -70,7 +71,7 @@ anyinit(NodeList *n)
return 1;
// is there an explicit init function
- snprint(namebuf, sizeof(namebuf), "init·%s", filename);
+ snprint(namebuf, sizeof(namebuf), "init·1");
s = lookup(namebuf);
if(s->def != N)
return 1;
@@ -92,6 +93,7 @@ anyinit(NodeList *n)
void
fninit(NodeList *n)
{
+ int i;
Node *gatevar;
Node *a, *b, *fn;
NodeList *r;
@@ -110,7 +112,7 @@ fninit(NodeList *n)
r = nil;
// (1)
- snprint(namebuf, sizeof(namebuf), "initdone·%s", filename);
+ snprint(namebuf, sizeof(namebuf), "initdone·");
gatevar = newname(lookup(namebuf));
addvar(gatevar, types[TUINT8], PEXTERN);
@@ -118,7 +120,7 @@ fninit(NodeList *n)
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
// call the top level init function out of rt0
@@ -168,13 +170,15 @@ fninit(NodeList *n)
}
// (8)
- r = concat(r, initfix(n));
+ r = concat(r, n);
// (9)
// could check that it is fn of no args/returns
- snprint(namebuf, sizeof(namebuf), "init·%s", filename);
- s = lookup(namebuf);
- if(s->def != N) {
+ for(i=1;; i++) {
+ snprint(namebuf, sizeof(namebuf), "init·%d", i);
+ s = lookup(namebuf);
+ if(s->def == N)
+ break;
a = nod(OCALL, s->def, N);
r = list(r, a);
}
diff --git a/src/cmd/gc/lex.c b/src/cmd/gc/lex.c
index 8770ee536..fddb17e98 100644
--- a/src/cmd/gc/lex.c
+++ b/src/cmd/gc/lex.c
@@ -10,6 +10,7 @@
extern int yychar;
Sym *anysym;
+char nopackage[] = "____";
#define DBG if(!debug['x']);else print
enum
@@ -20,10 +21,11 @@ enum
int
main(int argc, char *argv[])
{
- int c;
+ int i, c;
+ NodeList *l;
outfile = nil;
- package = "____";
+ package = nopackage;
ARGBEGIN {
default:
c = ARGC();
@@ -44,7 +46,7 @@ main(int argc, char *argv[])
break;
} ARGEND
- if(argc != 1)
+ if(argc < 1)
goto usage;
pathname = mal(100);
@@ -69,31 +71,57 @@ main(int argc, char *argv[])
lexinit();
typeinit();
- lineno = 1;
- block = 1;
blockgen = 1;
+ dclcontext = PEXTERN;
+ nerrors = 0;
+ lineno = 1;
- setfilename(argv[0]);
- infile = argv[0];
- linehist(infile, 0, 0);
+ for(i=0; i<argc; i++) {
+ if(i == 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;
- curio.bin = Bopen(infile, OREAD);
- if(curio.bin == nil)
- fatal("cant open: %s", infile);
- curio.peekc = 0;
- curio.peekc1 = 0;
+ block = 1;
- dclcontext = PEXTERN;
+ yyparse();
+ if(nsyntaxerrors != 0)
+ errorexit();
- nerrors = 0;
- yyparse();
- runifacechecks();
+ linehist(nil, 0, 0);
+ if(curio.bin != nil)
+ Bterm(curio.bin);
+ }
- linehist(nil, 0, 0);
- if(curio.bin != nil)
- Bterm(curio.bin);
+ testdclstack();
+
+ 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)
errorexit();
@@ -264,6 +292,8 @@ importfile(Val *f)
int32 c;
int len;
+// TODO: don't bother reloading imports more than once
+
if(f->ctype != CTSTR) {
yyerror("import statement not a string");
return;
@@ -1427,6 +1457,16 @@ lexname(int lex)
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
mkpackage(char* pkg)
{
@@ -1434,23 +1474,43 @@ mkpackage(char* pkg)
int32 h;
char *p;
- if(bout != nil) {
- yyerror("mkpackage: called again %s %s", pkg, package);
- return;
+ if(package == nopackage) {
+ // 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 == 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
s = lookup(package);
s->def = nod(OPACK, N, N);
s->def->sym = s;
s->block = -1; // above top level
+*/
if(outfile == nil) {
p = strrchr(infile, '/');
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index 83db9bff1..4b46f7c7c 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -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*
initfix(NodeList *l)
{
Node *r;
xxx.list = nil;
- initlin(l);
+ initreorder(l, &xxx.list);
if(0)
return xxx.list;