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