1
2
3
4
5 package testimporter
6
7 import (
8 "cmp"
9 "slices"
10
11 "cmd/compile/internal/base"
12 "cmd/compile/internal/syntax"
13 "cmd/compile/internal/types2"
14 "cmd/internal/src"
15 "internal/pkgbits"
16 )
17
18 type pkgReader struct {
19 pkgbits.PkgDecoder
20
21 ctxt *types2.Context
22 imports map[string]*types2.Package
23 enableAlias bool
24
25 posBases []*syntax.PosBase
26 pkgs []*types2.Package
27 typs []types2.Type
28 }
29
30 func ReadPackage(ctxt *types2.Context, imports map[string]*types2.Package, input pkgbits.PkgDecoder) *types2.Package {
31 pr := pkgReader{
32 PkgDecoder: input,
33
34 ctxt: ctxt,
35 imports: imports,
36 enableAlias: true,
37
38 posBases: make([]*syntax.PosBase, input.NumElems(pkgbits.SectionPosBase)),
39 pkgs: make([]*types2.Package, input.NumElems(pkgbits.SectionPkg)),
40 typs: make([]types2.Type, input.NumElems(pkgbits.SectionType)),
41 }
42
43 r := pr.newReader(pkgbits.SectionMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic)
44 pkg := r.pkg()
45
46 if r.Version().Has(pkgbits.HasInit) {
47 r.Bool()
48 }
49
50 for i, n := 0, r.Len(); i < n; i++ {
51
52
53 r.Sync(pkgbits.SyncObject)
54 if r.Version().Has(pkgbits.DerivedFuncInstance) {
55 assert(!r.Bool())
56 }
57 r.p.objIdx(r.Reloc(pkgbits.SectionObj))
58 assert(r.Len() == 0)
59 }
60
61 r.Sync(pkgbits.SyncEOF)
62
63 pkg.MarkComplete()
64 return pkg
65 }
66
67 type reader struct {
68 pkgbits.Decoder
69
70 p *pkgReader
71
72 dict *readerDict
73 delayed []func()
74 }
75
76 type readerDict struct {
77 rtbounds []typeInfo
78 rtparams []*types2.TypeParam
79
80 tbounds []typeInfo
81 tparams []*types2.TypeParam
82
83 derived []derivedInfo
84 derivedTypes []types2.Type
85 }
86
87 type readerTypeBound struct {
88 derived bool
89 boundIdx int
90 }
91
92 func (pr *pkgReader) newReader(k pkgbits.SectionKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
93 return &reader{
94 Decoder: pr.NewDecoder(k, idx, marker),
95 p: pr,
96 }
97 }
98
99 func (pr *pkgReader) tempReader(k pkgbits.SectionKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
100 return &reader{
101 Decoder: pr.TempDecoder(k, idx, marker),
102 p: pr,
103 }
104 }
105
106 func (pr *pkgReader) retireReader(r *reader) {
107 pr.RetireDecoder(&r.Decoder)
108 }
109
110
111
112 func (r *reader) pos() syntax.Pos {
113 r.Sync(pkgbits.SyncPos)
114 if !r.Bool() {
115 return syntax.Pos{}
116 }
117
118
119 posBase := r.posBase()
120 line := r.Uint()
121 col := r.Uint()
122 return syntax.MakePos(posBase, line, col)
123 }
124
125 func (r *reader) posBase() *syntax.PosBase {
126 return r.p.posBaseIdx(r.Reloc(pkgbits.SectionPosBase))
127 }
128
129 func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *syntax.PosBase {
130 if b := pr.posBases[idx]; b != nil {
131 return b
132 }
133 var b *syntax.PosBase
134 {
135 r := pr.tempReader(pkgbits.SectionPosBase, idx, pkgbits.SyncPosBase)
136
137 filename := r.String()
138
139 if r.Bool() {
140 b = syntax.NewTrimmedFileBase(filename, true)
141 } else {
142 pos := r.pos()
143 line := r.Uint()
144 col := r.Uint()
145 b = syntax.NewLineBase(pos, filename, true, line, col)
146 }
147 pr.retireReader(r)
148 }
149
150 pr.posBases[idx] = b
151 return b
152 }
153
154
155
156 func (r *reader) pkg() *types2.Package {
157 r.Sync(pkgbits.SyncPkg)
158 return r.p.pkgIdx(r.Reloc(pkgbits.SectionPkg))
159 }
160
161 func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types2.Package {
162
163
164 if pkg := pr.pkgs[idx]; pkg != nil {
165 return pkg
166 }
167
168 pkg := pr.newReader(pkgbits.SectionPkg, idx, pkgbits.SyncPkgDef).doPkg()
169 pr.pkgs[idx] = pkg
170 return pkg
171 }
172
173 func (r *reader) doPkg() *types2.Package {
174 path := r.String()
175 switch path {
176 case "":
177 path = r.p.PkgPath()
178 case "builtin":
179 return nil
180 case "unsafe":
181 return types2.Unsafe
182 }
183
184 if pkg := r.p.imports[path]; pkg != nil {
185 return pkg
186 }
187
188 name := r.String()
189 pkg := types2.NewPackage(path, name)
190 r.p.imports[path] = pkg
191
192
193
194 imports := make([]*types2.Package, r.Len())
195 for i := range imports {
196 imports[i] = r.pkg()
197 }
198 pkg.SetImports(imports)
199
200 return pkg
201 }
202
203
204
205 func (r *reader) typ() types2.Type {
206 return r.p.typIdx(r.typInfo(), r.dict)
207 }
208
209 func (r *reader) typInfo() typeInfo {
210 r.Sync(pkgbits.SyncType)
211 if r.Bool() {
212 return typeInfo{idx: pkgbits.Index(r.Len()), derived: true}
213 }
214 return typeInfo{idx: r.Reloc(pkgbits.SectionType), derived: false}
215 }
216
217 func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types2.Type {
218 idx := info.idx
219 var where *types2.Type
220 if info.derived {
221 where = &dict.derivedTypes[idx]
222 idx = dict.derived[idx].idx
223 } else {
224 where = &pr.typs[idx]
225 }
226
227 if typ := *where; typ != nil {
228 return typ
229 }
230
231 var typ types2.Type
232 {
233 r := pr.tempReader(pkgbits.SectionType, idx, pkgbits.SyncTypeIdx)
234 r.dict = dict
235
236 typ = r.doTyp()
237 assert(typ != nil)
238 pr.retireReader(r)
239 }
240
241
242 if prev := *where; prev != nil {
243 return prev
244 }
245
246 *where = typ
247 return typ
248 }
249
250 func (r *reader) doTyp() (res types2.Type) {
251 switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {
252 default:
253 base.FatalfAt(src.NoXPos, "unhandled type tag: %v", tag)
254 panic("unreachable")
255
256 case pkgbits.TypeBasic:
257 return types2.Typ[r.Len()]
258
259 case pkgbits.TypeNamed:
260 obj, targs := r.obj()
261 name := obj.(*types2.TypeName)
262 if len(targs) != 0 {
263 t, _ := types2.Instantiate(r.p.ctxt, name.Type(), targs, false)
264 return t
265 }
266 return name.Type()
267
268 case pkgbits.TypeTypeParam:
269 n := r.Len()
270 if n < len(r.dict.rtbounds) {
271 return r.dict.rtparams[n]
272 }
273 return r.dict.tparams[n-len(r.dict.rtbounds)]
274
275 case pkgbits.TypeArray:
276 len := int64(r.Uint64())
277 return types2.NewArray(r.typ(), len)
278 case pkgbits.TypeChan:
279 dir := types2.ChanDir(r.Len())
280 return types2.NewChan(dir, r.typ())
281 case pkgbits.TypeMap:
282 return types2.NewMap(r.typ(), r.typ())
283 case pkgbits.TypePointer:
284 return types2.NewPointer(r.typ())
285 case pkgbits.TypeSignature:
286 return r.signature(nil, nil, nil)
287 case pkgbits.TypeSlice:
288 return types2.NewSlice(r.typ())
289 case pkgbits.TypeStruct:
290 return r.structType()
291 case pkgbits.TypeInterface:
292 return r.interfaceType()
293 case pkgbits.TypeUnion:
294 return r.unionType()
295 }
296 }
297
298 func (r *reader) structType() *types2.Struct {
299 fields := make([]*types2.Var, r.Len())
300 var tags []string
301 for i := range fields {
302 pos := r.pos()
303 pkg, name := r.selector()
304 ftyp := r.typ()
305 tag := r.String()
306 embedded := r.Bool()
307
308 fields[i] = types2.NewField(pos, pkg, name, ftyp, embedded)
309 if tag != "" {
310 for len(tags) < i {
311 tags = append(tags, "")
312 }
313 tags = append(tags, tag)
314 }
315 }
316 return types2.NewStruct(fields, tags)
317 }
318
319 func (r *reader) unionType() *types2.Union {
320 terms := make([]*types2.Term, r.Len())
321 for i := range terms {
322 terms[i] = types2.NewTerm(r.Bool(), r.typ())
323 }
324 return types2.NewUnion(terms)
325 }
326
327 func (r *reader) interfaceType() *types2.Interface {
328 methods := make([]*types2.Func, r.Len())
329 embeddeds := make([]types2.Type, r.Len())
330 implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool()
331
332 for i := range methods {
333 pos := r.pos()
334 pkg, name := r.selector()
335 mtyp := r.signature(nil, nil, nil)
336 methods[i] = types2.NewFunc(pos, pkg, name, mtyp)
337 }
338
339 for i := range embeddeds {
340 embeddeds[i] = r.typ()
341 }
342
343 iface := types2.NewInterfaceType(methods, embeddeds)
344 if implicit {
345 iface.MarkImplicit()
346 }
347 return iface
348 }
349
350 func (r *reader) signature(recv *types2.Var, rtparams, tparams []*types2.TypeParam) *types2.Signature {
351 r.Sync(pkgbits.SyncSignature)
352
353 params := r.params()
354 results := r.params()
355 variadic := r.Bool()
356
357 return types2.NewSignatureType(recv, rtparams, tparams, params, results, variadic)
358 }
359
360 func (r *reader) params() *types2.Tuple {
361 r.Sync(pkgbits.SyncParams)
362 params := make([]*types2.Var, r.Len())
363 for i := range params {
364 params[i] = r.param()
365 }
366 return types2.NewTuple(params...)
367 }
368
369 func (r *reader) param() *types2.Var {
370 r.Sync(pkgbits.SyncParam)
371
372 pos := r.pos()
373 pkg, name := r.localIdent()
374 typ := r.typ()
375
376 return types2.NewParam(pos, pkg, name, typ)
377 }
378
379
380
381 func (r *reader) obj() (types2.Object, []types2.Type) {
382 r.Sync(pkgbits.SyncObject)
383
384 if r.Version().Has(pkgbits.DerivedFuncInstance) {
385 assert(!r.Bool())
386 }
387
388 pkg, name := r.p.objIdx(r.Reloc(pkgbits.SectionObj))
389 obj := pkg.Scope().Lookup(name)
390
391 targs := make([]types2.Type, r.Len())
392 for i := range targs {
393 targs[i] = r.typ()
394 }
395
396 return obj, targs
397 }
398
399 func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
400 var objPkg *types2.Package
401 var objName string
402 var tag pkgbits.CodeObj
403 {
404 rname := pr.tempReader(pkgbits.SectionName, idx, pkgbits.SyncObject1)
405
406 objPkg, objName = rname.qualifiedIdent()
407 assert(objName != "")
408
409 tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
410 pr.retireReader(rname)
411 }
412
413 if tag == pkgbits.ObjStub {
414 base.Assertf(objPkg == nil || objPkg == types2.Unsafe, "unexpected stub package: %v", objPkg)
415 return objPkg, objName
416 }
417
418 objPkg.Scope().InsertLazy(objName, func() types2.Object {
419 dict := pr.objDictIdx(idx)
420
421 r := pr.newReader(pkgbits.SectionObj, idx, pkgbits.SyncObject1)
422 r.dict = dict
423
424 switch tag {
425 default:
426 panic("weird")
427
428 case pkgbits.ObjAlias:
429 pos := r.pos()
430 var tparams []*types2.TypeParam
431 if r.Version().Has(pkgbits.AliasTypeParamNames) {
432 tparams = r.typeParamNames(false, false)
433 }
434 typ := r.typ()
435 return newAliasTypeName(pr.enableAlias, pos, objPkg, objName, typ, tparams)
436
437 case pkgbits.ObjConst:
438 pos := r.pos()
439 typ := r.typ()
440 val := r.Value()
441 return types2.NewConst(pos, objPkg, objName, typ, val)
442
443 case pkgbits.ObjFunc:
444 pos := r.pos()
445 if r.Version().Has(pkgbits.GenericMethods) {
446 assert(!r.Bool())
447 }
448 tparams := r.typeParamNames(false, false)
449 sig := r.signature(nil, nil, tparams)
450 return types2.NewFunc(pos, objPkg, objName, sig)
451
452 case pkgbits.ObjType:
453 pos := r.pos()
454
455 return types2.NewTypeNameLazy(pos, objPkg, objName, func(_ *types2.Named) ([]*types2.TypeParam, types2.Type, []*types2.Func, []func()) {
456 tparams := r.typeParamNames(true, false)
457
458
459
460
461
462 underlying := r.typ().Underlying()
463
464 type indexedMethod struct {
465 index int
466 fn *types2.Func
467 }
468 var methods []indexedMethod
469
470 if r.Version().Has(pkgbits.GenericMethods) {
471
472
473
474
475
476
477
478 for range r.Len() {
479 idx, m := r.method(true)
480 methods = append(methods, indexedMethod{idx, m})
481 }
482
483
484 for range r.Len() {
485
486
487
488 idx := r.Reloc(pkgbits.SectionObj)
489
490 t := pr.tempReader(pkgbits.SectionObj, idx, pkgbits.SyncObject1)
491 t.dict = pr.objDictIdx(idx)
492
493 pos := t.pos()
494 assert(t.Bool())
495 pkg, name := t.selector()
496 rtparams := t.typeParamNames(true, true)
497 recv := t.param()
498 methodIdx := -1
499 if r.Version().Has(pkgbits.PreserveMethodOrder) {
500 methodIdx = t.Len()
501 }
502 tparams := t.typeParamNames(true, false)
503 sig := t.signature(recv, rtparams, tparams)
504
505 r.delayed = append(r.delayed, t.delayed...)
506 pr.retireReader(t)
507 methods = append(methods, indexedMethod{methodIdx, types2.NewFunc(pos, pkg, name, sig)})
508 }
509
510 if r.Version().Has(pkgbits.PreserveMethodOrder) {
511 slices.SortFunc(methods, func(a, b indexedMethod) int {
512 return cmp.Compare(a.index, b.index)
513 })
514 }
515 } else {
516 for range r.Len() {
517 _, m := r.method(true)
518 methods = append(methods, indexedMethod{-1, m})
519 }
520 }
521
522 funcs := make([]*types2.Func, len(methods))
523 for i, m := range methods {
524 funcs[i] = m.fn
525 }
526
527 return tparams, underlying, funcs, r.delayed
528 })
529
530 case pkgbits.ObjVar:
531 pos := r.pos()
532 typ := r.typ()
533 return types2.NewVar(pos, objPkg, objName, typ)
534 }
535 })
536
537 return objPkg, objName
538 }
539
540 func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict {
541 var dict readerDict
542 {
543 r := pr.tempReader(pkgbits.SectionObjDict, idx, pkgbits.SyncObject1)
544
545 if implicits := r.Len(); implicits != 0 {
546 base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits)
547 }
548
549 nreceivers := 0
550 if r.Version().Has(pkgbits.GenericMethods) {
551 nreceivers = r.Len()
552 }
553 nexplicits := r.Len()
554
555 dict.rtbounds = make([]typeInfo, nreceivers)
556 for i := range dict.rtbounds {
557 dict.rtbounds[i] = r.typInfo()
558 }
559
560 dict.tbounds = make([]typeInfo, nexplicits)
561 for i := range dict.tbounds {
562 dict.tbounds[i] = r.typInfo()
563 }
564
565 dict.derived = make([]derivedInfo, r.Len())
566 dict.derivedTypes = make([]types2.Type, len(dict.derived))
567 for i := range dict.derived {
568 dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.SectionType)}
569 if r.Version().Has(pkgbits.DerivedInfoNeeded) {
570 assert(!r.Bool())
571 }
572 }
573
574 pr.retireReader(r)
575 }
576
577
578 return &dict
579 }
580
581 func (r *reader) typeParamNames(isLazy bool, isGenMeth bool) []*types2.TypeParam {
582 r.Sync(pkgbits.SyncTypeParamNames)
583
584
585
586
587
588 var in []typeInfo
589 var out *[]*types2.TypeParam
590 if isGenMeth {
591 in = r.dict.rtbounds
592 out = &r.dict.rtparams
593 } else {
594 in = r.dict.tbounds
595 out = &r.dict.tparams
596 }
597
598 if len(in) == 0 {
599 return nil
600 }
601
602
603
604
605
606
607
608
609 tparams := make([]*types2.TypeParam, len(in))
610 *out = tparams
611
612 for i := range in {
613 pos := r.pos()
614 pkg, name := r.localIdent()
615
616 tname := types2.NewTypeName(pos, pkg, name, nil)
617 tparams[i] = types2.NewTypeParam(tname, nil)
618 }
619
620
621
622 if isLazy {
623
624
625 types := make([]types2.Type, len(in))
626 for i, info := range in {
627 types[i] = r.p.typIdx(info, r.dict)
628 }
629
630 r.delayed = append(r.delayed, func() {
631 for i, typ := range types {
632 tparams[i].SetConstraint(typ)
633 }
634 })
635 } else {
636 for i, info := range in {
637 tparams[i].SetConstraint(r.p.typIdx(info, r.dict))
638 }
639 }
640
641 return tparams
642 }
643
644 func (r *reader) method(isLazy bool) (int, *types2.Func) {
645 r.Sync(pkgbits.SyncMethod)
646 idx := -1
647 if r.Version().Has(pkgbits.PreserveMethodOrder) {
648 idx = r.Len()
649 }
650 pos := r.pos()
651 pkg, name := r.selector()
652
653 rtparams := r.typeParamNames(isLazy, false)
654 sig := r.signature(r.param(), rtparams, nil)
655
656 _ = r.pos()
657 return idx, types2.NewFunc(pos, pkg, name, sig)
658 }
659
660 func (r *reader) qualifiedIdent() (*types2.Package, string) { return r.ident(pkgbits.SyncSym) }
661 func (r *reader) localIdent() (*types2.Package, string) { return r.ident(pkgbits.SyncLocalIdent) }
662 func (r *reader) selector() (*types2.Package, string) { return r.ident(pkgbits.SyncSelector) }
663
664 func (r *reader) ident(marker pkgbits.SyncMarker) (*types2.Package, string) {
665 r.Sync(marker)
666 return r.pkg(), r.String()
667 }
668
669
670 func newAliasTypeName(aliases bool, pos syntax.Pos, pkg *types2.Package, name string, rhs types2.Type, tparams []*types2.TypeParam) *types2.TypeName {
671
672
673 if aliases {
674 tname := types2.NewTypeName(pos, pkg, name, nil)
675 a := types2.NewAlias(tname, rhs)
676 a.SetTypeParams(tparams)
677 return tname
678 }
679 assert(len(tparams) == 0)
680 return types2.NewTypeName(pos, pkg, name, rhs)
681 }
682
View as plain text