]> Cypherpunks repositories - gostls13.git/commitdiff
whole-package compilation
authorRuss Cox <rsc@golang.org>
Wed, 12 Aug 2009 20:18:19 +0000 (13:18 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 12 Aug 2009 20:18:19 +0000 (13:18 -0700)
R=ken
OCL=33063
CL=33095

src/cmd/gc/dcl.c
src/cmd/gc/export.c
src/cmd/gc/go.h
src/cmd/gc/go.y
src/cmd/gc/init.c
src/cmd/gc/lex.c
src/cmd/gc/sinit.c

index fe64ee08d7a8daa4ef6086b2422075666d7fee98..d19c0a4d2ed37eee666b7da351e09b3159b54d3e 100644 (file)
@@ -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
index 20831d16143649441362a53593795bc69df29064..b5abec3cca49ce8f4d3430a9b6e5c178b8219f33 100644 (file)
@@ -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);
index 72c6b745d4c0098f296b7750f379c5df9020a678..e5cdadbb73be97698833c04e00dc135defab11e4 100644 (file)
@@ -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;
index 4b59dfc3f26864c539962d120d29bf19b2cf5a22..439340caba37a16a8c20c5bfc40c9b49456d58f7 100644 (file)
@@ -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
index ca6b1eb373b839a60238d71dde4650897a1abb59..dd641de96b4c8ee5bae50f2d0afad5d748b562d2 100644 (file)
@@ -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);
        }
index 8770ee5361a050b9d289084bc009b96436a66737..fddb17e98c070008e803527627c75d5be6cfb1dd 100644 (file)
@@ -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, '/');
index 83db9bff1fc7066accbc800e7e8da35e70c4912a..4b46f7c7c08b423a60e6b27befa9f17961fe6d13 100644 (file)
@@ -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;