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