1
2
3
4
5 package ssa
6
7 import (
8 "cmd/compile/internal/abi"
9 "cmd/compile/internal/base"
10 "cmd/compile/internal/ir"
11 "cmd/compile/internal/types"
12 "cmd/internal/obj"
13 "fmt"
14 rtabi "internal/abi"
15 "strings"
16 )
17
18
19
20
21
22
23
24 type Op int32
25
26 type opInfo struct {
27 name string
28 reg regInfo
29 auxType auxType
30 argLen int32
31 asm obj.As
32 generic bool
33 rematerializeable bool
34 commutative bool
35 resultInArg0 bool
36 resultNotInArgs bool
37 clobberFlags bool
38 needIntTemp bool
39 call bool
40 tailCall bool
41 nilCheck bool
42 faultOnNilArg0 bool
43 faultOnNilArg1 bool
44 usesScratch bool
45 hasSideEffects bool
46 zeroWidth bool
47 unsafePoint bool
48 fixedReg bool
49 symEffect SymEffect
50 scale uint8
51 }
52
53 type inputInfo struct {
54 idx int
55 regs regMask
56 }
57
58 type outputInfo struct {
59 idx int
60 regs regMask
61 }
62
63 type regInfo struct {
64
65
66
67
68
69 inputs []inputInfo
70
71
72 clobbers regMask
73
74 outputs []outputInfo
75 }
76
77 func (r *regInfo) String() string {
78 s := ""
79 s += "INS:\n"
80 for _, i := range r.inputs {
81 mask := fmt.Sprintf("%64b", i.regs)
82 mask = strings.ReplaceAll(mask, "0", ".")
83 s += fmt.Sprintf("%2d |%s|\n", i.idx, mask)
84 }
85 s += "OUTS:\n"
86 for _, i := range r.outputs {
87 mask := fmt.Sprintf("%64b", i.regs)
88 mask = strings.ReplaceAll(mask, "0", ".")
89 s += fmt.Sprintf("%2d |%s|\n", i.idx, mask)
90 }
91 s += "CLOBBERS:\n"
92 mask := fmt.Sprintf("%64b", r.clobbers)
93 mask = strings.ReplaceAll(mask, "0", ".")
94 s += fmt.Sprintf(" |%s|\n", mask)
95 return s
96 }
97
98 type auxType int8
99
100 type AuxNameOffset struct {
101 Name *ir.Name
102 Offset int64
103 }
104
105 func (a *AuxNameOffset) CanBeAnSSAAux() {}
106 func (a *AuxNameOffset) String() string {
107 return fmt.Sprintf("%s+%d", a.Name.Sym().Name, a.Offset)
108 }
109
110 func (a *AuxNameOffset) FrameOffset() int64 {
111 return a.Name.FrameOffset() + a.Offset
112 }
113
114 type AuxCall struct {
115 Fn *obj.LSym
116 reg *regInfo
117 abiInfo *abi.ABIParamResultInfo
118 }
119
120
121
122
123
124
125
126
127
128
129
130 func (a *AuxCall) Reg(i *regInfo, c *Config) *regInfo {
131 if a.reg.clobbers != 0 {
132
133 return a.reg
134 }
135 if a.abiInfo.InRegistersUsed()+a.abiInfo.OutRegistersUsed() == 0 {
136
137 a.reg = i
138 return a.reg
139 }
140
141 k := len(i.inputs)
142 for _, p := range a.abiInfo.InParams() {
143 for _, r := range p.Registers {
144 m := archRegForAbiReg(r, c)
145 a.reg.inputs = append(a.reg.inputs, inputInfo{idx: k, regs: (1 << m)})
146 k++
147 }
148 }
149 a.reg.inputs = append(a.reg.inputs, i.inputs...)
150 k = len(i.outputs)
151 for _, p := range a.abiInfo.OutParams() {
152 for _, r := range p.Registers {
153 m := archRegForAbiReg(r, c)
154 a.reg.outputs = append(a.reg.outputs, outputInfo{idx: k, regs: (1 << m)})
155 k++
156 }
157 }
158 a.reg.outputs = append(a.reg.outputs, i.outputs...)
159 a.reg.clobbers = i.clobbers
160 return a.reg
161 }
162 func (a *AuxCall) ABI() *abi.ABIConfig {
163 return a.abiInfo.Config()
164 }
165 func (a *AuxCall) ABIInfo() *abi.ABIParamResultInfo {
166 return a.abiInfo
167 }
168 func (a *AuxCall) ResultReg(c *Config) *regInfo {
169 if a.abiInfo.OutRegistersUsed() == 0 {
170 return a.reg
171 }
172 if len(a.reg.inputs) > 0 {
173 return a.reg
174 }
175 k := 0
176 for _, p := range a.abiInfo.OutParams() {
177 for _, r := range p.Registers {
178 m := archRegForAbiReg(r, c)
179 a.reg.inputs = append(a.reg.inputs, inputInfo{idx: k, regs: (1 << m)})
180 k++
181 }
182 }
183 return a.reg
184 }
185
186
187
188 func archRegForAbiReg(r abi.RegIndex, c *Config) uint8 {
189 var m int8
190 if int(r) < len(c.intParamRegs) {
191 m = c.intParamRegs[r]
192 } else {
193 m = c.floatParamRegs[int(r)-len(c.intParamRegs)]
194 }
195 return uint8(m)
196 }
197
198
199
200 func ObjRegForAbiReg(r abi.RegIndex, c *Config) int16 {
201 m := archRegForAbiReg(r, c)
202 return c.registers[m].objNum
203 }
204
205
206
207
208
209
210
211 func (a *AuxCall) ArgWidth() int64 {
212 return a.abiInfo.ArgWidth()
213 }
214
215
216 func (a *AuxCall) ParamAssignmentForResult(which int64) *abi.ABIParamAssignment {
217 return a.abiInfo.OutParam(int(which))
218 }
219
220
221 func (a *AuxCall) OffsetOfResult(which int64) int64 {
222 n := int64(a.abiInfo.OutParam(int(which)).Offset())
223 return n
224 }
225
226
227
228 func (a *AuxCall) OffsetOfArg(which int64) int64 {
229 n := int64(a.abiInfo.InParam(int(which)).Offset())
230 return n
231 }
232
233
234 func (a *AuxCall) RegsOfResult(which int64) []abi.RegIndex {
235 return a.abiInfo.OutParam(int(which)).Registers
236 }
237
238
239
240 func (a *AuxCall) RegsOfArg(which int64) []abi.RegIndex {
241 return a.abiInfo.InParam(int(which)).Registers
242 }
243
244
245 func (a *AuxCall) NameOfResult(which int64) *ir.Name {
246 return a.abiInfo.OutParam(int(which)).Name
247 }
248
249
250 func (a *AuxCall) TypeOfResult(which int64) *types.Type {
251 return a.abiInfo.OutParam(int(which)).Type
252 }
253
254
255
256 func (a *AuxCall) TypeOfArg(which int64) *types.Type {
257 return a.abiInfo.InParam(int(which)).Type
258 }
259
260
261 func (a *AuxCall) SizeOfResult(which int64) int64 {
262 return a.TypeOfResult(which).Size()
263 }
264
265
266
267 func (a *AuxCall) SizeOfArg(which int64) int64 {
268 return a.TypeOfArg(which).Size()
269 }
270
271
272 func (a *AuxCall) NResults() int64 {
273 return int64(len(a.abiInfo.OutParams()))
274 }
275
276
277
278 func (a *AuxCall) LateExpansionResultType() *types.Type {
279 var tys []*types.Type
280 for i := int64(0); i < a.NResults(); i++ {
281 tys = append(tys, a.TypeOfResult(i))
282 }
283 tys = append(tys, types.TypeMem)
284 return types.NewResults(tys)
285 }
286
287
288 func (a *AuxCall) NArgs() int64 {
289 return int64(len(a.abiInfo.InParams()))
290 }
291
292
293 func (a *AuxCall) String() string {
294 var fn string
295 if a.Fn == nil {
296 fn = "AuxCall{nil"
297 } else {
298 fn = fmt.Sprintf("AuxCall{%v", a.Fn)
299 }
300
301
302 return fn + "}"
303 }
304
305
306 func StaticAuxCall(sym *obj.LSym, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
307 if paramResultInfo == nil {
308 panic(fmt.Errorf("Nil paramResultInfo, sym=%v", sym))
309 }
310 var reg *regInfo
311 if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
312 reg = ®Info{}
313 }
314 return &AuxCall{Fn: sym, abiInfo: paramResultInfo, reg: reg}
315 }
316
317
318 func InterfaceAuxCall(paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
319 var reg *regInfo
320 if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
321 reg = ®Info{}
322 }
323 return &AuxCall{Fn: nil, abiInfo: paramResultInfo, reg: reg}
324 }
325
326
327 func ClosureAuxCall(paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
328 var reg *regInfo
329 if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
330 reg = ®Info{}
331 }
332 return &AuxCall{Fn: nil, abiInfo: paramResultInfo, reg: reg}
333 }
334
335 func (*AuxCall) CanBeAnSSAAux() {}
336
337
338 func OwnAuxCall(fn *obj.LSym, paramResultInfo *abi.ABIParamResultInfo) *AuxCall {
339
340 var reg *regInfo
341 if paramResultInfo.InRegistersUsed()+paramResultInfo.OutRegistersUsed() > 0 {
342 reg = ®Info{}
343 }
344 return &AuxCall{Fn: fn, abiInfo: paramResultInfo, reg: reg}
345 }
346
347 const (
348 auxNone auxType = iota
349 auxBool
350 auxInt8
351 auxInt16
352 auxInt32
353 auxInt64
354 auxInt128
355 auxUInt8
356 auxFloat32
357 auxFloat64
358 auxFlagConstant
359 auxCCop
360 auxNameOffsetInt8
361 auxString
362 auxSym
363 auxSymOff
364 auxSymValAndOff
365 auxTyp
366 auxTypSize
367 auxCall
368 auxCallOff
369
370 auxPanicBoundsC
371 auxPanicBoundsCC
372
373
374 auxARM64BitField
375 auxS390XRotateParams
376 auxS390XCCMask
377 auxS390XCCMaskInt8
378 auxS390XCCMaskUint8
379 )
380
381
382
383 type SymEffect int8
384
385 const (
386 SymRead SymEffect = 1 << iota
387 SymWrite
388 SymAddr
389
390 SymRdWr = SymRead | SymWrite
391
392 SymNone SymEffect = 0
393 )
394
395
396
397
398
399
400 type Sym interface {
401 Aux
402 CanBeAnSSASym()
403 }
404
405
406
407
408
409
410
411 type ValAndOff int64
412
413 func (x ValAndOff) Val() int32 { return int32(int64(x) >> 32) }
414 func (x ValAndOff) Val64() int64 { return int64(x) >> 32 }
415 func (x ValAndOff) Val16() int16 { return int16(int64(x) >> 32) }
416 func (x ValAndOff) Val8() int8 { return int8(int64(x) >> 32) }
417
418 func (x ValAndOff) Off64() int64 { return int64(int32(x)) }
419 func (x ValAndOff) Off() int32 { return int32(x) }
420
421 func (x ValAndOff) String() string {
422 return fmt.Sprintf("val=%d,off=%d", x.Val(), x.Off())
423 }
424
425
426
427 func validVal(val int64) bool {
428 return val == int64(int32(val))
429 }
430
431 func makeValAndOff(val, off int32) ValAndOff {
432 return ValAndOff(int64(val)<<32 + int64(uint32(off)))
433 }
434
435 func (x ValAndOff) canAdd32(off int32) bool {
436 newoff := x.Off64() + int64(off)
437 return newoff == int64(int32(newoff))
438 }
439 func (x ValAndOff) canAdd64(off int64) bool {
440 newoff := x.Off64() + off
441 return newoff == int64(int32(newoff))
442 }
443
444 func (x ValAndOff) addOffset32(off int32) ValAndOff {
445 if !x.canAdd32(off) {
446 panic("invalid ValAndOff.addOffset32")
447 }
448 return makeValAndOff(x.Val(), x.Off()+off)
449 }
450 func (x ValAndOff) addOffset64(off int64) ValAndOff {
451 if !x.canAdd64(off) {
452 panic("invalid ValAndOff.addOffset64")
453 }
454 return makeValAndOff(x.Val(), x.Off()+int32(off))
455 }
456
457
458
459 type int128 int64
460
461 type BoundsKind uint8
462
463 const (
464 BoundsIndex BoundsKind = iota
465 BoundsIndexU
466 BoundsSliceAlen
467 BoundsSliceAlenU
468 BoundsSliceAcap
469 BoundsSliceAcapU
470 BoundsSliceB
471 BoundsSliceBU
472 BoundsSlice3Alen
473 BoundsSlice3AlenU
474 BoundsSlice3Acap
475 BoundsSlice3AcapU
476 BoundsSlice3B
477 BoundsSlice3BU
478 BoundsSlice3C
479 BoundsSlice3CU
480 BoundsConvert
481 BoundsKindCount
482 )
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504 func boundsABI(b int64) int {
505 switch BoundsKind(b) {
506 case BoundsSlice3Alen,
507 BoundsSlice3AlenU,
508 BoundsSlice3Acap,
509 BoundsSlice3AcapU,
510 BoundsConvert:
511 return 0
512 case BoundsSliceAlen,
513 BoundsSliceAlenU,
514 BoundsSliceAcap,
515 BoundsSliceAcapU,
516 BoundsSlice3B,
517 BoundsSlice3BU:
518 return 1
519 case BoundsIndex,
520 BoundsIndexU,
521 BoundsSliceB,
522 BoundsSliceBU,
523 BoundsSlice3C,
524 BoundsSlice3CU:
525 return 2
526 default:
527 panic("bad BoundsKind")
528 }
529 }
530
531
532
533 func (b BoundsKind) Code() (rtabi.BoundsErrorCode, bool) {
534 switch b {
535 case BoundsIndex:
536 return rtabi.BoundsIndex, true
537 case BoundsIndexU:
538 return rtabi.BoundsIndex, false
539 case BoundsSliceAlen:
540 return rtabi.BoundsSliceAlen, true
541 case BoundsSliceAlenU:
542 return rtabi.BoundsSliceAlen, false
543 case BoundsSliceAcap:
544 return rtabi.BoundsSliceAcap, true
545 case BoundsSliceAcapU:
546 return rtabi.BoundsSliceAcap, false
547 case BoundsSliceB:
548 return rtabi.BoundsSliceB, true
549 case BoundsSliceBU:
550 return rtabi.BoundsSliceB, false
551 case BoundsSlice3Alen:
552 return rtabi.BoundsSlice3Alen, true
553 case BoundsSlice3AlenU:
554 return rtabi.BoundsSlice3Alen, false
555 case BoundsSlice3Acap:
556 return rtabi.BoundsSlice3Acap, true
557 case BoundsSlice3AcapU:
558 return rtabi.BoundsSlice3Acap, false
559 case BoundsSlice3B:
560 return rtabi.BoundsSlice3B, true
561 case BoundsSlice3BU:
562 return rtabi.BoundsSlice3B, false
563 case BoundsSlice3C:
564 return rtabi.BoundsSlice3C, true
565 case BoundsSlice3CU:
566 return rtabi.BoundsSlice3C, false
567 case BoundsConvert:
568 return rtabi.BoundsConvert, false
569 default:
570 base.Fatalf("bad bounds kind %d", b)
571 return 0, false
572 }
573 }
574
575
576
577
578
579 type arm64BitField int16
580
View as plain text