...
1
2
3
4
5 package ssa
6
7 import (
8 "fmt"
9 "go/types"
10 "sync"
11 )
12
13
14
15 type generic struct {
16 instancesMu sync.Mutex
17 instances map[*typeList]*Function
18 }
19
20
21
22
23
24
25
26 func (fn *Function) instance(targs []types.Type, cr *creator) *Function {
27 key := fn.Prog.canon.List(targs)
28
29 gen := fn.generic
30
31 gen.instancesMu.Lock()
32 defer gen.instancesMu.Unlock()
33 inst, ok := gen.instances[key]
34 if !ok {
35 inst = createInstance(fn, targs, cr)
36 if gen.instances == nil {
37 gen.instances = make(map[*typeList]*Function)
38 }
39 gen.instances[key] = inst
40 }
41 return inst
42 }
43
44
45
46
47
48 func createInstance(fn *Function, targs []types.Type, cr *creator) *Function {
49 prog := fn.Prog
50
51
52 var sig *types.Signature
53 var obj *types.Func
54 if recv := fn.Signature.Recv(); recv != nil {
55
56 obj = prog.canon.instantiateMethod(fn.object, targs, prog.ctxt)
57 sig = obj.Type().(*types.Signature)
58 } else {
59
60 instSig, err := types.Instantiate(prog.ctxt, fn.Signature, targs, false)
61 if err != nil {
62 panic(err)
63 }
64 instance, ok := instSig.(*types.Signature)
65 if !ok {
66 panic("Instantiate of a Signature returned a non-signature")
67 }
68 obj = fn.object
69 sig = prog.canon.Type(instance).(*types.Signature)
70 }
71
72
73 var (
74 synthetic string
75 subst *subster
76 build buildFunc
77 )
78 if prog.mode&InstantiateGenerics != 0 && !prog.isParameterized(targs...) {
79 synthetic = fmt.Sprintf("instance of %s", fn.Name())
80 if fn.syntax != nil {
81 scope := obj.Origin().Scope()
82 subst = makeSubster(prog.ctxt, scope, fn.typeparams, targs, false)
83 build = (*builder).buildFromSyntax
84 } else {
85 build = (*builder).buildParamsOnly
86 }
87 } else {
88 synthetic = fmt.Sprintf("instantiation wrapper of %s", fn.Name())
89 build = (*builder).buildInstantiationWrapper
90 }
91
92
93 instance := &Function{
94 name: fmt.Sprintf("%s%s", fn.Name(), targs),
95 object: obj,
96 Signature: sig,
97 Synthetic: synthetic,
98 syntax: fn.syntax,
99 info: fn.info,
100 goversion: fn.goversion,
101 build: build,
102 topLevelOrigin: fn,
103 pos: obj.Pos(),
104 Pkg: nil,
105 Prog: fn.Prog,
106 typeparams: fn.typeparams,
107 typeargs: targs,
108 subst: subst,
109 }
110 cr.Add(instance)
111 return instance
112 }
113
114
115
116 func (prog *Program) isParameterized(ts ...types.Type) bool {
117 prog.hasParamsMu.Lock()
118 defer prog.hasParamsMu.Unlock()
119
120
121
122
123
124 for _, t := range ts {
125 if prog.hasParams.Has(t) {
126 return true
127 }
128 }
129 return false
130 }
131
View as plain text