1
2
3
4
5
6
7
8 package noder
9
10 import (
11 "bytes"
12 "cmd/compile/internal/base"
13 "cmd/compile/internal/ir"
14 "cmd/compile/internal/typecheck"
15 "cmd/compile/internal/types"
16 "cmd/internal/src"
17 "fmt"
18 "strings"
19 )
20
21
22
23 func assert(p bool) {
24 if !p {
25 panic("assertion failed")
26 }
27 }
28
29
30
31
32
33
34 func (g *irgen) stencil() {
35 g.target.Stencils = make(map[*types.Sym]*ir.Func)
36
37
38 g.instantiateMethods()
39
40
41
42
43 for i := 0; i < len(g.target.Decls); i++ {
44 decl := g.target.Decls[i]
45
46
47
48
49 switch decl.Op() {
50 case ir.ODCLFUNC:
51 if decl.Type().HasTParam() {
52
53 continue
54 }
55
56 ir.CurFunc = decl.(*ir.Func)
57
58 case ir.OAS, ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV, ir.OASOP:
59
60
61
62
63 default:
64
65
66
67 continue
68 }
69
70
71
72
73
74 modified := false
75 foundFuncInst := false
76 ir.Visit(decl, func(n ir.Node) {
77 if n.Op() == ir.OFUNCINST {
78
79
80 foundFuncInst = true
81 }
82 if n.Op() != ir.OCALL || n.(*ir.CallExpr).X.Op() != ir.OFUNCINST {
83 return
84 }
85
86
87 call := n.(*ir.CallExpr)
88 inst := call.X.(*ir.InstExpr)
89 st := g.getInstantiationForNode(inst)
90
91
92 call.X = st.Nname
93 if inst.X.Op() == ir.OCALLPART {
94
95
96
97
98 withRecv := make([]ir.Node, len(call.Args)+1)
99 dot := inst.X.(*ir.SelectorExpr)
100 withRecv[0] = dot.X
101 copy(withRecv[1:], call.Args)
102 call.Args = withRecv
103 }
104
105
106 transformCall(call)
107 modified = true
108 })
109
110
111
112
113
114
115
116
117 if foundFuncInst {
118 var edit func(ir.Node) ir.Node
119 edit = func(x ir.Node) ir.Node {
120 if x.Op() == ir.OFUNCINST {
121 st := g.getInstantiationForNode(x.(*ir.InstExpr))
122 return st.Nname
123 }
124 ir.EditChildren(x, edit)
125 return x
126 }
127 edit(decl)
128 }
129 if base.Flag.W > 1 && modified {
130 ir.Dump(fmt.Sprintf("\nmodified %v", decl), decl)
131 }
132 ir.CurFunc = nil
133
134
135
136
137 g.instantiateMethods()
138 }
139
140 }
141
142
143
144 func (g *irgen) instantiateMethods() {
145 for i := 0; i < len(g.instTypeList); i++ {
146 typ := g.instTypeList[i]
147
148
149 baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym()))
150 baseType := baseSym.Def.(*ir.Name).Type()
151 for j, m := range typ.Methods().Slice() {
152 name := m.Nname.(*ir.Name)
153 targs := make([]ir.Node, len(typ.RParams()))
154 for k, targ := range typ.RParams() {
155 targs[k] = ir.TypeNode(targ)
156 }
157 baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
158 name.Func = g.getInstantiation(baseNname, targs, true)
159 }
160 }
161 g.instTypeList = nil
162
163 }
164
165
166
167
168 func genericTypeName(sym *types.Sym) string {
169 return sym.Name[0:strings.Index(sym.Name, "[")]
170 }
171
172
173
174 func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) *ir.Func {
175 if meth, ok := inst.X.(*ir.SelectorExpr); ok {
176 return g.getInstantiation(meth.Selection.Nname.(*ir.Name), inst.Targs, true)
177 } else {
178 return g.getInstantiation(inst.X.(*ir.Name), inst.Targs, false)
179 }
180 }
181
182
183
184
185 func (g *irgen) getInstantiation(nameNode *ir.Name, targs []ir.Node, isMeth bool) *ir.Func {
186 sym := makeInstName(nameNode.Sym(), targs, isMeth)
187 st := g.target.Stencils[sym]
188 if st == nil {
189
190
191 st = g.genericSubst(sym, nameNode, targs, isMeth)
192 g.target.Stencils[sym] = st
193 g.target.Decls = append(g.target.Decls, st)
194 if base.Flag.W > 1 {
195 ir.Dump(fmt.Sprintf("\nstenciled %v", st), st)
196 }
197 }
198 return st
199 }
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 func makeInstName(fnsym *types.Sym, targs []ir.Node, hasBrackets bool) *types.Sym {
215 b := bytes.NewBufferString("")
216 name := fnsym.Name
217 i := strings.Index(name, "[")
218 assert(hasBrackets == (i >= 0))
219 if i >= 0 {
220 b.WriteString(name[0:i])
221 } else {
222 b.WriteString(name)
223 }
224 b.WriteString("[")
225 for i, targ := range targs {
226 if i > 0 {
227 b.WriteString(",")
228 }
229 b.WriteString(targ.Type().String())
230 }
231 b.WriteString("]")
232 if i >= 0 {
233 i2 := strings.Index(name[i:], "]")
234 assert(i2 >= 0)
235 b.WriteString(name[i+i2+1:])
236 }
237 return typecheck.Lookup(b.String())
238 }
239
240
241
242 type subster struct {
243 g *irgen
244 isMethod bool
245 newf *ir.Func
246 tparams []*types.Field
247 targs []ir.Node
248
249
250 vars map[*ir.Name]*ir.Name
251 }
252
253
254
255
256
257
258
259 func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []ir.Node, isMethod bool) *ir.Func {
260 var tparams []*types.Field
261 if isMethod {
262
263
264 recvType := nameNode.Type().Recv().Type
265 recvType = deref(recvType)
266 tparams = make([]*types.Field, len(recvType.RParams()))
267 for i, rparam := range recvType.RParams() {
268 tparams[i] = types.NewField(src.NoXPos, nil, rparam)
269 }
270 } else {
271 tparams = nameNode.Type().TParams().Fields().Slice()
272 }
273 gf := nameNode.Func
274
275 newf := ir.NewFunc(gf.Pos())
276 newf.Pragma = gf.Pragma
277 newf.Nname = ir.NewNameAt(gf.Pos(), newsym)
278 newf.Nname.Func = newf
279 newf.Nname.Defn = newf
280 newsym.Def = newf.Nname
281 savef := ir.CurFunc
282
283
284 ir.CurFunc = newf
285
286 assert(len(tparams) == len(targs))
287
288 subst := &subster{
289 g: g,
290 isMethod: isMethod,
291 newf: newf,
292 tparams: tparams,
293 targs: targs,
294 vars: make(map[*ir.Name]*ir.Name),
295 }
296
297 newf.Dcl = make([]*ir.Name, len(gf.Dcl))
298 for i, n := range gf.Dcl {
299 newf.Dcl[i] = subst.node(n).(*ir.Name)
300 }
301
302
303
304
305 oldt := nameNode.Type()
306
307
308 newt := types.NewSignature(oldt.Pkg(), nil, nil,
309 subst.fields(ir.PPARAM, append(oldt.Recvs().FieldSlice(), oldt.Params().FieldSlice()...), newf.Dcl),
310 subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl))
311
312 newf.Nname.SetType(newt)
313 ir.MarkFunc(newf.Nname)
314 newf.SetTypecheck(1)
315 newf.Nname.SetTypecheck(1)
316
317
318 newf.Body = subst.list(gf.Body)
319 ir.CurFunc = savef
320
321 return newf
322 }
323
324
325
326
327 func (subst *subster) node(n ir.Node) ir.Node {
328
329 var edit func(ir.Node) ir.Node
330 edit = func(x ir.Node) ir.Node {
331 switch x.Op() {
332 case ir.OTYPE:
333 return ir.TypeNode(subst.typ(x.Type()))
334
335 case ir.ONAME:
336 name := x.(*ir.Name)
337 if v := subst.vars[name]; v != nil {
338 return v
339 }
340 m := ir.NewNameAt(name.Pos(), name.Sym())
341 if name.IsClosureVar() {
342 m.SetIsClosureVar(true)
343 }
344 t := x.Type()
345 if t == nil {
346 assert(name.BuiltinOp != 0)
347 } else {
348 newt := subst.typ(t)
349 m.SetType(newt)
350 }
351 m.BuiltinOp = name.BuiltinOp
352 m.Curfn = subst.newf
353 m.Class = name.Class
354 m.Func = name.Func
355 subst.vars[name] = m
356 m.SetTypecheck(1)
357 return m
358 case ir.OLITERAL, ir.ONIL:
359 if x.Sym() != nil {
360 return x
361 }
362 }
363 m := ir.Copy(x)
364 if _, isExpr := m.(ir.Expr); isExpr {
365 t := x.Type()
366 if t == nil {
367
368
369
370 _, isCallExpr := m.(*ir.CallExpr)
371 _, isStructKeyExpr := m.(*ir.StructKeyExpr)
372 if !isCallExpr && !isStructKeyExpr && x.Op() != ir.OPANIC &&
373 x.Op() != ir.OCLOSE {
374 base.Fatalf(fmt.Sprintf("Nil type for %v", x))
375 }
376 } else if x.Op() != ir.OCLOSURE {
377 m.SetType(subst.typ(x.Type()))
378 }
379 }
380 ir.EditChildren(m, edit)
381
382 if x.Typecheck() == 3 {
383
384
385 m.SetTypecheck(1)
386 if typecheck.IsCmp(x.Op()) {
387 transformCompare(m.(*ir.BinaryExpr))
388 } else {
389 switch x.Op() {
390 case ir.OSLICE, ir.OSLICE3:
391 transformSlice(m.(*ir.SliceExpr))
392
393 case ir.OADD:
394 m = transformAdd(m.(*ir.BinaryExpr))
395
396 case ir.OINDEX:
397 transformIndex(m.(*ir.IndexExpr))
398
399 case ir.OAS2:
400 as2 := m.(*ir.AssignListStmt)
401 transformAssign(as2, as2.Lhs, as2.Rhs)
402
403 case ir.OAS:
404 as := m.(*ir.AssignStmt)
405 lhs, rhs := []ir.Node{as.X}, []ir.Node{as.Y}
406 transformAssign(as, lhs, rhs)
407
408 case ir.OASOP:
409 as := m.(*ir.AssignOpStmt)
410 transformCheckAssign(as, as.X)
411
412 case ir.ORETURN:
413 transformReturn(m.(*ir.ReturnStmt))
414
415 case ir.OSEND:
416 transformSend(m.(*ir.SendStmt))
417
418 default:
419 base.Fatalf("Unexpected node with Typecheck() == 3")
420 }
421 }
422 }
423
424 switch x.Op() {
425 case ir.OLITERAL:
426 t := m.Type()
427 if t != x.Type() {
428
429
430
431
432
433
434
435
436
437 m.SetType(types.UntypedInt)
438 m = typecheck.DefaultLit(m, t)
439 }
440
441 case ir.OXDOT:
442
443
444
445
446
447
448
449
450
451
452 transformDot(m.(*ir.SelectorExpr), false)
453 m.SetTypecheck(1)
454
455 case ir.OCALL:
456 call := m.(*ir.CallExpr)
457 switch call.X.Op() {
458 case ir.OTYPE:
459
460
461 m = transformConvCall(m.(*ir.CallExpr))
462
463 case ir.OCALLPART:
464
465
466
467 call.X.(*ir.SelectorExpr).SetOp(ir.OXDOT)
468 transformDot(call.X.(*ir.SelectorExpr), true)
469 transformCall(call)
470
471 case ir.ODOT, ir.ODOTPTR:
472
473
474
475
476 transformCall(call)
477
478 case ir.ONAME:
479 name := call.X.Name()
480 if name.BuiltinOp != ir.OXXX {
481 switch name.BuiltinOp {
482 case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OLEN, ir.OCAP, ir.OAPPEND:
483
484
485 m = transformBuiltin(call)
486 default:
487 base.FatalfAt(call.Pos(), "Unexpected builtin op")
488 }
489 } else {
490
491
492
493 transformCall(call)
494 }
495
496 case ir.OCLOSURE:
497 transformCall(call)
498
499 case ir.OFUNCINST:
500
501
502
503
504 default:
505 base.FatalfAt(call.Pos(), fmt.Sprintf("Unexpected op with CALL during stenciling: %v", call.X.Op()))
506 }
507
508 case ir.OCLOSURE:
509 x := x.(*ir.ClosureExpr)
510
511
512 oldfn := x.Func
513 newfn := ir.NewFunc(oldfn.Pos())
514 if oldfn.ClosureCalled() {
515 newfn.SetClosureCalled(true)
516 }
517 newfn.SetIsHiddenClosure(true)
518 m.(*ir.ClosureExpr).Func = newfn
519
520
521 newsym := makeInstName(oldfn.Nname.Sym(), subst.targs, subst.isMethod)
522 newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), newsym)
523 newfn.Nname.Func = newfn
524 newfn.Nname.Defn = newfn
525 ir.MarkFunc(newfn.Nname)
526 newfn.OClosure = m.(*ir.ClosureExpr)
527
528 saveNewf := subst.newf
529 ir.CurFunc = newfn
530 subst.newf = newfn
531 newfn.Dcl = subst.namelist(oldfn.Dcl)
532 newfn.ClosureVars = subst.namelist(oldfn.ClosureVars)
533
534 typed(subst.typ(oldfn.Nname.Type()), newfn.Nname)
535 typed(newfn.Nname.Type(), m)
536 newfn.SetTypecheck(1)
537
538
539 newfn.Body = subst.list(oldfn.Body)
540 subst.newf = saveNewf
541 ir.CurFunc = saveNewf
542
543 subst.g.target.Decls = append(subst.g.target.Decls, newfn)
544 }
545 return m
546 }
547
548 return edit(n)
549 }
550
551 func (subst *subster) namelist(l []*ir.Name) []*ir.Name {
552 s := make([]*ir.Name, len(l))
553 for i, n := range l {
554 s[i] = subst.node(n).(*ir.Name)
555 if n.Defn != nil {
556 s[i].Defn = subst.node(n.Defn)
557 }
558 if n.Outer != nil {
559 s[i].Outer = subst.node(n.Outer).(*ir.Name)
560 }
561 }
562 return s
563 }
564
565 func (subst *subster) list(l []ir.Node) []ir.Node {
566 s := make([]ir.Node, len(l))
567 for i, n := range l {
568 s[i] = subst.node(n)
569 }
570 return s
571 }
572
573
574
575
576
577
578 func (subst *subster) tstruct(t *types.Type, force bool) *types.Type {
579 if t.NumFields() == 0 {
580 if t.HasTParam() {
581
582
583
584 return types.NewStruct(t.Pkg(), nil)
585 }
586 return t
587 }
588 var newfields []*types.Field
589 if force {
590 newfields = make([]*types.Field, t.NumFields())
591 }
592 for i, f := range t.Fields().Slice() {
593 t2 := subst.typ(f.Type)
594 if (t2 != f.Type || f.Nname != nil) && newfields == nil {
595 newfields = make([]*types.Field, t.NumFields())
596 for j := 0; j < i; j++ {
597 newfields[j] = t.Field(j)
598 }
599 }
600 if newfields != nil {
601
602
603
604 newfields[i] = types.NewField(f.Pos, f.Sym, t2)
605 if f.Nname != nil {
606
607
608
609 v := subst.vars[f.Nname.(*ir.Name)]
610
611
612
613 if v != nil {
614 newfields[i].Nname = v
615 }
616 }
617 }
618 }
619 if newfields != nil {
620 return types.NewStruct(t.Pkg(), newfields)
621 }
622 return t
623
624 }
625
626
627 func (subst *subster) tinter(t *types.Type) *types.Type {
628 if t.Methods().Len() == 0 {
629 return t
630 }
631 var newfields []*types.Field
632 for i, f := range t.Methods().Slice() {
633 t2 := subst.typ(f.Type)
634 if (t2 != f.Type || f.Nname != nil) && newfields == nil {
635 newfields = make([]*types.Field, t.Methods().Len())
636 for j := 0; j < i; j++ {
637 newfields[j] = t.Methods().Index(j)
638 }
639 }
640 if newfields != nil {
641 newfields[i] = types.NewField(f.Pos, f.Sym, t2)
642 }
643 }
644 if newfields != nil {
645 return types.NewInterface(t.Pkg(), newfields)
646 }
647 return t
648 }
649
650
651
652 func instTypeName(name string, targs []*types.Type) string {
653 b := bytes.NewBufferString(name)
654 b.WriteByte('[')
655 for i, targ := range targs {
656 if i > 0 {
657 b.WriteByte(',')
658 }
659 b.WriteString(targ.String())
660 }
661 b.WriteByte(']')
662 return b.String()
663 }
664
665
666
667
668
669 func (subst *subster) typ(t *types.Type) *types.Type {
670 if !t.HasTParam() && t.Kind() != types.TFUNC {
671
672
673
674 return t
675 }
676
677 if t.Kind() == types.TTYPEPARAM {
678 for i, tp := range subst.tparams {
679 if tp.Type == t {
680 return subst.targs[i].Type()
681 }
682 }
683
684
685
686
687
688
689
690
691
692
693
694
695 if t.Underlying() == t {
696
697 return t
698 }
699
700
701 assert(t.Sym() != nil)
702 }
703
704 var newsym *types.Sym
705 var neededTargs []*types.Type
706 var forw *types.Type
707
708 if t.Sym() != nil {
709
710
711 neededTargs = make([]*types.Type, len(t.RParams()))
712 for i, rparam := range t.RParams() {
713 neededTargs[i] = subst.typ(rparam)
714 }
715
716
717
718
719 genName := genericTypeName(t.Sym())
720 newsym = t.Sym().Pkg.Lookup(instTypeName(genName, neededTargs))
721 if newsym.Def != nil {
722
723 return newsym.Def.Type()
724 }
725
726
727
728
729 forw = newIncompleteNamedType(t.Pos(), newsym)
730
731 forw.SetRParams(neededTargs)
732 }
733
734 var newt *types.Type
735
736 switch t.Kind() {
737 case types.TTYPEPARAM:
738 if t.Sym() == newsym {
739
740 return t
741 }
742
743
744 newt = subst.typ(t.Underlying())
745 assert(newt != t)
746
747 case types.TARRAY:
748 elem := t.Elem()
749 newelem := subst.typ(elem)
750 if newelem != elem {
751 newt = types.NewArray(newelem, t.NumElem())
752 }
753
754 case types.TPTR:
755 elem := t.Elem()
756 newelem := subst.typ(elem)
757 if newelem != elem {
758 newt = types.NewPtr(newelem)
759 }
760
761 case types.TSLICE:
762 elem := t.Elem()
763 newelem := subst.typ(elem)
764 if newelem != elem {
765 newt = types.NewSlice(newelem)
766 }
767
768 case types.TSTRUCT:
769 newt = subst.tstruct(t, false)
770 if newt == t {
771 newt = nil
772 }
773
774 case types.TFUNC:
775 newrecvs := subst.tstruct(t.Recvs(), false)
776 newparams := subst.tstruct(t.Params(), false)
777 newresults := subst.tstruct(t.Results(), false)
778 if newrecvs != t.Recvs() || newparams != t.Params() || newresults != t.Results() {
779
780
781
782
783 var newrecv *types.Field
784 if newrecvs.NumFields() > 0 {
785 if newrecvs == t.Recvs() {
786 newrecvs = subst.tstruct(t.Recvs(), true)
787 }
788 newrecv = newrecvs.Field(0)
789 }
790 if newparams == t.Params() {
791 newparams = subst.tstruct(t.Params(), true)
792 }
793 if newresults == t.Results() {
794 newresults = subst.tstruct(t.Results(), true)
795 }
796 newt = types.NewSignature(t.Pkg(), newrecv, t.TParams().FieldSlice(), newparams.FieldSlice(), newresults.FieldSlice())
797 }
798
799 case types.TINTER:
800 newt = subst.tinter(t)
801 if newt == t {
802 newt = nil
803 }
804
805 case types.TMAP:
806 newkey := subst.typ(t.Key())
807 newval := subst.typ(t.Elem())
808 if newkey != t.Key() || newval != t.Elem() {
809 newt = types.NewMap(newkey, newval)
810 }
811
812 case types.TCHAN:
813 elem := t.Elem()
814 newelem := subst.typ(elem)
815 if newelem != elem {
816 newt = types.NewChan(newelem, t.ChanDir())
817 if !newt.HasTParam() {
818
819
820 types.CheckSize(newt)
821 }
822 }
823 }
824 if newt == nil {
825
826
827
828 return t
829 }
830
831 if t.Sym() == nil {
832
833
834 assert(t.Methods().Len() == 0)
835 return newt
836 }
837
838 forw.SetUnderlying(newt)
839 newt = forw
840
841 if t.Kind() != types.TINTER && t.Methods().Len() > 0 {
842
843 var newfields []*types.Field
844 newfields = make([]*types.Field, t.Methods().Len())
845 for i, f := range t.Methods().Slice() {
846 t2 := subst.typ(f.Type)
847 oldsym := f.Nname.Sym()
848 newsym := makeInstName(oldsym, subst.targs, true)
849 var nname *ir.Name
850 if newsym.Def != nil {
851 nname = newsym.Def.(*ir.Name)
852 } else {
853 nname = ir.NewNameAt(f.Pos, newsym)
854 nname.SetType(t2)
855 newsym.Def = nname
856 }
857 newfields[i] = types.NewField(f.Pos, f.Sym, t2)
858 newfields[i].Nname = nname
859 }
860 newt.Methods().Set(newfields)
861 if !newt.HasTParam() {
862
863 subst.g.instTypeList = append(subst.g.instTypeList, newt)
864 }
865 }
866 return newt
867 }
868
869
870
871
872 func (subst *subster) fields(class ir.Class, oldfields []*types.Field, dcl []*ir.Name) []*types.Field {
873
874
875 var i int
876 for i = range dcl {
877 if dcl[i].Class == class {
878 break
879 }
880 }
881
882
883
884
885 newfields := make([]*types.Field, len(oldfields))
886 for j := range oldfields {
887 newfields[j] = oldfields[j].Copy()
888 newfields[j].Type = subst.typ(oldfields[j].Type)
889
890
891
892
893 if i < len(dcl) && dcl[i].Sym() == oldfields[j].Sym {
894 newfields[j].Nname = dcl[i]
895 i++
896 }
897 }
898 return newfields
899 }
900
901
902 func deref(t *types.Type) *types.Type {
903 if t.IsPtr() {
904 return t.Elem()
905 }
906 return t
907 }
908
909
910
911 func newIncompleteNamedType(pos src.XPos, sym *types.Sym) *types.Type {
912 name := ir.NewDeclNameAt(pos, ir.OTYPE, sym)
913 forw := types.NewNamed(name)
914 name.SetType(forw)
915 sym.Def = name
916 return forw
917 }
918
View as plain text