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

import (
	"fmt"
	"go/constant"
	"go/token"
	"os"
	"strings"

	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/reflectdata"
	"cmd/compile/internal/staticdata"
	"cmd/compile/internal/typecheck"
	"cmd/compile/internal/types"
	"cmd/internal/obj"
	"cmd/internal/objabi"
	"cmd/internal/src"
)

type Entry struct {
	Xoffset int64   // struct, array only
	Expr    ir.Node // bytes of run-time computed expressions
}

type Plan struct {
	E []Entry
}

// An Schedule is used to decompose assignment statements into
// static and dynamic initialization parts. Static initializations are
// handled by populating variables' linker symbol data, while dynamic
// initializations are accumulated to be executed in order.
type Schedule struct {
	// Out is the ordered list of dynamic initialization
	// statements.
	Out []ir.Node

	Plans map[ir.Node]*Plan
	Temps map[ir.Node]*ir.Name
}

func (s *Schedule) append(n ir.Node) {
	s.Out = append(s.Out, n)
}

// StaticInit adds an initialization statement n to the schedule.
func (s *Schedule) StaticInit(n ir.Node) {
	if !s.tryStaticInit(n) {
		if base.Flag.Percent != 0 {
			ir.Dump("StaticInit failed", n)
		}
		s.append(n)
	}
}

// varToMapInit holds book-keeping state for global map initialization;
// it records the init function created by the compiler to host the
// initialization code for the map in question.
var varToMapInit map[*ir.Name]*ir.Func

// MapInitToVar is the inverse of VarToMapInit; it maintains a mapping
// from a compiler-generated init function to the map the function is
// initializing.
var MapInitToVar map[*ir.Func]*ir.Name

// recordFuncForVar establishes a mapping between global map var "v" and
// outlined init function "fn" (and vice versa); so that we can use
// the mappings later on to update relocations.
func recordFuncForVar(v *ir.Name, fn *ir.Func) {
	if varToMapInit == nil {
		varToMapInit = make(map[*ir.Name]*ir.Func)
		MapInitToVar = make(map[*ir.Func]*ir.Name)
	}
	varToMapInit[v] = fn
	MapInitToVar[fn] = v
}

// tryStaticInit attempts to statically execute an initialization
// statement and reports whether it succeeded.
func (s *Schedule) tryStaticInit(nn ir.Node) bool {
	// Only worry about simple "l = r" assignments. Multiple
	// variable/expression OAS2 assignments have already been
	// replaced by multiple simple OAS assignments, and the other
	// OAS2* assignments mostly necessitate dynamic execution
	// anyway.
	if nn.Op() != ir.OAS {
		return false
	}
	n := nn.(*ir.AssignStmt)
	if ir.IsBlank(n.X) && !AnySideEffects(n.Y) {
		// Discard.
		return true
	}
	lno := ir.SetPos(n)
	defer func() { base.Pos = lno }()
	nam := n.X.(*ir.Name)
	return s.StaticAssign(nam, 0, n.Y, nam.Type())
}

// like staticassign but we are copying an already
// initialized value r.
func (s *Schedule) staticcopy(l *ir.Name, loff int64, rn *ir.Name, typ *types.Type) bool {
	if rn.Class == ir.PFUNC {
		// TODO if roff != 0 { panic }
		staticdata.InitAddr(l, loff, staticdata.FuncLinksym(rn))
		return true
	}
	if rn.Class != ir.PEXTERN || rn.Sym().Pkg != types.LocalPkg {
		return false
	}
	if rn.Defn.Op() != ir.OAS {
		return false
	}
	if rn.Type().IsString() { // perhaps overwritten by cmd/link -X (#34675)
		return false
	}
	if rn.Embed != nil {
		return false
	}
	orig := rn
	r := rn.Defn.(*ir.AssignStmt).Y
	if r == nil {
		// No explicit initialization value. Probably zeroed but perhaps
		// supplied externally and of unknown value.
		return false
	}

	for r.Op() == ir.OCONVNOP && !types.Identical(r.Type(), typ) {
		r = r.(*ir.ConvExpr).X
	}

	switch r.Op() {
	case ir.OMETHEXPR:
		r = r.(*ir.SelectorExpr).FuncName()
		fallthrough
	case ir.ONAME:
		r := r.(*ir.Name)
		if s.staticcopy(l, loff, r, typ) {
			return true
		}
		// We may have skipped past one or more OCONVNOPs, so
		// use conv to ensure r is assignable to l (#13263).
		dst := ir.Node(l)
		if loff != 0 || !types.Identical(typ, l.Type()) {
			dst = ir.NewNameOffsetExpr(base.Pos, l, loff, typ)
		}
		s.append(ir.NewAssignStmt(base.Pos, dst, typecheck.Conv(r, typ)))
		return true

	case ir.ONIL:
		return true

	case ir.OLITERAL:
		if ir.IsZero(r) {
			return true
		}
		staticdata.InitConst(l, loff, r, int(typ.Size()))
		return true

	case ir.OADDR:
		r := r.(*ir.AddrExpr)
		if a, ok := r.X.(*ir.Name); ok && a.Op() == ir.ONAME {
			staticdata.InitAddr(l, loff, staticdata.GlobalLinksym(a))
			return true
		}

	case ir.OPTRLIT:
		r := r.(*ir.AddrExpr)
		switch r.X.Op() {
		case ir.OARRAYLIT, ir.OSLICELIT, ir.OSTRUCTLIT, ir.OMAPLIT:
			// copy pointer
			staticdata.InitAddr(l, loff, staticdata.GlobalLinksym(s.Temps[r]))
			return true
		}

	case ir.OSLICELIT:
		r := r.(*ir.CompLitExpr)
		// copy slice
		staticdata.InitSlice(l, loff, staticdata.GlobalLinksym(s.Temps[r]), r.Len)
		return true

	case ir.OARRAYLIT, ir.OSTRUCTLIT:
		r := r.(*ir.CompLitExpr)
		p := s.Plans[r]
		for i := range p.E {
			e := &p.E[i]
			typ := e.Expr.Type()
			if e.Expr.Op() == ir.OLITERAL || e.Expr.Op() == ir.ONIL {
				staticdata.InitConst(l, loff+e.Xoffset, e.Expr, int(typ.Size()))
				continue
			}
			x := e.Expr
			if x.Op() == ir.OMETHEXPR {
				x = x.(*ir.SelectorExpr).FuncName()
			}
			if x.Op() == ir.ONAME && s.staticcopy(l, loff+e.Xoffset, x.(*ir.Name), typ) {
				continue
			}
			// Requires computation, but we're
			// copying someone else's computation.
			ll := ir.NewNameOffsetExpr(base.Pos, l, loff+e.Xoffset, typ)
			rr := ir.NewNameOffsetExpr(base.Pos, orig, e.Xoffset, typ)
			ir.SetPos(rr)
			s.append(ir.NewAssignStmt(base.Pos, ll, rr))
		}

		return true
	}

	return false
}

func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Type) bool {
	if r == nil {
		// No explicit initialization value. Either zero or supplied
		// externally.
		return true
	}
	for r.Op() == ir.OCONVNOP {
		r = r.(*ir.ConvExpr).X
	}

	assign := func(pos src.XPos, a *ir.Name, aoff int64, v ir.Node) {
		if s.StaticAssign(a, aoff, v, v.Type()) {
			return
		}
		var lhs ir.Node
		if ir.IsBlank(a) {
			// Don't use NameOffsetExpr with blank (#43677).
			lhs = ir.BlankNode
		} else {
			lhs = ir.NewNameOffsetExpr(pos, a, aoff, v.Type())
		}
		s.append(ir.NewAssignStmt(pos, lhs, v))
	}

	switch r.Op() {
	case ir.ONAME:
		r := r.(*ir.Name)
		return s.staticcopy(l, loff, r, typ)

	case ir.OMETHEXPR:
		r := r.(*ir.SelectorExpr)
		return s.staticcopy(l, loff, r.FuncName(), typ)

	case ir.ONIL:
		return true

	case ir.OLITERAL:
		if ir.IsZero(r) {
			return true
		}
		staticdata.InitConst(l, loff, r, int(typ.Size()))
		return true

	case ir.OADDR:
		r := r.(*ir.AddrExpr)
		if name, offset, ok := StaticLoc(r.X); ok && name.Class == ir.PEXTERN {
			staticdata.InitAddrOffset(l, loff, name.Linksym(), offset)
			return true
		}
		fallthrough

	case ir.OPTRLIT:
		r := r.(*ir.AddrExpr)
		switch r.X.Op() {
		case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT:
			// Init pointer.
			a := StaticName(r.X.Type())

			s.Temps[r] = a
			staticdata.InitAddr(l, loff, a.Linksym())

			// Init underlying literal.
			assign(base.Pos, a, 0, r.X)
			return true
		}
		//dump("not static ptrlit", r);

	case ir.OSTR2BYTES:
		r := r.(*ir.ConvExpr)
		if l.Class == ir.PEXTERN && r.X.Op() == ir.OLITERAL {
			sval := ir.StringVal(r.X)
			staticdata.InitSliceBytes(l, loff, sval)
			return true
		}

	case ir.OSLICELIT:
		r := r.(*ir.CompLitExpr)
		s.initplan(r)
		// Init slice.
		ta := types.NewArray(r.Type().Elem(), r.Len)
		ta.SetNoalg(true)
		a := StaticName(ta)
		s.Temps[r] = a
		staticdata.InitSlice(l, loff, a.Linksym(), r.Len)
		// Fall through to init underlying array.
		l = a
		loff = 0
		fallthrough

	case ir.OARRAYLIT, ir.OSTRUCTLIT:
		r := r.(*ir.CompLitExpr)
		s.initplan(r)

		p := s.Plans[r]
		for i := range p.E {
			e := &p.E[i]
			if e.Expr.Op() == ir.OLITERAL || e.Expr.Op() == ir.ONIL {
				staticdata.InitConst(l, loff+e.Xoffset, e.Expr, int(e.Expr.Type().Size()))
				continue
			}
			ir.SetPos(e.Expr)
			assign(base.Pos, l, loff+e.Xoffset, e.Expr)
		}

		return true

	case ir.OMAPLIT:
		break

	case ir.OCLOSURE:
		r := r.(*ir.ClosureExpr)
		if ir.IsTrivialClosure(r) {
			if base.Debug.Closure > 0 {
				base.WarnfAt(r.Pos(), "closure converted to global")
			}
			// Issue 59680: if the closure we're looking at was produced
			// by inlining, it could be marked as hidden, which we don't
			// want (moving the func to a static init will effectively
			// hide it from escape analysis). Mark as non-hidden here.
			// so that it will participated in escape analysis.
			r.Func.SetIsHiddenClosure(false)
			// Closures with no captured variables are globals,
			// so the assignment can be done at link time.
			// TODO if roff != 0 { panic }
			staticdata.InitAddr(l, loff, staticdata.FuncLinksym(r.Func.Nname))
			return true
		}
		ir.ClosureDebugRuntimeCheck(r)

	case ir.OCONVIFACE:
		// This logic is mirrored in isStaticCompositeLiteral.
		// If you change something here, change it there, and vice versa.

		// Determine the underlying concrete type and value we are converting from.
		r := r.(*ir.ConvExpr)
		val := ir.Node(r)
		for val.Op() == ir.OCONVIFACE {
			val = val.(*ir.ConvExpr).X
		}

		if val.Type().IsInterface() {
			// val is an interface type.
			// If val is nil, we can statically initialize l;
			// both words are zero and so there no work to do, so report success.
			// If val is non-nil, we have no concrete type to record,
			// and we won't be able to statically initialize its value, so report failure.
			return val.Op() == ir.ONIL
		}

		if val.Type().HasShape() {
			// See comment in cmd/compile/internal/walk/convert.go:walkConvInterface
			return false
		}

		reflectdata.MarkTypeUsedInInterface(val.Type(), l.Linksym())

		var itab *ir.AddrExpr
		if typ.IsEmptyInterface() {
			itab = reflectdata.TypePtr(val.Type())
		} else {
			itab = reflectdata.ITabAddr(val.Type(), typ)
		}

		// Create a copy of l to modify while we emit data.

		// Emit itab, advance offset.
		staticdata.InitAddr(l, loff, itab.X.(*ir.LinksymOffsetExpr).Linksym)

		// Emit data.
		if types.IsDirectIface(val.Type()) {
			if val.Op() == ir.ONIL {
				// Nil is zero, nothing to do.
				return true
			}
			// Copy val directly into n.
			ir.SetPos(val)
			assign(base.Pos, l, loff+int64(types.PtrSize), val)
		} else {
			// Construct temp to hold val, write pointer to temp into n.
			a := StaticName(val.Type())
			s.Temps[val] = a
			assign(base.Pos, a, 0, val)
			staticdata.InitAddr(l, loff+int64(types.PtrSize), a.Linksym())
		}

		return true

	case ir.OINLCALL:
		r := r.(*ir.InlinedCallExpr)
		return s.staticAssignInlinedCall(l, loff, r, typ)
	}

	if base.Flag.Percent != 0 {
		ir.Dump("not static", r)
	}
	return false
}

func (s *Schedule) initplan(n ir.Node) {
	if s.Plans[n] != nil {
		return
	}
	p := new(Plan)
	s.Plans[n] = p
	switch n.Op() {
	default:
		base.Fatalf("initplan")

	case ir.OARRAYLIT, ir.OSLICELIT:
		n := n.(*ir.CompLitExpr)
		var k int64
		for _, a := range n.List {
			if a.Op() == ir.OKEY {
				kv := a.(*ir.KeyExpr)
				k = typecheck.IndexConst(kv.Key)
				if k < 0 {
					base.Fatalf("initplan arraylit: invalid index %v", kv.Key)
				}
				a = kv.Value
			}
			s.addvalue(p, k*n.Type().Elem().Size(), a)
			k++
		}

	case ir.OSTRUCTLIT:
		n := n.(*ir.CompLitExpr)
		for _, a := range n.List {
			if a.Op() != ir.OSTRUCTKEY {
				base.Fatalf("initplan structlit")
			}
			a := a.(*ir.StructKeyExpr)
			if a.Sym().IsBlank() {
				continue
			}
			s.addvalue(p, a.Field.Offset, a.Value)
		}

	case ir.OMAPLIT:
		n := n.(*ir.CompLitExpr)
		for _, a := range n.List {
			if a.Op() != ir.OKEY {
				base.Fatalf("initplan maplit")
			}
			a := a.(*ir.KeyExpr)
			s.addvalue(p, -1, a.Value)
		}
	}
}

func (s *Schedule) addvalue(p *Plan, xoffset int64, n ir.Node) {
	// special case: zero can be dropped entirely
	if ir.IsZero(n) {
		return
	}

	// special case: inline struct and array (not slice) literals
	if isvaluelit(n) {
		s.initplan(n)
		q := s.Plans[n]
		for _, qe := range q.E {
			// qe is a copy; we are not modifying entries in q.E
			qe.Xoffset += xoffset
			p.E = append(p.E, qe)
		}
		return
	}

	// add to plan
	p.E = append(p.E, Entry{Xoffset: xoffset, Expr: n})
}

func (s *Schedule) staticAssignInlinedCall(l *ir.Name, loff int64, call *ir.InlinedCallExpr, typ *types.Type) bool {
	if base.Debug.InlStaticInit == 0 {
		return false
	}

	// Handle the special case of an inlined call of
	// a function body with a single return statement,
	// which turns into a single assignment plus a goto.
	//
	// For example code like this:
	//
	//	type T struct{ x int }
	//	func F(x int) *T { return &T{x} }
	//	var Global = F(400)
	//
	// turns into IR like this:
	//
	// 	INLCALL-init
	// 	.   AS2-init
	// 	.   .   DCL # x.go:18:13
	// 	.   .   .   NAME-p.x Class:PAUTO Offset:0 InlFormal OnStack Used int tc(1) # x.go:14:9,x.go:18:13
	// 	.   AS2 Def tc(1) # x.go:18:13
	// 	.   AS2-Lhs
	// 	.   .   NAME-p.x Class:PAUTO Offset:0 InlFormal OnStack Used int tc(1) # x.go:14:9,x.go:18:13
	// 	.   AS2-Rhs
	// 	.   .   LITERAL-400 int tc(1) # x.go:18:14
	// 	.   INLMARK Index:1 # +x.go:18:13
	// 	INLCALL PTR-*T tc(1) # x.go:18:13
	// 	INLCALL-Body
	// 	.   BLOCK tc(1) # x.go:18:13
	// 	.   BLOCK-List
	// 	.   .   DCL tc(1) # x.go:18:13
	// 	.   .   .   NAME-p.~R0 Class:PAUTO Offset:0 OnStack Used PTR-*T tc(1) # x.go:18:13
	// 	.   .   AS2 tc(1) # x.go:18:13
	// 	.   .   AS2-Lhs
	// 	.   .   .   NAME-p.~R0 Class:PAUTO Offset:0 OnStack Used PTR-*T tc(1) # x.go:18:13
	// 	.   .   AS2-Rhs
	// 	.   .   .   INLINED RETURN ARGUMENT HERE
	// 	.   .   GOTO p..i1 tc(1) # x.go:18:13
	// 	.   LABEL p..i1 # x.go:18:13
	// 	INLCALL-ReturnVars
	// 	.   NAME-p.~R0 Class:PAUTO Offset:0 OnStack Used PTR-*T tc(1) # x.go:18:13
	//
	// In non-unified IR, the tree is slightly different:
	//  - if there are no arguments to the inlined function,
	//    the INLCALL-init omits the AS2.
	//  - the DCL inside BLOCK is on the AS2's init list,
	//    not its own statement in the top level of the BLOCK.
	//
	// If the init values are side-effect-free and each either only
	// appears once in the function body or is safely repeatable,
	// then we inline the value expressions into the return argument
	// and then call StaticAssign to handle that copy.
	//
	// This handles simple cases like
	//
	//	var myError = errors.New("mine")
	//
	// where errors.New is
	//
	//	func New(text string) error {
	//		return &errorString{text}
	//	}
	//
	// We could make things more sophisticated but this kind of initializer
	// is the most important case for us to get right.

	init := call.Init()
	var as2init *ir.AssignListStmt
	if len(init) == 2 && init[0].Op() == ir.OAS2 && init[1].Op() == ir.OINLMARK {
		as2init = init[0].(*ir.AssignListStmt)
	} else if len(init) == 1 && init[0].Op() == ir.OINLMARK {
		as2init = new(ir.AssignListStmt)
	} else {
		return false
	}
	if len(call.Body) != 2 || call.Body[0].Op() != ir.OBLOCK || call.Body[1].Op() != ir.OLABEL {
		return false
	}
	label := call.Body[1].(*ir.LabelStmt).Label
	block := call.Body[0].(*ir.BlockStmt)
	list := block.List
	var dcl *ir.Decl
	if len(list) == 3 && list[0].Op() == ir.ODCL {
		dcl = list[0].(*ir.Decl)
		list = list[1:]
	}
	if len(list) != 2 ||
		list[0].Op() != ir.OAS2 ||
		list[1].Op() != ir.OGOTO ||
		list[1].(*ir.BranchStmt).Label != label {
		return false
	}
	as2body := list[0].(*ir.AssignListStmt)
	if dcl == nil {
		ainit := as2body.Init()
		if len(ainit) != 1 || ainit[0].Op() != ir.ODCL {
			return false
		}
		dcl = ainit[0].(*ir.Decl)
	}
	if len(as2body.Lhs) != 1 || as2body.Lhs[0] != dcl.X {
		return false
	}

	// Can't remove the parameter variables if an address is taken.
	for _, v := range as2init.Lhs {
		if v.(*ir.Name).Addrtaken() {
			return false
		}
	}
	// Can't move the computation of the args if they have side effects.
	for _, r := range as2init.Rhs {
		if AnySideEffects(r) {
			return false
		}
	}

	// Can only substitute arg for param if param is used
	// at most once or is repeatable.
	count := make(map[*ir.Name]int)
	for _, x := range as2init.Lhs {
		count[x.(*ir.Name)] = 0
	}

	hasNonTrivialClosure := false
	ir.Visit(as2body.Rhs[0], func(n ir.Node) {
		if name, ok := n.(*ir.Name); ok {
			if c, ok := count[name]; ok {
				count[name] = c + 1
			}
		}
		if clo, ok := n.(*ir.ClosureExpr); ok {
			hasNonTrivialClosure = hasNonTrivialClosure || !ir.IsTrivialClosure(clo)
		}
	})

	// If there's a non-trivial closure, it has captured the param,
	// so we can't substitute arg for param.
	if hasNonTrivialClosure {
		return false
	}

	for name, c := range count {
		if c > 1 {
			// Check whether corresponding initializer can be repeated.
			// Something like 1 can be; make(chan int) or &T{} cannot,
			// because they need to evaluate to the same result in each use.
			for i, n := range as2init.Lhs {
				if n == name && !canRepeat(as2init.Rhs[i]) {
					return false
				}
			}
		}
	}

	// Possible static init.
	// Build tree with args substituted for params and try it.
	args := make(map[*ir.Name]ir.Node)
	for i, v := range as2init.Lhs {
		if ir.IsBlank(v) {
			continue
		}
		args[v.(*ir.Name)] = as2init.Rhs[i]
	}
	r, ok := subst(as2body.Rhs[0], args)
	if !ok {
		return false
	}
	ok = s.StaticAssign(l, loff, r, typ)

	if ok && base.Flag.Percent != 0 {
		ir.Dump("static inlined-LEFT", l)
		ir.Dump("static inlined-ORIG", call)
		ir.Dump("static inlined-RIGHT", r)
	}
	return ok
}

// from here down is the walk analysis
// of composite literals.
// most of the work is to generate
// data statements for the constant
// part of the composite literal.

var statuniqgen int // name generator for static temps

// StaticName returns a name backed by a (writable) static data symbol.
// Use readonlystaticname for read-only node.
func StaticName(t *types.Type) *ir.Name {
	// Don't use LookupNum; it interns the resulting string, but these are all unique.
	n := typecheck.NewName(typecheck.Lookup(fmt.Sprintf("%s%d", obj.StaticNamePref, statuniqgen)))
	statuniqgen++
	typecheck.Declare(n, ir.PEXTERN)
	n.SetType(t)
	n.Linksym().Set(obj.AttrStatic, true)
	return n
}

// StaticLoc returns the static address of n, if n has one, or else nil.
func StaticLoc(n ir.Node) (name *ir.Name, offset int64, ok bool) {
	if n == nil {
		return nil, 0, false
	}

	switch n.Op() {
	case ir.ONAME:
		n := n.(*ir.Name)
		return n, 0, true

	case ir.OMETHEXPR:
		n := n.(*ir.SelectorExpr)
		return StaticLoc(n.FuncName())

	case ir.ODOT:
		n := n.(*ir.SelectorExpr)
		if name, offset, ok = StaticLoc(n.X); !ok {
			break
		}
		offset += n.Offset()
		return name, offset, true

	case ir.OINDEX:
		n := n.(*ir.IndexExpr)
		if n.X.Type().IsSlice() {
			break
		}
		if name, offset, ok = StaticLoc(n.X); !ok {
			break
		}
		l := getlit(n.Index)
		if l < 0 {
			break
		}

		// Check for overflow.
		if n.Type().Size() != 0 && types.MaxWidth/n.Type().Size() <= int64(l) {
			break
		}
		offset += int64(l) * n.Type().Size()
		return name, offset, true
	}

	return nil, 0, false
}

func isSideEffect(n ir.Node) bool {
	switch n.Op() {
	// Assume side effects unless we know otherwise.
	default:
		return true

	// No side effects here (arguments are checked separately).
	case ir.ONAME,
		ir.ONONAME,
		ir.OTYPE,
		ir.OLITERAL,
		ir.ONIL,
		ir.OADD,
		ir.OSUB,
		ir.OOR,
		ir.OXOR,
		ir.OADDSTR,
		ir.OADDR,
		ir.OANDAND,
		ir.OBYTES2STR,
		ir.ORUNES2STR,
		ir.OSTR2BYTES,
		ir.OSTR2RUNES,
		ir.OCAP,
		ir.OCOMPLIT,
		ir.OMAPLIT,
		ir.OSTRUCTLIT,
		ir.OARRAYLIT,
		ir.OSLICELIT,
		ir.OPTRLIT,
		ir.OCONV,
		ir.OCONVIFACE,
		ir.OCONVNOP,
		ir.ODOT,
		ir.OEQ,
		ir.ONE,
		ir.OLT,
		ir.OLE,
		ir.OGT,
		ir.OGE,
		ir.OKEY,
		ir.OSTRUCTKEY,
		ir.OLEN,
		ir.OMUL,
		ir.OLSH,
		ir.ORSH,
		ir.OAND,
		ir.OANDNOT,
		ir.ONEW,
		ir.ONOT,
		ir.OBITNOT,
		ir.OPLUS,
		ir.ONEG,
		ir.OOROR,
		ir.OPAREN,
		ir.ORUNESTR,
		ir.OREAL,
		ir.OIMAG,
		ir.OCOMPLEX:
		return false

	// Only possible side effect is division by zero.
	case ir.ODIV, ir.OMOD:
		n := n.(*ir.BinaryExpr)
		if n.Y.Op() != ir.OLITERAL || constant.Sign(n.Y.Val()) == 0 {
			return true
		}

	// Only possible side effect is panic on invalid size,
	// but many makechan and makemap use size zero, which is definitely OK.
	case ir.OMAKECHAN, ir.OMAKEMAP:
		n := n.(*ir.MakeExpr)
		if !ir.IsConst(n.Len, constant.Int) || constant.Sign(n.Len.Val()) != 0 {
			return true
		}

	// Only possible side effect is panic on invalid size.
	// TODO(rsc): Merge with previous case (probably breaks toolstash -cmp).
	case ir.OMAKESLICE, ir.OMAKESLICECOPY:
		return true
	}
	return false
}

// AnySideEffects reports whether n contains any operations that could have observable side effects.
func AnySideEffects(n ir.Node) bool {
	return ir.Any(n, isSideEffect)
}

// canRepeat reports whether executing n multiple times has the same effect as
// assigning n to a single variable and using that variable multiple times.
func canRepeat(n ir.Node) bool {
	bad := func(n ir.Node) bool {
		if isSideEffect(n) {
			return true
		}
		switch n.Op() {
		case ir.OMAKECHAN,
			ir.OMAKEMAP,
			ir.OMAKESLICE,
			ir.OMAKESLICECOPY,
			ir.OMAPLIT,
			ir.ONEW,
			ir.OPTRLIT,
			ir.OSLICELIT,
			ir.OSTR2BYTES,
			ir.OSTR2RUNES:
			return true
		}
		return false
	}
	return !ir.Any(n, bad)
}

func getlit(lit ir.Node) int {
	if ir.IsSmallIntConst(lit) {
		return int(ir.Int64Val(lit))
	}
	return -1
}

func isvaluelit(n ir.Node) bool {
	return n.Op() == ir.OARRAYLIT || n.Op() == ir.OSTRUCTLIT
}

func subst(n ir.Node, m map[*ir.Name]ir.Node) (ir.Node, bool) {
	valid := true
	var edit func(ir.Node) ir.Node
	edit = func(x ir.Node) ir.Node {
		switch x.Op() {
		case ir.ONAME:
			x := x.(*ir.Name)
			if v, ok := m[x]; ok {
				return ir.DeepCopy(v.Pos(), v)
			}
			return x
		case ir.ONONAME, ir.OLITERAL, ir.ONIL, ir.OTYPE:
			return x
		}
		x = ir.Copy(x)
		ir.EditChildrenWithHidden(x, edit)

		// TODO: handle more operations, see details discussion in go.dev/cl/466277.
		switch x.Op() {
		case ir.OCONV:
			x := x.(*ir.ConvExpr)
			if x.X.Op() == ir.OLITERAL {
				if x, ok := truncate(x.X, x.Type()); ok {
					return x
				}
				valid = false
				return x
			}
		case ir.OADDSTR:
			return addStr(x.(*ir.AddStringExpr))
		}
		return x
	}
	n = edit(n)
	return n, valid
}

// truncate returns the result of force converting c to type t,
// truncating its value as needed, like a conversion of a variable.
// If the conversion is too difficult, truncate returns nil, false.
func truncate(c ir.Node, t *types.Type) (ir.Node, bool) {
	ct := c.Type()
	cv := c.Val()
	if ct.Kind() != t.Kind() {
		switch {
		default:
			// Note: float -> float/integer and complex -> complex are valid but subtle.
			// For example a float32(float64 1e300) evaluates to +Inf at runtime
			// and the compiler doesn't have any concept of +Inf, so that would
			// have to be left for runtime code evaluation.
			// For now
			return nil, false

		case ct.IsInteger() && t.IsInteger():
			// truncate or sign extend
			bits := t.Size() * 8
			cv = constant.BinaryOp(cv, token.AND, constant.MakeUint64(1<<bits-1))
			if t.IsSigned() && constant.Compare(cv, token.GEQ, constant.MakeUint64(1<<(bits-1))) {
				cv = constant.BinaryOp(cv, token.OR, constant.MakeInt64(-1<<(bits-1)))
			}
		}
	}
	c = ir.NewConstExpr(cv, c)
	c.SetType(t)
	return c, true
}

func addStr(n *ir.AddStringExpr) ir.Node {
	// Merge adjacent constants in the argument list.
	s := n.List
	need := 0
	for i := 0; i < len(s); i++ {
		if i == 0 || !ir.IsConst(s[i-1], constant.String) || !ir.IsConst(s[i], constant.String) {
			// Can't merge s[i] into s[i-1]; need a slot in the list.
			need++
		}
	}
	if need == len(s) {
		return n
	}
	if need == 1 {
		var strs []string
		for _, c := range s {
			strs = append(strs, ir.StringVal(c))
		}
		return typecheck.OrigConst(n, constant.MakeString(strings.Join(strs, "")))
	}
	newList := make([]ir.Node, 0, need)
	for i := 0; i < len(s); i++ {
		if ir.IsConst(s[i], constant.String) && i+1 < len(s) && ir.IsConst(s[i+1], constant.String) {
			// merge from i up to but not including i2
			var strs []string
			i2 := i
			for i2 < len(s) && ir.IsConst(s[i2], constant.String) {
				strs = append(strs, ir.StringVal(s[i2]))
				i2++
			}

			nl := ir.Copy(n).(*ir.AddStringExpr)
			nl.List = s[i:i2]
			newList = append(newList, typecheck.OrigConst(nl, constant.MakeString(strings.Join(strs, ""))))
			i = i2 - 1
		} else {
			newList = append(newList, s[i])
		}
	}

	nn := ir.Copy(n).(*ir.AddStringExpr)
	nn.List = newList
	return nn
}

const wrapGlobalMapInitSizeThreshold = 20

// tryWrapGlobalMapInit examines the node 'n' to see if it is a map
// variable initialization, and if so, possibly returns the mapvar
// being assigned, a new function containing the init code, and a call
// to the function passing the mapvar. Returns will be nil if the
// assignment is not to a map, or the map init is not big enough,
// or if the expression being assigned to the map has side effects.
func tryWrapGlobalMapInit(n ir.Node) (mapvar *ir.Name, genfn *ir.Func, call ir.Node) {
	// Look for "X = ..." where X has map type.
	// FIXME: might also be worth trying to look for cases where
	// the LHS is of interface type but RHS is map type.
	if n.Op() != ir.OAS {
		return nil, nil, nil
	}
	as := n.(*ir.AssignStmt)
	if ir.IsBlank(as.X) || as.X.Op() != ir.ONAME {
		return nil, nil, nil
	}
	nm := as.X.(*ir.Name)
	if !nm.Type().IsMap() {
		return nil, nil, nil
	}

	// Determine size of RHS.
	rsiz := 0
	ir.Any(as.Y, func(n ir.Node) bool {
		rsiz++
		return false
	})
	if base.Debug.WrapGlobalMapDbg > 0 {
		fmt.Fprintf(os.Stderr, "=-= mapassign %s %v rhs size %d\n",
			base.Ctxt.Pkgpath, n, rsiz)
	}

	// Reject smaller candidates if not in stress mode.
	if rsiz < wrapGlobalMapInitSizeThreshold && base.Debug.WrapGlobalMapCtl != 2 {
		if base.Debug.WrapGlobalMapDbg > 1 {
			fmt.Fprintf(os.Stderr, "=-= skipping %v size too small at %d\n",
				nm, rsiz)
		}
		return nil, nil, nil
	}

	// Reject right hand sides with side effects.
	if AnySideEffects(as.Y) {
		if base.Debug.WrapGlobalMapDbg > 0 {
			fmt.Fprintf(os.Stderr, "=-= rejected %v due to side effects\n", nm)
		}
		return nil, nil, nil
	}

	if base.Debug.WrapGlobalMapDbg > 1 {
		fmt.Fprintf(os.Stderr, "=-= committed for: %+v\n", n)
	}

	// Create a new function that will (eventually) have this form:
	//
	//    func map.init.%d() {
	//      globmapvar = <map initialization>
	//    }
	//
	minitsym := typecheck.LookupNum("map.init.", mapinitgen)
	mapinitgen++
	newfn := typecheck.DeclFunc(minitsym, nil, nil, nil)
	if base.Debug.WrapGlobalMapDbg > 0 {
		fmt.Fprintf(os.Stderr, "=-= generated func is %v\n", newfn)
	}

	// NB: we're relying on this phase being run before inlining;
	// if for some reason we need to move it after inlining, we'll
	// need code here that relocates or duplicates inline temps.

	// Insert assignment into function body; mark body finished.
	newfn.Body = append(newfn.Body, as)
	typecheck.FinishFuncBody()

	typecheck.Func(newfn)

	const no = `
	// Register new function with decls.
	typecheck.Target.Decls = append(typecheck.Target.Decls, newfn)
`

	// Create call to function, passing mapvar.
	fncall := ir.NewCallExpr(n.Pos(), ir.OCALL, newfn.Nname, nil)

	if base.Debug.WrapGlobalMapDbg > 1 {
		fmt.Fprintf(os.Stderr, "=-= mapvar is %v\n", nm)
		fmt.Fprintf(os.Stderr, "=-= newfunc is %+v\n", newfn)
		fmt.Fprintf(os.Stderr, "=-= call is %+v\n", fncall)
	}

	return nm, newfn, typecheck.Stmt(fncall)
}

// mapinitgen is a counter used to uniquify compiler-generated
// map init functions.
var mapinitgen int

// AddKeepRelocations adds a dummy "R_KEEP" relocation from each
// global map variable V to its associated outlined init function.
// These relocation ensure that if the map var itself is determined to
// be reachable at link time, we also mark the init function as
// reachable.
func AddKeepRelocations() {
	if varToMapInit == nil {
		return
	}
	for k, v := range varToMapInit {
		// Add R_KEEP relocation from map to init function.
		fs := v.Linksym()
		if fs == nil {
			base.Fatalf("bad: func %v has no linksym", v)
		}
		vs := k.Linksym()
		if vs == nil {
			base.Fatalf("bad: mapvar %v has no linksym", k)
		}
		r := obj.Addrel(vs)
		r.Sym = fs
		r.Type = objabi.R_KEEP
		if base.Debug.WrapGlobalMapDbg > 1 {
			fmt.Fprintf(os.Stderr, "=-= add R_KEEP relo from %s to %s\n",
				vs.Name, fs.Name)
		}
	}
	varToMapInit = nil
}

// OutlineMapInits walks through a list of init statements (candidates
// for inclusion in the package "init" function) and returns an
// updated list in which items corresponding to map variable
// initializations have been replaced with calls to outline "map init"
// functions (if legal/profitable). Return value is an updated list
// and a list of any newly generated "map init" functions.
func OutlineMapInits(stmts []ir.Node) ([]ir.Node, []*ir.Func) {
	if base.Debug.WrapGlobalMapCtl == 1 {
		return stmts, nil
	}
	newfuncs := []*ir.Func{}
	for i := range stmts {
		s := stmts[i]
		// Call the helper tryWrapGlobalMapInit to see if the LHS of
		// this assignment is to a map var, and if so whether the RHS
		// should be outlined into a separate init function. If the
		// outline goes through, then replace the original init
		// statement with the call to the outlined func, and append
		// the new outlined func to our return list.
		if mapvar, genfn, call := tryWrapGlobalMapInit(s); call != nil {
			stmts[i] = call
			newfuncs = append(newfuncs, genfn)
			recordFuncForVar(mapvar, genfn)
		}
	}

	return stmts, newfuncs
}
