github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/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 switch opcodeTable[v.Op].auxType { 102 case auxBool: 103 if v.AuxInt == 0 { 104 s += " [false]" 105 } else { 106 s += " [true]" 107 } 108 case auxInt8: 109 s += fmt.Sprintf(" [%d]", v.AuxInt8()) 110 case auxInt16: 111 s += fmt.Sprintf(" [%d]", v.AuxInt16()) 112 case auxInt32: 113 s += fmt.Sprintf(" [%d]", v.AuxInt32()) 114 case auxInt64: 115 s += fmt.Sprintf(" [%d]", v.AuxInt) 116 case auxFloat32, auxFloat64: 117 s += fmt.Sprintf(" [%g]", v.AuxFloat()) 118 case auxString: 119 s += fmt.Sprintf(" {%s}", v.Aux) 120 case auxSym: 121 if v.Aux != nil { 122 s += fmt.Sprintf(" {%s}", v.Aux) 123 } 124 case auxSymOff: 125 if v.Aux != nil { 126 s += fmt.Sprintf(" {%s}", v.Aux) 127 } 128 s += fmt.Sprintf(" [%d]", v.AuxInt) 129 case auxSymValAndOff: 130 if v.Aux != nil { 131 s += fmt.Sprintf(" {%s}", v.Aux) 132 } 133 s += fmt.Sprintf(" [%s]", v.AuxValAndOff()) 134 } 135 for _, a := range v.Args { 136 s += fmt.Sprintf(" %v", a) 137 } 138 r := v.Block.Func.RegAlloc 139 if int(v.ID) < len(r) && r[v.ID] != nil { 140 s += " : " + r[v.ID].Name() 141 } 142 return s 143 } 144 145 func (v *Value) AddArg(w *Value) { 146 if v.Args == nil { 147 v.resetArgs() // use argstorage 148 } 149 v.Args = append(v.Args, w) 150 w.Uses++ 151 } 152 func (v *Value) AddArgs(a ...*Value) { 153 if v.Args == nil { 154 v.resetArgs() // use argstorage 155 } 156 v.Args = append(v.Args, a...) 157 for _, x := range a { 158 x.Uses++ 159 } 160 } 161 func (v *Value) SetArg(i int, w *Value) { 162 v.Args[i].Uses-- 163 v.Args[i] = w 164 w.Uses++ 165 } 166 func (v *Value) RemoveArg(i int) { 167 v.Args[i].Uses-- 168 copy(v.Args[i:], v.Args[i+1:]) 169 v.Args[len(v.Args)-1] = nil // aid GC 170 v.Args = v.Args[:len(v.Args)-1] 171 } 172 func (v *Value) SetArgs1(a *Value) { 173 v.resetArgs() 174 v.AddArg(a) 175 } 176 func (v *Value) SetArgs2(a *Value, b *Value) { 177 v.resetArgs() 178 v.AddArg(a) 179 v.AddArg(b) 180 } 181 182 func (v *Value) resetArgs() { 183 for _, a := range v.Args { 184 a.Uses-- 185 } 186 v.argstorage[0] = nil 187 v.argstorage[1] = nil 188 v.Args = v.argstorage[:0] 189 } 190 191 func (v *Value) reset(op Op) { 192 v.Op = op 193 v.resetArgs() 194 v.AuxInt = 0 195 v.Aux = nil 196 } 197 198 // copyInto makes a new value identical to v and adds it to the end of b. 199 func (v *Value) copyInto(b *Block) *Value { 200 c := b.NewValue0(v.Line, v.Op, v.Type) 201 c.Aux = v.Aux 202 c.AuxInt = v.AuxInt 203 c.AddArgs(v.Args...) 204 for _, a := range v.Args { 205 if a.Type.IsMemory() { 206 v.Fatalf("can't move a value with a memory arg %s", v.LongString()) 207 } 208 } 209 return c 210 } 211 212 func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) } 213 func (v *Value) Log() bool { return v.Block.Log() } 214 func (v *Value) Fatalf(msg string, args ...interface{}) { 215 v.Block.Func.Config.Fatalf(v.Line, msg, args...) 216 } 217 func (v *Value) Unimplementedf(msg string, args ...interface{}) { 218 v.Block.Func.Config.Unimplementedf(v.Line, msg, args...) 219 } 220 221 // isGenericIntConst returns whether v is a generic integer constant. 222 func (v *Value) isGenericIntConst() bool { 223 return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8) 224 } 225 226 // ExternSymbol is an aux value that encodes a variable's 227 // constant offset from the static base pointer. 228 type ExternSymbol struct { 229 Typ Type // Go type 230 Sym fmt.Stringer // A *gc.Sym referring to a global variable 231 // Note: the offset for an external symbol is not 232 // calculated until link time. 233 } 234 235 // ArgSymbol is an aux value that encodes an argument or result 236 // variable's constant offset from FP (FP = SP + framesize). 237 type ArgSymbol struct { 238 Typ Type // Go type 239 Node GCNode // A *gc.Node referring to the argument/result variable. 240 } 241 242 // AutoSymbol is an aux value that encodes a local variable's 243 // constant offset from SP. 244 type AutoSymbol struct { 245 Typ Type // Go type 246 Node GCNode // A *gc.Node referring to a local (auto) variable. 247 } 248 249 func (s *ExternSymbol) String() string { 250 return s.Sym.String() 251 } 252 253 func (s *ArgSymbol) String() string { 254 return s.Node.String() 255 } 256 257 func (s *AutoSymbol) String() string { 258 return s.Node.String() 259 }