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