github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/init.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/gc/init.go 2 3 // Copyright 2009 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 package gc 8 9 // case OADD: 10 // if(n->right->op == OLITERAL) { 11 // v = n->right->vconst; 12 // naddr(n->left, a, canemitcode); 13 // } else 14 // if(n->left->op == OLITERAL) { 15 // v = n->left->vconst; 16 // naddr(n->right, a, canemitcode); 17 // } else 18 // goto bad; 19 // a->offset += v; 20 // break; 21 22 /* 23 * a function named init is a special case. 24 * it is called by the initialization before 25 * main is run. to make it unique within a 26 * package and also uncallable, the name, 27 * normally "pkg.init", is altered to "pkg.init.1". 28 */ 29 30 var renameinit_initgen int 31 32 func renameinit() *Sym { 33 renameinit_initgen++ 34 return Lookupf("init.%d", renameinit_initgen) 35 } 36 37 /* 38 * hand-craft the following initialization code 39 * var initdone· uint8 (1) 40 * func init() (2) 41 * if initdone· != 0 { (3) 42 * if initdone· == 2 (4) 43 * return 44 * throw(); (5) 45 * } 46 * initdone· = 1; (6) 47 * // over all matching imported symbols 48 * <pkg>.init() (7) 49 * { <init stmts> } (8) 50 * init.<n>() // if any (9) 51 * initdone· = 2; (10) 52 * return (11) 53 * } 54 */ 55 func anyinit(n *NodeList) bool { 56 // are there any interesting init statements 57 for l := n; l != nil; l = l.Next { 58 switch l.N.Op { 59 case ODCLFUNC, ODCLCONST, ODCLTYPE, OEMPTY: 60 break 61 62 case OAS, OASWB: 63 if isblank(l.N.Left) && candiscard(l.N.Right) { 64 break 65 } 66 fallthrough 67 68 // fall through 69 default: 70 return true 71 } 72 } 73 74 // is this main 75 if localpkg.Name == "main" { 76 return true 77 } 78 79 // is there an explicit init function 80 s := Lookup("init.1") 81 82 if s.Def != nil { 83 return true 84 } 85 86 // are there any imported init functions 87 for _, s := range initSyms { 88 if s.Def != nil { 89 return true 90 } 91 } 92 93 // then none 94 return false 95 } 96 97 func fninit(n *NodeList) { 98 if Debug['A'] != 0 { 99 // sys.go or unsafe.go during compiler build 100 return 101 } 102 103 n = initfix(n) 104 if !anyinit(n) { 105 return 106 } 107 108 var r *NodeList 109 110 // (1) 111 gatevar := newname(Lookup("initdone·")) 112 addvar(gatevar, Types[TUINT8], PEXTERN) 113 114 // (2) 115 Maxarg = 0 116 117 fn := Nod(ODCLFUNC, nil, nil) 118 initsym := Lookup("init") 119 fn.Nname = newname(initsym) 120 fn.Nname.Defn = fn 121 fn.Nname.Ntype = Nod(OTFUNC, nil, nil) 122 declare(fn.Nname, PFUNC) 123 funchdr(fn) 124 125 // (3) 126 a := Nod(OIF, nil, nil) 127 128 a.Ntest = Nod(ONE, gatevar, Nodintconst(0)) 129 r = list(r, a) 130 131 // (4) 132 b := Nod(OIF, nil, nil) 133 134 b.Ntest = Nod(OEQ, gatevar, Nodintconst(2)) 135 b.Nbody = list1(Nod(ORETURN, nil, nil)) 136 a.Nbody = list1(b) 137 138 // (5) 139 b = syslook("throwinit", 0) 140 141 b = Nod(OCALL, b, nil) 142 a.Nbody = list(a.Nbody, b) 143 144 // (6) 145 a = Nod(OAS, gatevar, Nodintconst(1)) 146 147 r = list(r, a) 148 149 // (7) 150 for _, s := range initSyms { 151 if s.Def != nil && s != initsym { 152 // could check that it is fn of no args/returns 153 a = Nod(OCALL, s.Def, nil) 154 r = list(r, a) 155 } 156 } 157 158 // (8) 159 r = concat(r, n) 160 161 // (9) 162 // could check that it is fn of no args/returns 163 for i := 1; ; i++ { 164 s := Lookupf("init.%d", i) 165 if s.Def == nil { 166 break 167 } 168 a = Nod(OCALL, s.Def, nil) 169 r = list(r, a) 170 } 171 172 // (10) 173 a = Nod(OAS, gatevar, Nodintconst(2)) 174 175 r = list(r, a) 176 177 // (11) 178 a = Nod(ORETURN, nil, nil) 179 180 r = list(r, a) 181 exportsym(fn.Nname) 182 183 fn.Nbody = r 184 funcbody(fn) 185 186 Curfn = fn 187 typecheck(&fn, Etop) 188 typechecklist(r, Etop) 189 Curfn = nil 190 funccompile(fn) 191 }