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