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