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