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