1
2
3
4
5 package noder
6
7 import (
8 "fmt"
9 "internal/pkgbits"
10 "io"
11 "runtime"
12 "sort"
13 "strings"
14
15 "cmd/compile/internal/base"
16 "cmd/compile/internal/inline"
17 "cmd/compile/internal/ir"
18 "cmd/compile/internal/pgo"
19 "cmd/compile/internal/typecheck"
20 "cmd/compile/internal/types"
21 "cmd/compile/internal/types2"
22 "cmd/internal/src"
23 )
24
25
26
27
28 var localPkgReader *pkgReader
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 func LookupFunc(fullName string) (*ir.Func, error) {
44 pkgPath, symName, err := ir.ParseLinkFuncName(fullName)
45 if err != nil {
46 return nil, fmt.Errorf("error parsing symbol name %q: %v", fullName, err)
47 }
48
49 pkg, ok := types.PkgMap()[pkgPath]
50 if !ok {
51 return nil, fmt.Errorf("pkg %s doesn't exist in %v", pkgPath, types.PkgMap())
52 }
53
54
55
56
57
58
59 fn, err := lookupFunction(pkg, symName)
60 if err == nil {
61 return fn, nil
62 }
63
64 fn, mErr := lookupMethod(pkg, symName)
65 if mErr == nil {
66 return fn, nil
67 }
68
69 return nil, fmt.Errorf("%s is not a function (%v) or method (%v)", fullName, err, mErr)
70 }
71
72 func lookupFunction(pkg *types.Pkg, symName string) (*ir.Func, error) {
73 sym := pkg.Lookup(symName)
74
75
76
77
78 pri, ok := objReader[sym]
79 if !ok {
80 return nil, fmt.Errorf("func sym %v missing objReader", sym)
81 }
82
83 node, err := pri.pr.objIdxMayFail(pri.idx, nil, nil, false)
84 if err != nil {
85 return nil, fmt.Errorf("func sym %v lookup error: %w", sym, err)
86 }
87 name := node.(*ir.Name)
88 if name.Op() != ir.ONAME || name.Class != ir.PFUNC {
89 return nil, fmt.Errorf("func sym %v refers to non-function name: %v", sym, name)
90 }
91 return name.Func, nil
92 }
93
94 func lookupMethod(pkg *types.Pkg, symName string) (*ir.Func, error) {
95
96
97
98
99
100
101
102 typ, meth, err := ir.LookupMethodSelector(pkg, symName)
103 if err != nil {
104 return nil, fmt.Errorf("error looking up method symbol %q: %v", symName, err)
105 }
106
107 pri, ok := objReader[typ]
108 if !ok {
109 return nil, fmt.Errorf("type sym %v missing objReader", typ)
110 }
111
112 node, err := pri.pr.objIdxMayFail(pri.idx, nil, nil, false)
113 if err != nil {
114 return nil, fmt.Errorf("func sym %v lookup error: %w", typ, err)
115 }
116 name := node.(*ir.Name)
117 if name.Op() != ir.OTYPE {
118 return nil, fmt.Errorf("type sym %v refers to non-type name: %v", typ, name)
119 }
120 if name.Alias() {
121 return nil, fmt.Errorf("type sym %v refers to alias", typ)
122 }
123 if name.Type().IsInterface() {
124 return nil, fmt.Errorf("type sym %v refers to interface type", typ)
125 }
126
127 for _, m := range name.Type().Methods() {
128 if m.Sym == meth {
129 fn := m.Nname.(*ir.Name).Func
130 return fn, nil
131 }
132 }
133
134 return nil, fmt.Errorf("method %s missing from method set of %v", symName, typ)
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 func unified(m posMap, noders []*noder) {
179 inline.InlineCall = unifiedInlineCall
180 typecheck.HaveInlineBody = unifiedHaveInlineBody
181 pgo.LookupFunc = LookupFunc
182
183 data := writePkgStub(m, noders)
184
185 target := typecheck.Target
186
187 localPkgReader = newPkgReader(pkgbits.NewPkgDecoder(types.LocalPkg.Path, data))
188 readPackage(localPkgReader, types.LocalPkg, true)
189
190 r := localPkgReader.newReader(pkgbits.RelocMeta, pkgbits.PrivateRootIdx, pkgbits.SyncPrivate)
191 r.pkgInit(types.LocalPkg, target)
192
193 readBodies(target, false)
194
195
196 for _, fn := range target.Funcs {
197 if fn.Typecheck() == 0 {
198 base.FatalfAt(fn.Pos(), "missed typecheck: %v", fn)
199 }
200
201
202
203 if len(fn.Body) != 0 {
204 if stmt := fn.Body[0]; stmt.Typecheck() == 0 {
205 base.FatalfAt(stmt.Pos(), "missed typecheck: %v", stmt)
206 }
207 }
208 }
209
210
211
212 for _, fn := range target.Funcs {
213 if !base.Flag.CompilingRuntime && types.RuntimeSymName(fn.Sym()) != "" {
214 fn.Pragma |= ir.Norace
215 }
216 }
217
218 base.ExitIfErrors()
219 }
220
221
222
223
224
225
226
227 func readBodies(target *ir.Package, duringInlining bool) {
228 var inlDecls []*ir.Func
229
230
231 for {
232
233
234
235
236
237
238
239
240 if len(todoDicts) > 0 {
241 fn := todoDicts[len(todoDicts)-1]
242 todoDicts = todoDicts[:len(todoDicts)-1]
243 fn()
244 continue
245 }
246
247 if len(todoBodies) > 0 {
248 fn := todoBodies[len(todoBodies)-1]
249 todoBodies = todoBodies[:len(todoBodies)-1]
250
251 pri, ok := bodyReader[fn]
252 assert(ok)
253 pri.funcBody(fn)
254
255
256
257 if fn.OClosure == nil && len(pri.dict.targs) != 0 {
258
259
260
261 canSkipNonGenericMethod := !(base.Ctxt.Flag_linkshared && ir.IsMethod(fn))
262 if duringInlining && canSkipNonGenericMethod {
263 inlDecls = append(inlDecls, fn)
264 } else {
265 target.Funcs = append(target.Funcs, fn)
266 }
267 }
268
269 continue
270 }
271
272 break
273 }
274
275 todoDicts = nil
276 todoBodies = nil
277
278 if len(inlDecls) != 0 {
279
280
281
282
283
284
285
286
287
288
289
290
291
292 oldLowerM := base.Flag.LowerM
293 base.Flag.LowerM = 0
294 inline.CanInlineFuncs(inlDecls, nil)
295 base.Flag.LowerM = oldLowerM
296
297 for _, fn := range inlDecls {
298 fn.Body = nil
299 }
300 }
301 }
302
303
304
305
306 func writePkgStub(m posMap, noders []*noder) string {
307 pkg, info := checkFiles(m, noders)
308
309 pw := newPkgWriter(m, pkg, info)
310
311 pw.collectDecls(noders)
312
313 publicRootWriter := pw.newWriter(pkgbits.RelocMeta, pkgbits.SyncPublic)
314 privateRootWriter := pw.newWriter(pkgbits.RelocMeta, pkgbits.SyncPrivate)
315
316 assert(publicRootWriter.Idx == pkgbits.PublicRootIdx)
317 assert(privateRootWriter.Idx == pkgbits.PrivateRootIdx)
318
319 {
320 w := publicRootWriter
321 w.pkg(pkg)
322 w.Bool(false)
323
324 scope := pkg.Scope()
325 names := scope.Names()
326 w.Len(len(names))
327 for _, name := range names {
328 w.obj(scope.Lookup(name), nil)
329 }
330
331 w.Sync(pkgbits.SyncEOF)
332 w.Flush()
333 }
334
335 {
336 w := privateRootWriter
337 w.pkgInit(noders)
338 w.Flush()
339 }
340
341 var sb strings.Builder
342 pw.DumpTo(&sb)
343
344
345
346 freePackage(pkg)
347
348 return sb.String()
349 }
350
351
352 func freePackage(pkg *types2.Package) {
353
354
355
356
357
358
359 if base.CompilerBootstrap || base.Debug.GCCheck == 0 {
360 *pkg = types2.Package{}
361 return
362 }
363
364
365 done := make(chan struct{})
366 runtime.SetFinalizer(pkg, func(*types2.Package) { close(done) })
367
368
369
370 *pkg = types2.Package{}
371
372
373
374 for i := 0; i < 10; i++ {
375 select {
376 case <-done:
377 return
378 default:
379 runtime.GC()
380 }
381 }
382
383 base.Fatalf("package never finalized")
384 }
385
386
387
388
389
390
391
392 func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) {
393 {
394 r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
395
396 pkg := r.pkg()
397 base.Assertf(pkg == importpkg, "have package %q (%p), want package %q (%p)", pkg.Path, pkg, importpkg.Path, importpkg)
398
399 r.Bool()
400
401 for i, n := 0, r.Len(); i < n; i++ {
402 r.Sync(pkgbits.SyncObject)
403 assert(!r.Bool())
404 idx := r.Reloc(pkgbits.RelocObj)
405 assert(r.Len() == 0)
406
407 path, name, code := r.p.PeekObj(idx)
408 if code != pkgbits.ObjStub {
409 objReader[types.NewPkg(path, "").Lookup(name)] = pkgReaderIndex{pr, idx, nil, nil, nil}
410 }
411 }
412
413 r.Sync(pkgbits.SyncEOF)
414 }
415
416 if !localStub {
417 r := pr.newReader(pkgbits.RelocMeta, pkgbits.PrivateRootIdx, pkgbits.SyncPrivate)
418
419 if r.Bool() {
420 sym := importpkg.Lookup(".inittask")
421 task := ir.NewNameAt(src.NoXPos, sym, nil)
422 task.Class = ir.PEXTERN
423 sym.Def = task
424 }
425
426 for i, n := 0, r.Len(); i < n; i++ {
427 path := r.String()
428 name := r.String()
429 idx := r.Reloc(pkgbits.RelocBody)
430
431 sym := types.NewPkg(path, "").Lookup(name)
432 if _, ok := importBodyReader[sym]; !ok {
433 importBodyReader[sym] = pkgReaderIndex{pr, idx, nil, nil, nil}
434 }
435 }
436
437 r.Sync(pkgbits.SyncEOF)
438 }
439 }
440
441
442
443 func writeUnifiedExport(out io.Writer) {
444 l := linker{
445 pw: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
446
447 pkgs: make(map[string]pkgbits.Index),
448 decls: make(map[*types.Sym]pkgbits.Index),
449 bodies: make(map[*types.Sym]pkgbits.Index),
450 }
451
452 publicRootWriter := l.pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPublic)
453 privateRootWriter := l.pw.NewEncoder(pkgbits.RelocMeta, pkgbits.SyncPrivate)
454 assert(publicRootWriter.Idx == pkgbits.PublicRootIdx)
455 assert(privateRootWriter.Idx == pkgbits.PrivateRootIdx)
456
457 var selfPkgIdx pkgbits.Index
458
459 {
460 pr := localPkgReader
461 r := pr.NewDecoder(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
462
463 r.Sync(pkgbits.SyncPkg)
464 selfPkgIdx = l.relocIdx(pr, pkgbits.RelocPkg, r.Reloc(pkgbits.RelocPkg))
465
466 r.Bool()
467
468 for i, n := 0, r.Len(); i < n; i++ {
469 r.Sync(pkgbits.SyncObject)
470 assert(!r.Bool())
471 idx := r.Reloc(pkgbits.RelocObj)
472 assert(r.Len() == 0)
473
474 xpath, xname, xtag := pr.PeekObj(idx)
475 assert(xpath == pr.PkgPath())
476 assert(xtag != pkgbits.ObjStub)
477
478 if types.IsExported(xname) {
479 l.relocIdx(pr, pkgbits.RelocObj, idx)
480 }
481 }
482
483 r.Sync(pkgbits.SyncEOF)
484 }
485
486 {
487 var idxs []pkgbits.Index
488 for _, idx := range l.decls {
489 idxs = append(idxs, idx)
490 }
491 sort.Slice(idxs, func(i, j int) bool { return idxs[i] < idxs[j] })
492
493 w := publicRootWriter
494
495 w.Sync(pkgbits.SyncPkg)
496 w.Reloc(pkgbits.RelocPkg, selfPkgIdx)
497 w.Bool(false)
498
499 w.Len(len(idxs))
500 for _, idx := range idxs {
501 w.Sync(pkgbits.SyncObject)
502 w.Bool(false)
503 w.Reloc(pkgbits.RelocObj, idx)
504 w.Len(0)
505 }
506
507 w.Sync(pkgbits.SyncEOF)
508 w.Flush()
509 }
510
511 {
512 type symIdx struct {
513 sym *types.Sym
514 idx pkgbits.Index
515 }
516 var bodies []symIdx
517 for sym, idx := range l.bodies {
518 bodies = append(bodies, symIdx{sym, idx})
519 }
520 sort.Slice(bodies, func(i, j int) bool { return bodies[i].idx < bodies[j].idx })
521
522 w := privateRootWriter
523
524 w.Bool(typecheck.Lookup(".inittask").Def != nil)
525
526 w.Len(len(bodies))
527 for _, body := range bodies {
528 w.String(body.sym.Pkg.Path)
529 w.String(body.sym.Name)
530 w.Reloc(pkgbits.RelocBody, body.idx)
531 }
532
533 w.Sync(pkgbits.SyncEOF)
534 w.Flush()
535 }
536
537 base.Ctxt.Fingerprint = l.pw.DumpTo(out)
538 }
539
View as plain text