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