// 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 pkginit

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/noder"
	"cmd/compile/internal/objw"
	"cmd/compile/internal/staticinit"
	"cmd/compile/internal/typecheck"
	"cmd/compile/internal/types"
	"cmd/internal/obj"
	"cmd/internal/src"
)

// MakeInit creates a synthetic init function to handle any
// package-scope initialization statements.
//
// TODO(mdempsky): Move into noder, so that the types2-based frontends
// can use Info.InitOrder instead.
func MakeInit() {
	nf := initOrder(typecheck.Target.Decls)
	if len(nf) == 0 {
		return
	}

	// Make a function that contains all the initialization statements.
	base.Pos = nf[0].Pos() // prolog/epilog gets line number of first init stmt
	initializers := typecheck.Lookup("init")
	fn := typecheck.DeclFunc(initializers, nil, nil, nil)
	for _, dcl := range typecheck.InitTodoFunc.Dcl {
		dcl.Curfn = fn
	}
	fn.Dcl = append(fn.Dcl, typecheck.InitTodoFunc.Dcl...)
	typecheck.InitTodoFunc.Dcl = nil
	fn.SetIsPackageInit(true)

	// Suppress useless "can inline" diagnostics.
	// Init functions are only called dynamically.
	fn.SetInlinabilityChecked(true)

	fn.Body = nf
	typecheck.FinishFuncBody()

	typecheck.Func(fn)
	ir.WithFunc(fn, func() {
		typecheck.Stmts(nf)
	})
	typecheck.Target.Decls = append(typecheck.Target.Decls, fn)

	// Prepend to Inits, so it runs first, before any user-declared init
	// functions.
	typecheck.Target.Inits = append([]*ir.Func{fn}, typecheck.Target.Inits...)

	if typecheck.InitTodoFunc.Dcl != nil {
		// We only generate temps using InitTodoFunc if there
		// are package-scope initialization statements, so
		// something's weird if we get here.
		base.Fatalf("InitTodoFunc still has declarations")
	}
	typecheck.InitTodoFunc = nil
}

// Task makes and returns an initialization record for the package.
// See runtime/proc.go:initTask for its layout.
// The 3 tasks for initialization are:
//  1. Initialize all of the packages the current package depends on.
//  2. Initialize all the variables that have initializers.
//  3. Run any init functions.
func Task() *ir.Name {
	var deps []*obj.LSym // initTask records for packages the current package depends on
	var fns []*obj.LSym  // functions to call for package initialization

	// Find imported packages with init tasks.
	for _, pkg := range typecheck.Target.Imports {
		n, ok := pkg.Lookup(".inittask").Def.(*ir.Name)
		if !ok {
			continue
		}
		if n.Op() != ir.ONAME || n.Class != ir.PEXTERN {
			base.Fatalf("bad inittask: %v", n)
		}
		deps = append(deps, n.Linksym())
	}
	if base.Flag.ASan {
		// Make an initialization function to call runtime.asanregisterglobals to register an
		// array of instrumented global variables when -asan is enabled. An instrumented global
		// variable is described by a structure.
		// See the _asan_global structure declared in src/runtime/asan/asan.go.
		//
		// func init {
		// 		var globals []_asan_global {...}
		// 		asanregisterglobals(&globals[0], len(globals))
		// }
		for _, n := range typecheck.Target.Externs {
			if canInstrumentGlobal(n) {
				name := n.Sym().Name
				InstrumentGlobalsMap[name] = n
				InstrumentGlobalsSlice = append(InstrumentGlobalsSlice, n)
			}
		}
		ni := len(InstrumentGlobalsMap)
		if ni != 0 {
			// Make an init._ function.
			base.Pos = base.AutogeneratedPos
			typecheck.DeclContext = ir.PEXTERN
			name := noder.Renameinit()
			fnInit := typecheck.DeclFunc(name, nil, nil, nil)

			// Get an array of intrumented global variables.
			globals := instrumentGlobals(fnInit)

			// Call runtime.asanregisterglobals function to poison redzones.
			// runtime.asanregisterglobals(unsafe.Pointer(&globals[0]), ni)
			asanf := typecheck.NewName(ir.Pkgs.Runtime.Lookup("asanregisterglobals"))
			ir.MarkFunc(asanf)
			asanf.SetType(types.NewSignature(nil, []*types.Field{
				types.NewField(base.Pos, nil, types.Types[types.TUNSAFEPTR]),
				types.NewField(base.Pos, nil, types.Types[types.TUINTPTR]),
			}, nil))
			asancall := ir.NewCallExpr(base.Pos, ir.OCALL, asanf, nil)
			asancall.Args.Append(typecheck.ConvNop(typecheck.NodAddr(
				ir.NewIndexExpr(base.Pos, globals, ir.NewInt(0))), types.Types[types.TUNSAFEPTR]))
			asancall.Args.Append(typecheck.ConvNop(ir.NewInt(int64(ni)), types.Types[types.TUINTPTR]))

			fnInit.Body.Append(asancall)
			typecheck.FinishFuncBody()
			typecheck.Func(fnInit)
			ir.CurFunc = fnInit
			typecheck.Stmts(fnInit.Body)
			ir.CurFunc = nil

			typecheck.Target.Decls = append(typecheck.Target.Decls, fnInit)
			typecheck.Target.Inits = append(typecheck.Target.Inits, fnInit)
		}
	}

	// Record user init functions.
	for _, fn := range typecheck.Target.Inits {
		if fn.Sym().Name == "init" {
			// Synthetic init function for initialization of package-scope
			// variables. We can use staticinit to optimize away static
			// assignments.
			s := staticinit.Schedule{
				Plans: make(map[ir.Node]*staticinit.Plan),
				Temps: make(map[ir.Node]*ir.Name),
			}
			for _, n := range fn.Body {
				s.StaticInit(n)
			}
			fn.Body = s.Out
			ir.WithFunc(fn, func() {
				typecheck.Stmts(fn.Body)
			})

			if len(fn.Body) == 0 {
				fn.Body = []ir.Node{ir.NewBlockStmt(src.NoXPos, nil)}
			}
		}

		// Skip init functions with empty bodies.
		if len(fn.Body) == 1 {
			if stmt := fn.Body[0]; stmt.Op() == ir.OBLOCK && len(stmt.(*ir.BlockStmt).List) == 0 {
				continue
			}
		}
		fns = append(fns, fn.Nname.Linksym())
	}

	if len(deps) == 0 && len(fns) == 0 && types.LocalPkg.Path != "main" && types.LocalPkg.Path != "runtime" {
		return nil // nothing to initialize
	}

	// Make an .inittask structure.
	sym := typecheck.Lookup(".inittask")
	task := typecheck.NewName(sym)
	task.SetType(types.Types[types.TUINT8]) // fake type
	task.Class = ir.PEXTERN
	sym.Def = task
	lsym := task.Linksym()
	ot := 0
	ot = objw.Uintptr(lsym, ot, 0) // state: not initialized yet
	ot = objw.Uintptr(lsym, ot, uint64(len(deps)))
	ot = objw.Uintptr(lsym, ot, uint64(len(fns)))
	for _, d := range deps {
		ot = objw.SymPtr(lsym, ot, d, 0)
	}
	for _, f := range fns {
		ot = objw.SymPtr(lsym, ot, f, 0)
	}
	// An initTask has pointers, but none into the Go heap.
	// It's not quite read only, the state field must be modifiable.
	objw.Global(lsym, int32(ot), obj.NOPTR)
	return task
}

// initRequiredForCoverage returns TRUE if we need to force creation
// of an init function for the package so as to insert a coverage
// runtime registration call.
func initRequiredForCoverage(l []ir.Node) bool {
	if base.Flag.Cfg.CoverageInfo == nil {
		return false
	}
	for _, n := range l {
		if n.Op() == ir.ODCLFUNC {
			return true
		}
	}
	return false
}
