1
2
3
4
5 package midway
6
7 import (
8 "fmt"
9 "strings"
10
11 "cmd/compile/internal/base"
12 "cmd/compile/internal/syntax"
13 "cmd/compile/internal/types2"
14 )
15
16
17 type DeepCopier struct {
18 VecLen int
19 info *types2.Info
20 pkg *types2.Package
21 analyzer *Analyzer
22 suffix string
23
24 vars map[*types2.Var]*types2.Var
25 }
26
27 func NewDeepCopier(pkg *types2.Package, info *types2.Info, vecLen int, analyzer *Analyzer, suffix string) *DeepCopier {
28 return &DeepCopier{
29 VecLen: vecLen,
30 info: info,
31 pkg: pkg,
32 analyzer: analyzer,
33 suffix: suffix,
34 vars: make(map[*types2.Var]*types2.Var),
35 }
36 }
37
38 func (c *DeepCopier) registerDef(newName *syntax.Name, oldName *syntax.Name) {
39 if oldName == nil || newName == nil {
40 return
41 }
42 if oldObj := c.info.Defs[oldName]; oldObj != nil {
43 if val, isVar := oldObj.(*types2.Var); isVar {
44 newObj := types2.NewVar(newName.Pos(), c.pkg, newName.Value, val.Type())
45 c.vars[val] = newObj
46 c.info.Defs[newName] = newObj
47 } else {
48 c.info.Defs[newName] = oldObj
49 }
50 }
51 }
52
53 func (c *DeepCopier) mapUse(newName *syntax.Name, oldName *syntax.Name) {
54 if oldName == nil || newName == nil {
55 return
56 }
57 if oldObj := c.info.Uses[oldName]; oldObj != nil {
58 if val, isVar := oldObj.(*types2.Var); isVar && c.vars[val] != nil {
59 c.info.Uses[newName] = c.vars[val]
60 } else {
61 c.info.Uses[newName] = oldObj
62 }
63 }
64 }
65
66
67 func (c *DeepCopier) OnName(id *syntax.Name) *syntax.Name {
68 obj := c.info.Uses[id]
69 if obj == nil {
70 obj = c.info.Defs[id]
71 }
72 if obj == nil {
73 return nil
74 }
75
76 if c.analyzer.dependentObj[obj] || isBaseSimdTypeObj(obj) {
77 newId := syntax.NewName(id.Pos(), id.Value+c.suffix)
78
79 if base.Debug.Simd > 0 {
80 base.Warn("Rewriting name %s to %s", id.Value, newId.Value)
81 }
82 return newId
83 }
84 return nil
85 }
86
87
88
89 func (c *DeepCopier) OnNameExpr(id *syntax.Name) syntax.Expr {
90 obj := c.info.Uses[id]
91 if obj == nil {
92 obj = c.info.Defs[id]
93 }
94 if obj == nil {
95 return nil
96 }
97
98 if isBaseSimdTypeObj(obj) {
99
100
101
102 name := id.Value
103 width := nameToElemBitWidth(name)
104 if width > 0 {
105 archsimdId := syntax.NewName(id.Pos(), archPkg)
106 if c.VecLen == 0 {
107
108 newSel := &syntax.SelectorExpr{
109 X: archsimdId,
110 Sel: id,
111 }
112 newSel.SetPos(id.Pos())
113 return newSel
114 }
115
116 count := c.VecLen / width
117 base := name[:len(name)-1]
118 newName := fmt.Sprintf("%sx%d", base, count)
119 newSelId := syntax.NewName(id.Pos(), newName)
120 newSel := &syntax.SelectorExpr{
121 X: archsimdId,
122 Sel: newSelId,
123 }
124 newSel.SetPos(id.Pos())
125 return newSel
126 }
127 }
128
129 if c.analyzer.dependentObj[obj] {
130 newId := syntax.NewName(id.Pos(), id.Value+c.suffix)
131
132 if base.Debug.Simd > 0 {
133 base.Warn("Rewriting name %s to %s", id.Value, newId.Value)
134 }
135 return newId
136 }
137 return nil
138 }
139
140
141
142
143 func (c *DeepCopier) OnSelector(se *syntax.SelectorExpr) syntax.Expr {
144 if x, ok := se.X.(*syntax.Name); ok {
145 obj := c.info.Uses[x]
146 if pkgName, isPkg := obj.(*types2.PkgName); isPkg && pkgName.Imported().Path() == simdPkg {
147
148
149
150 prefix := ""
151 nameSuffix := ""
152 name := se.Sel.Value
153 end := len(name)
154 if strings.HasPrefix(name, "Load") {
155 prefix = "Load"
156 if strings.HasSuffix(name, "Part") {
157 end = strings.Index(name, "Part")
158 nameSuffix = "Part"
159 }
160 name = name[len("Load"):end]
161 }
162 if strings.HasPrefix(name, "Broadcast") {
163 prefix = "Broadcast"
164 name = name[len("Broadcast"):end]
165 }
166
167 width := nameToElemBitWidth(name)
168 if width > 0 {
169 archsimdId := syntax.NewName(se.Pos(), archPkg)
170 if c.VecLen == 0 {
171
172 newSel := &syntax.SelectorExpr{
173 X: archsimdId,
174 Sel: se.Sel,
175 }
176 newSel.SetPos(se.Pos())
177 return newSel
178 }
179
180 count := c.VecLen / width
181 base := name[:len(name)-1]
182 newName := fmt.Sprintf("%sx%d", base, count)
183 newName = prefix + newName + nameSuffix
184
185 newSelId := syntax.NewName(se.Sel.Pos(), newName)
186
187 newSel := &syntax.SelectorExpr{
188 X: archsimdId,
189 Sel: newSelId,
190 }
191 newSel.SetPos(se.Pos())
192 return newSel
193 }
194 }
195 }
196 return nil
197 }
198
199 func (c *DeepCopier) CopyDecl(d syntax.Decl) syntax.Decl {
200 if d == nil {
201 return nil
202 }
203 switch d := d.(type) {
204 case *syntax.FuncDecl:
205 return c.CopyFuncDecl(d)
206 case *syntax.VarDecl:
207 return c.CopyVarDecl(d)
208 case *syntax.TypeDecl:
209 return c.CopyTypeDecl(d)
210 case *syntax.ConstDecl:
211 return c.CopyConstDecl(d)
212 case *syntax.ImportDecl:
213 newD := &syntax.ImportDecl{
214 Group: d.Group,
215 Pragma: d.Pragma,
216 LocalPkgName: c.CopyName(d.LocalPkgName, false),
217 Path: c.CopyExpr(d.Path).(*syntax.BasicLit),
218 }
219 newD.SetPos(d.Pos())
220 return newD
221 default:
222 return d
223 }
224 }
225
226 func (c *DeepCopier) CopyVarDecl(d *syntax.VarDecl) *syntax.VarDecl {
227 newD := &syntax.VarDecl{
228 Group: d.Group,
229 Pragma: d.Pragma,
230 Type: c.CopyExpr(d.Type),
231 Values: c.CopyExpr(d.Values),
232 }
233 newD.SetPos(d.Pos())
234 for _, n := range d.NameList {
235 newN := c.CopyName(n, true)
236 newD.NameList = append(newD.NameList, newN)
237 }
238 return newD
239 }
240
241 func (c *DeepCopier) CopyTypeDecl(d *syntax.TypeDecl) *syntax.TypeDecl {
242 newD := &syntax.TypeDecl{
243 Group: d.Group,
244 Pragma: d.Pragma,
245 Name: c.CopyName(d.Name, true),
246 TParamList: c.CopyFieldList(d.TParamList),
247 Alias: d.Alias,
248 Type: c.CopyExpr(d.Type),
249 }
250 newD.SetPos(d.Pos())
251 return newD
252 }
253
254 func (c *DeepCopier) CopyConstDecl(d *syntax.ConstDecl) *syntax.ConstDecl {
255 newD := &syntax.ConstDecl{
256 Group: d.Group,
257 Pragma: d.Pragma,
258 Type: c.CopyExpr(d.Type),
259 Values: c.CopyExpr(d.Values),
260 }
261 newD.SetPos(d.Pos())
262 for _, n := range d.NameList {
263 newD.NameList = append(newD.NameList, c.CopyName(n, true))
264 }
265 return newD
266 }
267
268 func (c *DeepCopier) CopyFuncDecl(d *syntax.FuncDecl) *syntax.FuncDecl {
269 newD := &syntax.FuncDecl{
270 Pragma: d.Pragma,
271 Recv: c.CopyField(d.Recv),
272 Name: c.CopyName(d.Name, true),
273 TParamList: c.CopyFieldList(d.TParamList),
274 Type: c.CopyExpr(d.Type).(*syntax.FuncType),
275 }
276 newD.SetPos(d.Pos())
277
278
279 if oldFuncObj, ok := c.info.Defs[d.Name].(*types2.Func); ok {
280 newFuncObj := types2.NewFunc(newD.Name.Pos(), c.pkg, newD.Name.Value, oldFuncObj.Type().(*types2.Signature))
281 c.info.Defs[newD.Name] = newFuncObj
282 }
283
284 newD.Body = c.CopyBlockStmt(d.Body)
285 return newD
286 }
287
288 func (c *DeepCopier) CopyName(id *syntax.Name, isDef bool) *syntax.Name {
289 if id == nil {
290 return nil
291 }
292 if match := c.OnName(id); match != nil {
293 match.SetPos(id.Pos())
294 if isDef {
295 c.registerDef(match, id)
296 } else {
297 c.mapUse(match, id)
298 }
299 return match
300 }
301 newId := syntax.NewName(id.Pos(), id.Value)
302 if isDef {
303 c.registerDef(newId, id)
304 } else {
305 c.mapUse(newId, id)
306 }
307 return newId
308 }
309
310 func (c *DeepCopier) CopyNameExpr(id *syntax.Name) syntax.Expr {
311 if !c.analyzer.inSimd {
312 return c.CopyName(id, false)
313 }
314 if id == nil {
315 return nil
316 }
317
318 if match := c.OnNameExpr(id); match != nil {
319 match.SetPos(id.Pos())
320 if n, ok := match.(*syntax.Name); ok {
321 c.mapUse(n, id)
322 }
323 return match
324 }
325
326 newId := syntax.NewName(id.Pos(), id.Value)
327 c.mapUse(newId, id)
328 return newId
329 }
330
331 func (c *DeepCopier) CopyExpr(e syntax.Expr) syntax.Expr {
332 if e == nil {
333 return nil
334 }
335 var newE syntax.Expr
336 switch e := e.(type) {
337 case *syntax.Name:
338 return c.CopyNameExpr(e)
339 case *syntax.BasicLit:
340 newLit := &syntax.BasicLit{Value: e.Value, Kind: e.Kind, Bad: e.Bad}
341 newE = newLit
342 case *syntax.CompositeLit:
343 newLit := &syntax.CompositeLit{
344 Type: c.CopyExpr(e.Type),
345 NKeys: e.NKeys,
346 Rbrace: e.Rbrace,
347 }
348 for _, el := range e.ElemList {
349 newLit.ElemList = append(newLit.ElemList, c.CopyExpr(el))
350 }
351 newE = newLit
352 case *syntax.KeyValueExpr:
353 newE = &syntax.KeyValueExpr{Key: c.CopyExpr(e.Key), Value: c.CopyExpr(e.Value)}
354 case *syntax.FuncLit:
355 newE = &syntax.FuncLit{Type: c.CopyExpr(e.Type).(*syntax.FuncType), Body: c.CopyBlockStmt(e.Body)}
356 case *syntax.ParenExpr:
357 newE = &syntax.ParenExpr{X: c.CopyExpr(e.X)}
358 case *syntax.SelectorExpr:
359 if sub := c.OnSelector(e); sub != nil {
360 sub.SetPos(e.Pos())
361 if sel := c.info.Selections[e]; sel != nil {
362 c.info.Selections[sub.(*syntax.SelectorExpr)] = sel
363 }
364 return sub
365 }
366 newSel := &syntax.SelectorExpr{X: c.CopyExpr(e.X), Sel: c.CopyName(e.Sel, false)}
367 if sel := c.info.Selections[e]; sel != nil {
368 c.info.Selections[newSel] = sel
369 }
370 newE = newSel
371 case *syntax.IndexExpr:
372 newE = &syntax.IndexExpr{X: c.CopyExpr(e.X), Index: c.CopyExpr(e.Index)}
373 case *syntax.SliceExpr:
374 newE = &syntax.SliceExpr{
375 X: c.CopyExpr(e.X),
376 Index: [3]syntax.Expr{c.CopyExpr(e.Index[0]), c.CopyExpr(e.Index[1]), c.CopyExpr(e.Index[2])},
377 Full: e.Full,
378 }
379 case *syntax.AssertExpr:
380 newE = &syntax.AssertExpr{X: c.CopyExpr(e.X), Type: c.CopyExpr(e.Type)}
381 case *syntax.TypeSwitchGuard:
382 newE = &syntax.TypeSwitchGuard{Lhs: c.CopyName(e.Lhs, true), X: c.CopyExpr(e.X)}
383 case *syntax.Operation:
384 newE = &syntax.Operation{Op: e.Op, X: c.CopyExpr(e.X), Y: c.CopyExpr(e.Y)}
385 case *syntax.CallExpr:
386 newCall := &syntax.CallExpr{
387 Fun: c.CopyExpr(e.Fun),
388 HasDots: e.HasDots,
389 }
390 for _, a := range e.ArgList {
391 newCall.ArgList = append(newCall.ArgList, c.CopyExpr(a))
392 }
393 newE = newCall
394 case *syntax.ListExpr:
395 newList := &syntax.ListExpr{}
396 for _, el := range e.ElemList {
397 newList.ElemList = append(newList.ElemList, c.CopyExpr(el))
398 }
399 newE = newList
400 case *syntax.ArrayType:
401 newE = &syntax.ArrayType{Len: c.CopyExpr(e.Len), Elem: c.CopyExpr(e.Elem)}
402 case *syntax.SliceType:
403 newE = &syntax.SliceType{Elem: c.CopyExpr(e.Elem)}
404 case *syntax.DotsType:
405 newE = &syntax.DotsType{Elem: c.CopyExpr(e.Elem)}
406 case *syntax.StructType:
407 newE = &syntax.StructType{
408 FieldList: c.CopyFieldList(e.FieldList),
409 TagList: e.TagList,
410 }
411 case *syntax.InterfaceType:
412 newE = &syntax.InterfaceType{MethodList: c.CopyFieldList(e.MethodList)}
413 case *syntax.FuncType:
414 newE = &syntax.FuncType{
415 ParamList: c.CopyFieldList(e.ParamList),
416 ResultList: c.CopyFieldList(e.ResultList),
417 }
418 case *syntax.MapType:
419 newE = &syntax.MapType{Key: c.CopyExpr(e.Key), Value: c.CopyExpr(e.Value)}
420 case *syntax.ChanType:
421 newE = &syntax.ChanType{Dir: e.Dir, Elem: c.CopyExpr(e.Elem)}
422 case *syntax.BadExpr:
423 newE = &syntax.BadExpr{}
424 default:
425 newE = e
426 }
427 newE.SetPos(e.Pos())
428 return newE
429 }
430
431 func (c *DeepCopier) CopyStmt(s syntax.Stmt) syntax.Stmt {
432 if s == nil {
433 return nil
434 }
435 var newS syntax.Stmt
436 switch s := s.(type) {
437 case *syntax.DeclStmt:
438 newDeclList := make([]syntax.Decl, len(s.DeclList))
439 for i, v := range s.DeclList {
440 newDeclList[i] = c.CopyDecl(v)
441 }
442 newS = &syntax.DeclStmt{DeclList: newDeclList}
443 case *syntax.ExprStmt:
444 newS = &syntax.ExprStmt{X: c.CopyExpr(s.X)}
445 case *syntax.SendStmt:
446 newS = &syntax.SendStmt{Chan: c.CopyExpr(s.Chan), Value: c.CopyExpr(s.Value)}
447 case *syntax.AssignStmt:
448 newS = &syntax.AssignStmt{Op: s.Op, Lhs: c.CopyExpr(s.Lhs), Rhs: c.CopyExpr(s.Rhs)}
449 case *syntax.ReturnStmt:
450 newS = &syntax.ReturnStmt{Results: c.CopyExpr(s.Results)}
451 case *syntax.BranchStmt:
452
453 newS = &syntax.BranchStmt{Tok: s.Tok, Label: c.CopyName(s.Label, false), Target: nil}
454 case *syntax.CallStmt:
455 newS = &syntax.CallStmt{Tok: s.Tok, Call: c.CopyExpr(s.Call), DeferAt: c.CopyExpr(s.DeferAt)}
456 case *syntax.IfStmt:
457 newS = &syntax.IfStmt{
458 Init: c.CopySimpleStmt(s.Init),
459 Cond: c.CopyExpr(s.Cond),
460 Then: c.CopyBlockStmt(s.Then),
461 Else: c.CopyStmt(s.Else),
462 }
463 case *syntax.ForStmt:
464 newS = &syntax.ForStmt{
465 Init: c.CopySimpleStmt(s.Init),
466 Cond: c.CopyExpr(s.Cond),
467 Post: c.CopySimpleStmt(s.Post),
468 Body: c.CopyBlockStmt(s.Body),
469 }
470 case *syntax.SwitchStmt:
471 newS = &syntax.SwitchStmt{
472 Init: c.CopySimpleStmt(s.Init),
473 Tag: c.CopyExpr(s.Tag),
474 Body: c.CopyCaseClauses(s.Body),
475 Rbrace: s.Rbrace,
476 }
477 case *syntax.SelectStmt:
478 newS = &syntax.SelectStmt{
479 Body: c.CopyCommClauses(s.Body),
480 Rbrace: s.Rbrace,
481 }
482 case *syntax.EmptyStmt:
483 newS = &syntax.EmptyStmt{}
484 case *syntax.LabeledStmt:
485 newS = &syntax.LabeledStmt{Label: c.CopyName(s.Label, true), Stmt: c.CopyStmt(s.Stmt)}
486 case *syntax.BlockStmt:
487 return c.CopyBlockStmt(s)
488 default:
489 newS = s
490 }
491 newS.SetPos(s.Pos())
492 return newS
493 }
494
495 func (c *DeepCopier) CopySimpleStmt(s syntax.SimpleStmt) syntax.SimpleStmt {
496 if s == nil {
497 return nil
498 }
499 switch s := s.(type) {
500 case *syntax.RangeClause:
501 newS := &syntax.RangeClause{
502 Def: s.Def,
503 X: c.CopyExpr(s.X),
504 }
505
506 if list, ok := s.Lhs.(*syntax.ListExpr); ok && s.Def {
507 newList := &syntax.ListExpr{}
508 for _, el := range list.ElemList {
509 if id, ok := el.(*syntax.Name); ok {
510 newList.ElemList = append(newList.ElemList, c.CopyName(id, true))
511 } else {
512 newList.ElemList = append(newList.ElemList, c.CopyExpr(el))
513 }
514 }
515 newS.Lhs = newList
516 } else if id, ok := s.Lhs.(*syntax.Name); ok && s.Def {
517 newS.Lhs = c.CopyName(id, true)
518 } else {
519 newS.Lhs = c.CopyExpr(s.Lhs)
520 }
521 newS.Lhs.SetPos(s.Lhs.Pos())
522 newS.SetPos(s.Pos())
523 return newS
524 case *syntax.AssignStmt:
525
526 isDef := false
527 if list, ok := s.Lhs.(*syntax.ListExpr); ok {
528 for _, el := range list.ElemList {
529 if id, ok := el.(*syntax.Name); ok && c.info.Defs[id] != nil {
530 isDef = true
531 break
532 }
533 }
534 } else if id, ok := s.Lhs.(*syntax.Name); ok && c.info.Defs[id] != nil {
535 isDef = true
536 }
537
538 newS := &syntax.AssignStmt{Op: s.Op, Rhs: c.CopyExpr(s.Rhs)}
539 if isDef {
540 if list, ok := s.Lhs.(*syntax.ListExpr); ok {
541 newList := &syntax.ListExpr{}
542 for _, el := range list.ElemList {
543 if id, ok := el.(*syntax.Name); ok && c.info.Defs[id] != nil {
544 newList.ElemList = append(newList.ElemList, c.CopyName(id, true))
545 } else {
546 newList.ElemList = append(newList.ElemList, c.CopyExpr(el))
547 }
548 }
549 newS.Lhs = newList
550 } else if id, ok := s.Lhs.(*syntax.Name); ok {
551 newS.Lhs = c.CopyName(id, true)
552 }
553 } else {
554 newS.Lhs = c.CopyExpr(s.Lhs)
555 }
556 newS.Lhs.SetPos(s.Lhs.Pos())
557 newS.SetPos(s.Pos())
558 return newS
559 default:
560 return c.CopyStmt(s).(syntax.SimpleStmt)
561 }
562 }
563
564 func (c *DeepCopier) CopyCaseClauses(list []*syntax.CaseClause) []*syntax.CaseClause {
565 var newList []*syntax.CaseClause
566 for _, cc := range list {
567 newC := &syntax.CaseClause{Cases: c.CopyExpr(cc.Cases), Colon: cc.Colon}
568 for _, b := range cc.Body {
569 newC.Body = append(newC.Body, c.CopyStmt(b))
570 }
571 newC.SetPos(cc.Pos())
572 newList = append(newList, newC)
573 }
574 return newList
575 }
576
577 func (c *DeepCopier) CopyCommClauses(list []*syntax.CommClause) []*syntax.CommClause {
578 var newList []*syntax.CommClause
579 for _, cc := range list {
580 newC := &syntax.CommClause{Comm: c.CopySimpleStmt(cc.Comm), Colon: cc.Colon}
581 for _, b := range cc.Body {
582 newC.Body = append(newC.Body, c.CopyStmt(b))
583 }
584 newC.SetPos(cc.Pos())
585 newList = append(newList, newC)
586 }
587 return newList
588 }
589
590 func (c *DeepCopier) CopyBlockStmt(b *syntax.BlockStmt) *syntax.BlockStmt {
591 if b == nil {
592 return nil
593 }
594 newB := &syntax.BlockStmt{Rbrace: b.Rbrace}
595 for _, s := range b.List {
596 newB.List = append(newB.List, c.CopyStmt(s))
597 }
598 newB.SetPos(b.Pos())
599 return newB
600 }
601
602 func (c *DeepCopier) CopyFieldList(f []*syntax.Field) []*syntax.Field {
603 if f == nil {
604 return nil
605 }
606 var newF []*syntax.Field
607 for _, field := range f {
608 newF = append(newF, c.CopyField(field))
609 }
610 return newF
611 }
612
613 func (c *DeepCopier) CopyField(f *syntax.Field) *syntax.Field {
614 if f == nil {
615 return nil
616 }
617 newF := &syntax.Field{
618 Name: c.CopyName(f.Name, true),
619 Type: c.CopyExpr(f.Type),
620 }
621 newF.SetPos(f.Pos())
622 return newF
623 }
624
View as plain text