// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gc

import (
	"cmd/compile/internal/types"
)

// A function named init is a special case.
// It is called by the initialization before main is run.
// To make it unique within a package and also uncallable,
// the name, normally "pkg.init", is altered to "pkg.init.0".
var renameinitgen int

func renameinit() *types.Sym {
	s := lookupN("init.", renameinitgen)
	renameinitgen++
	return s
}

// anyinit reports whether there any interesting init statements.
func anyinit(n []*Node) bool {
	for _, ln := range n {
		switch ln.Op {
		case ODCLFUNC, ODCLCONST, ODCLTYPE, OEMPTY:
		case OAS:
			if !ln.Left.isBlank() || !candiscard(ln.Right) {
				return true
			}
		default:
			return true
		}
	}

	// is this main
	if localpkg.Name == "main" {
		return true
	}

	// is there an explicit init function
	if renameinitgen > 0 {
		return true
	}

	// are there any imported init functions
	for _, s := range types.InitSyms {
		if s.Def != nil {
			return true
		}
	}

	// then none
	return false
}

// fninit hand-crafts package initialization code.
//
//      func init.ializers() {                          (0)
//              <init stmts>
//      }
//      var initdone· uint8                             (1)
//      func init() {                                   (2)
//              if initdone· > 1 {                      (3)
//                      return                          (3a)
//              }
//              if initdone· == 1 {                     (4)
//                      throw()                         (4a)
//              }
//              initdone· = 1                           (5)
//              // over all matching imported symbols
//                      <pkg>.init()                    (6)
//              init.ializers()                         (7)
//              init.<n>() // if any                    (8)
//              initdone· = 2                           (9)
//              return                                  (10)
//      }
func fninit(n []*Node) {
	lineno = autogeneratedPos
	nf := initfix(n)
	if !anyinit(nf) {
		return
	}

	// (0)
	// Make a function that contains all the initialization statements.
	// This is a separate function because we want it to appear in
	// stack traces, where the init function itself does not.
	var initializers *types.Sym
	if len(nf) > 0 {
		lineno = nf[0].Pos // prolog/epilog gets line number of first init stmt
		initializers = lookup("init.ializers")
		disableExport(initializers)
		fn := dclfunc(initializers, nod(OTFUNC, nil, nil))
		fn.Nbody.Set(nf)
		funcbody()

		fn = typecheck(fn, ctxStmt)
		Curfn = fn
		typecheckslice(nf, ctxStmt)
		Curfn = nil
		funccompile(fn)
		lineno = autogeneratedPos
	}

	var r []*Node

	// (1)
	gatevar := newname(lookup("initdone·"))
	addvar(gatevar, types.Types[TUINT8], PEXTERN)

	// (2)
	initsym := lookup("init")
	fn := dclfunc(initsym, nod(OTFUNC, nil, nil))

	// (3)
	a := nod(OIF, nil, nil)
	a.Left = nod(OGT, gatevar, nodintconst(1))
	a.SetLikely(true)
	r = append(r, a)
	// (3a)
	a.Nbody.Set1(nod(ORETURN, nil, nil))

	// (4)
	b := nod(OIF, nil, nil)
	b.Left = nod(OEQ, gatevar, nodintconst(1))
	// this actually isn't likely, but code layout is better
	// like this: no JMP needed after the call.
	b.SetLikely(true)
	r = append(r, b)
	// (4a)
	b.Nbody.Set1(nod(OCALL, syslook("throwinit"), nil))

	// (5)
	a = nod(OAS, gatevar, nodintconst(1))

	r = append(r, a)

	// (6)
	for _, s := range types.InitSyms {
		if s == initsym {
			continue
		}
		n := resolve(oldname(s))
		if n.Op == ONONAME {
			// No package-scope init function; just a
			// local variable, field name, or something.
			continue
		}
		n.checkInitFuncSignature()
		a = nod(OCALL, n, nil)
		r = append(r, a)
	}

	// (7)
	if initializers != nil {
		n := newname(initializers)
		addvar(n, functype(nil, nil, nil), PFUNC)
		r = append(r, nod(OCALL, n, nil))
	}

	// (8)

	// maxInlineInitCalls is the threshold at which we switch
	// from generating calls inline to generating a static array
	// of functions and calling them in a loop.
	// See CL 41500 for more discussion.
	const maxInlineInitCalls = 500

	if renameinitgen < maxInlineInitCalls {
		// Not many init functions. Just call them all directly.
		for i := 0; i < renameinitgen; i++ {
			s := lookupN("init.", i)
			n := asNode(s.Def)
			n.checkInitFuncSignature()
			a = nod(OCALL, n, nil)
			r = append(r, a)
		}
	} else {
		// Lots of init functions.
		// Set up an array of functions and loop to call them.
		// This is faster to compile and similar at runtime.

		// Build type [renameinitgen]func().
		typ := types.NewArray(functype(nil, nil, nil), int64(renameinitgen))

		// Make and fill array.
		fnarr := staticname(typ)
		fnarr.Name.SetReadonly(true)
		for i := 0; i < renameinitgen; i++ {
			s := lookupN("init.", i)
			lhs := nod(OINDEX, fnarr, nodintconst(int64(i)))
			rhs := asNode(s.Def)
			rhs.checkInitFuncSignature()
			as := nod(OAS, lhs, rhs)
			as = typecheck(as, ctxStmt)
			genAsStatic(as)
		}

		// Generate a loop that calls each function in turn.
		// for i := 0; i < renameinitgen; i++ {
		//   fnarr[i]()
		// }
		i := temp(types.Types[TINT])
		fnidx := nod(OINDEX, fnarr, i)
		fnidx.SetBounded(true)

		zero := nod(OAS, i, nodintconst(0))
		cond := nod(OLT, i, nodintconst(int64(renameinitgen)))
		incr := nod(OAS, i, nod(OADD, i, nodintconst(1)))
		body := nod(OCALL, fnidx, nil)

		loop := nod(OFOR, cond, incr)
		loop.Nbody.Set1(body)
		loop.Ninit.Set1(zero)

		loop = typecheck(loop, ctxStmt)
		r = append(r, loop)
	}

	// (9)
	a = nod(OAS, gatevar, nodintconst(2))

	r = append(r, a)

	// (10)
	a = nod(ORETURN, nil, nil)

	r = append(r, a)
	exportsym(fn.Func.Nname)

	fn.Nbody.Set(r)
	funcbody()

	Curfn = fn
	fn = typecheck(fn, ctxStmt)
	typecheckslice(r, ctxStmt)
	Curfn = nil
	funccompile(fn)
}

func (n *Node) checkInitFuncSignature() {
	if n.Type.NumRecvs()+n.Type.NumParams()+n.Type.NumResults() > 0 {
		Fatalf("init function cannot have receiver, params, or results: %v (%v)", n, n.Type)
	}
}
