Source file src/pkg/cmd/compile/internal/ssa/value.go
1
2
3
4
5 package ssa
6
7 import (
8 "cmd/compile/internal/types"
9 "cmd/internal/src"
10 "fmt"
11 "math"
12 "sort"
13 "strings"
14 )
15
16
17
18
19 type Value struct {
20
21
22 ID ID
23
24
25 Op Op
26
27
28
29 Type *types.Type
30
31
32
33
34
35
36
37
38 AuxInt int64
39 Aux interface{}
40
41
42 Args []*Value
43
44
45 Block *Block
46
47
48 Pos src.XPos
49
50
51 Uses int32
52
53
54
55 OnWasmStack bool
56
57
58 argstorage [3]*Value
59 }
60
61
62
63
64
65
66
67
68
69 func (v *Value) String() string {
70 if v == nil {
71 return "nil"
72 }
73 return fmt.Sprintf("v%d", v.ID)
74 }
75
76 func (v *Value) AuxInt8() int8 {
77 if opcodeTable[v.Op].auxType != auxInt8 {
78 v.Fatalf("op %s doesn't have an int8 aux field", v.Op)
79 }
80 return int8(v.AuxInt)
81 }
82
83 func (v *Value) AuxInt16() int16 {
84 if opcodeTable[v.Op].auxType != auxInt16 {
85 v.Fatalf("op %s doesn't have an int16 aux field", v.Op)
86 }
87 return int16(v.AuxInt)
88 }
89
90 func (v *Value) AuxInt32() int32 {
91 if opcodeTable[v.Op].auxType != auxInt32 {
92 v.Fatalf("op %s doesn't have an int32 aux field", v.Op)
93 }
94 return int32(v.AuxInt)
95 }
96
97
98
99
100 func (v *Value) AuxUnsigned() uint64 {
101 c := v.AuxInt
102 switch v.Op {
103 case OpConst64:
104 return uint64(c)
105 case OpConst32:
106 return uint64(uint32(c))
107 case OpConst16:
108 return uint64(uint16(c))
109 case OpConst8:
110 return uint64(uint8(c))
111 }
112 v.Fatalf("op %s isn't OpConst*", v.Op)
113 return 0
114 }
115
116 func (v *Value) AuxFloat() float64 {
117 if opcodeTable[v.Op].auxType != auxFloat32 && opcodeTable[v.Op].auxType != auxFloat64 {
118 v.Fatalf("op %s doesn't have a float aux field", v.Op)
119 }
120 return math.Float64frombits(uint64(v.AuxInt))
121 }
122 func (v *Value) AuxValAndOff() ValAndOff {
123 if opcodeTable[v.Op].auxType != auxSymValAndOff {
124 v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op)
125 }
126 return ValAndOff(v.AuxInt)
127 }
128
129
130 func (v *Value) LongString() string {
131 s := fmt.Sprintf("v%d = %s", v.ID, v.Op)
132 s += " <" + v.Type.String() + ">"
133 s += v.auxString()
134 for _, a := range v.Args {
135 s += fmt.Sprintf(" %v", a)
136 }
137 var r []Location
138 if v.Block != nil {
139 r = v.Block.Func.RegAlloc
140 }
141 if int(v.ID) < len(r) && r[v.ID] != nil {
142 s += " : " + r[v.ID].String()
143 }
144 var names []string
145 if v.Block != nil {
146 for name, values := range v.Block.Func.NamedValues {
147 for _, value := range values {
148 if value == v {
149 names = append(names, name.String())
150 break
151 }
152 }
153 }
154 }
155 if len(names) != 0 {
156 sort.Strings(names)
157 s += " (" + strings.Join(names, ", ") + ")"
158 }
159 return s
160 }
161
162 func (v *Value) auxString() string {
163 switch opcodeTable[v.Op].auxType {
164 case auxBool:
165 if v.AuxInt == 0 {
166 return " [false]"
167 } else {
168 return " [true]"
169 }
170 case auxInt8:
171 return fmt.Sprintf(" [%d]", v.AuxInt8())
172 case auxInt16:
173 return fmt.Sprintf(" [%d]", v.AuxInt16())
174 case auxInt32:
175 return fmt.Sprintf(" [%d]", v.AuxInt32())
176 case auxInt64, auxInt128:
177 return fmt.Sprintf(" [%d]", v.AuxInt)
178 case auxFloat32, auxFloat64:
179 return fmt.Sprintf(" [%g]", v.AuxFloat())
180 case auxString:
181 return fmt.Sprintf(" {%q}", v.Aux)
182 case auxSym, auxTyp:
183 if v.Aux != nil {
184 return fmt.Sprintf(" {%v}", v.Aux)
185 }
186 case auxSymOff, auxSymInt32, auxTypSize:
187 s := ""
188 if v.Aux != nil {
189 s = fmt.Sprintf(" {%v}", v.Aux)
190 }
191 if v.AuxInt != 0 {
192 s += fmt.Sprintf(" [%v]", v.AuxInt)
193 }
194 return s
195 case auxSymValAndOff:
196 s := ""
197 if v.Aux != nil {
198 s = fmt.Sprintf(" {%v}", v.Aux)
199 }
200 return s + fmt.Sprintf(" [%s]", v.AuxValAndOff())
201 case auxCCop:
202 return fmt.Sprintf(" {%s}", v.Aux.(Op))
203 }
204 return ""
205 }
206
207
208
209
210 func (v *Value) AddArg(w *Value) {
211 if v.Args == nil {
212 v.resetArgs()
213 }
214 v.Args = append(v.Args, w)
215 w.Uses++
216 }
217 func (v *Value) AddArgs(a ...*Value) {
218 if v.Args == nil {
219 v.resetArgs()
220 }
221 v.Args = append(v.Args, a...)
222 for _, x := range a {
223 x.Uses++
224 }
225 }
226 func (v *Value) SetArg(i int, w *Value) {
227 v.Args[i].Uses--
228 v.Args[i] = w
229 w.Uses++
230 }
231 func (v *Value) RemoveArg(i int) {
232 v.Args[i].Uses--
233 copy(v.Args[i:], v.Args[i+1:])
234 v.Args[len(v.Args)-1] = nil
235 v.Args = v.Args[:len(v.Args)-1]
236 }
237 func (v *Value) SetArgs1(a *Value) {
238 v.resetArgs()
239 v.AddArg(a)
240 }
241 func (v *Value) SetArgs2(a *Value, b *Value) {
242 v.resetArgs()
243 v.AddArg(a)
244 v.AddArg(b)
245 }
246
247 func (v *Value) resetArgs() {
248 for _, a := range v.Args {
249 a.Uses--
250 }
251 v.argstorage[0] = nil
252 v.argstorage[1] = nil
253 v.argstorage[2] = nil
254 v.Args = v.argstorage[:0]
255 }
256
257 func (v *Value) reset(op Op) {
258 v.Op = op
259 if op != OpCopy && notStmtBoundary(op) {
260
261 v.Pos = v.Pos.WithNotStmt()
262 }
263 v.resetArgs()
264 v.AuxInt = 0
265 v.Aux = nil
266 }
267
268
269 func (v *Value) copyInto(b *Block) *Value {
270 c := b.NewValue0(v.Pos.WithNotStmt(), v.Op, v.Type)
271 c.Aux = v.Aux
272 c.AuxInt = v.AuxInt
273 c.AddArgs(v.Args...)
274 for _, a := range v.Args {
275 if a.Type.IsMemory() {
276 v.Fatalf("can't move a value with a memory arg %s", v.LongString())
277 }
278 }
279 return c
280 }
281
282
283
284 func (v *Value) copyIntoWithXPos(b *Block, pos src.XPos) *Value {
285 c := b.NewValue0(pos, v.Op, v.Type)
286 c.Aux = v.Aux
287 c.AuxInt = v.AuxInt
288 c.AddArgs(v.Args...)
289 for _, a := range v.Args {
290 if a.Type.IsMemory() {
291 v.Fatalf("can't move a value with a memory arg %s", v.LongString())
292 }
293 }
294 return c
295 }
296
297 func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) }
298 func (v *Value) Log() bool { return v.Block.Log() }
299 func (v *Value) Fatalf(msg string, args ...interface{}) {
300 v.Block.Func.fe.Fatalf(v.Pos, msg, args...)
301 }
302
303
304 func (v *Value) isGenericIntConst() bool {
305 return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8)
306 }
307
308
309 func (v *Value) Reg() int16 {
310 reg := v.Block.Func.RegAlloc[v.ID]
311 if reg == nil {
312 v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
313 }
314 return reg.(*Register).objNum
315 }
316
317
318 func (v *Value) Reg0() int16 {
319 reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0]
320 if reg == nil {
321 v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
322 }
323 return reg.(*Register).objNum
324 }
325
326
327 func (v *Value) Reg1() int16 {
328 reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1]
329 if reg == nil {
330 v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
331 }
332 return reg.(*Register).objNum
333 }
334
335 func (v *Value) RegName() string {
336 reg := v.Block.Func.RegAlloc[v.ID]
337 if reg == nil {
338 v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
339 }
340 return reg.(*Register).name
341 }
342
343
344
345
346 func (v *Value) MemoryArg() *Value {
347 if v.Op == OpPhi {
348 v.Fatalf("MemoryArg on Phi")
349 }
350 na := len(v.Args)
351 if na == 0 {
352 return nil
353 }
354 if m := v.Args[na-1]; m.Type.IsMemory() {
355 return m
356 }
357 return nil
358 }
359
360
361
362
363 func (v *Value) LackingPos() bool {
364
365
366
367 return v.Op == OpVarDef || v.Op == OpVarKill || v.Op == OpVarLive || v.Op == OpPhi ||
368 (v.Op == OpFwdRef || v.Op == OpCopy) && v.Type == types.TypeMem
369 }
370
View as plain text