1
2
3
4
5
6
7
8 package gcimporter
9
10 import (
11 "bufio"
12 "bytes"
13 "encoding/binary"
14 "fmt"
15 "go/constant"
16 "go/token"
17 "go/types"
18 "internal/saferio"
19 "io"
20 "math"
21 "math/big"
22 "slices"
23 "strings"
24 )
25
26 type intReader struct {
27 *bufio.Reader
28 path string
29 }
30
31 func (r *intReader) int64() int64 {
32 i, err := binary.ReadVarint(r.Reader)
33 if err != nil {
34 errorf("import %q: read varint error: %v", r.path, err)
35 }
36 return i
37 }
38
39 func (r *intReader) uint64() uint64 {
40 i, err := binary.ReadUvarint(r.Reader)
41 if err != nil {
42 errorf("import %q: read varint error: %v", r.path, err)
43 }
44 return i
45 }
46
47
48 const (
49 iexportVersionGo1_11 = 0
50 iexportVersionPosCol = 1
51 iexportVersionGenerics = 2
52 iexportVersionGo1_18 = 2
53
54 iexportVersionCurrent = 2
55 )
56
57 type ident struct {
58 pkg *types.Package
59 name string
60 }
61
62 const predeclReserved = 32
63
64 type itag uint64
65
66 const (
67
68 definedType itag = iota
69 pointerType
70 sliceType
71 arrayType
72 chanType
73 mapType
74 signatureType
75 structType
76 interfaceType
77 typeParamType
78 instanceType
79 unionType
80 )
81
82
83
84
85
86 func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataReader *bufio.Reader, path string) (pkg *types.Package, err error) {
87 const currentVersion = iexportVersionCurrent
88 version := int64(-1)
89 defer func() {
90 if e := recover(); e != nil {
91 if version > currentVersion {
92 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
93 } else {
94 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
95 }
96 }
97 }()
98
99 r := &intReader{dataReader, path}
100
101 version = int64(r.uint64())
102 switch version {
103 case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11:
104 default:
105 errorf("unknown iexport format version %d", version)
106 }
107
108 sLen := r.uint64()
109 dLen := r.uint64()
110
111 if sLen > math.MaxUint64-dLen {
112 errorf("lengths out of range (%d, %d)", sLen, dLen)
113 }
114
115 data, err := saferio.ReadData(r, sLen+dLen)
116 if err != nil {
117 errorf("cannot read %d bytes of stringData and declData: %s", sLen+dLen, err)
118 }
119 stringData := data[:sLen]
120 declData := data[sLen:]
121
122 p := iimporter{
123 exportVersion: version,
124 ipath: path,
125 version: int(version),
126
127 stringData: stringData,
128 stringCache: make(map[uint64]string),
129 pkgCache: make(map[uint64]*types.Package),
130
131 declData: declData,
132 pkgIndex: make(map[*types.Package]map[string]uint64),
133 typCache: make(map[uint64]types.Type),
134
135
136 tparamIndex: make(map[ident]*types.TypeParam),
137
138 fake: fakeFileSet{
139 fset: fset,
140 files: make(map[string]*fileInfo),
141 },
142 }
143 defer p.fake.setLines()
144
145 for i, pt := range predeclared {
146 p.typCache[uint64(i)] = pt
147 }
148
149
150 p.typCache[uint64(len(predeclared))] = types.Universe.Lookup("any").Type()
151
152 pkgList := make([]*types.Package, r.uint64())
153 for i := range pkgList {
154 pkgPathOff := r.uint64()
155 pkgPath := p.stringAt(pkgPathOff)
156 pkgName := p.stringAt(r.uint64())
157 _ = r.uint64()
158
159 if pkgPath == "" {
160 pkgPath = path
161 }
162 pkg := imports[pkgPath]
163 if pkg == nil {
164 pkg = types.NewPackage(pkgPath, pkgName)
165 imports[pkgPath] = pkg
166 } else if pkg.Name() != pkgName {
167 errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
168 }
169
170 p.pkgCache[pkgPathOff] = pkg
171
172 nameIndex := make(map[string]uint64)
173 for nSyms := r.uint64(); nSyms > 0; nSyms-- {
174 name := p.stringAt(r.uint64())
175 nameIndex[name] = r.uint64()
176 }
177
178 p.pkgIndex[pkg] = nameIndex
179 pkgList[i] = pkg
180 }
181
182 localpkg := pkgList[0]
183
184 names := make([]string, 0, len(p.pkgIndex[localpkg]))
185 for name := range p.pkgIndex[localpkg] {
186 names = append(names, name)
187 }
188 slices.Sort(names)
189 for _, name := range names {
190 p.doDecl(localpkg, name)
191 }
192
193
194
195
196
197
198 for _, d := range p.later {
199 d.t.SetConstraint(d.constraint)
200 }
201
202 for _, typ := range p.interfaceList {
203 typ.Complete()
204 }
205
206
207 list := append(([]*types.Package)(nil), pkgList[1:]...)
208 slices.SortFunc(list, func(a, b *types.Package) int {
209 return strings.Compare(a.Path(), b.Path())
210 })
211 localpkg.SetImports(list)
212
213
214 localpkg.MarkComplete()
215 return localpkg, nil
216 }
217
218 type setConstraintArgs struct {
219 t *types.TypeParam
220 constraint types.Type
221 }
222
223 type iimporter struct {
224 exportVersion int64
225 ipath string
226 version int
227
228 stringData []byte
229 stringCache map[uint64]string
230 pkgCache map[uint64]*types.Package
231
232 declData []byte
233 pkgIndex map[*types.Package]map[string]uint64
234 typCache map[uint64]types.Type
235 tparamIndex map[ident]*types.TypeParam
236
237 fake fakeFileSet
238 interfaceList []*types.Interface
239
240
241 later []setConstraintArgs
242 }
243
244 func (p *iimporter) doDecl(pkg *types.Package, name string) {
245
246 if obj := pkg.Scope().Lookup(name); obj != nil {
247 return
248 }
249
250 off, ok := p.pkgIndex[pkg][name]
251 if !ok {
252 errorf("%v.%v not in index", pkg, name)
253 }
254
255 r := &importReader{p: p, currPkg: pkg}
256 r.declReader.Reset(p.declData[off:])
257
258 r.obj(name)
259 }
260
261 func (p *iimporter) stringAt(off uint64) string {
262 if s, ok := p.stringCache[off]; ok {
263 return s
264 }
265
266 slen, n := binary.Uvarint(p.stringData[off:])
267 if n <= 0 {
268 errorf("varint failed")
269 }
270 spos := off + uint64(n)
271 s := string(p.stringData[spos : spos+slen])
272 p.stringCache[off] = s
273 return s
274 }
275
276 func (p *iimporter) pkgAt(off uint64) *types.Package {
277 if pkg, ok := p.pkgCache[off]; ok {
278 return pkg
279 }
280 path := p.stringAt(off)
281 errorf("missing package %q in %q", path, p.ipath)
282 return nil
283 }
284
285 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
286 if t, ok := p.typCache[off]; ok && canReuse(base, t) {
287 return t
288 }
289
290 if off < predeclReserved {
291 errorf("predeclared type missing from cache: %v", off)
292 }
293
294 r := &importReader{p: p}
295 r.declReader.Reset(p.declData[off-predeclReserved:])
296 t := r.doType(base)
297
298 if canReuse(base, t) {
299 p.typCache[off] = t
300 }
301 return t
302 }
303
304
305
306
307
308
309
310 func canReuse(def *types.Named, rhs types.Type) bool {
311 if def == nil {
312 return true
313 }
314 iface, _ := rhs.(*types.Interface)
315 if iface == nil {
316 return true
317 }
318
319 return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0
320 }
321
322 type importReader struct {
323 p *iimporter
324 declReader bytes.Reader
325 currPkg *types.Package
326 prevFile string
327 prevLine int64
328 prevColumn int64
329 }
330
331 func (r *importReader) obj(name string) {
332 tag := r.byte()
333 pos := r.pos()
334
335 switch tag {
336 case 'A':
337 typ := r.typ()
338
339 r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
340
341 case 'C':
342 typ, val := r.value()
343
344 r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
345
346 case 'F', 'G':
347 var tparams []*types.TypeParam
348 if tag == 'G' {
349 tparams = r.tparamList()
350 }
351 sig := r.signature(nil, nil, tparams)
352 r.declare(types.NewFunc(pos, r.currPkg, name, sig))
353
354 case 'T', 'U':
355
356
357 obj := types.NewTypeName(pos, r.currPkg, name, nil)
358 named := types.NewNamed(obj, nil, nil)
359
360
361 r.declare(obj)
362 if tag == 'U' {
363 tparams := r.tparamList()
364 named.SetTypeParams(tparams)
365 }
366
367 underlying := r.p.typAt(r.uint64(), named).Underlying()
368 named.SetUnderlying(underlying)
369
370 if !isInterface(underlying) {
371 for n := r.uint64(); n > 0; n-- {
372 mpos := r.pos()
373 mname := r.ident()
374 recv := r.param()
375
376
377
378
379 targs := baseType(recv.Type()).TypeArgs()
380 var rparams []*types.TypeParam
381 if targs.Len() > 0 {
382 rparams = make([]*types.TypeParam, targs.Len())
383 for i := range rparams {
384 rparams[i], _ = targs.At(i).(*types.TypeParam)
385 }
386 }
387 msig := r.signature(recv, rparams, nil)
388
389 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
390 }
391 }
392
393 case 'P':
394
395
396
397 if r.p.exportVersion < iexportVersionGenerics {
398 errorf("unexpected type param type")
399 }
400
401
402 name0 := tparamName(name)
403 tn := types.NewTypeName(pos, r.currPkg, name0, nil)
404 t := types.NewTypeParam(tn, nil)
405
406
407 id := ident{r.currPkg, name}
408 r.p.tparamIndex[id] = t
409
410 var implicit bool
411 if r.p.exportVersion >= iexportVersionGo1_18 {
412 implicit = r.bool()
413 }
414 constraint := r.typ()
415 if implicit {
416 iface, _ := constraint.(*types.Interface)
417 if iface == nil {
418 errorf("non-interface constraint marked implicit")
419 }
420 iface.MarkImplicit()
421 }
422
423
424
425
426 r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
427
428 case 'V':
429 typ := r.typ()
430
431 r.declare(types.NewVar(pos, r.currPkg, name, typ))
432
433 default:
434 errorf("unexpected tag: %v", tag)
435 }
436 }
437
438 func (r *importReader) declare(obj types.Object) {
439 obj.Pkg().Scope().Insert(obj)
440 }
441
442 func (r *importReader) value() (typ types.Type, val constant.Value) {
443 typ = r.typ()
444 if r.p.exportVersion >= iexportVersionGo1_18 {
445
446 _ = constant.Kind(r.int64())
447 }
448
449 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
450 case types.IsBoolean:
451 val = constant.MakeBool(r.bool())
452
453 case types.IsString:
454 val = constant.MakeString(r.string())
455
456 case types.IsInteger:
457 var x big.Int
458 r.mpint(&x, b)
459 val = constant.Make(&x)
460
461 case types.IsFloat:
462 val = r.mpfloat(b)
463
464 case types.IsComplex:
465 re := r.mpfloat(b)
466 im := r.mpfloat(b)
467 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
468
469 default:
470 errorf("unexpected type %v", typ)
471 panic("unreachable")
472 }
473
474 return
475 }
476
477 func intSize(b *types.Basic) (signed bool, maxBytes uint) {
478 if (b.Info() & types.IsUntyped) != 0 {
479 return true, 64
480 }
481
482 switch b.Kind() {
483 case types.Float32, types.Complex64:
484 return true, 3
485 case types.Float64, types.Complex128:
486 return true, 7
487 }
488
489 signed = (b.Info() & types.IsUnsigned) == 0
490 switch b.Kind() {
491 case types.Int8, types.Uint8:
492 maxBytes = 1
493 case types.Int16, types.Uint16:
494 maxBytes = 2
495 case types.Int32, types.Uint32:
496 maxBytes = 4
497 default:
498 maxBytes = 8
499 }
500
501 return
502 }
503
504 func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
505 signed, maxBytes := intSize(typ)
506
507 maxSmall := 256 - maxBytes
508 if signed {
509 maxSmall = 256 - 2*maxBytes
510 }
511 if maxBytes == 1 {
512 maxSmall = 256
513 }
514
515 n, _ := r.declReader.ReadByte()
516 if uint(n) < maxSmall {
517 v := int64(n)
518 if signed {
519 v >>= 1
520 if n&1 != 0 {
521 v = ^v
522 }
523 }
524 x.SetInt64(v)
525 return
526 }
527
528 v := -n
529 if signed {
530 v = -(n &^ 1) >> 1
531 }
532 if v < 1 || uint(v) > maxBytes {
533 errorf("weird decoding: %v, %v => %v", n, signed, v)
534 }
535 b := make([]byte, v)
536 io.ReadFull(&r.declReader, b)
537 x.SetBytes(b)
538 if signed && n&1 != 0 {
539 x.Neg(x)
540 }
541 }
542
543 func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
544 var mant big.Int
545 r.mpint(&mant, typ)
546 var f big.Float
547 f.SetInt(&mant)
548 if f.Sign() != 0 {
549 f.SetMantExp(&f, int(r.int64()))
550 }
551 return constant.Make(&f)
552 }
553
554 func (r *importReader) ident() string {
555 return r.string()
556 }
557
558 func (r *importReader) qualifiedIdent() (*types.Package, string) {
559 name := r.string()
560 pkg := r.pkg()
561 return pkg, name
562 }
563
564 func (r *importReader) pos() token.Pos {
565 if r.p.version >= 1 {
566 r.posv1()
567 } else {
568 r.posv0()
569 }
570
571 if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
572 return token.NoPos
573 }
574 return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
575 }
576
577 func (r *importReader) posv0() {
578 delta := r.int64()
579 if delta != deltaNewFile {
580 r.prevLine += delta
581 } else if l := r.int64(); l == -1 {
582 r.prevLine += deltaNewFile
583 } else {
584 r.prevFile = r.string()
585 r.prevLine = l
586 }
587 }
588
589 func (r *importReader) posv1() {
590 delta := r.int64()
591 r.prevColumn += delta >> 1
592 if delta&1 != 0 {
593 delta = r.int64()
594 r.prevLine += delta >> 1
595 if delta&1 != 0 {
596 r.prevFile = r.string()
597 }
598 }
599 }
600
601 func (r *importReader) typ() types.Type {
602 return r.p.typAt(r.uint64(), nil)
603 }
604
605 func isInterface(t types.Type) bool {
606 _, ok := t.(*types.Interface)
607 return ok
608 }
609
610 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
611 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
612
613 func (r *importReader) doType(base *types.Named) types.Type {
614 switch k := r.kind(); k {
615 default:
616 errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
617 return nil
618
619 case definedType:
620 pkg, name := r.qualifiedIdent()
621 r.p.doDecl(pkg, name)
622 return pkg.Scope().Lookup(name).(*types.TypeName).Type()
623 case pointerType:
624 return types.NewPointer(r.typ())
625 case sliceType:
626 return types.NewSlice(r.typ())
627 case arrayType:
628 n := r.uint64()
629 return types.NewArray(r.typ(), int64(n))
630 case chanType:
631 dir := chanDir(int(r.uint64()))
632 return types.NewChan(dir, r.typ())
633 case mapType:
634 return types.NewMap(r.typ(), r.typ())
635 case signatureType:
636 r.currPkg = r.pkg()
637 return r.signature(nil, nil, nil)
638
639 case structType:
640 r.currPkg = r.pkg()
641
642 fields := make([]*types.Var, r.uint64())
643 tags := make([]string, len(fields))
644 for i := range fields {
645 fpos := r.pos()
646 fname := r.ident()
647 ftyp := r.typ()
648 emb := r.bool()
649 tag := r.string()
650
651 fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
652 tags[i] = tag
653 }
654 return types.NewStruct(fields, tags)
655
656 case interfaceType:
657 r.currPkg = r.pkg()
658
659 embeddeds := make([]types.Type, r.uint64())
660 for i := range embeddeds {
661 _ = r.pos()
662 embeddeds[i] = r.typ()
663 }
664
665 methods := make([]*types.Func, r.uint64())
666 for i := range methods {
667 mpos := r.pos()
668 mname := r.ident()
669
670
671
672 var recv *types.Var
673 if base != nil {
674 recv = types.NewVar(token.NoPos, r.currPkg, "", base)
675 }
676
677 msig := r.signature(recv, nil, nil)
678 methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
679 }
680
681 typ := types.NewInterfaceType(methods, embeddeds)
682 r.p.interfaceList = append(r.p.interfaceList, typ)
683 return typ
684
685 case typeParamType:
686 if r.p.exportVersion < iexportVersionGenerics {
687 errorf("unexpected type param type")
688 }
689 pkg, name := r.qualifiedIdent()
690 id := ident{pkg, name}
691 if t, ok := r.p.tparamIndex[id]; ok {
692
693 return t
694 }
695
696 r.p.doDecl(pkg, name)
697 return r.p.tparamIndex[id]
698
699 case instanceType:
700 if r.p.exportVersion < iexportVersionGenerics {
701 errorf("unexpected instantiation type")
702 }
703
704
705 _ = r.pos()
706 len := r.uint64()
707 targs := make([]types.Type, len)
708 for i := range targs {
709 targs[i] = r.typ()
710 }
711 baseType := r.typ()
712
713
714
715 t, _ := types.Instantiate(nil, baseType, targs, false)
716 return t
717
718 case unionType:
719 if r.p.exportVersion < iexportVersionGenerics {
720 errorf("unexpected instantiation type")
721 }
722 terms := make([]*types.Term, r.uint64())
723 for i := range terms {
724 terms[i] = types.NewTerm(r.bool(), r.typ())
725 }
726 return types.NewUnion(terms)
727 }
728 }
729
730 func (r *importReader) kind() itag {
731 return itag(r.uint64())
732 }
733
734 func (r *importReader) signature(recv *types.Var, rparams, tparams []*types.TypeParam) *types.Signature {
735 params := r.paramList()
736 results := r.paramList()
737 variadic := params.Len() > 0 && r.bool()
738 return types.NewSignatureType(recv, rparams, tparams, params, results, variadic)
739 }
740
741 func (r *importReader) tparamList() []*types.TypeParam {
742 n := r.uint64()
743 if n == 0 {
744 return nil
745 }
746 xs := make([]*types.TypeParam, n)
747 for i := range xs {
748 xs[i], _ = r.typ().(*types.TypeParam)
749 }
750 return xs
751 }
752
753 func (r *importReader) paramList() *types.Tuple {
754 xs := make([]*types.Var, r.uint64())
755 for i := range xs {
756 xs[i] = r.param()
757 }
758 return types.NewTuple(xs...)
759 }
760
761 func (r *importReader) param() *types.Var {
762 pos := r.pos()
763 name := r.ident()
764 typ := r.typ()
765 return types.NewParam(pos, r.currPkg, name, typ)
766 }
767
768 func (r *importReader) bool() bool {
769 return r.uint64() != 0
770 }
771
772 func (r *importReader) int64() int64 {
773 n, err := binary.ReadVarint(&r.declReader)
774 if err != nil {
775 errorf("readVarint: %v", err)
776 }
777 return n
778 }
779
780 func (r *importReader) uint64() uint64 {
781 n, err := binary.ReadUvarint(&r.declReader)
782 if err != nil {
783 errorf("readUvarint: %v", err)
784 }
785 return n
786 }
787
788 func (r *importReader) byte() byte {
789 x, err := r.declReader.ReadByte()
790 if err != nil {
791 errorf("declReader.ReadByte: %v", err)
792 }
793 return x
794 }
795
796 func baseType(typ types.Type) *types.Named {
797
798 if p, _ := typ.(*types.Pointer); p != nil {
799 typ = p.Elem()
800 }
801
802 n, _ := typ.(*types.Named)
803 return n
804 }
805
806 const blankMarker = "$"
807
808
809
810
811 func tparamName(exportName string) string {
812
813 ix := strings.LastIndex(exportName, ".")
814 if ix < 0 {
815 errorf("malformed type parameter export name %s: missing prefix", exportName)
816 }
817 name := exportName[ix+1:]
818 if strings.HasPrefix(name, blankMarker) {
819 return "_"
820 }
821 return name
822 }
823
View as plain text