github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/init.go (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  package gc
     6  
     7  import (
     8  	"github.com/gagliardetto/golang-go/cmd/compile/internal/types"
     9  	"github.com/gagliardetto/golang-go/cmd/internal/obj"
    10  )
    11  
    12  // A function named init is a special case.
    13  // It is called by the initialization before main is run.
    14  // To make it unique within a package and also uncallable,
    15  // the name, normally "pkg.init", is altered to "pkg.init.0".
    16  var renameinitgen int
    17  
    18  // Dummy function for autotmps generated during typechecking.
    19  var dummyInitFn = nod(ODCLFUNC, nil, nil)
    20  
    21  func renameinit() *types.Sym {
    22  	s := lookupN("init.", renameinitgen)
    23  	renameinitgen++
    24  	return s
    25  }
    26  
    27  // fninit makes an initialization record for the package.
    28  // See runtime/proc.go:initTask for its layout.
    29  // The 3 tasks for initialization are:
    30  //   1) Initialize all of the packages the current package depends on.
    31  //   2) Initialize all the variables that have initializers.
    32  //   3) Run any init functions.
    33  func fninit(n []*Node) {
    34  	nf := initOrder(n)
    35  
    36  	var deps []*obj.LSym // initTask records for packages the current package depends on
    37  	var fns []*obj.LSym  // functions to call for package initialization
    38  
    39  	// Find imported packages with init tasks.
    40  	for _, s := range types.InitSyms {
    41  		deps = append(deps, s.Linksym())
    42  	}
    43  
    44  	// Make a function that contains all the initialization statements.
    45  	if len(nf) > 0 {
    46  		lineno = nf[0].Pos // prolog/epilog gets line number of first init stmt
    47  		initializers := lookup("init")
    48  		disableExport(initializers)
    49  		fn := dclfunc(initializers, nod(OTFUNC, nil, nil))
    50  		for _, dcl := range dummyInitFn.Func.Dcl {
    51  			dcl.Name.Curfn = fn
    52  		}
    53  		fn.Func.Dcl = append(fn.Func.Dcl, dummyInitFn.Func.Dcl...)
    54  		dummyInitFn.Func.Dcl = nil
    55  
    56  		fn.Nbody.Set(nf)
    57  		funcbody()
    58  
    59  		fn = typecheck(fn, ctxStmt)
    60  		Curfn = fn
    61  		typecheckslice(nf, ctxStmt)
    62  		Curfn = nil
    63  		funccompile(fn)
    64  		fns = append(fns, initializers.Linksym())
    65  	}
    66  	if dummyInitFn.Func.Dcl != nil {
    67  		// We only generate temps using dummyInitFn if there
    68  		// are package-scope initialization statements, so
    69  		// something's weird if we get here.
    70  		Fatalf("dummyInitFn still has declarations")
    71  	}
    72  
    73  	// Record user init functions.
    74  	for i := 0; i < renameinitgen; i++ {
    75  		s := lookupN("init.", i)
    76  		fn := asNode(s.Def).Name.Defn
    77  		// Skip init functions with empty bodies.
    78  		// noder.go doesn't allow external init functions, and
    79  		// order.go has already removed any OEMPTY nodes, so
    80  		// checking Len() == 0 is sufficient here.
    81  		if fn.Nbody.Len() == 0 {
    82  			continue
    83  		}
    84  		fns = append(fns, s.Linksym())
    85  	}
    86  
    87  	if len(deps) == 0 && len(fns) == 0 && localpkg.Name != "main" && localpkg.Name != "runtime" {
    88  		return // nothing to initialize
    89  	}
    90  
    91  	// Make an .inittask structure.
    92  	sym := lookup(".inittask")
    93  	nn := newname(sym)
    94  	nn.Type = types.Types[TUINT8] // dummy type
    95  	nn.SetClass(PEXTERN)
    96  	sym.Def = asTypesNode(nn)
    97  	exportsym(nn)
    98  	lsym := sym.Linksym()
    99  	ot := 0
   100  	ot = duintptr(lsym, ot, 0) // state: not initialized yet
   101  	ot = duintptr(lsym, ot, uint64(len(deps)))
   102  	ot = duintptr(lsym, ot, uint64(len(fns)))
   103  	for _, d := range deps {
   104  		ot = dsymptr(lsym, ot, d, 0)
   105  	}
   106  	for _, f := range fns {
   107  		ot = dsymptr(lsym, ot, f, 0)
   108  	}
   109  	// An initTask has pointers, but none into the Go heap.
   110  	// It's not quite read only, the state field must be modifiable.
   111  	ggloblsym(lsym, int32(ot), obj.NOPTR)
   112  }