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) AuxUInt8() uint8 {
88 if opcodeTable[v.Op].auxType != auxUInt8 {
89 v.Fatalf("op %s doesn't have a uint8 aux field", v.Op)
90 }
91 return uint8(v.AuxInt)
92 }
93
94 func (v *Value) AuxInt16() int16 {
95 if opcodeTable[v.Op].auxType != auxInt16 {
96 v.Fatalf("op %s doesn't have an int16 aux field", v.Op)
97 }
98 return int16(v.AuxInt)
99 }
100
101 func (v *Value) AuxInt32() int32 {
102 if opcodeTable[v.Op].auxType != auxInt32 {
103 v.Fatalf("op %s doesn't have an int32 aux field", v.Op)
104 }
105 return int32(v.AuxInt)
106 }
107
108
109
110
111 func (v *Value) AuxUnsigned() uint64 {
112 c := v.AuxInt
113 switch v.Op {
114 case OpConst64:
115 return uint64(c)
116 case OpConst32:
117 return uint64(uint32(c))
118 case OpConst16:
119 return uint64(uint16(c))
120 case OpConst8:
121 return uint64(uint8(c))
122 }
123 v.Fatalf("op %s isn't OpConst*", v.Op)
124 return 0
125 }
126
127 func (v *Value) AuxFloat() float64 {
128 if opcodeTable[v.Op].auxType != auxFloat32 && opcodeTable[v.Op].auxType != auxFloat64 {
129 v.Fatalf("op %s doesn't have a float aux field", v.Op)
130 }
131 return math.Float64frombits(uint64(v.AuxInt))
132 }
133 func (v *Value) AuxValAndOff() ValAndOff {
134 if opcodeTable[v.Op].auxType != auxSymValAndOff {
135 v.Fatalf("op %s doesn't have a ValAndOff aux field", v.Op)
136 }
137 return ValAndOff(v.AuxInt)
138 }
139
140 func (v *Value) AuxArm64BitField() arm64BitField {
141 if opcodeTable[v.Op].auxType != auxARM64BitField {
142 v.Fatalf("op %s doesn't have a ARM64BitField aux field", v.Op)
143 }
144 return arm64BitField(v.AuxInt)
145 }
146
147
148 func (v *Value) LongString() string {
149 if v == nil {
150 return "<NIL VALUE>"
151 }
152 s := fmt.Sprintf("v%d = %s", v.ID, v.Op)
153 s += " <" + v.Type.String() + ">"
154 s += v.auxString()
155 for _, a := range v.Args {
156 s += fmt.Sprintf(" %v", a)
157 }
158 if v.Block == nil {
159 return s
160 }
161 r := v.Block.Func.RegAlloc
162 if int(v.ID) < len(r) && r[v.ID] != nil {
163 s += " : " + r[v.ID].String()
164 }
165 if reg := v.Block.Func.tempRegs[v.ID]; reg != nil {
166 s += " tmp=" + reg.String()
167 }
168 var names []string
169 for name, values := range v.Block.Func.NamedValues {
170 for _, value := range values {
171 if value == v {
172 names = append(names, name.String())
173 break
174 }
175 }
176 }
177 if len(names) != 0 {
178 sort.Strings(names)
179 s += " (" + strings.Join(names, ", ") + ")"
180 }
181 return s
182 }
183
184 func (v *Value) auxString() string {
185 switch opcodeTable[v.Op].auxType {
186 case auxBool:
187 if v.AuxInt == 0 {
188 return " [false]"
189 } else {
190 return " [true]"
191 }
192 case auxInt8:
193 return fmt.Sprintf(" [%d]", v.AuxInt8())
194 case auxInt16:
195 return fmt.Sprintf(" [%d]", v.AuxInt16())
196 case auxInt32:
197 return fmt.Sprintf(" [%d]", v.AuxInt32())
198 case auxInt64, auxInt128:
199 return fmt.Sprintf(" [%d]", v.AuxInt)
200 case auxUInt8:
201 return fmt.Sprintf(" [%d]", v.AuxUInt8())
202 case auxARM64BitField:
203 lsb := v.AuxArm64BitField().lsb()
204 width := v.AuxArm64BitField().width()
205 return fmt.Sprintf(" [lsb=%d,width=%d]", lsb, width)
206 case auxFloat32, auxFloat64:
207 return fmt.Sprintf(" [%g]", v.AuxFloat())
208 case auxString:
209 return fmt.Sprintf(" {%q}", v.Aux)
210 case auxSym, auxCall, auxTyp:
211 if v.Aux != nil {
212 return fmt.Sprintf(" {%v}", v.Aux)
213 }
214 return ""
215 case auxSymOff, auxCallOff, auxTypSize, auxNameOffsetInt8:
216 s := ""
217 if v.Aux != nil {
218 s = fmt.Sprintf(" {%v}", v.Aux)
219 }
220 if v.AuxInt != 0 || opcodeTable[v.Op].auxType == auxNameOffsetInt8 {
221 s += fmt.Sprintf(" [%v]", v.AuxInt)
222 }
223 return s
224 case auxSymValAndOff:
225 s := ""
226 if v.Aux != nil {
227 s = fmt.Sprintf(" {%v}", v.Aux)
228 }
229 return s + fmt.Sprintf(" [%s]", v.AuxValAndOff())
230 case auxCCop:
231 return fmt.Sprintf(" [%s]", Op(v.AuxInt))
232 case auxS390XCCMask, auxS390XRotateParams:
233 return fmt.Sprintf(" {%v}", v.Aux)
234 case auxFlagConstant:
235 return fmt.Sprintf("[%s]", flagConstant(v.AuxInt))
236 case auxNone:
237 return ""
238 default:
239
240 return fmt.Sprintf("[auxtype=%d AuxInt=%d Aux=%v]", opcodeTable[v.Op].auxType, v.AuxInt, v.Aux)
241 }
242 }
243
244
245
246
247
248 func (v *Value) AddArg(w *Value) {
249 if v.Args == nil {
250 v.resetArgs()
251 }
252 v.Args = append(v.Args, w)
253 w.Uses++
254 }
255
256
257 func (v *Value) AddArg2(w1, w2 *Value) {
258 if v.Args == nil {
259 v.resetArgs()
260 }
261 v.Args = append(v.Args, w1, w2)
262 w1.Uses++
263 w2.Uses++
264 }
265
266
267 func (v *Value) AddArg3(w1, w2, w3 *Value) {
268 if v.Args == nil {
269 v.resetArgs()
270 }
271 v.Args = append(v.Args, w1, w2, w3)
272 w1.Uses++
273 w2.Uses++
274 w3.Uses++
275 }
276
277
278 func (v *Value) AddArg4(w1, w2, w3, w4 *Value) {
279 v.Args = append(v.Args, w1, w2, w3, w4)
280 w1.Uses++
281 w2.Uses++
282 w3.Uses++
283 w4.Uses++
284 }
285
286
287 func (v *Value) AddArg5(w1, w2, w3, w4, w5 *Value) {
288 v.Args = append(v.Args, w1, w2, w3, w4, w5)
289 w1.Uses++
290 w2.Uses++
291 w3.Uses++
292 w4.Uses++
293 w5.Uses++
294 }
295
296
297 func (v *Value) AddArg6(w1, w2, w3, w4, w5, w6 *Value) {
298 v.Args = append(v.Args, w1, w2, w3, w4, w5, w6)
299 w1.Uses++
300 w2.Uses++
301 w3.Uses++
302 w4.Uses++
303 w5.Uses++
304 w6.Uses++
305 }
306
307 func (v *Value) AddArgs(a ...*Value) {
308 if v.Args == nil {
309 v.resetArgs()
310 }
311 v.Args = append(v.Args, a...)
312 for _, x := range a {
313 x.Uses++
314 }
315 }
316 func (v *Value) SetArg(i int, w *Value) {
317 v.Args[i].Uses--
318 v.Args[i] = w
319 w.Uses++
320 }
321 func (v *Value) SetArgs1(a *Value) {
322 v.resetArgs()
323 v.AddArg(a)
324 }
325 func (v *Value) SetArgs2(a, b *Value) {
326 v.resetArgs()
327 v.AddArg(a)
328 v.AddArg(b)
329 }
330 func (v *Value) SetArgs3(a, b, c *Value) {
331 v.resetArgs()
332 v.AddArg(a)
333 v.AddArg(b)
334 v.AddArg(c)
335 }
336 func (v *Value) SetArgs4(a, b, c, d *Value) {
337 v.resetArgs()
338 v.AddArg(a)
339 v.AddArg(b)
340 v.AddArg(c)
341 v.AddArg(d)
342 }
343
344 func (v *Value) resetArgs() {
345 for _, a := range v.Args {
346 a.Uses--
347 }
348 v.argstorage[0] = nil
349 v.argstorage[1] = nil
350 v.argstorage[2] = nil
351 v.Args = v.argstorage[:0]
352 }
353
354
355
356
357
358
359 func (v *Value) reset(op Op) {
360 if v.InCache {
361 v.Block.Func.unCache(v)
362 }
363 v.Op = op
364 v.resetArgs()
365 v.AuxInt = 0
366 v.Aux = nil
367 }
368
369
370
371
372
373
374
375
376
377 func (v *Value) invalidateRecursively() bool {
378 lostStmt := v.Pos.IsStmt() == src.PosIsStmt
379 if v.InCache {
380 v.Block.Func.unCache(v)
381 }
382 v.Op = OpInvalid
383
384 for _, a := range v.Args {
385 a.Uses--
386 if a.Uses == 0 {
387 lost := a.invalidateRecursively()
388 lostStmt = lost || lostStmt
389 }
390 }
391
392 v.argstorage[0] = nil
393 v.argstorage[1] = nil
394 v.argstorage[2] = nil
395 v.Args = v.argstorage[:0]
396
397 v.AuxInt = 0
398 v.Aux = nil
399 return lostStmt
400 }
401
402
403
404
405
406 func (v *Value) copyOf(a *Value) {
407 if v == a {
408 return
409 }
410 if v.InCache {
411 v.Block.Func.unCache(v)
412 }
413 v.Op = OpCopy
414 v.resetArgs()
415 v.AddArg(a)
416 v.AuxInt = 0
417 v.Aux = nil
418 v.Type = a.Type
419 }
420
421
422
423 func (v *Value) copyInto(b *Block) *Value {
424 c := b.NewValue0(v.Pos.WithNotStmt(), v.Op, v.Type)
425 c.Aux = v.Aux
426 c.AuxInt = v.AuxInt
427 c.AddArgs(v.Args...)
428 for _, a := range v.Args {
429 if a.Type.IsMemory() {
430 v.Fatalf("can't move a value with a memory arg %s", v.LongString())
431 }
432 }
433 return c
434 }
435
436
437
438
439
440
441
442 func (v *Value) copyIntoWithXPos(b *Block, pos src.XPos) *Value {
443 if v.Pos.IsStmt() == src.PosIsStmt && pos.IsStmt() != src.PosIsStmt && v.Pos.SameFileAndLine(pos) {
444 pos = pos.WithIsStmt()
445 }
446 c := b.NewValue0(pos, v.Op, v.Type)
447 c.Aux = v.Aux
448 c.AuxInt = v.AuxInt
449 c.AddArgs(v.Args...)
450 for _, a := range v.Args {
451 if a.Type.IsMemory() {
452 v.Fatalf("can't move a value with a memory arg %s", v.LongString())
453 }
454 }
455 return c
456 }
457
458 func (v *Value) Logf(msg string, args ...interface{}) { v.Block.Logf(msg, args...) }
459 func (v *Value) Log() bool { return v.Block.Log() }
460 func (v *Value) Fatalf(msg string, args ...interface{}) {
461 v.Block.Func.fe.Fatalf(v.Pos, msg, args...)
462 }
463
464
465 func (v *Value) isGenericIntConst() bool {
466 return v != nil && (v.Op == OpConst64 || v.Op == OpConst32 || v.Op == OpConst16 || v.Op == OpConst8)
467 }
468
469
470
471
472 func (v *Value) ResultReg() int16 {
473 reg := v.Block.Func.RegAlloc[v.ID]
474 if reg == nil {
475 v.Fatalf("nil reg for value: %s\n%s\n", v.LongString(), v.Block.Func)
476 }
477 if pair, ok := reg.(LocPair); ok {
478 reg = pair[0]
479 }
480 if reg == nil {
481 v.Fatalf("nil reg0 for value: %s\n%s\n", v.LongString(), v.Block.Func)
482 }
483 return reg.(*Register).objNum
484 }
485
486
487 func (v *Value) Reg() int16 {
488 reg := v.Block.Func.RegAlloc[v.ID]
489 if reg == nil {
490 v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
491 }
492 return reg.(*Register).objNum
493 }
494
495
496 func (v *Value) Reg0() int16 {
497 reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[0]
498 if reg == nil {
499 v.Fatalf("nil first register for value: %s\n%s\n", v.LongString(), v.Block.Func)
500 }
501 return reg.(*Register).objNum
502 }
503
504
505 func (v *Value) Reg1() int16 {
506 reg := v.Block.Func.RegAlloc[v.ID].(LocPair)[1]
507 if reg == nil {
508 v.Fatalf("nil second register for value: %s\n%s\n", v.LongString(), v.Block.Func)
509 }
510 return reg.(*Register).objNum
511 }
512
513
514 func (v *Value) RegTmp() int16 {
515 reg := v.Block.Func.tempRegs[v.ID]
516 if reg == nil {
517 v.Fatalf("nil tmp register for value: %s\n%s\n", v.LongString(), v.Block.Func)
518 }
519 return reg.objNum
520 }
521
522 func (v *Value) RegName() string {
523 reg := v.Block.Func.RegAlloc[v.ID]
524 if reg == nil {
525 v.Fatalf("nil register for value: %s\n%s\n", v.LongString(), v.Block.Func)
526 }
527 return reg.(*Register).name
528 }
529
530
531
532
533 func (v *Value) MemoryArg() *Value {
534 if v.Op == OpPhi {
535 v.Fatalf("MemoryArg on Phi")
536 }
537 na := len(v.Args)
538 if na == 0 {
539 return nil
540 }
541 if m := v.Args[na-1]; m.Type.IsMemory() {
542 return m
543 }
544 return nil
545 }
546
547
548
549
550 func (v *Value) LackingPos() bool {
551
552
553
554 return v.Op == OpVarDef || v.Op == OpVarLive || v.Op == OpPhi ||
555 (v.Op == OpFwdRef || v.Op == OpCopy) && v.Type == types.TypeMem
556 }
557
558
559
560 func (v *Value) removeable() bool {
561 if v.Type.IsVoid() {
562
563 return false
564 }
565 if opcodeTable[v.Op].nilCheck {
566
567 return false
568 }
569 if v.Type.IsMemory() {
570
571
572
573 return false
574 }
575 if v.Op.HasSideEffects() {
576
577 return false
578 }
579 return true
580 }
581
582
583
584 func AutoVar(v *Value) (*ir.Name, int64) {
585 if loc, ok := v.Block.Func.RegAlloc[v.ID].(LocalSlot); ok {
586 if v.Type.Size() > loc.Type.Size() {
587 v.Fatalf("spill/restore type %s doesn't fit in slot type %s", v.Type, loc.Type)
588 }
589 return loc.N, loc.Off
590 }
591
592 nameOff := v.Aux.(*AuxNameOffset)
593 return nameOff.Name, nameOff.Offset
594 }
595
596
597 func CanSSA(t *types.Type) bool {
598 types.CalcSize(t)
599 if t.Size() > int64(4*types.PtrSize) {
600
601
602
603 return false
604 }
605 switch t.Kind() {
606 case types.TARRAY:
607
608
609
610 if t.NumElem() <= 1 {
611 return CanSSA(t.Elem())
612 }
613 return false
614 case types.TSTRUCT:
615 if t.NumFields() > MaxStruct {
616 return false
617 }
618 for _, t1 := range t.Fields() {
619 if !CanSSA(t1.Type) {
620 return false
621 }
622 }
623 return true
624 default:
625 return true
626 }
627 }
628
View as plain text