github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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 auxSizeAndAlign:
   132  		return fmt.Sprintf(" [%s]", SizeAndAlign(v.AuxInt))
   133  	case auxFloat32, auxFloat64:
   134  		return fmt.Sprintf(" [%g]", v.AuxFloat())
   135  	case auxString:
   136  		return fmt.Sprintf(" {%q}", v.Aux)
   137  	case auxSym:
   138  		if v.Aux != nil {
   139  			return fmt.Sprintf(" {%v}", v.Aux)
   140  		}
   141  	case auxSymOff, auxSymInt32:
   142  		s := ""
   143  		if v.Aux != nil {
   144  			s = fmt.Sprintf(" {%v}", v.Aux)
   145  		}
   146  		if v.AuxInt != 0 {
   147  			s += fmt.Sprintf(" [%v]", v.AuxInt)
   148  		}
   149  		return s
   150  	case auxSymValAndOff:
   151  		s := ""
   152  		if v.Aux != nil {
   153  			s = fmt.Sprintf(" {%v}", v.Aux)
   154  		}
   155  		return s + fmt.Sprintf(" [%s]", v.AuxValAndOff())
   156  	case auxSymSizeAndAlign:
   157  		s := ""
   158  		if v.Aux != nil {
   159  			s = fmt.Sprintf(" {%v}", v.Aux)
   160  		}
   161  		return s + fmt.Sprintf(" [%s]", SizeAndAlign(v.AuxInt))
   162  	}
   163  	return ""
   164  }
   165  
   166  func (v *Value) AddArg(w *Value) {
   167  	if v.Args == nil {
   168  		v.resetArgs() // use argstorage
   169  	}
   170  	v.Args = append(v.Args, w)
   171  	w.Uses++
   172  }
   173  func (v *Value) AddArgs(a ...*Value) {
   174  	if v.Args == nil {
   175  		v.resetArgs() // use argstorage
   176  	}
   177  	v.Args = append(v.Args, a...)
   178  	for _, x := range a {
   179  		x.Uses++
   180  	}
   181  }
   182  func (v *Value) SetArg(i int, w *Value) {
   183  	v.Args[i].Uses--
   184  	v.Args[i] = w
   185  	w.Uses++
   186  }
   187  func (v *Value) RemoveArg(i int) {
   188  	v.Args[i].Uses--
   189  	copy(v.Args[i:], v.Args[i+1:])
   190  	v.Args[len(v.Args)-1] = nil // aid GC
   191  	v.Args = v.Args[:len(v.Args)-1]
   192  }
   193  func (v *Value) SetArgs1(a *Value) {
   194  	v.resetArgs()
   195  	v.AddArg(a)
   196  }
   197  func (v *Value) SetArgs2(a *Value, b *Value) {
   198  	v.resetArgs()
   199  	v.AddArg(a)
   200  	v.AddArg(b)
   201  }
   202  
   203  func (v *Value) resetArgs() {
   204  	for _, a := range v.Args {
   205  		a.Uses--
   206  	}
   207  	v.argstorage[0] = nil
   208  	v.argstorage[1] = nil
   209  	v.argstorage[2] = nil
   210  	v.Args = v.argstorage[:0]
   211  }
   212  
   213  func (v *Value) reset(op Op) {
   214  	v.Op = op
   215  	v.resetArgs()
   216  	v.AuxInt = 0
   217  	v.Aux = nil
   218  }
   219  
   220  // copyInto makes a new value identical to v and adds it to the end of b.
   221  func (v *Value) copyInto(b *Block) *Value {
   222  	c := b.NewValue0(v.Pos, v.Op, v.Type)
   223  	c.Aux = v.Aux
   224  	c.AuxInt = v.AuxInt
   225  	c.AddArgs(v.Args...)
   226  	for _, a := range v.Args {
   227  		if a.Type.IsMemory() {
   228  			v.Fatalf("can't move a value with a memory arg %s", v.LongString())
   229  		}
   230  	}
   231  	return c
   232  }
   233  
   234  func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) }
   235  func (v *Value) Log() bool                            { return v.Block.Log() }
   236  func (v *Value) Fatalf(msg string, args ...interface{}) {
   237  	v.Block.Func.Config.Fatalf(v.Pos, msg, args...)
   238  }
   239  
   240  // isGenericIntConst returns whether v is a generic integer constant.
   241  func (v *Value) isGenericIntConst() bool {
   242  	return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8)
   243  }
   244  
   245  // ExternSymbol is an aux value that encodes a variable's
   246  // constant offset from the static base pointer.
   247  type ExternSymbol struct {
   248  	Typ Type // Go type
   249  	Sym *obj.LSym
   250  	// Note: the offset for an external symbol is not
   251  	// calculated until link time.
   252  }
   253  
   254  // ArgSymbol is an aux value that encodes an argument or result
   255  // variable's constant offset from FP (FP = SP + framesize).
   256  type ArgSymbol struct {
   257  	Typ  Type   // Go type
   258  	Node GCNode // A *gc.Node referring to the argument/result variable.
   259  }
   260  
   261  // AutoSymbol is an aux value that encodes a local variable's
   262  // constant offset from SP.
   263  type AutoSymbol struct {
   264  	Typ  Type   // Go type
   265  	Node GCNode // A *gc.Node referring to a local (auto) variable.
   266  }
   267  
   268  func (s *ExternSymbol) String() string {
   269  	return s.Sym.String()
   270  }
   271  
   272  func (s *ArgSymbol) String() string {
   273  	return s.Node.String()
   274  }
   275  
   276  func (s *AutoSymbol) String() string {
   277  	return s.Node.String()
   278  }
   279  
   280  // Reg returns the register assigned to v, in cmd/internal/obj/$ARCH numbering.
   281  func (v *Value) Reg() int16 {
   282  	reg := v.Block.Func.RegAlloc[v.ID]
   283  	if reg == nil {
   284  		v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
   285  	}
   286  	return reg.(*Register).objNum
   287  }
   288  
   289  // Reg0 returns the register assigned to the first output of v, in cmd/internal/obj/$ARCH numbering.
   290  func (v *Value) Reg0() int16 {
   291  	reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0]
   292  	if reg == nil {
   293  		v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
   294  	}
   295  	return reg.(*Register).objNum
   296  }
   297  
   298  // Reg1 returns the register assigned to the second output of v, in cmd/internal/obj/$ARCH numbering.
   299  func (v *Value) Reg1() int16 {
   300  	reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1]
   301  	if reg == nil {
   302  		v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
   303  	}
   304  	return reg.(*Register).objNum
   305  }
   306  
   307  func (v *Value) RegName() string {
   308  	reg := v.Block.Func.RegAlloc[v.ID]
   309  	if reg == nil {
   310  		v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
   311  	}
   312  	return reg.(*Register).name
   313  }