github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/gc/init.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <u.h> 6 #include <libc.h> 7 #include "go.h" 8 9 /* 10 * a function named init is a special case. 11 * it is called by the initialization before 12 * main is run. to make it unique within a 13 * package and also uncallable, the name, 14 * normally "pkg.init", is altered to "pkg.init·1". 15 */ 16 Sym* 17 renameinit(void) 18 { 19 static int initgen; 20 21 snprint(namebuf, sizeof(namebuf), "init·%d", ++initgen); 22 return lookup(namebuf); 23 } 24 25 /* 26 * hand-craft the following initialization code 27 * var initdone· uint8 (1) 28 * func init() (2) 29 * if initdone· != 0 { (3) 30 * if initdone· == 2 (4) 31 * return 32 * throw(); (5) 33 * } 34 * initdone· = 1; (6) 35 * // over all matching imported symbols 36 * <pkg>.init() (7) 37 * { <init stmts> } (8) 38 * init·<n>() // if any (9) 39 * initdone· = 2; (10) 40 * return (11) 41 * } 42 */ 43 static int 44 anyinit(NodeList *n) 45 { 46 uint32 h; 47 Sym *s; 48 NodeList *l; 49 50 // are there any interesting init statements 51 for(l=n; l; l=l->next) { 52 switch(l->n->op) { 53 case ODCLFUNC: 54 case ODCLCONST: 55 case ODCLTYPE: 56 case OEMPTY: 57 break; 58 case OAS: 59 if(isblank(l->n->left) && candiscard(l->n->right)) 60 break; 61 // fall through 62 default: 63 return 1; 64 } 65 } 66 67 // is this main 68 if(strcmp(localpkg->name, "main") == 0) 69 return 1; 70 71 // is there an explicit init function 72 snprint(namebuf, sizeof(namebuf), "init·1"); 73 s = lookup(namebuf); 74 if(s->def != N) 75 return 1; 76 77 // are there any imported init functions 78 for(h=0; h<NHASH; h++) 79 for(s = hash[h]; s != S; s = s->link) { 80 if(s->name[0] != 'i' || strcmp(s->name, "init") != 0) 81 continue; 82 if(s->def == N) 83 continue; 84 return 1; 85 } 86 87 // then none 88 return 0; 89 } 90 91 void 92 fninit(NodeList *n) 93 { 94 int i; 95 Node *gatevar; 96 Node *a, *b, *fn; 97 NodeList *r; 98 uint32 h; 99 Sym *s, *initsym; 100 101 if(debug['A']) { 102 // sys.go or unsafe.go during compiler build 103 return; 104 } 105 106 n = initfix(n); 107 if(!anyinit(n)) 108 return; 109 110 r = nil; 111 112 // (1) 113 snprint(namebuf, sizeof(namebuf), "initdone·"); 114 gatevar = newname(lookup(namebuf)); 115 addvar(gatevar, types[TUINT8], PEXTERN); 116 117 // (2) 118 maxarg = 0; 119 snprint(namebuf, sizeof(namebuf), "init"); 120 121 fn = nod(ODCLFUNC, N, N); 122 initsym = lookup(namebuf); 123 fn->nname = newname(initsym); 124 fn->nname->defn = fn; 125 fn->nname->ntype = nod(OTFUNC, N, N); 126 declare(fn->nname, PFUNC); 127 funchdr(fn); 128 129 // (3) 130 a = nod(OIF, N, N); 131 a->ntest = nod(ONE, gatevar, nodintconst(0)); 132 r = list(r, a); 133 134 // (4) 135 b = nod(OIF, N, N); 136 b->ntest = nod(OEQ, gatevar, nodintconst(2)); 137 b->nbody = list1(nod(ORETURN, N, N)); 138 a->nbody = list1(b); 139 140 // (5) 141 b = syslook("throwinit", 0); 142 b = nod(OCALL, b, N); 143 a->nbody = list(a->nbody, b); 144 145 // (6) 146 a = nod(OAS, gatevar, nodintconst(1)); 147 r = list(r, a); 148 149 // (7) 150 for(h=0; h<NHASH; h++) 151 for(s = hash[h]; s != S; s = s->link) { 152 if(s->name[0] != 'i' || strcmp(s->name, "init") != 0) 153 continue; 154 if(s->def == N) 155 continue; 156 if(s == initsym) 157 continue; 158 159 // could check that it is fn of no args/returns 160 a = nod(OCALL, s->def, N); 161 r = list(r, a); 162 } 163 164 // (8) 165 r = concat(r, n); 166 167 // (9) 168 // could check that it is fn of no args/returns 169 for(i=1;; i++) { 170 snprint(namebuf, sizeof(namebuf), "init·%d", i); 171 s = lookup(namebuf); 172 if(s->def == N) 173 break; 174 a = nod(OCALL, s->def, N); 175 r = list(r, a); 176 } 177 178 // (10) 179 a = nod(OAS, gatevar, nodintconst(2)); 180 r = list(r, a); 181 182 // (11) 183 a = nod(ORETURN, N, N); 184 r = list(r, a); 185 exportsym(fn->nname); 186 187 fn->nbody = r; 188 funcbody(fn); 189 190 curfn = fn; 191 typecheck(&fn, Etop); 192 typechecklist(r, Etop); 193 curfn = nil; 194 funccompile(fn, 0); 195 }