From e2613711aacd9b6655366061eb4ecaee7b946910 Mon Sep 17 00:00:00 2001 From: Ken Thompson Date: Thu, 28 May 2009 16:00:55 -0700 Subject: [PATCH] detect recursive initialization R=r OCL=29544 CL=29544 --- src/cmd/gc/builtin.c.boot | 1 + src/cmd/gc/dcl.c | 68 ++++++++++++++++++++++++++------------- src/cmd/gc/sinit.c | 6 ++-- src/cmd/gc/sys.go | 1 + src/runtime/runtime.c | 6 ++++ 5 files changed, 57 insertions(+), 25 deletions(-) diff --git a/src/cmd/gc/builtin.c.boot b/src/cmd/gc/builtin.c.boot index 6ee50e035e..54aebd89fc 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 6068651b85..e5d6392e65 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· bool (1) -// func Init·() (2) -// if initdone· { return } (3) -// initdone. = true; (4) -// // over all matching imported symbols -// .init·() (5) -// { } (6) -// init·() // if any (7) -// return (8) -// } - +/* + * hand-craft the following initialization code + * var initdone· uint8 (1) + * func Init·() (2) + * if initdone· { (3) + * if initdone· == 2 (4) + * return + * throw(); (5) + * } + * initdone.++; (6) + * // over all matching imported symbols + * .init·() (7) + * { } (8) + * init·() // if any (9) + * initdone.++; (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; hlink) { 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 b15061c2eb..a6727e0115 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 3a278d9ff9..d4313d2f23 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 57e2570905..fb9bf5cbc2 100644 --- a/src/runtime/runtime.c +++ b/src/runtime/runtime.c @@ -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) {