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