github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/cmd/compile/internal/ssa/value.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssa
     6  
     7  import (
     8  	"cmd/internal/obj"
     9  	"cmd/internal/src"
    10  	"fmt"
    11  	"math"
    12  )
    13  
    14  // A Value represents a value in the SSA representation of the program.
    15  // The ID and Type fields must not be modified. The remainder may be modified
    16  // if they preserve the value of the Value (e.g. changing a (mul 2 x) to an (add x x)).
    17  type Value struct {
    18  	// A unique identifier for the value. For performance we allocate these IDs
    19  	// densely starting at 1.  There is no guarantee that there won't be occasional holes, though.
    20  	ID ID
    21  
    22  	// The operation that computes this value. See op.go.
    23  	Op Op
    24  
    25  	// The type of this value. Normally this will be a Go type, but there
    26  	// are a few other pseudo-types, see type.go.
    27  	Type Type
    28  
    29  	// Auxiliary info for this value. The type of this information depends on the opcode and type.
    30  	// AuxInt is used for integer values, Aux is used for other values.
    31  	// Floats are stored in AuxInt using math.Float64bits(f).
    32  	AuxInt int64
    33  	Aux    interface{}
    34  
    35  	// Arguments of this value
    36  	Args []*Value
    37  
    38  	// Containing basic block
    39  	Block *Block
    40  
    41  	// Source position
    42  	Pos src.XPos
    43  
    44  	// Use count. Each appearance in Value.Args and Block.Control counts once.
    45  	Uses int32
    46  
    47  	// Storage for the first three args
    48  	argstorage [3]*Value
    49  }
    50  
    51  // Examples:
    52  // Opcode          aux   args
    53  //  OpAdd          nil      2
    54  //  OpConst     string      0    string constant
    55  //  OpConst      int64      0    int64 constant
    56  //  OpAddcq      int64      1    amd64 op: v = arg[0] + constant
    57  
    58  // short form print. Just v#.
    59  func (v *Value) String() string {
    60  	if v == nil {
    61  		return "nil" // should never happen, but not panicking helps with debugging
    62  	}
    63  	return fmt.Sprintf("v%d", v.ID)
    64  }
    65  
    66  func (v *Value) AuxInt8() int8 {
    67  	if opcodeTable[v.Op].auxType != auxInt8 {
    68  		v.Fatalf("op %s doesn't have an int8 aux field", v.Op)
    69  	}
    70  	return int8(v.AuxInt)
    71  }
    72  
    73  func (v *Value) AuxInt16() int16 {
    74  	if opcodeTable[v.Op].auxType != auxInt16 {
    75  		v.Fatalf("op %s doesn't have an int16 aux field", v.Op)
    76  	}
    77  	return int16(v.AuxInt)
    78  }
    79  
    80  func (v *Value) AuxInt32() int32 {
    81  	if opcodeTable[v.Op].auxType != auxInt32 {
    82  		v.Fatalf("op %s doesn't have an int32 aux field", v.Op)
    83  	}
    84  	return int32(v.AuxInt)
    85  }
    86  
    87  func (v *Value) AuxFloat() float64 {
    88  	if opcodeTable[v.Op].auxType != auxFloat32 && opcodeTable[v.Op].auxType != auxFloat64 {
    89  		v.Fatalf("op %s doesn't have a float aux field", v.Op)
    90  	}
    91  	return math.Float64frombits(uint64(v.AuxInt))
    92  }
    93  func (v *Value) AuxValAndOff() ValAndOff {
    94  	if opcodeTable[v.Op].auxType != auxSymValAndOff {
    95  		v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op)
    96  	}
    97  	return ValAndOff(v.AuxInt)
    98  }
    99  
   100  // long form print.  v# = opcode <type> [aux] args [: reg]
   101  func (v *Value) LongString() string {
   102  	s := fmt.Sprintf("v%d = %s", v.ID, v.Op)
   103  	s += " <" + v.Type.String() + ">"
   104  	s += v.auxString()
   105  	for _, a := range v.Args {
   106  		s += fmt.Sprintf(" %v", a)
   107  	}
   108  	r := v.Block.Func.RegAlloc
   109  	if int(v.ID) < len(r) && r[v.ID] != nil {
   110  		s += " : " + r[v.ID].Name()
   111  	}
   112  	return s
   113  }
   114  
   115  func (v *Value) auxString() string {
   116  	switch opcodeTable[v.Op].auxType {
   117  	case auxBool:
   118  		if v.AuxInt == 0 {
   119  			return " [false]"
   120  		} else {
   121  			return " [true]"
   122  		}
   123  	case auxInt8:
   124  		return fmt.Sprintf(" [%d]", v.AuxInt8())
   125  	case auxInt16:
   126  		return fmt.Sprintf(" [%d]", v.AuxInt16())
   127  	case auxInt32:
   128  		return fmt.Sprintf(" [%d]", v.AuxInt32())
   129  	case auxInt64, auxInt128:
   130  		return fmt.Sprintf(" [%d]", v.AuxInt)
   131  	case auxFloat32, auxFloat64:
   132  		return fmt.Sprintf(" [%g]", v.AuxFloat())
   133  	case auxString:
   134  		return fmt.Sprintf(" {%q}", v.Aux)
   135  	case auxSym, auxTyp:
   136  		if v.Aux != nil {
   137  			return fmt.Sprintf(" {%v}", v.Aux)
   138  		}
   139  	case auxSymOff, auxSymInt32, auxTypSize:
   140  		s := ""
   141  		if v.Aux != nil {
   142  			s = fmt.Sprintf(" {%v}", v.Aux)
   143  		}
   144  		if v.AuxInt != 0 {
   145  			s += fmt.Sprintf(" [%v]", v.AuxInt)
   146  		}
   147  		return s
   148  	case auxSymValAndOff:
   149  		s := ""
   150  		if v.Aux != nil {
   151  			s = fmt.Sprintf(" {%v}", v.Aux)
   152  		}
   153  		return s + fmt.Sprintf(" [%s]", v.AuxValAndOff())
   154  	}
   155  	return ""
   156  }
   157  
   158  func (v *Value) AddArg(w *Value) {
   159  	if v.Args == nil {
   160  		v.resetArgs() // use argstorage
   161  	}
   162  	v.Args = append(v.Args, w)
   163  	w.Uses++
   164  }
   165  func (v *Value) AddArgs(a ...*Value) {
   166  	if v.Args == nil {
   167  		v.resetArgs() // use argstorage
   168  	}
   169  	v.Args = append(v.Args, a...)
   170  	for _, x := range a {
   171  		x.Uses++
   172  	}
   173  }
   174  func (v *Value) SetArg(i int, w *Value) {
   175  	v.Args[i].Uses--
   176  	v.Args[i] = w
   177  	w.Uses++
   178  }
   179  func (v *Value) RemoveArg(i int) {
   180  	v.Args[i].Uses--
   181  	copy(v.Args[i:], v.Args[i+1:])
   182  	v.Args[len(v.Args)-1] = nil // aid GC
   183  	v.Args = v.Args[:len(v.Args)-1]
   184  }
   185  func (v *Value) SetArgs1(a *Value) {
   186  	v.resetArgs()
   187  	v.AddArg(a)
   188  }
   189  func (v *Value) SetArgs2(a *Value, b *Value) {
   190  	v.resetArgs()
   191  	v.AddArg(a)
   192  	v.AddArg(b)
   193  }
   194  
   195  func (v *Value) resetArgs() {
   196  	for _, a := range v.Args {
   197  		a.Uses--
   198  	}
   199  	v.argstorage[0] = nil
   200  	v.argstorage[1] = nil
   201  	v.argstorage[2] = nil
   202  	v.Args = v.argstorage[:0]
   203  }
   204  
   205  func (v *Value) reset(op Op) {
   206  	v.Op = op
   207  	v.resetArgs()
   208  	v.AuxInt = 0
   209  	v.Aux = nil
   210  }
   211  
   212  // copyInto makes a new value identical to v and adds it to the end of b.
   213  func (v *Value) copyInto(b *Block) *Value {
   214  	c := b.NewValue0(v.Pos, v.Op, v.Type)
   215  	c.Aux = v.Aux
   216  	c.AuxInt = v.AuxInt
   217  	c.AddArgs(v.Args...)
   218  	for _, a := range v.Args {
   219  		if a.Type.IsMemory() {
   220  			v.Fatalf("can't move a value with a memory arg %s", v.LongString())
   221  		}
   222  	}
   223  	return c
   224  }
   225  
   226  func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) }
   227  func (v *Value) Log() bool                            { return v.Block.Log() }
   228  func (v *Value) Fatalf(msg string, args ...interface{}) {
   229  	v.Block.Func.fe.Fatalf(v.Pos, msg, args...)
   230  }
   231  
   232  // isGenericIntConst returns whether v is a generic integer constant.
   233  func (v *Value) isGenericIntConst() bool {
   234  	return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8)
   235  }
   236  
   237  // ExternSymbol is an aux value that encodes a variable's
   238  // constant offset from the static base pointer.
   239  type ExternSymbol struct {
   240  	Sym *obj.LSym
   241  	// Note: the offset for an external symbol is not
   242  	// calculated until link time.
   243  }
   244  
   245  // ArgSymbol is an aux value that encodes an argument or result
   246  // variable's constant offset from FP (FP = SP + framesize).
   247  type ArgSymbol struct {
   248  	Node GCNode // A *gc.Node referring to the argument/result variable.
   249  }
   250  
   251  // AutoSymbol is an aux value that encodes a local variable's
   252  // constant offset from SP.
   253  type AutoSymbol struct {
   254  	Node GCNode // A *gc.Node referring to a local (auto) variable.
   255  }
   256  
   257  func (s *ExternSymbol) String() string {
   258  	return s.Sym.String()
   259  }
   260  
   261  func (s *ArgSymbol) String() string {
   262  	return s.Node.String()
   263  }
   264  
   265  func (s *AutoSymbol) String() string {
   266  	return s.Node.String()
   267  }
   268  
   269  // Reg returns the register assigned to v, in cmd/internal/obj/$ARCH numbering.
   270  func (v *Value) Reg() int16 {
   271  	reg := v.Block.Func.RegAlloc[v.ID]
   272  	if reg == nil {
   273  		v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
   274  	}
   275  	return reg.(*Register).objNum
   276  }
   277  
   278  // Reg0 returns the register assigned to the first output of v, in cmd/internal/obj/$ARCH numbering.
   279  func (v *Value) Reg0() int16 {
   280  	reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0]
   281  	if reg == nil {
   282  		v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
   283  	}
   284  	return reg.(*Register).objNum
   285  }
   286  
   287  // Reg1 returns the register assigned to the second output of v, in cmd/internal/obj/$ARCH numbering.
   288  func (v *Value) Reg1() int16 {
   289  	reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1]
   290  	if reg == nil {
   291  		v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
   292  	}
   293  	return reg.(*Register).objNum
   294  }
   295  
   296  func (v *Value) RegName() string {
   297  	reg := v.Block.Func.RegAlloc[v.ID]
   298  	if reg == nil {
   299  		v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
   300  	}
   301  	return reg.(*Register).name
   302  }
   303  
   304  // MemoryArg returns the memory argument for the Value.
   305  // The returned value, if non-nil, will be memory-typed,
   306  // except in the case where v is Select1, in which case
   307  // the returned value will be a tuple containing a memory
   308  // type. Otherwise, nil is returned.
   309  func (v *Value) MemoryArg() *Value {
   310  	if v.Op == OpPhi {
   311  		v.Fatalf("MemoryArg on Phi")
   312  	}
   313  	na := len(v.Args)
   314  	if na == 0 {
   315  		return nil
   316  	}
   317  	if m := v.Args[na-1]; m.Type.IsMemory() ||
   318  		(v.Op == OpSelect1 && m.Type.FieldType(1).IsMemory()) {
   319  		return m
   320  	}
   321  	return nil
   322  }