// Copyright 2015 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 ssacompile

import (
	"cmp"
	"slices"

	"cmd/compile/internal/ssa"
	"cmd/compile/internal/ssa/rewrite/dec"
	"cmd/compile/internal/ssa/rewrite/dec64"
	"cmd/compile/internal/ssa/ssaop"
	"cmd/compile/internal/types"
)

// decompose converts phi ops on compound builtin types into phi
// ops on simple types, then invokes rewrite rules to decompose
// other ops on those types.
func decomposeBuiltin(f *ssa.Func) {
	// Decompose phis
	for _, b := range f.Blocks {
		for _, v := range b.Values {
			if v.Op != ssaop.OpPhi {
				continue
			}
			decomposeBuiltinPhi(v)
		}
	}

	// Decompose other values
	// Note: Leave dead values because we need to keep the original
	// values around so the name component resolution below can still work.
	applyRewrite(f, dec.RewriteBlock, dec.RewriteValue, ssa.LeaveDeadValues)
	if f.Config.RegSize == 4 {
		applyRewrite(f, dec64.RewriteBlock, dec64.RewriteValue, ssa.LeaveDeadValues)
	}

	// Split up named values into their components.
	// accumulate old names for aggregates (that are decomposed) in toDelete for efficient bulk deletion,
	// accumulate new LocalSlots in newNames for addition after the iteration.  This decomposition is for
	// builtin types with leaf components, and thus there is no need to reprocess the newly create LocalSlots.
	var toDelete []namedVal
	var newNames []ssa.LocalSlot
	for i, name := range f.Names {
		t := name.Type
		switch {
		case t.IsInteger() && t.Size() > f.Config.RegSize:
			hiName, loName := f.SplitInt64(f.LocalSlotAddr(name))
			newNames = maybeAppend2(f, newNames, hiName, loName)
			for j, v := range f.NamedValues[name] {
				if v.Op != ssaop.OpInt64Make {
					continue
				}
				f.NamedValues[*hiName] = append(f.NamedValues[*hiName], v.Args[0])
				f.NamedValues[*loName] = append(f.NamedValues[*loName], v.Args[1])
				toDelete = append(toDelete, namedVal{i, j})
			}
		case t.IsComplex():
			rName, iName := f.SplitComplex(f.LocalSlotAddr(name))
			newNames = maybeAppend2(f, newNames, rName, iName)
			for j, v := range f.NamedValues[name] {
				if v.Op != ssaop.OpComplexMake {
					continue
				}
				f.NamedValues[*rName] = append(f.NamedValues[*rName], v.Args[0])
				f.NamedValues[*iName] = append(f.NamedValues[*iName], v.Args[1])
				toDelete = append(toDelete, namedVal{i, j})
			}
		case t.IsString():
			ptrName, lenName := f.SplitString(f.LocalSlotAddr(name))
			newNames = maybeAppend2(f, newNames, ptrName, lenName)
			for j, v := range f.NamedValues[name] {
				if v.Op != ssaop.OpStringMake {
					continue
				}
				f.NamedValues[*ptrName] = append(f.NamedValues[*ptrName], v.Args[0])
				f.NamedValues[*lenName] = append(f.NamedValues[*lenName], v.Args[1])
				toDelete = append(toDelete, namedVal{i, j})
			}
		case t.IsSlice():
			ptrName, lenName, capName := f.SplitSlice(f.LocalSlotAddr(name))
			newNames = maybeAppend2(f, newNames, ptrName, lenName)
			newNames = maybeAppend(f, newNames, capName)
			for j, v := range f.NamedValues[name] {
				if v.Op != ssaop.OpSliceMake {
					continue
				}
				f.NamedValues[*ptrName] = append(f.NamedValues[*ptrName], v.Args[0])
				f.NamedValues[*lenName] = append(f.NamedValues[*lenName], v.Args[1])
				f.NamedValues[*capName] = append(f.NamedValues[*capName], v.Args[2])
				toDelete = append(toDelete, namedVal{i, j})
			}
		case t.IsInterface():
			typeName, dataName := f.SplitInterface(f.LocalSlotAddr(name))
			newNames = maybeAppend2(f, newNames, typeName, dataName)
			for j, v := range f.NamedValues[name] {
				if v.Op != ssaop.OpIMake {
					continue
				}
				f.NamedValues[*typeName] = append(f.NamedValues[*typeName], v.Args[0])
				f.NamedValues[*dataName] = append(f.NamedValues[*dataName], v.Args[1])
				toDelete = append(toDelete, namedVal{i, j})
			}
		case t.IsFloat():
			// floats are never decomposed, even ones bigger than RegSize
		case t.Size() > f.Config.RegSize && !t.IsSIMD():
			f.Fatalf("undecomposed named type %s %v", name, t)
		}
	}

	deleteNamedVals(f, toDelete)
	f.Names = append(f.Names, newNames...)
}

func maybeAppend(f *ssa.Func, ss []ssa.LocalSlot, s *ssa.LocalSlot) []ssa.LocalSlot {
	if _, ok := f.NamedValues[*s]; !ok {
		f.NamedValues[*s] = nil
		return append(ss, *s)
	}
	return ss
}

func maybeAppend2(f *ssa.Func, ss []ssa.LocalSlot, s1, s2 *ssa.LocalSlot) []ssa.LocalSlot {
	return maybeAppend(f, maybeAppend(f, ss, s1), s2)
}

func decomposeBuiltinPhi(v *ssa.Value) {
	switch {
	case v.Type.IsInteger() && v.Type.Size() > v.Block.Func.Config.RegSize:
		decomposeInt64Phi(v)
	case v.Type.IsComplex():
		decomposeComplexPhi(v)
	case v.Type.IsString():
		decomposeStringPhi(v)
	case v.Type.IsSlice():
		decomposeSlicePhi(v)
	case v.Type.IsInterface():
		decomposeInterfacePhi(v)
	case v.Type.IsFloat():
		// floats are never decomposed, even ones bigger than RegSize
	case v.Type.Size() > v.Block.Func.Config.RegSize && !v.Type.IsSIMD():
		v.Fatalf("%v undecomposed type %v", v, v.Type)
	}
}

func decomposeStringPhi(v *ssa.Value) {
	types := &v.Block.Func.Config.Types
	ptrType := types.BytePtr
	lenType := types.Int

	ptr := v.Block.NewValue0(v.Pos, ssaop.OpPhi, ptrType)
	len := v.Block.NewValue0(v.Pos, ssaop.OpPhi, lenType)
	for _, a := range v.Args {
		ptr.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpStringPtr, ptrType, a))
		len.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpStringLen, lenType, a))
	}
	v.Reset(ssaop.OpStringMake)
	v.AddArg(ptr)
	v.AddArg(len)
}

func decomposeSlicePhi(v *ssa.Value) {
	types := &v.Block.Func.Config.Types
	ptrType := v.Type.Elem().PtrTo()
	lenType := types.Int

	ptr := v.Block.NewValue0(v.Pos, ssaop.OpPhi, ptrType)
	len := v.Block.NewValue0(v.Pos, ssaop.OpPhi, lenType)
	cap := v.Block.NewValue0(v.Pos, ssaop.OpPhi, lenType)
	for _, a := range v.Args {
		ptr.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpSlicePtr, ptrType, a))
		len.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpSliceLen, lenType, a))
		cap.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpSliceCap, lenType, a))
	}
	v.Reset(ssaop.OpSliceMake)
	v.AddArg(ptr)
	v.AddArg(len)
	v.AddArg(cap)
}

func decomposeInt64Phi(v *ssa.Value) {
	cfgtypes := &v.Block.Func.Config.Types
	var partType *types.Type
	if v.Type.IsSigned() {
		partType = cfgtypes.Int32
	} else {
		partType = cfgtypes.UInt32
	}

	hi := v.Block.NewValue0(v.Pos, ssaop.OpPhi, partType)
	lo := v.Block.NewValue0(v.Pos, ssaop.OpPhi, cfgtypes.UInt32)
	for _, a := range v.Args {
		hi.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpInt64Hi, partType, a))
		lo.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpInt64Lo, cfgtypes.UInt32, a))
	}
	v.Reset(ssaop.OpInt64Make)
	v.AddArg(hi)
	v.AddArg(lo)
}

func decomposeComplexPhi(v *ssa.Value) {
	cfgtypes := &v.Block.Func.Config.Types
	var partType *types.Type
	switch z := v.Type.Size(); z {
	case 8:
		partType = cfgtypes.Float32
	case 16:
		partType = cfgtypes.Float64
	default:
		v.Fatalf("decomposeComplexPhi: bad complex size %d", z)
	}

	real := v.Block.NewValue0(v.Pos, ssaop.OpPhi, partType)
	imag := v.Block.NewValue0(v.Pos, ssaop.OpPhi, partType)
	for _, a := range v.Args {
		real.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpComplexReal, partType, a))
		imag.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpComplexImag, partType, a))
	}
	v.Reset(ssaop.OpComplexMake)
	v.AddArg(real)
	v.AddArg(imag)
}

func decomposeInterfacePhi(v *ssa.Value) {
	uintptrType := v.Block.Func.Config.Types.Uintptr
	ptrType := v.Block.Func.Config.Types.BytePtr

	itab := v.Block.NewValue0(v.Pos, ssaop.OpPhi, uintptrType)
	data := v.Block.NewValue0(v.Pos, ssaop.OpPhi, ptrType)
	for _, a := range v.Args {
		itab.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpITab, uintptrType, a))
		data.AddArg(a.Block.NewValue1(v.Pos, ssaop.OpIData, ptrType, a))
	}
	v.Reset(ssaop.OpIMake)
	v.AddArg(itab)
	v.AddArg(data)
}

func decomposeUser(f *ssa.Func) {
	for _, b := range f.Blocks {
		for _, v := range b.Values {
			if v.Op != ssaop.OpPhi {
				continue
			}
			decomposeUserPhi(v)
		}
	}
	// Split up named values into their components.
	i := 0
	var newNames []ssa.LocalSlot
	for _, name := range f.Names {
		t := name.Type
		switch {
		case isStructNotSIMD(t):
			newNames = decomposeUserStructInto(f, f.LocalSlotAddr(name), newNames)
		case t.IsArray():
			newNames = decomposeUserArrayInto(f, f.LocalSlotAddr(name), newNames)
		default:
			f.Names[i] = name
			i++
		}
	}
	f.Names = f.Names[:i]
	f.Names = append(f.Names, newNames...)
}

// decomposeUserArrayInto creates names for the element(s) of arrays referenced
// by name where possible, and appends those new names to slots, which is then
// returned.
func decomposeUserArrayInto(f *ssa.Func, name *ssa.LocalSlot, slots []ssa.LocalSlot) []ssa.LocalSlot {
	t := name.Type
	if t.Size() == 0 {
		// TODO(khr): Not sure what to do here.  Probably nothing.
		// Names for empty arrays aren't important.
		return slots
	}
	if t.NumElem() != 1 {
		// shouldn't get here due to CanSSA
		f.Fatalf("array not of size 1")
	}
	elemName := f.SplitArray(name)
	var keep []*ssa.Value
	for _, v := range f.NamedValues[*name] {
		if v.Op != ssaop.OpArrayMake1 {
			keep = append(keep, v)
			continue
		}
		f.NamedValues[*elemName] = append(f.NamedValues[*elemName], v.Args[0])
	}
	if len(keep) == 0 {
		// delete the name for the array as a whole
		delete(f.NamedValues, *name)
	} else {
		f.NamedValues[*name] = keep
	}

	if t.Elem().IsArray() {
		return decomposeUserArrayInto(f, elemName, slots)
	} else if isStructNotSIMD(t.Elem()) {
		return decomposeUserStructInto(f, elemName, slots)
	}

	return append(slots, *elemName)
}

// decomposeUserStructInto creates names for the fields(s) of structs referenced
// by name where possible, and appends those new names to slots, which is then
// returned.
func decomposeUserStructInto(f *ssa.Func, name *ssa.LocalSlot, slots []ssa.LocalSlot) []ssa.LocalSlot {
	fnames := []*ssa.LocalSlot{} // slots for struct in name
	t := name.Type
	n := t.NumFields()

	for i := 0; i < n; i++ {
		fs := f.SplitStruct(name, i)
		fnames = append(fnames, fs)
		// arrays and structs will be decomposed further, so
		// there's no need to record a name
		if !fs.Type.IsArray() && !isStructNotSIMD(fs.Type) {
			slots = maybeAppend(f, slots, fs)
		}
	}

	var keep []*ssa.Value
	// create named values for each struct field
	for _, v := range f.NamedValues[*name] {
		if v.Op != ssaop.OpStructMake || len(v.Args) != n {
			keep = append(keep, v)
			continue
		}
		for i := 0; i < len(fnames); i++ {
			f.NamedValues[*fnames[i]] = append(f.NamedValues[*fnames[i]], v.Args[i])
		}
	}
	if len(keep) == 0 {
		// delete the name for the struct as a whole
		delete(f.NamedValues, *name)
	} else {
		f.NamedValues[*name] = keep
	}

	// now that this f.NamedValues contains values for the struct
	// fields, recurse into nested structs
	for i := 0; i < n; i++ {
		if isStructNotSIMD(name.Type.FieldType(i)) {
			slots = decomposeUserStructInto(f, fnames[i], slots)
			delete(f.NamedValues, *fnames[i])
		} else if name.Type.FieldType(i).IsArray() {
			slots = decomposeUserArrayInto(f, fnames[i], slots)
			delete(f.NamedValues, *fnames[i])
		}
	}
	return slots
}
func decomposeUserPhi(v *ssa.Value) {
	switch {
	case isStructNotSIMD(v.Type):
		decomposeStructPhi(v)
	case v.Type.IsArray():
		decomposeArrayPhi(v)
	}
}

// decomposeStructPhi replaces phi-of-struct with structmake(phi-for-each-field),
// and then recursively decomposes the phis for each field.
func decomposeStructPhi(v *ssa.Value) {
	t := v.Type
	if t.Size() == 0 {
		v.Reset(ssaop.OpEmpty)
		return
	}
	n := t.NumFields()
	fields := make([]*ssa.Value, 0, ssa.MaxStruct)
	for i := 0; i < n; i++ {
		fields = append(fields, v.Block.NewValue0(v.Pos, ssaop.OpPhi, t.FieldType(i)))
	}
	for _, a := range v.Args {
		for i := 0; i < n; i++ {
			fields[i].AddArg(a.Block.NewValue1I(v.Pos, ssaop.OpStructSelect, t.FieldType(i), int64(i), a))
		}
	}
	v.Reset(ssaop.OpStructMake)
	v.AddArgs(fields...)

	// Recursively decompose phis for each field.
	for _, f := range fields {
		decomposeUserPhi(f)
	}
}

// decomposeArrayPhi replaces phi-of-array with arraymake(phi-of-array-element),
// and then recursively decomposes the element phi.
func decomposeArrayPhi(v *ssa.Value) {
	t := v.Type
	if t.Size() == 0 {
		v.Reset(ssaop.OpEmpty)
		return
	}
	if t.NumElem() != 1 {
		v.Fatalf("SSAable array must have no more than 1 element")
	}
	elem := v.Block.NewValue0(v.Pos, ssaop.OpPhi, t.Elem())
	for _, a := range v.Args {
		elem.AddArg(a.Block.NewValue1I(v.Pos, ssaop.OpArraySelect, t.Elem(), 0, a))
	}
	v.Reset(ssaop.OpArrayMake1)
	v.AddArg(elem)

	// Recursively decompose elem phi.
	decomposeUserPhi(elem)
}

type namedVal struct {
	locIndex, valIndex int // f.NamedValues[f.Names[locIndex]][valIndex] = key
}

// deleteNamedVals removes particular values with debugger names from f's naming data structures,
// removes all values with OpInvalid, and re-sorts the list of Names.
func deleteNamedVals(f *ssa.Func, toDelete []namedVal) {
	// Arrange to delete from larger indices to smaller, to ensure swap-with-end deletion does not invalidate pending indices.
	slices.SortFunc(toDelete, func(a, b namedVal) int {
		if a.locIndex != b.locIndex {
			return cmp.Compare(b.locIndex, a.locIndex)
		}
		return cmp.Compare(b.valIndex, a.valIndex)
	})

	// Get rid of obsolete names
	for _, d := range toDelete {
		loc := f.Names[d.locIndex]
		vals := f.NamedValues[loc]
		l := len(vals) - 1
		if l > 0 {
			vals[d.valIndex] = vals[l]
		}
		vals[l] = nil
		f.NamedValues[loc] = vals[:l]
	}
	// Delete locations with no values attached.
	end := len(f.Names)
	for i := len(f.Names) - 1; i >= 0; i-- {
		loc := f.Names[i]
		vals := f.NamedValues[loc]
		last := len(vals)
		for j := len(vals) - 1; j >= 0; j-- {
			if vals[j].Op == ssaop.OpInvalid {
				last--
				vals[j] = vals[last]
				vals[last] = nil
			}
		}
		if last < len(vals) {
			f.NamedValues[loc] = vals[:last]
		}
		if len(vals) == 0 {
			delete(f.NamedValues, loc)
			end--
			f.Names[i] = f.Names[end]
			f.Names[end] = ssa.LocalSlot{}
		}
	}
	f.Names = f.Names[:end]
}

func isStructNotSIMD(t *types.Type) bool {
	return t.IsStruct() && !t.IsSIMD()
}
