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