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