// Copyright 2020 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 devirtualize implements two "devirtualization" optimization passes:
//
//   - "Static" devirtualization which replaces interface method calls with
//     direct concrete-type method calls where possible.
//   - "Profile-guided" devirtualization which replaces indirect calls with a
//     conditional direct call to the hottest concrete callee from a profile, as
//     well as a fallback using the original indirect call.
package devirtualize

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/typecheck"
	"cmd/compile/internal/types"
)

const go126ImprovedConcreteTypeAnalysis = true

// StaticCall devirtualizes the given call if possible when the concrete callee
// is available statically.
func StaticCall(s *State, call *ir.CallExpr) {
	// For promoted methods (including value-receiver methods promoted
	// to pointer-receivers), the interface method wrapper may contain
	// expressions that can panic (e.g., ODEREF, ODOTPTR,
	// ODOTINTER). Devirtualization involves inlining these expressions
	// (and possible panics) to the call site. This normally isn't a
	// problem, but for go/defer statements it can move the panic from
	// when/where the call executes to the go/defer statement itself,
	// which is a visible change in semantics (e.g., #52072). To prevent
	// this, we skip devirtualizing calls within go/defer statements
	// altogether.
	if call.GoDefer {
		return
	}

	if call.Op() != ir.OCALLINTER {
		return
	}

	sel := call.Fun.(*ir.SelectorExpr)
	var typ *types.Type
	if go126ImprovedConcreteTypeAnalysis {
		typ = concreteType(s, sel.X)
		if typ == nil {
			return
		}

		// Don't create type-assertions that would be impossible at compile-time.
		// This can happen in such case: any(0).(interface {A()}).A(), this typechecks without
		// any errors, but will cause a runtime panic. We statically know that int(0) does not
		// implement that interface, thus we skip the devirtualization, as it is not possible
		// to make an assertion: any(0).(interface{A()}).(int) (int does not implement interface{A()}).
		if !typecheck.Implements(typ, sel.X.Type()) {
			return
		}
	} else {
		r := ir.StaticValue(sel.X)
		if r.Op() != ir.OCONVIFACE {
			return
		}
		recv := r.(*ir.ConvExpr)
		typ = recv.X.Type()
		if typ.IsInterface() {
			return
		}
	}

	// If typ is a shape type, then it was a type argument originally
	// and we'd need an indirect call through the dictionary anyway.
	// We're unable to devirtualize this call.
	if typ.IsShape() {
		return
	}

	// If typ *has* a shape type, then it's a shaped, instantiated
	// type like T[go.shape.int], and its methods (may) have an extra
	// dictionary parameter. We could devirtualize this call if we
	// could derive an appropriate dictionary argument.
	//
	// TODO(mdempsky): If typ has a promoted non-generic method,
	// then that method won't require a dictionary argument. We could
	// still devirtualize those calls.
	//
	// TODO(mdempsky): We have the *runtime.itab in recv.TypeWord. It
	// should be possible to compute the represented type's runtime
	// dictionary from this (e.g., by adding a pointer from T[int]'s
	// *runtime._type to .dict.T[int]; or by recognizing static
	// references to go:itab.T[int],iface and constructing a direct
	// reference to .dict.T[int]).
	if typ.HasShape() {
		if base.Flag.LowerM != 0 {
			base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped receiver %v", call, typ)
		}
		return
	}

	// Further, if sel.X's type has a shape type, then it's a shaped
	// interface type. In this case, the (non-dynamic) TypeAssertExpr
	// we construct below would attempt to create an itab
	// corresponding to this shaped interface type; but the actual
	// itab pointer in the interface value will correspond to the
	// original (non-shaped) interface type instead. These are
	// functionally equivalent, but they have distinct pointer
	// identities, which leads to the type assertion failing.
	//
	// TODO(mdempsky): We know the type assertion here is safe, so we
	// could instead set a flag so that walk skips the itab check. For
	// now, punting is easy and safe.
	if sel.X.Type().HasShape() {
		if base.Flag.LowerM != 0 {
			base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped interface %v", call, sel.X.Type())
		}
		return
	}

	dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, typ)

	if go126ImprovedConcreteTypeAnalysis {
		// Consider:
		//
		//	var v Iface
		//	v.A()
		//	v = &Impl{}
		//
		// Here in the devirtualizer, we determine the concrete type of v as being an *Impl,
		// but it can still be a nil interface, we have not detected that. The v.(*Impl)
		// type assertion that we make here would also have failed, but with a different
		// panic "pkg.Iface is nil, not *pkg.Impl", where previously we would get a nil panic.
		// We fix this, by introducing an additional nilcheck on the itab.
		// Calling a method on a nil interface (in most cases) is a bug in a program, so it is fine
		// to devirtualize and further (possibly) inline them, even though we would never reach
		// the called function.
		dt.UseNilPanic = true
		dt.SetPos(call.Pos())
	}

	x := typecheck.XDotMethod(sel.Pos(), dt, sel.Sel, true)
	switch x.Op() {
	case ir.ODOTMETH:
		if base.Flag.LowerM != 0 {
			base.WarnfAt(call.Pos(), "devirtualizing %v to %v", sel, typ)
		}
		call.SetOp(ir.OCALLMETH)
		call.Fun = x
	case ir.ODOTINTER:
		// Promoted method from embedded interface-typed field (#42279).
		if base.Flag.LowerM != 0 {
			base.WarnfAt(call.Pos(), "partially devirtualizing %v to %v", sel, typ)
		}
		call.SetOp(ir.OCALLINTER)
		call.Fun = x
	default:
		base.FatalfAt(call.Pos(), "failed to devirtualize %v (%v)", x, x.Op())
	}

	// Duplicated logic from typecheck for function call return
	// value types.
	//
	// Receiver parameter size may have changed; need to update
	// call.Type to get correct stack offsets for result
	// parameters.
	types.CheckSize(x.Type())
	switch ft := x.Type(); ft.NumResults() {
	case 0:
	case 1:
		call.SetType(ft.Result(0).Type)
	default:
		call.SetType(ft.ResultsTuple())
	}

	// Desugar OCALLMETH, if we created one (#57309).
	typecheck.FixMethodCall(call)
}

const concreteTypeDebug = false

// concreteType determines the concrete type of n, following OCONVIFACEs and type asserts.
// Returns nil when the concrete type could not be determined, or when there are multiple
// (different) types assigned to an interface.
func concreteType(s *State, n ir.Node) (typ *types.Type) {
	typ = concreteType1(s, n, make(map[*ir.Name]struct{}))
	if typ == &noType {
		return nil
	}
	if typ != nil && typ.IsInterface() {
		base.FatalfAt(n.Pos(), "typ.IsInterface() = true; want = false; typ = %v", typ)
	}
	return typ
}

// noType is a sentinel value returned by [concreteType1].
var noType types.Type

// concreteType1 analyzes the node n and returns its concrete type if it is statically known.
// Otherwise, it returns a nil Type, indicating that a concrete type was not determined.
// When n is known to be statically nil or a self-assignment is detected, it returns a sentinel [noType] type instead.
func concreteType1(s *State, n ir.Node, seen map[*ir.Name]struct{}) (outT *types.Type) {
	nn := n // for debug messages

	if concreteTypeDebug {
		defer func() {
			t := "&noType"
			if outT != &noType {
				t = outT.String()
			}
			base.Warn("concreteType1(%v) -> %v", nn, t)
		}()
	}

	for {
		if concreteTypeDebug {
			base.Warn("concreteType1(%v): analyzing %v", nn, n)
		}

		if !n.Type().IsInterface() {
			return n.Type()
		}

		switch n1 := n.(type) {
		case *ir.ConvExpr:
			if n1.Op() == ir.OCONVNOP {
				if !n1.Type().IsInterface() || !types.Identical(n1.Type().Underlying(), n1.X.Type().Underlying()) {
					// As we check (directly before this switch) whether n is an interface, thus we should only reach
					// here for iface conversions where both operands are the same.
					base.FatalfAt(n1.Pos(), "not identical/interface types found n1.Type = %v; n1.X.Type = %v", n1.Type(), n1.X.Type())
				}
				n = n1.X
				continue
			}
			if n1.Op() == ir.OCONVIFACE {
				n = n1.X
				continue
			}
		case *ir.InlinedCallExpr:
			if n1.Op() == ir.OINLCALL {
				n = n1.SingleResult()
				continue
			}
		case *ir.ParenExpr:
			n = n1.X
			continue
		case *ir.TypeAssertExpr:
			n = n1.X
			continue
		}
		break
	}

	if n.Op() != ir.ONAME {
		return nil
	}

	name := n.(*ir.Name).Canonical()
	if name.Class != ir.PAUTO {
		return nil
	}

	if name.Op() != ir.ONAME {
		base.FatalfAt(name.Pos(), "name.Op = %v; want = ONAME", n.Op())
	}

	// name.Curfn must be set, as we checked name.Class != ir.PAUTO before.
	if name.Curfn == nil {
		base.FatalfAt(name.Pos(), "name.Curfn = nil; want not nil")
	}

	if name.Addrtaken() {
		return nil // conservatively assume it's reassigned with a different type indirectly
	}

	if _, ok := seen[name]; ok {
		return &noType // Already analyzed assignments to name, no need to do that twice.
	}
	seen[name] = struct{}{}

	if concreteTypeDebug {
		base.Warn("concreteType1(%v): analyzing assignments to %v", nn, name)
	}

	var typ *types.Type
	for _, v := range s.assignments(name) {
		var t *types.Type
		switch v := v.(type) {
		case *types.Type:
			t = v
		case ir.Node:
			t = concreteType1(s, v, seen)
			if t == &noType {
				continue
			}
		}
		if t == nil || (typ != nil && !types.Identical(typ, t)) {
			return nil
		}
		typ = t
	}

	if typ == nil {
		// Variable either declared with zero value, or only assigned with nil.
		return &noType
	}

	return typ
}

// assignment can be one of:
// - nil - assignment from an interface type.
// - *types.Type - assignment from a concrete type (non-interface).
// - ir.Node - assignment from an ir.Node.
//
// In most cases assignment should be an [ir.Node], but in cases where we
// do not follow the data-flow, we return either a concrete type (*types.Type) or a nil.
// For example in range over a slice, if the slice elem is of an interface type, then we return
// a nil, otherwise the elem's concrete type (We do so because we do not analyze assignment to the
// slice being ranged-over).
type assignment any

// State holds precomputed state for use in [StaticCall].
type State struct {
	// ifaceAssignments maps interface variables to all their assignments
	// defined inside functions stored in the analyzedFuncs set.
	// Note: it does not include direct assignments to nil.
	ifaceAssignments map[*ir.Name][]assignment

	// ifaceCallExprAssigns stores every [*ir.CallExpr], which has an interface
	// result, that is assigned to a variable.
	ifaceCallExprAssigns map[*ir.CallExpr][]ifaceAssignRef

	// analyzedFuncs is a set of Funcs that were analyzed for iface assignments.
	analyzedFuncs map[*ir.Func]struct{}
}

type ifaceAssignRef struct {
	name            *ir.Name // ifaceAssignments[name]
	assignmentIndex int      // ifaceAssignments[name][assignmentIndex]
	returnIndex     int      // (*ir.CallExpr).Result(returnIndex)
}

// InlinedCall updates the [State] to take into account a newly inlined call.
func (s *State) InlinedCall(fun *ir.Func, origCall *ir.CallExpr, inlinedCall *ir.InlinedCallExpr) {
	if _, ok := s.analyzedFuncs[fun]; !ok {
		// Full analyze has not been yet executed for the provided function, so we can skip it for now.
		// When no devirtualization happens in a function, it is unnecessary to analyze it.
		return
	}

	// Analyze assignments in the newly inlined function.
	s.analyze(inlinedCall.Init())
	s.analyze(inlinedCall.Body)

	refs, ok := s.ifaceCallExprAssigns[origCall]
	if !ok {
		return
	}
	delete(s.ifaceCallExprAssigns, origCall)

	// Update assignments to reference the new ReturnVars of the inlined call.
	for _, ref := range refs {
		vt := &s.ifaceAssignments[ref.name][ref.assignmentIndex]
		if *vt != nil {
			base.Fatalf("unexpected non-nil assignment")
		}
		if concreteTypeDebug {
			base.Warn(
				"InlinedCall(%v, %v): replacing interface node in (%v,%v) to %v (typ %v)",
				origCall, inlinedCall, ref.name, ref.assignmentIndex,
				inlinedCall.ReturnVars[ref.returnIndex],
				inlinedCall.ReturnVars[ref.returnIndex].Type(),
			)
		}

		// Update ifaceAssignments with an ir.Node from the inlined function’s ReturnVars.
		// This may enable future devirtualization of calls that reference ref.name.
		// We will get calls to [StaticCall] from the interleaved package,
		// to try devirtualize such calls afterwards.
		*vt = inlinedCall.ReturnVars[ref.returnIndex]
	}
}

// assignments returns all assignments to n.
func (s *State) assignments(n *ir.Name) []assignment {
	fun := n.Curfn
	if fun == nil {
		base.FatalfAt(n.Pos(), "n.Curfn = <nil>")
	}
	if n.Class != ir.PAUTO {
		base.FatalfAt(n.Pos(), "n.Class = %v; want = PAUTO", n.Class)
	}

	if !n.Type().IsInterface() {
		base.FatalfAt(n.Pos(), "name passed to assignments is not of an interface type: %v", n.Type())
	}

	// Analyze assignments in func, if not analyzed before.
	if _, ok := s.analyzedFuncs[fun]; !ok {
		if concreteTypeDebug {
			base.Warn("assignments(): analyzing assignments in %v func", fun)
		}
		if s.analyzedFuncs == nil {
			s.ifaceAssignments = make(map[*ir.Name][]assignment)
			s.ifaceCallExprAssigns = make(map[*ir.CallExpr][]ifaceAssignRef)
			s.analyzedFuncs = make(map[*ir.Func]struct{})
		}
		s.analyzedFuncs[fun] = struct{}{}
		s.analyze(fun.Init())
		s.analyze(fun.Body)
	}

	return s.ifaceAssignments[n]
}

// analyze analyzes every assignment to interface variables in nodes, updating [State].
func (s *State) analyze(nodes ir.Nodes) {
	assign := func(name ir.Node, assignment assignment) (*ir.Name, int) {
		if name == nil || name.Op() != ir.ONAME || ir.IsBlank(name) {
			return nil, -1
		}

		n, ok := ir.OuterValue(name).(*ir.Name)
		if !ok || n.Curfn == nil {
			return nil, -1
		}

		// Do not track variables that are not of interface types.
		// For devirtualization they are unnecessary, we will not even look them up.
		if !n.Type().IsInterface() {
			return nil, -1
		}

		n = n.Canonical()
		if n.Op() != ir.ONAME {
			base.FatalfAt(n.Pos(), "n.Op = %v; want = ONAME", n.Op())
		}
		if n.Class != ir.PAUTO {
			return nil, -1
		}

		switch a := assignment.(type) {
		case nil:
		case *types.Type:
			if a != nil && a.IsInterface() {
				assignment = nil // non-concrete type
			}
		case ir.Node:
			// nil assignment, we can safely ignore them, see [StaticCall].
			if ir.IsNil(a) {
				return nil, -1
			}
		default:
			base.Fatalf("unexpected type: %v", assignment)
		}

		if concreteTypeDebug {
			base.Warn("analyze(): assignment found %v = %v", name, assignment)
		}

		s.ifaceAssignments[n] = append(s.ifaceAssignments[n], assignment)
		return n, len(s.ifaceAssignments[n]) - 1
	}

	var do func(n ir.Node)
	do = func(n ir.Node) {
		switch n.Op() {
		case ir.OAS:
			n := n.(*ir.AssignStmt)
			if rhs := n.Y; rhs != nil {
				for {
					if r, ok := rhs.(*ir.ParenExpr); ok {
						rhs = r.X
						continue
					}
					break
				}
				if call, ok := rhs.(*ir.CallExpr); ok && call.Fun != nil {
					retTyp := call.Fun.Type().Results()[0].Type
					n, idx := assign(n.X, retTyp)
					if n != nil && retTyp.IsInterface() {
						// We have a call expression, that returns an interface, store it for later evaluation.
						// In case this func gets inlined later, we will update the assignment (added before)
						// with a reference to ReturnVars, see [State.InlinedCall], which might allow for future devirtualizing of n.X.
						s.ifaceCallExprAssigns[call] = append(s.ifaceCallExprAssigns[call], ifaceAssignRef{n, idx, 0})
					}
				} else {
					assign(n.X, rhs)
				}
			}
		case ir.OAS2:
			n := n.(*ir.AssignListStmt)
			for i, p := range n.Lhs {
				if n.Rhs[i] != nil {
					assign(p, n.Rhs[i])
				}
			}
		case ir.OAS2DOTTYPE:
			n := n.(*ir.AssignListStmt)
			if n.Rhs[0] == nil {
				base.FatalfAt(n.Pos(), "n.Rhs[0] == nil; n = %v", n)
			}
			assign(n.Lhs[0], n.Rhs[0])
			assign(n.Lhs[1], nil) // boolean does not have methods to devirtualize
		case ir.OAS2MAPR, ir.OAS2RECV, ir.OSELRECV2:
			n := n.(*ir.AssignListStmt)
			if n.Rhs[0] == nil {
				base.FatalfAt(n.Pos(), "n.Rhs[0] == nil; n = %v", n)
			}
			assign(n.Lhs[0], n.Rhs[0].Type())
			assign(n.Lhs[1], nil) // boolean does not have methods to devirtualize
		case ir.OAS2FUNC:
			n := n.(*ir.AssignListStmt)
			rhs := n.Rhs[0]
			for {
				if r, ok := rhs.(*ir.ParenExpr); ok {
					rhs = r.X
					continue
				}
				break
			}
			if call, ok := rhs.(*ir.CallExpr); ok {
				for i, p := range n.Lhs {
					retTyp := call.Fun.Type().Results()[i].Type
					n, idx := assign(p, retTyp)
					if n != nil && retTyp.IsInterface() {
						// We have a call expression, that returns an interface, store it for later evaluation.
						// In case this func gets inlined later, we will update the assignment (added before)
						// with a reference to ReturnVars, see [State.InlinedCall], which might allow for future devirtualizing of n.X.
						s.ifaceCallExprAssigns[call] = append(s.ifaceCallExprAssigns[call], ifaceAssignRef{n, idx, i})
					}
				}
			} else if call, ok := rhs.(*ir.InlinedCallExpr); ok {
				for i, p := range n.Lhs {
					assign(p, call.ReturnVars[i])
				}
			} else {
				base.FatalfAt(n.Pos(), "unexpected type %T in OAS2FUNC Rhs[0]", call)
			}
		case ir.ORANGE:
			n := n.(*ir.RangeStmt)
			xTyp := n.X.Type()

			// Range over an array pointer.
			if xTyp.IsPtr() && xTyp.Elem().IsArray() {
				xTyp = xTyp.Elem()
			}

			if xTyp.IsArray() || xTyp.IsSlice() {
				assign(n.Key, nil) // integer does not have methods to devirtualize
				assign(n.Value, xTyp.Elem())
			} else if xTyp.IsChan() {
				assign(n.Key, xTyp.Elem())
				base.AssertfAt(n.Value == nil, n.Pos(), "n.Value != nil in range over chan")
			} else if xTyp.IsMap() {
				assign(n.Key, xTyp.Key())
				assign(n.Value, xTyp.Elem())
			} else if xTyp.IsInteger() || xTyp.IsString() {
				// Range over int/string, results do not have methods, so nothing to devirtualize.
				assign(n.Key, nil)
				assign(n.Value, nil)
			} else {
				// We will not reach here in case of a range-over-func, as it is
				// rewritten to function calls in the noder package.
				base.FatalfAt(n.Pos(), "range over unexpected type %v", n.X.Type())
			}
		case ir.OSWITCH:
			n := n.(*ir.SwitchStmt)
			if guard, ok := n.Tag.(*ir.TypeSwitchGuard); ok {
				for _, v := range n.Cases {
					if v.Var == nil {
						base.Assert(guard.Tag == nil)
						continue
					}
					assign(v.Var, guard.X)
				}
			}
		case ir.OCLOSURE:
			n := n.(*ir.ClosureExpr)
			if _, ok := s.analyzedFuncs[n.Func]; !ok {
				s.analyzedFuncs[n.Func] = struct{}{}
				ir.Visit(n.Func, do)
			}
		}
	}
	ir.VisitList(nodes, do)
}
