1
2
3
4
5 package typecheck
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/types"
11 "cmd/internal/src"
12 )
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 func crawlExports(exports []*ir.Name) {
32 p := crawler{
33 marked: make(map[*types.Type]bool),
34 embedded: make(map[*types.Type]bool),
35 generic: make(map[*types.Type]bool),
36 checkFullyInst: make(map[*types.Type]bool),
37 }
38 for _, n := range exports {
39 p.markObject(n)
40 }
41 }
42
43 type crawler struct {
44 marked map[*types.Type]bool
45 embedded map[*types.Type]bool
46 generic map[*types.Type]bool
47 checkFullyInst map[*types.Type]bool
48 }
49
50
51 func (p *crawler) markObject(n *ir.Name) {
52 if n.Op() == ir.ONAME && n.Class == ir.PFUNC {
53 p.markInlBody(n)
54 }
55
56
57
58 if n.Op() == ir.OTYPE {
59 p.markEmbed(n.Type())
60 }
61
62 p.markType(n.Type())
63 }
64
65
66
67
68 func (p *crawler) markType(t *types.Type) {
69 if orig := t.OrigType(); orig != nil {
70
71 t = orig
72 }
73 if p.marked[t] {
74 return
75 }
76 p.marked[t] = true
77
78
79
80
81
82
83 if t.Sym() != nil && t.Kind() != types.TINTER {
84 for _, m := range t.Methods().Slice() {
85 if types.IsExported(m.Sym.Name) {
86 p.markObject(m.Nname.(*ir.Name))
87 }
88 }
89 }
90
91
92
93
94
95
96
97
98
99
100 switch t.Kind() {
101 case types.TPTR, types.TARRAY, types.TSLICE:
102 p.markType(t.Elem())
103
104 case types.TCHAN:
105 if t.ChanDir().CanRecv() {
106 p.markType(t.Elem())
107 }
108
109 case types.TMAP:
110 p.markType(t.Key())
111 p.markType(t.Elem())
112
113 case types.TSTRUCT:
114 if t.IsFuncArgStruct() {
115 break
116 }
117 for _, f := range t.FieldSlice() {
118
119
120
121
122 if types.IsExported(f.Sym.Name) || f.Embedded != 0 ||
123 isPtrFullyInstantiated(f.Type) {
124 p.markType(f.Type)
125 }
126 }
127
128 case types.TFUNC:
129 for _, f := range t.Results().FieldSlice() {
130 p.markType(f.Type)
131 }
132
133 case types.TINTER:
134 for _, f := range t.AllMethods().Slice() {
135 if types.IsExported(f.Sym.Name) {
136 p.markType(f.Type)
137 }
138 }
139
140 case types.TTYPEPARAM:
141
142 }
143 }
144
145
146
147
148 func (p *crawler) markEmbed(t *types.Type) {
149 if t.IsPtr() {
150
151 if t.Sym() != nil {
152 return
153 }
154 t = t.Elem()
155 }
156
157 if orig := t.OrigType(); orig != nil {
158
159 t = orig
160 }
161
162 if p.embedded[t] {
163 return
164 }
165 p.embedded[t] = true
166
167
168
169
170
171 if t.Sym() != nil && t.Kind() != types.TINTER {
172 for _, m := range t.Methods().Slice() {
173 p.markObject(m.Nname.(*ir.Name))
174 }
175 }
176
177
178 if t.IsStruct() {
179 for _, f := range t.FieldSlice() {
180 if f.Embedded != 0 {
181 p.markEmbed(f.Type)
182 }
183 }
184 }
185 }
186
187
188
189
190
191
192
193 func (p *crawler) markGeneric(t *types.Type) {
194 if t.IsPtr() {
195 t = t.Elem()
196 }
197 if orig := t.OrigType(); orig != nil {
198
199 t = orig
200 }
201 if p.generic[t] {
202 return
203 }
204 p.generic[t] = true
205
206 if t.Sym() != nil && t.Kind() != types.TINTER {
207 for _, m := range t.Methods().Slice() {
208 p.markObject(m.Nname.(*ir.Name))
209 }
210 }
211 }
212
213
214
215
216
217 func (p *crawler) checkForFullyInst(t *types.Type) {
218 if p.checkFullyInst[t] {
219 return
220 }
221 p.checkFullyInst[t] = true
222
223 if t.IsFullyInstantiated() && !t.HasShape() && !t.IsInterface() && t.Methods().Len() > 0 {
224
225
226
227
228
229
230
231
232 baseType := t.OrigType()
233 shapes := make([]*types.Type, len(t.RParams()))
234 for i, t1 := range t.RParams() {
235 shapes[i] = Shapify(t1, i, baseType.RParams()[i])
236 }
237 for j, tmethod := range t.Methods().Slice() {
238 baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
239 dictsym := MakeDictSym(baseNname.Sym(), t.RParams(), true)
240 if dictsym.Def == nil {
241 in := Resolve(ir.NewIdent(src.NoXPos, dictsym))
242 dictsym = in.Sym()
243 }
244 Export(dictsym.Def.(*ir.Name))
245 methsym := MakeFuncInstSym(baseNname.Sym(), shapes, false, true)
246 if methsym.Def == nil {
247 in := Resolve(ir.NewIdent(src.NoXPos, methsym))
248 methsym = in.Sym()
249 }
250 methNode := methsym.Def.(*ir.Name)
251 Export(methNode)
252 if HaveInlineBody(methNode.Func) {
253
254
255 ImportedBody(methNode.Func)
256 methNode.Func.SetExportInline(true)
257 }
258
259 p.checkForFullyInst(tmethod.Type)
260 }
261 }
262
263
264
265
266 switch t.Kind() {
267 case types.TPTR, types.TARRAY, types.TSLICE:
268 p.checkForFullyInst(t.Elem())
269
270 case types.TCHAN:
271 p.checkForFullyInst(t.Elem())
272
273 case types.TMAP:
274 p.checkForFullyInst(t.Key())
275 p.checkForFullyInst(t.Elem())
276
277 case types.TSTRUCT:
278 if t.IsFuncArgStruct() {
279 break
280 }
281 for _, f := range t.FieldSlice() {
282 p.checkForFullyInst(f.Type)
283 }
284
285 case types.TFUNC:
286 if recv := t.Recv(); recv != nil {
287 p.checkForFullyInst(t.Recv().Type)
288 }
289 for _, f := range t.Params().FieldSlice() {
290 p.checkForFullyInst(f.Type)
291 }
292 for _, f := range t.Results().FieldSlice() {
293 p.checkForFullyInst(f.Type)
294 }
295
296 case types.TINTER:
297 for _, f := range t.AllMethods().Slice() {
298 p.checkForFullyInst(f.Type)
299 }
300 }
301 }
302
303
304
305 func (p *crawler) markInlBody(n *ir.Name) {
306 if n == nil {
307 return
308 }
309 if n.Op() != ir.ONAME || n.Class != ir.PFUNC {
310 base.Fatalf("markInlBody: unexpected %v, %v, %v", n, n.Op(), n.Class)
311 }
312 fn := n.Func
313 if fn == nil {
314 base.Fatalf("markInlBody: missing Func on %v", n)
315 }
316 if !HaveInlineBody(fn) {
317 return
318 }
319
320 if fn.ExportInline() {
321 return
322 }
323 fn.SetExportInline(true)
324
325 ImportedBody(fn)
326
327 var doFlood func(n ir.Node)
328 doFlood = func(n ir.Node) {
329 t := n.Type()
330 if t != nil {
331 if t.HasTParam() {
332
333
334
335 p.markGeneric(t)
336 } else {
337 p.checkForFullyInst(t)
338 }
339 if base.Debug.Unified == 0 {
340
341
342
343
344
345
346
347
348
349
350
351
352 if t.IsStruct() {
353 for _, f := range t.FieldSlice() {
354 if f.Embedded != 0 {
355 p.markEmbed(f.Type)
356 }
357 }
358 }
359 }
360 }
361
362 switch n.Op() {
363 case ir.OMETHEXPR, ir.ODOTMETH:
364 p.markInlBody(ir.MethodExprName(n))
365 case ir.ONAME:
366 n := n.(*ir.Name)
367 switch n.Class {
368 case ir.PFUNC:
369 p.markInlBody(n)
370
371
372
373
374 Export(n)
375 case ir.PEXTERN:
376 Export(n)
377 }
378 case ir.OMETHVALUE:
379
380
381 case ir.OCLOSURE:
382
383
384 ir.VisitList(n.(*ir.ClosureExpr).Func.Body, doFlood)
385 }
386 }
387
388
389
390
391 ir.VisitList(fn.Inl.Body, doFlood)
392 }
393
394
395
396 func isPtrFullyInstantiated(t *types.Type) bool {
397 return t.IsPtr() && t.Elem().IsFullyInstantiated() ||
398 t.IsFullyInstantiated()
399 }
400
View as plain text