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 call bool
37 tailCall bool
38 nilCheck bool
39 faultOnNilArg0 bool
40 faultOnNilArg1 bool
41 usesScratch bool
42 hasSideEffects bool
43 zeroWidth bool
44 unsafePoint bool
45 symEffect SymEffect
46 scale uint8
47 }
48
49 type inputInfo struct {
50 idx int
51 regs regMask
52 }
53
54 type outputInfo struct {
55 idx int
56 regs regMask
57 }
58
59 type regInfo struct {
60
61
62
63
64
65 inputs []inputInfo
66
67
68 clobbers regMask
69
70 outputs []outputInfo
71 }
72
73 func (r *regInfo) String() string {
74 s := ""
75 s += "INS:\n"
76 for _, i := range r.inputs {
77 mask := fmt.Sprintf("%64b", i.regs)
78 mask = strings.Replace(mask, "0", ".", -1)
79 s += fmt.Sprintf("%2d |%s|\n", i.idx, mask)
80 }
81 s += "OUTS:\n"
82 for _, i := range r.outputs {
83 mask := fmt.Sprintf("%64b", i.regs)
84 mask = strings.Replace(mask, "0", ".", -1)
85 s += fmt.Sprintf("%2d |%s|\n", i.idx, mask)
86 }
87 s += "CLOBBERS:\n"
88 mask := fmt.Sprintf("%64b", r.clobbers)
89 mask = strings.Replace(mask, "0", ".", -1)
90 s += fmt.Sprintf(" |%s|\n", mask)
91 return s
92 }
93
94 type auxType int8
95
96 type AuxNameOffset struct {
97 Name *ir.Name
98 Offset int64
99 }
100
101 func (a *AuxNameOffset) CanBeAnSSAAux() {}
102 func (a *AuxNameOffset) String() string {
103 return fmt.Sprintf("%s+%d", a.Name.Sym().Name, a.Offset)
104 }
105
106 func (a *AuxNameOffset) FrameOffset() int64 {
107 return a.Name.FrameOffset() + a.Offset
108 }
109
110 type AuxCall struct {
111 Fn *obj.LSym
112 reg *regInfo
113 abiInfo *abi.ABIParamResultInfo
114 }
115
116
117
118
119
120
121
122
123
124
125
126 func (a *AuxCall) Reg(i *regInfo, c *Config) *regInfo {
127 if a.reg.clobbers != 0 {
128
129 return a.reg
130 }
131 if a.abiInfo.InRegistersUsed()+a.abiInfo.OutRegistersUsed() == 0 {
132
133 a.reg = i
134 return a.reg
135 }
136
137 k := len(i.inputs)
138 for _, p := range a.abiInfo.InParams() {
139 for _, r := range p.Registers {
140 m := archRegForAbiReg(r, c)
141 a.reg.inputs = append(a.reg.inputs, inputInfo{idx: k, regs: (1 << m)})
142 k++
143 }
144 }
145 a.reg.inputs = append(a.reg.inputs, i.inputs...)
146 k = len(i.outputs)
147 for _, p := range a.abiInfo.OutParams() {
148 for _, r := range p.Registers {
149 m := archRegForAbiReg(r, c)
150 a.reg.outputs = append(a.reg.outputs, outputInfo{idx: k, regs: (1 << m)})
151 k++
152 }
153 }
154 a.reg.outputs = append(a.reg.outputs, i.outputs...)
155 a.reg.clobbers = i.clobbers
156 return a.reg
157 }
158 func (a *AuxCall) ABI() *abi.ABIConfig {
159 return a.abiInfo.Config()
160 }
161 func (a *AuxCall) ABIInfo() *abi.ABIParamResultInfo {
162 return a.abiInfo
163 }
164 func (a *AuxCall) ResultReg(c *Config) *regInfo {
165 if a.abiInfo.OutRegistersUsed() == 0 {
166 return a.reg
167 }
168 if len(a.reg.inputs) > 0 {
169 return a.reg
170 }
171 k := 0
172 for _, p := range a.abiInfo.OutParams() {
173 for _, r := range p.Registers {
174 m := archRegForAbiReg(r, c)
175 a.reg.inputs = append(a.reg.inputs, inputInfo{idx: k, regs: (1 << m)})
176 k++
177 }
178 }
179 return a.reg
180 }
181
182
183
184 func archRegForAbiReg(r abi.RegIndex, c *Config) uint8 {
185 var m int8
186 if int(r) < len(c.intParamRegs) {
187 m = c.intParamRegs[r]
188 } else {
189 m = c.floatParamRegs[int(r)-len(c.intParamRegs)]
190 }
191 return uint8(m)
192 }
193
194
195
196 func ObjRegForAbiReg(r abi.RegIndex, c *Config) int16 {
197 m := archRegForAbiReg(r, c)
198 return c.registers[m].objNum
199 }
200
201
202
203
204
205
206
207 func (a *AuxCall) ArgWidth() int64 {
208 return a.abiInfo.ArgWidth()
209 }
210
211
212 func (a *AuxCall) ParamAssignmentForResult(which int64) *abi.ABIParamAssignment {
213 return a.abiInfo.OutParam(int(which))
214 }
215
216
217 func (a *AuxCall) OffsetOfResult(which int64) int64 {
218 n := int64(a.abiInfo.OutParam(int(which)).Offset())
219 return n
220 }
221
222
223
224 func (a *AuxCall) OffsetOfArg(which int64) int64 {
225 n := int64(a.abiInfo.InParam(int(which)).Offset())
226 return n
227 }
228
229
230 func (a *AuxCall) RegsOfResult(which int64) []abi.RegIndex {
231 return a.abiInfo.OutParam(int(which)).Registers
232 }
233
234
235
236 func (a *AuxCall) RegsOfArg(which int64) []abi.RegIndex {
237 return a.abiInfo.InParam(int(which)).Registers
238 }
239
240
241 func (a *AuxCall) NameOfResult(which int64) *ir.Name {
242 name := a.abiInfo.OutParam(int(which)).Name
243 if name == nil {
244 return nil
245 }
246 return name.(*ir.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 auxNameOffsetInt8
360 auxString
361 auxSym
362 auxSymOff
363 auxSymValAndOff
364 auxTyp
365 auxTypSize
366 auxCCop
367 auxCall
368 auxCallOff
369
370
371 auxARM64BitField
372 auxS390XRotateParams
373 auxS390XCCMask
374 auxS390XCCMaskInt8
375 auxS390XCCMaskUint8
376 )
377
378
379
380 type SymEffect int8
381
382 const (
383 SymRead SymEffect = 1 << iota
384 SymWrite
385 SymAddr
386
387 SymRdWr = SymRead | SymWrite
388
389 SymNone SymEffect = 0
390 )
391
392
393
394
395
396
397 type Sym interface {
398 CanBeAnSSASym()
399 CanBeAnSSAAux()
400 }
401
402
403
404
405
406
407
408 type ValAndOff int64
409
410 func (x ValAndOff) Val() int32 { return int32(int64(x) >> 32) }
411 func (x ValAndOff) Val64() int64 { return int64(x) >> 32 }
412 func (x ValAndOff) Val16() int16 { return int16(int64(x) >> 32) }
413 func (x ValAndOff) Val8() int8 { return int8(int64(x) >> 32) }
414
415 func (x ValAndOff) Off64() int64 { return int64(int32(x)) }
416 func (x ValAndOff) Off() int32 { return int32(x) }
417
418 func (x ValAndOff) String() string {
419 return fmt.Sprintf("val=%d,off=%d", x.Val(), x.Off())
420 }
421
422
423
424 func validVal(val int64) bool {
425 return val == int64(int32(val))
426 }
427
428 func makeValAndOff(val, off int32) ValAndOff {
429 return ValAndOff(int64(val)<<32 + int64(uint32(off)))
430 }
431
432 func (x ValAndOff) canAdd32(off int32) bool {
433 newoff := x.Off64() + int64(off)
434 return newoff == int64(int32(newoff))
435 }
436 func (x ValAndOff) canAdd64(off int64) bool {
437 newoff := x.Off64() + off
438 return newoff == int64(int32(newoff))
439 }
440
441 func (x ValAndOff) addOffset32(off int32) ValAndOff {
442 if !x.canAdd32(off) {
443 panic("invalid ValAndOff.addOffset32")
444 }
445 return makeValAndOff(x.Val(), x.Off()+off)
446 }
447 func (x ValAndOff) addOffset64(off int64) ValAndOff {
448 if !x.canAdd64(off) {
449 panic("invalid ValAndOff.addOffset64")
450 }
451 return makeValAndOff(x.Val(), x.Off()+int32(off))
452 }
453
454
455
456 type int128 int64
457
458 type BoundsKind uint8
459
460 const (
461 BoundsIndex BoundsKind = iota
462 BoundsIndexU
463 BoundsSliceAlen
464 BoundsSliceAlenU
465 BoundsSliceAcap
466 BoundsSliceAcapU
467 BoundsSliceB
468 BoundsSliceBU
469 BoundsSlice3Alen
470 BoundsSlice3AlenU
471 BoundsSlice3Acap
472 BoundsSlice3AcapU
473 BoundsSlice3B
474 BoundsSlice3BU
475 BoundsSlice3C
476 BoundsSlice3CU
477 BoundsConvert
478 BoundsKindCount
479 )
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500 func boundsABI(b int64) int {
501 switch BoundsKind(b) {
502 case BoundsSlice3Alen,
503 BoundsSlice3AlenU,
504 BoundsSlice3Acap,
505 BoundsSlice3AcapU,
506 BoundsConvert:
507 return 0
508 case BoundsSliceAlen,
509 BoundsSliceAlenU,
510 BoundsSliceAcap,
511 BoundsSliceAcapU,
512 BoundsSlice3B,
513 BoundsSlice3BU:
514 return 1
515 case BoundsIndex,
516 BoundsIndexU,
517 BoundsSliceB,
518 BoundsSliceBU,
519 BoundsSlice3C,
520 BoundsSlice3CU:
521 return 2
522 default:
523 panic("bad BoundsKind")
524 }
525 }
526
527
528
529
530
531 type arm64BitField int16
532
View as plain text