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