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 InCache bool
59
60
61 argstorage [3]*Value
62 }
63
64
65
66
67
68
69
70
71
72 func (v *Value) String() string {
73 if v == nil {
74 return "nil"
75 }
76 return fmt.Sprintf("v%d", v.ID)
77 }
78
79 func (v *Value) AuxInt8() int8 {
80 if opcodeTable[v.Op].auxType != auxInt8 {
81 v.Fatalf("op %s doesn't have an int8 aux field", v.Op)
82 }
83 return int8(v.AuxInt)
84 }
85
86 func (v *Value) AuxInt16() int16 {
87 if opcodeTable[v.Op].auxType != auxInt16 {
88 v.Fatalf("op %s doesn't have an int16 aux field", v.Op)
89 }
90 return int16(v.AuxInt)
91 }
92
93 func (v *Value) AuxInt32() int32 {
94 if opcodeTable[v.Op].auxType != auxInt32 {
95 v.Fatalf("op %s doesn't have an int32 aux field", v.Op)
96 }
97 return int32(v.AuxInt)
98 }
99
100
101
102
103 func (v *Value) AuxUnsigned() uint64 {
104 c := v.AuxInt
105 switch v.Op {
106 case OpConst64:
107 return uint64(c)
108 case OpConst32:
109 return uint64(uint32(c))
110 case OpConst16:
111 return uint64(uint16(c))
112 case OpConst8:
113 return uint64(uint8(c))
114 }
115 v.Fatalf("op %s isn't OpConst*", v.Op)
116 return 0
117 }
118
119 func (v *Value) AuxFloat() float64 {
120 if opcodeTable[v.Op].auxType != auxFloat32 && opcodeTable[v.Op].auxType != auxFloat64 {
121 v.Fatalf("op %s doesn't have a float aux field", v.Op)
122 }
123 return math.Float64frombits(uint64(v.AuxInt))
124 }
125 func (v *Value) AuxValAndOff() ValAndOff {
126 if opcodeTable[v.Op].auxType != auxSymValAndOff {
127 v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op)
128 }
129 return ValAndOff(v.AuxInt)
130 }
131
132 func (v *Value) AuxArm64BitField() arm64BitField {
133 if opcodeTable[v.Op].auxType != auxARM64BitField {
134 v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op)
135 }
136 return arm64BitField(v.AuxInt)
137 }
138
139
140 func (v *Value) LongString() string {
141 s := fmt.Sprintf("v%d = %s", v.ID, v.Op)
142 s += " <" + v.Type.String() + ">"
143 s += v.auxString()
144 for _, a := range v.Args {
145 s += fmt.Sprintf(" %v", a)
146 }
147 var r []Location
148 if v.Block != nil {
149 r = v.Block.Func.RegAlloc
150 }
151 if int(v.ID) < len(r) && r[v.ID] != nil {
152 s += " : " + r[v.ID].String()
153 }
154 var names []string
155 if v.Block != nil {
156 for name, values := range v.Block.Func.NamedValues {
157 for _, value := range values {
158 if value == v {
159 names = append(names, name.String())
160 break
161 }
162 }
163 }
164 }
165 if len(names) != 0 {
166 sort.Strings(names)
167 s += " (" + strings.Join(names, ", ") + ")"
168 }
169 return s
170 }
171
172 func (v *Value) auxString() string {
173 switch opcodeTable[v.Op].auxType {
174 case auxBool:
175 if v.AuxInt == 0 {
176 return " [false]"
177 } else {
178 return " [true]"
179 }
180 case auxInt8:
181 return fmt.Sprintf(" [%d]", v.AuxInt8())
182 case auxInt16:
183 return fmt.Sprintf(" [%d]", v.AuxInt16())
184 case auxInt32:
185 return fmt.Sprintf(" [%d]", v.AuxInt32())
186 case auxInt64, auxInt128:
187 return fmt.Sprintf(" [%d]", v.AuxInt)
188 case auxARM64BitField:
189 lsb := v.AuxArm64BitField().getARM64BFlsb()
190 width := v.AuxArm64BitField().getARM64BFwidth()
191 return fmt.Sprintf(" [lsb=%d,width=%d]", lsb, width)
192 case auxFloat32, auxFloat64:
193 return fmt.Sprintf(" [%g]", v.AuxFloat())
194 case auxString:
195 return fmt.Sprintf(" {%q}", v.Aux)
196 case auxSym, auxCall, auxTyp:
197 if v.Aux != nil {
198 return fmt.Sprintf(" {%v}", v.Aux)
199 }
200 case auxSymOff, auxCallOff, auxTypSize:
201 s := ""
202 if v.Aux != nil {
203 s = fmt.Sprintf(" {%v}", v.Aux)
204 }
205 if v.AuxInt != 0 {
206 s += fmt.Sprintf(" [%v]", v.AuxInt)
207 }
208 return s
209 case auxSymValAndOff:
210 s := ""
211 if v.Aux != nil {
212 s = fmt.Sprintf(" {%v}", v.Aux)
213 }
214 return s + fmt.Sprintf(" [%s]", v.AuxValAndOff())
215 case auxCCop:
216 return fmt.Sprintf(" {%s}", Op(v.AuxInt))
217 case auxS390XCCMask, auxS390XRotateParams:
218 return fmt.Sprintf(" {%v}", v.Aux)
219 case auxFlagConstant:
220 return fmt.Sprintf("[%s]", flagConstant(v.AuxInt))
221 }
222 return ""
223 }
224
225
226
227
228 func (v *Value) AddArg(w *Value) {
229 if v.Args == nil {
230 v.resetArgs()
231 }
232 v.Args = append(v.Args, w)
233 w.Uses++
234 }
235
236
237 func (v *Value) AddArg2(w1, w2 *Value) {
238 if v.Args == nil {
239 v.resetArgs()
240 }
241 v.Args = append(v.Args, w1, w2)
242 w1.Uses++
243 w2.Uses++
244 }
245
246
247 func (v *Value) AddArg3(w1, w2, w3 *Value) {
248 if v.Args == nil {
249 v.resetArgs()
250 }
251 v.Args = append(v.Args, w1, w2, w3)
252 w1.Uses++
253 w2.Uses++
254 w3.Uses++
255 }
256
257
258 func (v *Value) AddArg4(w1, w2, w3, w4 *Value) {
259 v.Args = append(v.Args, w1, w2, w3, w4)
260 w1.Uses++
261 w2.Uses++
262 w3.Uses++
263 w4.Uses++
264 }
265
266
267 func (v *Value) AddArg5(w1, w2, w3, w4, w5 *Value) {
268 v.Args = append(v.Args, w1, w2, w3, w4, w5)
269 w1.Uses++
270 w2.Uses++
271 w3.Uses++
272 w4.Uses++
273 w5.Uses++
274 }
275
276
277 func (v *Value) AddArg6(w1, w2, w3, w4, w5, w6 *Value) {
278 v.Args = append(v.Args, w1, w2, w3, w4, w5, w6)
279 w1.Uses++
280 w2.Uses++
281 w3.Uses++
282 w4.Uses++
283 w5.Uses++
284 w6.Uses++
285 }
286
287 func (v *Value) AddArgs(a ...*Value) {
288 if v.Args == nil {
289 v.resetArgs()
290 }
291 v.Args = append(v.Args, a...)
292 for _, x := range a {
293 x.Uses++
294 }
295 }
296 func (v *Value) SetArg(i int, w *Value) {
297 v.Args[i].Uses--
298 v.Args[i] = w
299 w.Uses++
300 }
301 func (v *Value) RemoveArg(i int) {
302 v.Args[i].Uses--
303 copy(v.Args[i:], v.Args[i+1:])
304 v.Args[len(v.Args)-1] = nil
305 v.Args = v.Args[:len(v.Args)-1]
306 }
307 func (v *Value) SetArgs1(a *Value) {
308 v.resetArgs()
309 v.AddArg(a)
310 }
311 func (v *Value) SetArgs2(a, b *Value) {
312 v.resetArgs()
313 v.AddArg(a)
314 v.AddArg(b)
315 }
316 func (v *Value) SetArgs3(a, b, c *Value) {
317 v.resetArgs()
318 v.AddArg(a)
319 v.AddArg(b)
320 v.AddArg(c)
321 }
322
323 func (v *Value) resetArgs() {
324 for _, a := range v.Args {
325 a.Uses--
326 }
327 v.argstorage[0] = nil
328 v.argstorage[1] = nil
329 v.argstorage[2] = nil
330 v.Args = v.argstorage[:0]
331 }
332
333
334
335
336
337 func (v *Value) reset(op Op) {
338 if v.InCache {
339 v.Block.Func.unCache(v)
340 }
341 v.Op = op
342 v.resetArgs()
343 v.AuxInt = 0
344 v.Aux = nil
345 }
346
347
348
349
350 func (v *Value) copyOf(a *Value) {
351 if v == a {
352 return
353 }
354 if v.InCache {
355 v.Block.Func.unCache(v)
356 }
357 v.Op = OpCopy
358 v.resetArgs()
359 v.AddArg(a)
360 v.AuxInt = 0
361 v.Aux = nil
362 v.Type = a.Type
363 }
364
365
366
367 func (v *Value) copyInto(b *Block) *Value {
368 c := b.NewValue0(v.Pos.WithNotStmt(), v.Op, v.Type)
369 c.Aux = v.Aux
370 c.AuxInt = v.AuxInt
371 c.AddArgs(v.Args...)
372 for _, a := range v.Args {
373 if a.Type.IsMemory() {
374 v.Fatalf("can't move a value with a memory arg %s", v.LongString())
375 }
376 }
377 return c
378 }
379
380
381
382
383
384
385
386 func (v *Value) copyIntoWithXPos(b *Block, pos src.XPos) *Value {
387 if v.Pos.IsStmt() == src.PosIsStmt && pos.IsStmt() != src.PosIsStmt && v.Pos.SameFileAndLine(pos) {
388 pos = pos.WithIsStmt()
389 }
390 c := b.NewValue0(pos, v.Op, v.Type)
391 c.Aux = v.Aux
392 c.AuxInt = v.AuxInt
393 c.AddArgs(v.Args...)
394 for _, a := range v.Args {
395 if a.Type.IsMemory() {
396 v.Fatalf("can't move a value with a memory arg %s", v.LongString())
397 }
398 }
399 return c
400 }
401
402 func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) }
403 func (v *Value) Log() bool { return v.Block.Log() }
404 func (v *Value) Fatalf(msg string, args ...interface{}) {
405 v.Block.Func.fe.Fatalf(v.Pos, msg, args...)
406 }
407
408
409 func (v *Value) isGenericIntConst() bool {
410 return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8)
411 }
412
413
414 func (v *Value) Reg() int16 {
415 reg := v.Block.Func.RegAlloc[v.ID]
416 if reg == nil {
417 v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
418 }
419 return reg.(*Register).objNum
420 }
421
422
423 func (v *Value) Reg0() int16 {
424 reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0]
425 if reg == nil {
426 v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
427 }
428 return reg.(*Register).objNum
429 }
430
431
432 func (v *Value) Reg1() int16 {
433 reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1]
434 if reg == nil {
435 v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
436 }
437 return reg.(*Register).objNum
438 }
439
440 func (v *Value) RegName() string {
441 reg := v.Block.Func.RegAlloc[v.ID]
442 if reg == nil {
443 v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
444 }
445 return reg.(*Register).name
446 }
447
448
449
450
451 func (v *Value) MemoryArg() *Value {
452 if v.Op == OpPhi {
453 v.Fatalf("MemoryArg on Phi")
454 }
455 na := len(v.Args)
456 if na == 0 {
457 return nil
458 }
459 if m := v.Args[na-1]; m.Type.IsMemory() {
460 return m
461 }
462 return nil
463 }
464
465
466
467
468 func (v *Value) LackingPos() bool {
469
470
471
472 return v.Op == OpVarDef || v.Op == OpVarKill || v.Op == OpVarLive || v.Op == OpPhi ||
473 (v.Op == OpFwdRef || v.Op == OpCopy) && v.Type == types.TypeMem
474 }
475
476
477
478 func (v *Value) removeable() bool {
479 if v.Type.IsVoid() {
480
481 return false
482 }
483 if v.Type.IsMemory() {
484
485
486
487 return false
488 }
489 if v.Op.HasSideEffects() {
490
491 return false
492 }
493 return true
494 }
495
View as plain text