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