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