diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index ac724a02b16..601acf5e7eb 100644 --- a/src/cmd/gc/dcl.c +++ b/src/cmd/gc/dcl.c @@ -877,3 +877,105 @@ forwdcl(Sym *s) s->forwtype = t; return t; } + +// hand-craft the following initialization code +// var init_%%%_done bool; (1) +// func init_%%%_function() (2) +// if init_%%%_done { return } (3) +// init_%%%_done = true; (4) +// for Y { +// init_%%%_function() (5) +// } +// if true { } (6) +// init() // if any (7) +// return (8) +// } +// export init_%%%_function (9) + +void +fninit(Node *n) +{ + Node *done, *any, *init; + Node *a, *b, *r; + Iter iter; + ulong h; + Sym *s; + + r = N; + + // (1) + vargen++; + snprint(namebuf, sizeof(namebuf), "init_%.3ld_done", vargen); + done = newname(lookup(namebuf)); + addvar(done, types[TBOOL], PEXTERN); + + // (2) + + maxarg = 0; + stksize = 0; + + vargen++; + h = vargen; + if(strcmp(package, "main") == 0) + h = 999; + snprint(namebuf, sizeof(namebuf), "init_%.3ld_function", h); + b = nod(ODCLFUNC, N, N); + b->nname = newname(lookup(namebuf)); + b->type = functype(N, N, N); + funchdr(b); + + // (3) + a = nod(OIF, N, N); + a->ntest = done; + a->nbody = nod(ORETURN, N, N); + r = list(r, a); + + // (4) + a = nod(OAS, done, booltrue); + r = list(r, a); + + // (5) + init = N; + for(h=0; hlink) { + if(s->name[0] != 'i') + continue; + if(strstr(s->name, "init") == nil) + continue; + if(strstr(s->name, "_function") == nil) { + if(strcmp(s->name, "init") == 0) + init = s->oname; + continue; + } + if(s->oname == N) + continue; + + a = nod(OCALL, s->oname, N); + r = list(r, a); + } + + // (6) + r = list(r, n); + + // (7) + if(init != N) { + a = nod(OCALL, init, N); + r = list(r, a); + } + + // (8) + a = nod(ORETURN, N, N); + r = list(r, a); + + // (9) + a = nod(OEXPORT, N, N); + a->sym = b->nname->sym; + markexport(a); + + b->nbody = rev(r); +//dump("b", b); +//dump("r", b->nbody); + + popdcl(); + compile(b); +} diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h index ffc75ade7a1..547be9d63b0 100644 --- a/src/cmd/gc/go.h +++ b/src/cmd/gc/go.h @@ -542,6 +542,7 @@ Node* oldname(Sym*); Type* newtype(Sym*); Type* oldtype(Sym*); Type* forwdcl(Sym*); +void fninit(Node*); /* * export.c diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y index 0b0e425c5f7..672e53ac5de 100644 --- a/src/cmd/gc/go.y +++ b/src/cmd/gc/go.y @@ -66,6 +66,7 @@ file: { if(debug['f']) frame(1); + fninit($4); testdclstack(); } @@ -138,12 +139,17 @@ xdcl: | LEXPORT export_list_r { markexport(rev($2)); + $$ = N; } | LEXPORT '(' export_list_r ')' { markexport(rev($3)); + $$ = N; } | xfndcl + { + $$ = N; + } | ';' { $$ = N; @@ -168,9 +174,9 @@ Acommon_dcl: } | LCONST '(' constdcl_list_r osemi ')' { - $$ = N; iota = 0; lastconst = N; + $$ = N; } | LTYPE Atypedcl { @@ -1089,7 +1095,7 @@ xdcl_list_r: xdcl | xdcl_list_r xdcl { - $$ = nod(OLIST, $1, $2); + $$ = list($1, $2); } vardcl_list_r: diff --git a/src/runtime/rt0_amd64.s b/src/runtime/rt0_amd64.s index aad67cbbda8..5544833e4b6 100644 --- a/src/runtime/rt0_amd64.s +++ b/src/runtime/rt0_amd64.s @@ -33,6 +33,7 @@ TEXT _rt0_amd64(SB),7,$-8 MOVQ 24(SP), AX // copy argv MOVQ AX, 8(SP) CALL args(SB) + CALL mainĀ·init_999_function(SB) // initialization // create a new goroutine to start program