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.
7 // a function named init is a special case.
8 // it is called by the initialization before
9 // main is run. to make it unique within a
10 // package and also uncallable, the name,
11 // normally "pkg.init", is altered to "pkg.init.1".
13 var renameinit_initgen int
15 func renameinit() *Sym {
17 return lookupN("init.", renameinit_initgen)
20 // hand-craft the following initialization code
21 // var initdone· uint8 (1)
23 // if initdone· > 1 { (3)
26 // if initdone· == 1 { (4)
30 // // over all matching imported symbols
32 // { <init stmts> } (7)
33 // init.<n>() // if any (8)
37 func anyinit(n []*Node) bool {
38 // are there any interesting init statements
39 for _, ln := range n {
41 case ODCLFUNC, ODCLCONST, ODCLTYPE, OEMPTY:
45 if isblank(ln.Left) && candiscard(ln.Right) {
55 if localpkg.Name == "main" {
59 // is there an explicit init function
66 // are there any imported init functions
67 for _, s := range initSyms {
77 func fninit(n []*Node) {
86 gatevar := newname(lookup("initdone·"))
87 addvar(gatevar, Types[TUINT8], PEXTERN)
92 fn := nod(ODCLFUNC, nil, nil)
93 initsym := lookup("init")
94 fn.Func.Nname = newname(initsym)
95 fn.Func.Nname.Name.Defn = fn
96 fn.Func.Nname.Name.Param.Ntype = nod(OTFUNC, nil, nil)
97 declare(fn.Func.Nname, PFUNC)
101 a := nod(OIF, nil, nil)
102 a.Left = nod(OGT, gatevar, nodintconst(1))
106 a.Nbody.Set1(nod(ORETURN, nil, nil))
109 b := nod(OIF, nil, nil)
110 b.Left = nod(OEQ, gatevar, nodintconst(1))
111 // this actually isn't likely, but code layout is better
112 // like this: no JMP needed after the call.
116 b.Nbody.Set1(nod(OCALL, syslook("throwinit"), nil))
119 a = nod(OAS, gatevar, nodintconst(1))
124 for _, s := range initSyms {
125 if s.Def != nil && s != initsym {
126 // could check that it is fn of no args/returns
127 a = nod(OCALL, s.Def, nil)
136 // could check that it is fn of no args/returns
138 s := lookupN("init.", i)
142 a = nod(OCALL, s.Def, nil)
147 a = nod(OAS, gatevar, nodintconst(2))
152 a = nod(ORETURN, nil, nil)
155 exportsym(fn.Func.Nname)
161 fn = typecheck(fn, Etop)
162 typecheckslice(r, Etop)