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