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  }