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)