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 }