github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/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 "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 AuxInt int64 30 Aux interface{} 31 32 // Arguments of this value 33 Args []*Value 34 35 // Containing basic block 36 Block *Block 37 38 // Source line number 39 Line int32 40 41 // Use count. Each appearance in Value.Args and Block.Control counts once. 42 Uses int32 43 44 // Storage for the first three args 45 argstorage [3]*Value 46 } 47 48 // Examples: 49 // Opcode aux args 50 // OpAdd nil 2 51 // OpConst string 0 string constant 52 // OpConst int64 0 int64 constant 53 // OpAddcq int64 1 amd64 op: v = arg[0] + constant 54 55 // short form print. Just v#. 56 func (v *Value) String() string { 57 if v == nil { 58 return "nil" // should never happen, but not panicking helps with debugging 59 } 60 return fmt.Sprintf("v%d", v.ID) 61 } 62 63 func (v *Value) AuxInt8() int8 { 64 if opcodeTable[v.Op].auxType != auxInt8 { 65 v.Fatalf("op %s doesn't have an int8 aux field", v.Op) 66 } 67 return int8(v.AuxInt) 68 } 69 70 func (v *Value) AuxInt16() int16 { 71 if opcodeTable[v.Op].auxType != auxInt16 { 72 v.Fatalf("op %s doesn't have an int16 aux field", v.Op) 73 } 74 return int16(v.AuxInt) 75 } 76 77 func (v *Value) AuxInt32() int32 { 78 if opcodeTable[v.Op].auxType != auxInt32 { 79 v.Fatalf("op %s doesn't have an int32 aux field", v.Op) 80 } 81 return int32(v.AuxInt) 82 } 83 84 func (v *Value) AuxFloat() float64 { 85 if opcodeTable[v.Op].auxType != auxFloat32 && opcodeTable[v.Op].auxType != auxFloat64 { 86 v.Fatalf("op %s doesn't have a float aux field", v.Op) 87 } 88 return math.Float64frombits(uint64(v.AuxInt)) 89 } 90 func (v *Value) AuxValAndOff() ValAndOff { 91 if opcodeTable[v.Op].auxType != auxSymValAndOff { 92 v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op) 93 } 94 return ValAndOff(v.AuxInt) 95 } 96 97 // long form print. v# = opcode <type> [aux] args [: reg] 98 func (v *Value) LongString() string { 99 s := fmt.Sprintf("v%d = %s", v.ID, v.Op.String()) 100 s += " <" + v.Type.String() + ">" 101 s += v.auxString() 102 for _, a := range v.Args { 103 s += fmt.Sprintf(" %v", a) 104 } 105 r := v.Block.Func.RegAlloc 106 if int(v.ID) < len(r) && r[v.ID] != nil { 107 s += " : " + r[v.ID].Name() 108 } 109 return s 110 } 111 112 func (v *Value) auxString() string { 113 switch opcodeTable[v.Op].auxType { 114 case auxBool: 115 if v.AuxInt == 0 { 116 return " [false]" 117 } else { 118 return " [true]" 119 } 120 case auxInt8: 121 return fmt.Sprintf(" [%d]", v.AuxInt8()) 122 case auxInt16: 123 return fmt.Sprintf(" [%d]", v.AuxInt16()) 124 case auxInt32: 125 return fmt.Sprintf(" [%d]", v.AuxInt32()) 126 case auxInt64, auxInt128: 127 return fmt.Sprintf(" [%d]", v.AuxInt) 128 case auxFloat32, auxFloat64: 129 return fmt.Sprintf(" [%g]", v.AuxFloat()) 130 case auxString: 131 return fmt.Sprintf(" {%q}", v.Aux) 132 case auxSym: 133 if v.Aux != nil { 134 return fmt.Sprintf(" {%s}", v.Aux) 135 } 136 case auxSymOff, auxSymInt32: 137 s := "" 138 if v.Aux != nil { 139 s = fmt.Sprintf(" {%s}", v.Aux) 140 } 141 if v.AuxInt != 0 { 142 s += fmt.Sprintf(" [%v]", v.AuxInt) 143 } 144 return s 145 case auxSymValAndOff: 146 s := "" 147 if v.Aux != nil { 148 s = fmt.Sprintf(" {%s}", v.Aux) 149 } 150 return s + fmt.Sprintf(" [%s]", v.AuxValAndOff()) 151 } 152 return "" 153 } 154 155 func (v *Value) AddArg(w *Value) { 156 if v.Args == nil { 157 v.resetArgs() // use argstorage 158 } 159 v.Args = append(v.Args, w) 160 w.Uses++ 161 } 162 func (v *Value) AddArgs(a ...*Value) { 163 if v.Args == nil { 164 v.resetArgs() // use argstorage 165 } 166 v.Args = append(v.Args, a...) 167 for _, x := range a { 168 x.Uses++ 169 } 170 } 171 func (v *Value) SetArg(i int, w *Value) { 172 v.Args[i].Uses-- 173 v.Args[i] = w 174 w.Uses++ 175 } 176 func (v *Value) RemoveArg(i int) { 177 v.Args[i].Uses-- 178 copy(v.Args[i:], v.Args[i+1:]) 179 v.Args[len(v.Args)-1] = nil // aid GC 180 v.Args = v.Args[:len(v.Args)-1] 181 } 182 func (v *Value) SetArgs1(a *Value) { 183 v.resetArgs() 184 v.AddArg(a) 185 } 186 func (v *Value) SetArgs2(a *Value, b *Value) { 187 v.resetArgs() 188 v.AddArg(a) 189 v.AddArg(b) 190 } 191 192 func (v *Value) resetArgs() { 193 for _, a := range v.Args { 194 a.Uses-- 195 } 196 v.argstorage[0] = nil 197 v.argstorage[1] = nil 198 v.argstorage[2] = nil 199 v.Args = v.argstorage[:0] 200 } 201 202 func (v *Value) reset(op Op) { 203 v.Op = op 204 v.resetArgs() 205 v.AuxInt = 0 206 v.Aux = nil 207 } 208 209 // copyInto makes a new value identical to v and adds it to the end of b. 210 func (v *Value) copyInto(b *Block) *Value { 211 c := b.NewValue0(v.Line, v.Op, v.Type) 212 c.Aux = v.Aux 213 c.AuxInt = v.AuxInt 214 c.AddArgs(v.Args...) 215 for _, a := range v.Args { 216 if a.Type.IsMemory() { 217 v.Fatalf("can't move a value with a memory arg %s", v.LongString()) 218 } 219 } 220 return c 221 } 222 223 func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) } 224 func (v *Value) Log() bool { return v.Block.Log() } 225 func (v *Value) Fatalf(msg string, args ...interface{}) { 226 v.Block.Func.Config.Fatalf(v.Line, msg, args...) 227 } 228 func (v *Value) Unimplementedf(msg string, args ...interface{}) { 229 v.Block.Func.Config.Unimplementedf(v.Line, 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 Typ Type // Go type 241 Sym fmt.Stringer // A *gc.Sym referring to a global variable 242 // Note: the offset for an external symbol is not 243 // calculated until link time. 244 } 245 246 // ArgSymbol is an aux value that encodes an argument or result 247 // variable's constant offset from FP (FP = SP + framesize). 248 type ArgSymbol struct { 249 Typ Type // Go type 250 Node GCNode // A *gc.Node referring to the argument/result variable. 251 } 252 253 // AutoSymbol is an aux value that encodes a local variable's 254 // constant offset from SP. 255 type AutoSymbol struct { 256 Typ Type // Go type 257 Node GCNode // A *gc.Node referring to a local (auto) variable. 258 } 259 260 func (s *ExternSymbol) String() string { 261 return s.Sym.String() 262 } 263 264 func (s *ArgSymbol) String() string { 265 return s.Node.String() 266 } 267 268 func (s *AutoSymbol) String() string { 269 return s.Node.String() 270 }