github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/engine/wazevo/ssa/vs.go (about)

     1  package ssa
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  
     7  	"github.com/wasilibs/wazerox/internal/engine/wazevo/wazevoapi"
     8  )
     9  
    10  // Variable is a unique identifier for a source program's variable and will correspond to
    11  // multiple ssa Value(s).
    12  //
    13  // For example, `Local 1` is a Variable in WebAssembly, and Value(s) will be created for it
    14  // whenever it executes `local.set 1`.
    15  //
    16  // Variable is useful to track the SSA Values of a variable in the source program, and
    17  // can be used to find the corresponding latest SSA Value via Builder.FindValue.
    18  type Variable uint32
    19  
    20  // String implements fmt.Stringer.
    21  func (v Variable) String() string {
    22  	return fmt.Sprintf("var%d", v)
    23  }
    24  
    25  // Value represents an SSA value with a type information. The relationship with Variable is 1: N (including 0),
    26  // that means there might be multiple Variable(s) for a Value.
    27  //
    28  // Higher 32-bit is used to store Type for this value.
    29  type Value uint64
    30  
    31  // ValueID is the lower 32bit of Value, which is the pure identifier of Value without type info.
    32  type ValueID uint32
    33  
    34  const (
    35  	valueIDInvalid ValueID = math.MaxUint32
    36  	ValueInvalid   Value   = Value(valueIDInvalid)
    37  )
    38  
    39  // Format creates a debug string for this Value using the data stored in Builder.
    40  func (v Value) Format(b Builder) string {
    41  	if annotation, ok := b.(*builder).valueAnnotations[v.ID()]; ok {
    42  		return annotation
    43  	}
    44  	return fmt.Sprintf("v%d", v.ID())
    45  }
    46  
    47  func (v Value) formatWithType(b Builder) (ret string) {
    48  	if annotation, ok := b.(*builder).valueAnnotations[v.ID()]; ok {
    49  		ret = annotation + ":" + v.Type().String()
    50  	} else {
    51  		ret = fmt.Sprintf("v%d:%s", v.ID(), v.Type())
    52  	}
    53  
    54  	if wazevoapi.SSALoggingEnabled { // This is useful to check live value analysis bugs.
    55  		if bd := b.(*builder); bd.donePasses {
    56  			id := v.ID()
    57  			ret += fmt.Sprintf("(ref=%d)", bd.valueRefCounts[id])
    58  		}
    59  	}
    60  	return ret
    61  }
    62  
    63  // Valid returns true if this value is valid.
    64  func (v Value) Valid() bool {
    65  	return v.ID() != valueIDInvalid
    66  }
    67  
    68  // Type returns the Type of this value.
    69  func (v Value) Type() Type {
    70  	return Type(v >> 32)
    71  }
    72  
    73  // ID returns the valueID of this value.
    74  func (v Value) ID() ValueID {
    75  	return ValueID(v)
    76  }
    77  
    78  // setType sets a type to this Value and returns the updated Value.
    79  func (v Value) setType(typ Type) Value {
    80  	return v | Value(typ)<<32
    81  }