]> Cypherpunks repositories - gostls13.git/commitdiff
detect recursive initialization
authorKen Thompson <ken@golang.org>
Thu, 28 May 2009 23:00:55 +0000 (16:00 -0700)
committerKen Thompson <ken@golang.org>
Thu, 28 May 2009 23:00:55 +0000 (16:00 -0700)
R=r
OCL=29544
CL=29544

src/cmd/gc/builtin.c.boot
src/cmd/gc/dcl.c
src/cmd/gc/sinit.c
src/cmd/gc/sys.go
src/runtime/runtime.c

index 6ee50e035e7bc7d2a052a28e6f0351938be4b76c..54aebd89fcb7d465b145534570d1078c8a7099d1 100644 (file)
@@ -3,6 +3,7 @@ char *sysimport =
        "func sys.mal (? int32) (? *any)\n"
        "func sys.throwindex ()\n"
        "func sys.throwreturn ()\n"
+       "func sys.throwinit ()\n"
        "func sys.panicl (? int32)\n"
        "func sys.printbool (? bool)\n"
        "func sys.printfloat (? float64)\n"
index 6068651b85ee3cdff69a360e56e1bb191d0ee0c6..e5d6392e658fdb4ef6286b9f80a061e5283fa778 100644 (file)
@@ -1284,18 +1284,24 @@ mixed:
        yyerror("cannot mix anonymous and named function arguments");
 }
 
-// hand-craft the following initialization code
-//     var initdone·<file> bool                       (1)
-//     func    Init·<file>()                          (2)
-//             if initdone·<file> { return }          (3)
-//             initdone.<file> = true;                 (4)
-//             // over all matching imported symbols
-//                     <pkg>.init·<file>()            (5)
-//             { <init stmts> }                        (6)
-//             init·<file>()  // if any               (7)
-//             return                                  (8)
-//     }
-
+/*
+ * hand-craft the following initialization code
+ *     var initdone·<file> uint8                      (1)
+ *     func    Init·<file>()                          (2)
+ *             if initdone·<file> {                   (3)
+ *                     if initdone·<file> == 2                (4)
+ *                             return                  
+ *                     throw();                        (5)
+ *             }
+ *             initdone.<file>++;                      (6)
+ *             // over all matching imported symbols
+ *                     <pkg>.init·<file>()            (7)
+ *             { <init stmts> }                        (8)
+ *             init·<file>()  // if any               (9)
+ *             initdone.<file>++;                      (10)
+ *             return                                  (11)
+ *     }
+ */
 int
 anyinit(Node *n)
 {
@@ -1333,8 +1339,8 @@ anyinit(Node *n)
 void
 fninit(Node *n)
 {
-       Node *done;
-       Node *a, *fn, *r;
+       Node *gatevar;
+       Node *a, *b, *fn, *r;
        uint32 h;
        Sym *s, *initsym;
 
@@ -1350,8 +1356,8 @@ fninit(Node *n)
 
        // (1)
        snprint(namebuf, sizeof(namebuf), "initdone·%s", filename);
-       done = newname(lookup(namebuf));
-       addvar(done, types[TBOOL], PEXTERN);
+       gatevar = newname(lookup(namebuf));
+       addvar(gatevar, types[TUINT8], PEXTERN);
 
        // (2)
 
@@ -1373,15 +1379,26 @@ fninit(Node *n)
 
        // (3)
        a = nod(OIF, N, N);
-       a->ntest = done;
-       a->nbody = nod(ORETURN, N, N);
+       a->ntest = nod(ONE, gatevar, nodintconst(0));
        r = list(r, a);
 
        // (4)
-       a = nod(OAS, done, nodbool(1));
-       r = list(r, a);
+       b = nod(OIF, N, N);
+       b->ntest = nod(OEQ, gatevar, nodintconst(2));
+       b->nbody = nod(ORETURN, N, N);
+       a->nbody = b;
 
        // (5)
+       b = syslook("throwinit", 0);
+       b = nod(OCALL, b, N);
+       a->nbody = list(a->nbody, b);
+
+       // (6)
+       a = nod(OASOP, gatevar, nodintconst(1));
+       a->etype = OADD;
+       r = list(r, a);
+
+       // (7)
        for(h=0; h<NHASH; h++)
        for(s = hash[h]; s != S; s = s->link) {
                if(s->name[0] != 'I' || strncmp(s->name, "Init·", 6) != 0)
@@ -1396,10 +1413,10 @@ fninit(Node *n)
                r = list(r, a);
        }
 
-       // (6)
+       // (8)
        r = list(r, initfix(n));
 
-       // (7)
+       // (9)
        // could check that it is fn of no args/returns
        snprint(namebuf, sizeof(namebuf), "init·%s", filename);
        s = lookup(namebuf);
@@ -1408,7 +1425,12 @@ fninit(Node *n)
                r = list(r, a);
        }
 
-       // (8)
+       // (10)
+       a = nod(OASOP, gatevar, nodintconst(1));
+       a->etype = OADD;
+       r = list(r, a);
+
+       // (11)
        a = nod(ORETURN, N, N);
        r = list(r, a);
 
index b15061c2ebe4c6a9148585017bac1e551bf67524..a6727e01153ac11ee3853db2c19cb210a205c19a 100644 (file)
@@ -61,6 +61,8 @@ typeclass(Type *t)
 void
 initlin(Node* n)
 {
+
+loop:
        if(n == N)
                return;
        initlin(n->ninit);
@@ -84,8 +86,8 @@ initlin(Node* n)
 
        case OLIST:
                initlin(n->left);
-               initlin(n->right);
-               break;
+               n = n->right;
+               goto loop;
        }
 }
 
index 3a278d9ff993c51c56eb085b2f05810be538a15f..d4313d2f2390d08540d6156f167824c736ff5a37 100644 (file)
@@ -10,6 +10,7 @@ package PACKAGE
 func   mal(int32) *any;
 func   throwindex();
 func   throwreturn();
+func   throwinit();
 func   panicl(int32);
 
 func   printbool(bool);
index 57e2570905bc689eccd05744141011954b2fe404..fb9bf5cbc2e08f394c819b2308c38b990e43cee6 100644 (file)
@@ -51,6 +51,12 @@ sys·throwreturn(void)
        throw("no return at end of a typed function");
 }
 
+void
+sys·throwinit(void)
+{
+       throw("recursive call during initialization");
+}
+
 void
 throw(int8 *s)
 {