package ssa

import (
	
	

	
)

// Variable is a unique identifier for a source program's variable and will correspond to
// multiple ssa Value(s).
//
// For example, `Local 1` is a Variable in WebAssembly, and Value(s) will be created for it
// whenever it executes `local.set 1`.
//
// Variable is useful to track the SSA Values of a variable in the source program, and
// can be used to find the corresponding latest SSA Value via Builder.FindValue.
//
// Higher 4-bit is used to store Type for this variable.
type Variable uint32

// String implements fmt.Stringer.
func ( Variable) () string {
	return fmt.Sprintf("var%d", &0x0fffffff)
}

func ( Variable) ( Type) Variable {
	if  >= 1<<28 {
		panic(fmt.Sprintf("Too large variable: %d", ))
	}
	return Variable()<<28 | 
}

func ( Variable) () Type {
	return Type( >> 28)
}

// Value represents an SSA value with a type information. The relationship with Variable is 1: N (including 0),
// that means there might be multiple Variable(s) for a Value.
//
// 32 to 59-bit is used to store the unique identifier of the Instruction that generates this value if any.
// 60 to 63-bit is used to store Type for this value.
type Value uint64

// ValueID is the lower 32bit of Value, which is the pure identifier of Value without type info.
type ValueID uint32

const (
	valueIDInvalid ValueID = math.MaxUint32
	ValueInvalid           = Value(valueIDInvalid)
)

// Format creates a debug string for this Value using the data stored in Builder.
func ( Value) ( Builder) string {
	if ,  := .(*builder).valueAnnotations[.ID()];  {
		return 
	}
	return fmt.Sprintf("v%d", .ID())
}

func ( Value) ( Builder) ( string) {
	if ,  := .(*builder).valueAnnotations[.ID()];  {
		 =  + ":" + .Type().String()
	} else {
		 = fmt.Sprintf("v%d:%s", .ID(), .Type())
	}

	if wazevoapi.SSALoggingEnabled { // This is useful to check live value analysis bugs.
		if  := .(*builder); .donePostBlockLayoutPasses {
			 := .ID()
			 += fmt.Sprintf("(ref=%d)", .valuesInfo[].RefCount)
		}
	}
	return 
}

// Valid returns true if this value is valid.
func ( Value) () bool {
	return .ID() != valueIDInvalid
}

// Type returns the Type of this value.
func ( Value) () Type {
	return Type( >> 60)
}

// ID returns the valueID of this value.
func ( Value) () ValueID {
	return ValueID()
}

// setType sets a type to this Value and returns the updated Value.
func ( Value) ( Type) Value {
	return  | Value()<<60
}

// setInstructionID sets an Instruction.id to this Value and returns the updated Value.
func ( Value) ( int) Value {
	if  < 0 || uint() >= 1<<28 {
		panic(fmt.Sprintf("Too large instruction ID: %d", ))
	}
	return  | Value()<<32
}

// instructionID() returns the Instruction.id of this Value.
func ( Value) () int {
	return int(>>32) & 0x0fffffff
}

// Values is a slice of Value. Use this instead of []Value to reuse the underlying memory.
type Values = wazevoapi.VarLength[Value]

// ValuesNil is a nil Values.
var ValuesNil = wazevoapi.NewNilVarLength[Value]()