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