package regalloc

import (
	

	
)

// VReg represents a register which is assigned to an SSA value. This is used to represent a register in the backend.
// A VReg may or may not be a physical register, and the info of physical register can be obtained by RealReg.
type VReg uint64

// VRegID is the lower 32bit of VReg, which is the pure identifier of VReg without RealReg info.
type VRegID uint32

// RealReg returns the RealReg of this VReg.
func ( VReg) () RealReg {
	return RealReg( >> 32)
}

// IsRealReg returns true if this VReg is backed by a physical register.
func ( VReg) () bool {
	return .RealReg() != RealRegInvalid
}

// FromRealReg returns a VReg from the given RealReg and RegType.
// This is used to represent a specific pre-colored register in the backend.
func ( RealReg,  RegType) VReg {
	 := VRegID()
	if  > vRegIDReservedForRealNum {
		panic(fmt.Sprintf("invalid real reg %d", ))
	}
	return VReg().SetRealReg().SetRegType()
}

// SetRealReg sets the RealReg of this VReg and returns the updated VReg.
func ( VReg) ( RealReg) VReg {
	return VReg()<<32 | ( & 0xff_00_ffffffff)
}

// RegType returns the RegType of this VReg.
func ( VReg) () RegType {
	return RegType( >> 40)
}

// SetRegType sets the RegType of this VReg and returns the updated VReg.
func ( VReg) ( RegType) VReg {
	return VReg()<<40 | ( & 0x00_ff_ffffffff)
}

// ID returns the VRegID of this VReg.
func ( VReg) () VRegID {
	return VRegID( & 0xffffffff)
}

// Valid returns true if this VReg is Valid.
func ( VReg) () bool {
	return .ID() != vRegIDInvalid && .RegType() != RegTypeInvalid
}

// RealReg represents a physical register.
type RealReg byte

const RealRegInvalid RealReg = 0

const (
	vRegIDInvalid            VRegID = 1 << 31
	VRegIDNonReservedBegin          = vRegIDReservedForRealNum
	vRegIDReservedForRealNum VRegID = 128
	VRegInvalid                     = VReg(vRegIDInvalid)
)

// String implements fmt.Stringer.
func ( RealReg) () string {
	switch  {
	case RealRegInvalid:
		return "invalid"
	default:
		return fmt.Sprintf("r%d", )
	}
}

// String implements fmt.Stringer.
func ( VReg) () string {
	if .IsRealReg() {
		return fmt.Sprintf("r%d", .ID())
	}
	return fmt.Sprintf("v%d?", .ID())
}

// RegType represents the type of a register.
type RegType byte

const (
	RegTypeInvalid RegType = iota
	RegTypeInt
	RegTypeFloat
	NumRegType
)

// String implements fmt.Stringer.
func ( RegType) () string {
	switch  {
	case RegTypeInt:
		return "int"
	case RegTypeFloat:
		return "float"
	default:
		return "invalid"
	}
}

// RegTypeOf returns the RegType of the given ssa.Type.
func ( ssa.Type) RegType {
	switch  {
	case ssa.TypeI32, ssa.TypeI64:
		return RegTypeInt
	case ssa.TypeF32, ssa.TypeF64, ssa.TypeV128:
		return RegTypeFloat
	default:
		panic("invalid type")
	}
}