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