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