// Copyright 2023 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 interleaved implements the interleaved devirtualization and
// inlining pass.
package interleaved

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/devirtualize"
	"cmd/compile/internal/inline"
	"cmd/compile/internal/inline/inlheur"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/pgoir"
	"cmd/compile/internal/typecheck"
	"fmt"
)

// DevirtualizeAndInlinePackage interleaves devirtualization and inlining on
// all functions within pkg.
func DevirtualizeAndInlinePackage(pkg *ir.Package, profile *pgoir.Profile) {
	if profile != nil && base.Debug.PGODevirtualize > 0 {
		// TODO(mdempsky): Integrate into DevirtualizeAndInlineFunc below.
		ir.VisitFuncsBottomUp(typecheck.Target.Funcs, func(list []*ir.Func, recursive bool) {
			for _, fn := range list {
				devirtualize.ProfileGuided(fn, profile)
			}
		})
		ir.CurFunc = nil
	}

	if base.Flag.LowerL != 0 {
		inlheur.SetupScoreAdjustments()
	}

	var inlProfile *pgoir.Profile // copy of profile for inlining
	if base.Debug.PGOInline != 0 {
		inlProfile = profile
	}

	// First compute inlinability of all functions in the package.
	inline.CanInlineFuncs(pkg.Funcs, inlProfile)

	// Now we make a second pass to do devirtualization and inlining of
	// calls. Order here should not matter.
	for _, fn := range pkg.Funcs {
		DevirtualizeAndInlineFunc(fn, inlProfile)
	}

	if base.Flag.LowerL != 0 {
		// Perform a garbage collection of hidden closures functions that
		// are no longer reachable from top-level functions following
		// inlining. See #59404 and #59638 for more context.
		inline.GarbageCollectUnreferencedHiddenClosures()

		if base.Debug.DumpInlFuncProps != "" {
			inlheur.DumpFuncProps(nil, base.Debug.DumpInlFuncProps)
		}
		if inlheur.Enabled() {
			inline.PostProcessCallSites(inlProfile)
			inlheur.TearDown()
		}
	}
}

// DevirtualizeAndInlineFunc interleaves devirtualization and inlining
// on a single function.
func DevirtualizeAndInlineFunc(fn *ir.Func, profile *pgoir.Profile) {
	ir.WithFunc(fn, func() {
		if base.Flag.LowerL != 0 {
			if inlheur.Enabled() && !fn.Wrapper() {
				inlheur.ScoreCalls(fn)
				defer inlheur.ScoreCallsCleanup()
			}
			if base.Debug.DumpInlFuncProps != "" && !fn.Wrapper() {
				inlheur.DumpFuncProps(fn, base.Debug.DumpInlFuncProps)
			}
		}

		bigCaller := base.Flag.LowerL != 0 && inline.IsBigFunc(fn)
		if bigCaller && base.Flag.LowerM > 1 {
			fmt.Printf("%v: function %v considered 'big'; reducing max cost of inlinees\n", ir.Line(fn), fn)
		}

		match := func(n ir.Node) bool {
			switch n := n.(type) {
			case *ir.CallExpr:
				return true
			case *ir.TailCallStmt:
				n.Call.NoInline = true // can't inline yet
			}
			return false
		}

		edit := func(n ir.Node) ir.Node {
			call, ok := n.(*ir.CallExpr)
			if !ok { // previously inlined
				return nil
			}

			devirtualize.StaticCall(call)
			if inlCall := inline.TryInlineCall(fn, call, bigCaller, profile); inlCall != nil {
				return inlCall
			}
			return nil
		}

		fixpoint(fn, match, edit)
	})
}

// fixpoint repeatedly edits a function until it stabilizes.
//
// First, fixpoint applies match to every node n within fn. Then it
// iteratively applies edit to each node satisfying match(n).
//
// If edit(n) returns nil, no change is made. Otherwise, the result
// replaces n in fn's body, and fixpoint iterates at least once more.
//
// After an iteration where all edit calls return nil, fixpoint
// returns.
func fixpoint(fn *ir.Func, match func(ir.Node) bool, edit func(ir.Node) ir.Node) {
	// Consider the expression "f(g())". We want to be able to replace
	// "g()" in-place with its inlined representation. But if we first
	// replace "f(...)" with its inlined representation, then "g()" will
	// instead appear somewhere within this new AST.
	//
	// To mitigate this, each matched node n is wrapped in a ParenExpr,
	// so we can reliably replace n in-place by assigning ParenExpr.X.
	// It's safe to use ParenExpr here, because typecheck already
	// removed them all.

	var parens []*ir.ParenExpr
	var mark func(ir.Node) ir.Node
	mark = func(n ir.Node) ir.Node {
		if _, ok := n.(*ir.ParenExpr); ok {
			return n // already visited n.X before wrapping
		}

		ok := match(n)

		ir.EditChildren(n, mark)

		if ok {
			paren := ir.NewParenExpr(n.Pos(), n)
			paren.SetType(n.Type())
			paren.SetTypecheck(n.Typecheck())

			parens = append(parens, paren)
			n = paren
		}

		return n
	}
	ir.EditChildren(fn, mark)

	// Edit until stable.
	for {
		done := true

		for i := 0; i < len(parens); i++ { // can't use "range parens" here
			paren := parens[i]
			if new := edit(paren.X); new != nil {
				// Update AST and recursively mark nodes.
				paren.X = new
				ir.EditChildren(new, mark) // mark may append to parens
				done = false
			}
		}

		if done {
			break
		}
	}

	// Finally, remove any parens we inserted.
	if len(parens) == 0 {
		return // short circuit
	}
	var unparen func(ir.Node) ir.Node
	unparen = func(n ir.Node) ir.Node {
		if paren, ok := n.(*ir.ParenExpr); ok {
			n = paren.X
		}
		ir.EditChildren(n, unparen)
		return n
	}
	ir.EditChildren(fn, unparen)
}
