summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKen Thompson <ken@golang.org>2009-05-28 16:00:55 -0700
committerKen Thompson <ken@golang.org>2009-05-28 16:00:55 -0700
commit103de3e314847a7ec67c8ff2a26f7dfe3e79ffe9 (patch)
treeef3051f1ef10e216f04df89c1aa50f6648f8b091
parent627363e8a8fddda42af80877cfed1546f44d87cb (diff)
downloadgolang-103de3e314847a7ec67c8ff2a26f7dfe3e79ffe9.tar.gz
detect recursive initialization
R=r OCL=29544 CL=29544
-rw-r--r--src/cmd/gc/builtin.c.boot1
-rw-r--r--src/cmd/gc/dcl.c68
-rw-r--r--src/cmd/gc/sinit.c6
-rw-r--r--src/cmd/gc/sys.go1
-rw-r--r--src/runtime/runtime.c6
5 files changed, 57 insertions, 25 deletions
diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot
index 6ee50e035..54aebd89f 100644
--- a/src/cmd/gc/builtin.c.boot
+++ b/src/cmd/gc/builtin.c.boot
@@ -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"
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 6068651b8..e5d6392e6 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -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);
diff --git a/src/cmd/gc/sinit.c b/src/cmd/gc/sinit.c
index b15061c2e..a6727e011 100644
--- a/src/cmd/gc/sinit.c
+++ b/src/cmd/gc/sinit.c
@@ -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;
}
}
diff --git a/src/cmd/gc/sys.go b/src/cmd/gc/sys.go
index 3a278d9ff..d4313d2f2 100644
--- a/src/cmd/gc/sys.go
+++ b/src/cmd/gc/sys.go
@@ -10,6 +10,7 @@ package PACKAGE
func mal(int32) *any;
func throwindex();
func throwreturn();
+func throwinit();
func panicl(int32);
func printbool(bool);
diff --git a/src/runtime/runtime.c b/src/runtime/runtime.c
index 57e257090..fb9bf5cbc 100644
--- a/src/runtime/runtime.c
+++ b/src/runtime/runtime.c
@@ -52,6 +52,12 @@ sys·throwreturn(void)
}
void
+sys·throwinit(void)
+{
+ throw("recursive call during initialization");
+}
+
+void
throw(int8 *s)
{
printf("throw: %s\n", s);