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

	"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/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)
	}
}

// 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")
			}
			// 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 base.Debug.Unified != 0 && 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)
		if x, ok := x.(*ir.ConvExpr); ok && x.X.Op() == ir.OLITERAL {
			// A conversion of variable or expression involving variables
			// may become a conversion of constant after inlining the parameters
			// and doing constant evaluation. Truncations that were valid
			// on variables are not valid on constants, so we might have
			// generated invalid code that will trip up the rest of the compiler.
			// Fix those by truncating the constants.
			if x, ok := truncate(x.X.(*ir.ConstExpr), x.Type()); ok {
				return x
			}
			valid = false
			return x
		}
		return typecheck.EvalConst(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.ConstExpr, t *types.Type) (*ir.ConstExpr, 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).(*ir.ConstExpr)
	c.SetType(t)
	return c, true
}
