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 "sort"
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 sort.Strings(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 sort.Sort(byPath(list))
209 localpkg.SetImports(list)
210
211
212 localpkg.MarkComplete()
213 return localpkg, nil
214 }
215
216 type setConstraintArgs struct {
217 t *types.TypeParam
218 constraint types.Type
219 }
220
221 type iimporter struct {
222 exportVersion int64
223 ipath string
224 version int
225
226 stringData []byte
227 stringCache map[uint64]string
228 pkgCache map[uint64]*types.Package
229
230 declData []byte
231 pkgIndex map[*types.Package]map[string]uint64
232 typCache map[uint64]types.Type
233 tparamIndex map[ident]*types.TypeParam
234
235 fake fakeFileSet
236 interfaceList []*types.Interface
237
238
239 later []setConstraintArgs
240 }
241
242 func (p *iimporter) doDecl(pkg *types.Package, name string) {
243
244 if obj := pkg.Scope().Lookup(name); obj != nil {
245 return
246 }
247
248 off, ok := p.pkgIndex[pkg][name]
249 if !ok {
250 errorf("%v.%v not in index", pkg, name)
251 }
252
253 r := &importReader{p: p, currPkg: pkg}
254 r.declReader.Reset(p.declData[off:])
255
256 r.obj(name)
257 }
258
259 func (p *iimporter) stringAt(off uint64) string {
260 if s, ok := p.stringCache[off]; ok {
261 return s
262 }
263
264 slen, n := binary.Uvarint(p.stringData[off:])
265 if n <= 0 {
266 errorf("varint failed")
267 }
268 spos := off + uint64(n)
269 s := string(p.stringData[spos : spos+slen])
270 p.stringCache[off] = s
271 return s
272 }
273
274 func (p *iimporter) pkgAt(off uint64) *types.Package {
275 if pkg, ok := p.pkgCache[off]; ok {
276 return pkg
277 }
278 path := p.stringAt(off)
279 errorf("missing package %q in %q", path, p.ipath)
280 return nil
281 }
282
283 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
284 if t, ok := p.typCache[off]; ok && canReuse(base, t) {
285 return t
286 }
287
288 if off < predeclReserved {
289 errorf("predeclared type missing from cache: %v", off)
290 }
291
292 r := &importReader{p: p}
293 r.declReader.Reset(p.declData[off-predeclReserved:])
294 t := r.doType(base)
295
296 if canReuse(base, t) {
297 p.typCache[off] = t
298 }
299 return t
300 }
301
302
303
304
305
306
307
308 func canReuse(def *types.Named, rhs types.Type) bool {
309 if def == nil {
310 return true
311 }
312 iface, _ := rhs.(*types.Interface)
313 if iface == nil {
314 return true
315 }
316
317 return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0
318 }
319
320 type importReader struct {
321 p *iimporter
322 declReader bytes.Reader
323 currPkg *types.Package
324 prevFile string
325 prevLine int64
326 prevColumn int64
327 }
328
329 func (r *importReader) obj(name string) {
330 tag := r.byte()
331 pos := r.pos()
332
333 switch tag {
334 case 'A':
335 typ := r.typ()
336
337 r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
338
339 case 'C':
340 typ, val := r.value()
341
342 r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
343
344 case 'F', 'G':
345 var tparams []*types.TypeParam
346 if tag == 'G' {
347 tparams = r.tparamList()
348 }
349 sig := r.signature(nil, nil, tparams)
350 r.declare(types.NewFunc(pos, r.currPkg, name, sig))
351
352 case 'T', 'U':
353
354
355 obj := types.NewTypeName(pos, r.currPkg, name, nil)
356 named := types.NewNamed(obj, nil, nil)
357
358
359 r.declare(obj)
360 if tag == 'U' {
361 tparams := r.tparamList()
362 named.SetTypeParams(tparams)
363 }
364
365 underlying := r.p.typAt(r.uint64(), named).Underlying()
366 named.SetUnderlying(underlying)
367
368 if !isInterface(underlying) {
369 for n := r.uint64(); n > 0; n-- {
370 mpos := r.pos()
371 mname := r.ident()
372 recv := r.param()
373
374
375
376
377 targs := baseType(recv.Type()).TypeArgs()
378 var rparams []*types.TypeParam
379 if targs.Len() > 0 {
380 rparams = make([]*types.TypeParam, targs.Len())
381 for i := range rparams {
382 rparams[i], _ = targs.At(i).(*types.TypeParam)
383 }
384 }
385 msig := r.signature(recv, rparams, nil)
386
387 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
388 }
389 }
390
391 case 'P':
392
393
394
395 if r.p.exportVersion < iexportVersionGenerics {
396 errorf("unexpected type param type")
397 }
398
399
400 name0 := tparamName(name)
401 tn := types.NewTypeName(pos, r.currPkg, name0, nil)
402 t := types.NewTypeParam(tn, nil)
403
404
405 id := ident{r.currPkg, name}
406 r.p.tparamIndex[id] = t
407
408 var implicit bool
409 if r.p.exportVersion >= iexportVersionGo1_18 {
410 implicit = r.bool()
411 }
412 constraint := r.typ()
413 if implicit {
414 iface, _ := constraint.(*types.Interface)
415 if iface == nil {
416 errorf("non-interface constraint marked implicit")
417 }
418 iface.MarkImplicit()
419 }
420
421
422
423
424 r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint})
425
426 case 'V':
427 typ := r.typ()
428
429 r.declare(types.NewVar(pos, r.currPkg, name, typ))
430
431 default:
432 errorf("unexpected tag: %v", tag)
433 }
434 }
435
436 func (r *importReader) declare(obj types.Object) {
437 obj.Pkg().Scope().Insert(obj)
438 }
439
440 func (r *importReader) value() (typ types.Type, val constant.Value) {
441 typ = r.typ()
442 if r.p.exportVersion >= iexportVersionGo1_18 {
443
444 _ = constant.Kind(r.int64())
445 }
446
447 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
448 case types.IsBoolean:
449 val = constant.MakeBool(r.bool())
450
451 case types.IsString:
452 val = constant.MakeString(r.string())
453
454 case types.IsInteger:
455 var x big.Int
456 r.mpint(&x, b)
457 val = constant.Make(&x)
458
459 case types.IsFloat:
460 val = r.mpfloat(b)
461
462 case types.IsComplex:
463 re := r.mpfloat(b)
464 im := r.mpfloat(b)
465 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
466
467 default:
468 errorf("unexpected type %v", typ)
469 panic("unreachable")
470 }
471
472 return
473 }
474
475 func intSize(b *types.Basic) (signed bool, maxBytes uint) {
476 if (b.Info() & types.IsUntyped) != 0 {
477 return true, 64
478 }
479
480 switch b.Kind() {
481 case types.Float32, types.Complex64:
482 return true, 3
483 case types.Float64, types.Complex128:
484 return true, 7
485 }
486
487 signed = (b.Info() & types.IsUnsigned) == 0
488 switch b.Kind() {
489 case types.Int8, types.Uint8:
490 maxBytes = 1
491 case types.Int16, types.Uint16:
492 maxBytes = 2
493 case types.Int32, types.Uint32:
494 maxBytes = 4
495 default:
496 maxBytes = 8
497 }
498
499 return
500 }
501
502 func (r *importReader) mpint(x *big.Int, typ *types.Basic) {
503 signed, maxBytes := intSize(typ)
504
505 maxSmall := 256 - maxBytes
506 if signed {
507 maxSmall = 256 - 2*maxBytes
508 }
509 if maxBytes == 1 {
510 maxSmall = 256
511 }
512
513 n, _ := r.declReader.ReadByte()
514 if uint(n) < maxSmall {
515 v := int64(n)
516 if signed {
517 v >>= 1
518 if n&1 != 0 {
519 v = ^v
520 }
521 }
522 x.SetInt64(v)
523 return
524 }
525
526 v := -n
527 if signed {
528 v = -(n &^ 1) >> 1
529 }
530 if v < 1 || uint(v) > maxBytes {
531 errorf("weird decoding: %v, %v => %v", n, signed, v)
532 }
533 b := make([]byte, v)
534 io.ReadFull(&r.declReader, b)
535 x.SetBytes(b)
536 if signed && n&1 != 0 {
537 x.Neg(x)
538 }
539 }
540
541 func (r *importReader) mpfloat(typ *types.Basic) constant.Value {
542 var mant big.Int
543 r.mpint(&mant, typ)
544 var f big.Float
545 f.SetInt(&mant)
546 if f.Sign() != 0 {
547 f.SetMantExp(&f, int(r.int64()))
548 }
549 return constant.Make(&f)
550 }
551
552 func (r *importReader) ident() string {
553 return r.string()
554 }
555
556 func (r *importReader) qualifiedIdent() (*types.Package, string) {
557 name := r.string()
558 pkg := r.pkg()
559 return pkg, name
560 }
561
562 func (r *importReader) pos() token.Pos {
563 if r.p.version >= 1 {
564 r.posv1()
565 } else {
566 r.posv0()
567 }
568
569 if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
570 return token.NoPos
571 }
572 return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
573 }
574
575 func (r *importReader) posv0() {
576 delta := r.int64()
577 if delta != deltaNewFile {
578 r.prevLine += delta
579 } else if l := r.int64(); l == -1 {
580 r.prevLine += deltaNewFile
581 } else {
582 r.prevFile = r.string()
583 r.prevLine = l
584 }
585 }
586
587 func (r *importReader) posv1() {
588 delta := r.int64()
589 r.prevColumn += delta >> 1
590 if delta&1 != 0 {
591 delta = r.int64()
592 r.prevLine += delta >> 1
593 if delta&1 != 0 {
594 r.prevFile = r.string()
595 }
596 }
597 }
598
599 func (r *importReader) typ() types.Type {
600 return r.p.typAt(r.uint64(), nil)
601 }
602
603 func isInterface(t types.Type) bool {
604 _, ok := t.(*types.Interface)
605 return ok
606 }
607
608 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
609 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
610
611 func (r *importReader) doType(base *types.Named) types.Type {
612 switch k := r.kind(); k {
613 default:
614 errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
615 return nil
616
617 case definedType:
618 pkg, name := r.qualifiedIdent()
619 r.p.doDecl(pkg, name)
620 return pkg.Scope().Lookup(name).(*types.TypeName).Type()
621 case pointerType:
622 return types.NewPointer(r.typ())
623 case sliceType:
624 return types.NewSlice(r.typ())
625 case arrayType:
626 n := r.uint64()
627 return types.NewArray(r.typ(), int64(n))
628 case chanType:
629 dir := chanDir(int(r.uint64()))
630 return types.NewChan(dir, r.typ())
631 case mapType:
632 return types.NewMap(r.typ(), r.typ())
633 case signatureType:
634 r.currPkg = r.pkg()
635 return r.signature(nil, nil, nil)
636
637 case structType:
638 r.currPkg = r.pkg()
639
640 fields := make([]*types.Var, r.uint64())
641 tags := make([]string, len(fields))
642 for i := range fields {
643 fpos := r.pos()
644 fname := r.ident()
645 ftyp := r.typ()
646 emb := r.bool()
647 tag := r.string()
648
649 fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
650 tags[i] = tag
651 }
652 return types.NewStruct(fields, tags)
653
654 case interfaceType:
655 r.currPkg = r.pkg()
656
657 embeddeds := make([]types.Type, r.uint64())
658 for i := range embeddeds {
659 _ = r.pos()
660 embeddeds[i] = r.typ()
661 }
662
663 methods := make([]*types.Func, r.uint64())
664 for i := range methods {
665 mpos := r.pos()
666 mname := r.ident()
667
668
669
670 var recv *types.Var
671 if base != nil {
672 recv = types.NewVar(token.NoPos, r.currPkg, "", base)
673 }
674
675 msig := r.signature(recv, nil, nil)
676 methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
677 }
678
679 typ := types.NewInterfaceType(methods, embeddeds)
680 r.p.interfaceList = append(r.p.interfaceList, typ)
681 return typ
682
683 case typeParamType:
684 if r.p.exportVersion < iexportVersionGenerics {
685 errorf("unexpected type param type")
686 }
687 pkg, name := r.qualifiedIdent()
688 id := ident{pkg, name}
689 if t, ok := r.p.tparamIndex[id]; ok {
690
691 return t
692 }
693
694 r.p.doDecl(pkg, name)
695 return r.p.tparamIndex[id]
696
697 case instanceType:
698 if r.p.exportVersion < iexportVersionGenerics {
699 errorf("unexpected instantiation type")
700 }
701
702
703 _ = r.pos()
704 len := r.uint64()
705 targs := make([]types.Type, len)
706 for i := range targs {
707 targs[i] = r.typ()
708 }
709 baseType := r.typ()
710
711
712
713 t, _ := types.Instantiate(nil, baseType, targs, false)
714 return t
715
716 case unionType:
717 if r.p.exportVersion < iexportVersionGenerics {
718 errorf("unexpected instantiation type")
719 }
720 terms := make([]*types.Term, r.uint64())
721 for i := range terms {
722 terms[i] = types.NewTerm(r.bool(), r.typ())
723 }
724 return types.NewUnion(terms)
725 }
726 }
727
728 func (r *importReader) kind() itag {
729 return itag(r.uint64())
730 }
731
732 func (r *importReader) signature(recv *types.Var, rparams, tparams []*types.TypeParam) *types.Signature {
733 params := r.paramList()
734 results := r.paramList()
735 variadic := params.Len() > 0 && r.bool()
736 return types.NewSignatureType(recv, rparams, tparams, params, results, variadic)
737 }
738
739 func (r *importReader) tparamList() []*types.TypeParam {
740 n := r.uint64()
741 if n == 0 {
742 return nil
743 }
744 xs := make([]*types.TypeParam, n)
745 for i := range xs {
746 xs[i], _ = r.typ().(*types.TypeParam)
747 }
748 return xs
749 }
750
751 func (r *importReader) paramList() *types.Tuple {
752 xs := make([]*types.Var, r.uint64())
753 for i := range xs {
754 xs[i] = r.param()
755 }
756 return types.NewTuple(xs...)
757 }
758
759 func (r *importReader) param() *types.Var {
760 pos := r.pos()
761 name := r.ident()
762 typ := r.typ()
763 return types.NewParam(pos, r.currPkg, name, typ)
764 }
765
766 func (r *importReader) bool() bool {
767 return r.uint64() != 0
768 }
769
770 func (r *importReader) int64() int64 {
771 n, err := binary.ReadVarint(&r.declReader)
772 if err != nil {
773 errorf("readVarint: %v", err)
774 }
775 return n
776 }
777
778 func (r *importReader) uint64() uint64 {
779 n, err := binary.ReadUvarint(&r.declReader)
780 if err != nil {
781 errorf("readUvarint: %v", err)
782 }
783 return n
784 }
785
786 func (r *importReader) byte() byte {
787 x, err := r.declReader.ReadByte()
788 if err != nil {
789 errorf("declReader.ReadByte: %v", err)
790 }
791 return x
792 }
793
794 func baseType(typ types.Type) *types.Named {
795
796 if p, _ := typ.(*types.Pointer); p != nil {
797 typ = p.Elem()
798 }
799
800 n, _ := typ.(*types.Named)
801 return n
802 }
803
804 const blankMarker = "$"
805
806
807
808
809 func tparamName(exportName string) string {
810
811 ix := strings.LastIndex(exportName, ".")
812 if ix < 0 {
813 errorf("malformed type parameter export name %s: missing prefix", exportName)
814 }
815 name := exportName[ix+1:]
816 if strings.HasPrefix(name, blankMarker) {
817 return "_"
818 }
819 return name
820 }
821
View as plain text