Source file src/go/internal/gcimporter/bimport.go
1
2
3
4
5 package gcimporter
6
7 import (
8 "encoding/binary"
9 "fmt"
10 "go/constant"
11 "go/token"
12 "go/types"
13 "sort"
14 "strconv"
15 "strings"
16 "sync"
17 )
18
19 type importer struct {
20 imports map[string]*types.Package
21 data []byte
22 importpath string
23 buf []byte
24 version int
25
26
27 strList []string
28 pathList []string
29 pkgList []*types.Package
30 typList []types.Type
31 interfaceList []*types.Interface
32 trackAllTypes bool
33
34
35 posInfoFormat bool
36 prevFile string
37 prevLine int
38 fake fakeFileSet
39
40
41 debugFormat bool
42 read int
43 }
44
45
46
47
48
49 func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
50
51 const currentVersion = 6
52 version := -1
53 defer func() {
54 if e := recover(); e != nil {
55
56 if version > currentVersion {
57 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
58 } else {
59 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
60 }
61 }
62 }()
63
64 p := importer{
65 imports: imports,
66 data: data,
67 importpath: path,
68 version: version,
69 strList: []string{""},
70 pathList: []string{""},
71 fake: fakeFileSet{
72 fset: fset,
73 files: make(map[string]*token.File),
74 },
75 }
76
77
78 var versionstr string
79 if b := p.rawByte(); b == 'c' || b == 'd' {
80
81
82
83
84
85
86 if b == 'd' {
87 p.debugFormat = true
88 }
89 p.trackAllTypes = p.rawByte() == 'a'
90 p.posInfoFormat = p.int() != 0
91 versionstr = p.string()
92 if versionstr == "v1" {
93 version = 0
94 }
95 } else {
96
97
98 versionstr = p.rawStringln(b)
99 if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
100 if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
101 version = v
102 }
103 }
104 }
105 p.version = version
106
107
108 switch p.version {
109
110
111
112 case currentVersion, 5, 4, 3, 2, 1:
113 p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
114 p.trackAllTypes = p.int() != 0
115 p.posInfoFormat = p.int() != 0
116 case 0:
117
118 default:
119 errorf("unknown bexport format version %d (%q)", p.version, versionstr)
120 }
121
122
123
124
125 p.typList = append(p.typList, predeclared...)
126
127
128 pkg = p.pkg()
129
130
131 objcount := 0
132 for {
133 tag := p.tagOrIndex()
134 if tag == endTag {
135 break
136 }
137 p.obj(tag)
138 objcount++
139 }
140
141
142 if count := p.int(); count != objcount {
143 errorf("got %d objects; want %d", objcount, count)
144 }
145
146
147
148
149
150 for _, typ := range p.interfaceList {
151 typ.Complete()
152 }
153
154
155 list := append(([]*types.Package)(nil), p.pkgList[1:]...)
156 sort.Sort(byPath(list))
157 pkg.SetImports(list)
158
159
160 pkg.MarkComplete()
161
162 return p.read, pkg, nil
163 }
164
165 func errorf(format string, args ...interface{}) {
166 panic(fmt.Sprintf(format, args...))
167 }
168
169 func (p *importer) pkg() *types.Package {
170
171 i := p.tagOrIndex()
172 if i >= 0 {
173 return p.pkgList[i]
174 }
175
176
177 if i != packageTag {
178 errorf("unexpected package tag %d version %d", i, p.version)
179 }
180
181
182 name := p.string()
183 var path string
184 if p.version >= 5 {
185 path = p.path()
186 } else {
187 path = p.string()
188 }
189 if p.version >= 6 {
190 p.int()
191 }
192
193
194 if name == "" {
195 errorf("empty package name in import")
196 }
197
198
199
200 if (path == "") != (len(p.pkgList) == 0) {
201 errorf("package path %q for pkg index %d", path, len(p.pkgList))
202 }
203
204
205 if path == "" {
206 path = p.importpath
207 }
208 pkg := p.imports[path]
209 if pkg == nil {
210 pkg = types.NewPackage(path, name)
211 p.imports[path] = pkg
212 } else if pkg.Name() != name {
213 errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path)
214 }
215 p.pkgList = append(p.pkgList, pkg)
216
217 return pkg
218 }
219
220
221 func objTag(obj types.Object) int {
222 switch obj.(type) {
223 case *types.Const:
224 return constTag
225 case *types.TypeName:
226 return typeTag
227 case *types.Var:
228 return varTag
229 case *types.Func:
230 return funcTag
231 default:
232 errorf("unexpected object: %v (%T)", obj, obj)
233 panic("unreachable")
234 }
235 }
236
237 func sameObj(a, b types.Object) bool {
238
239
240
241 return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type())
242 }
243
244 func (p *importer) declare(obj types.Object) {
245 pkg := obj.Pkg()
246 if alt := pkg.Scope().Insert(obj); alt != nil {
247
248
249
250
251
252
253
254
255
256 if !sameObj(obj, alt) {
257 errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
258 }
259 }
260 }
261
262 func (p *importer) obj(tag int) {
263 switch tag {
264 case constTag:
265 pos := p.pos()
266 pkg, name := p.qualifiedName()
267 typ := p.typ(nil, nil)
268 val := p.value()
269 p.declare(types.NewConst(pos, pkg, name, typ, val))
270
271 case aliasTag:
272
273 pos := p.pos()
274 pkg, name := p.qualifiedName()
275 typ := p.typ(nil, nil)
276 p.declare(types.NewTypeName(pos, pkg, name, typ))
277
278 case typeTag:
279 p.typ(nil, nil)
280
281 case varTag:
282 pos := p.pos()
283 pkg, name := p.qualifiedName()
284 typ := p.typ(nil, nil)
285 p.declare(types.NewVar(pos, pkg, name, typ))
286
287 case funcTag:
288 pos := p.pos()
289 pkg, name := p.qualifiedName()
290 params, isddd := p.paramList()
291 result, _ := p.paramList()
292 sig := types.NewSignature(nil, params, result, isddd)
293 p.declare(types.NewFunc(pos, pkg, name, sig))
294
295 default:
296 errorf("unexpected object tag %d", tag)
297 }
298 }
299
300 const deltaNewFile = -64
301
302 func (p *importer) pos() token.Pos {
303 if !p.posInfoFormat {
304 return token.NoPos
305 }
306
307 file := p.prevFile
308 line := p.prevLine
309 delta := p.int()
310 line += delta
311 if p.version >= 5 {
312 if delta == deltaNewFile {
313 if n := p.int(); n >= 0 {
314
315 file = p.path()
316 line = n
317 }
318 }
319 } else {
320 if delta == 0 {
321 if n := p.int(); n >= 0 {
322
323 file = p.prevFile[:n] + p.string()
324 line = p.int()
325 }
326 }
327 }
328 p.prevFile = file
329 p.prevLine = line
330
331 return p.fake.pos(file, line)
332 }
333
334
335 type fakeFileSet struct {
336 fset *token.FileSet
337 files map[string]*token.File
338 }
339
340 func (s *fakeFileSet) pos(file string, line int) token.Pos {
341
342
343 const maxlines = 64 * 1024
344 f := s.files[file]
345 if f == nil {
346 f = s.fset.AddFile(file, -1, maxlines)
347 s.files[file] = f
348
349
350 fakeLinesOnce.Do(func() {
351 fakeLines = make([]int, maxlines)
352 for i := range fakeLines {
353 fakeLines[i] = i
354 }
355 })
356 f.SetLines(fakeLines)
357 }
358
359 if line > maxlines {
360 line = 1
361 }
362
363
364
365 return f.Pos(line - 1)
366 }
367
368 var (
369 fakeLines []int
370 fakeLinesOnce sync.Once
371 )
372
373 func (p *importer) qualifiedName() (pkg *types.Package, name string) {
374 name = p.string()
375 pkg = p.pkg()
376 return
377 }
378
379 func (p *importer) record(t types.Type) {
380 p.typList = append(p.typList, t)
381 }
382
383
384
385
386 type dddSlice struct {
387 elem types.Type
388 }
389
390 func (t *dddSlice) Underlying() types.Type { return t }
391 func (t *dddSlice) String() string { return "..." + t.elem.String() }
392
393
394
395
396
397
398
399
400
401 func (p *importer) typ(parent *types.Package, tname *types.Named) types.Type {
402
403 i := p.tagOrIndex()
404 if i >= 0 {
405 return p.typList[i]
406 }
407
408
409 switch i {
410 case namedTag:
411
412 pos := p.pos()
413 parent, name := p.qualifiedName()
414 scope := parent.Scope()
415 obj := scope.Lookup(name)
416
417
418 if obj == nil {
419 obj = types.NewTypeName(pos, parent, name, nil)
420 scope.Insert(obj)
421 }
422
423 if _, ok := obj.(*types.TypeName); !ok {
424 errorf("pkg = %s, name = %s => %s", parent, name, obj)
425 }
426
427
428 t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
429
430
431 tname := obj.Type().(*types.Named)
432 p.record(tname)
433
434
435 t0.SetUnderlying(p.typ(parent, t0))
436
437
438 if types.IsInterface(t0) {
439 return tname
440 }
441
442
443 for i := p.int(); i > 0; i-- {
444
445 pos := p.pos()
446 name := p.string()
447 if !token.IsExported(name) {
448 p.pkg()
449 }
450
451 recv, _ := p.paramList()
452 params, isddd := p.paramList()
453 result, _ := p.paramList()
454 p.int()
455
456 sig := types.NewSignature(recv.At(0), params, result, isddd)
457 t0.AddMethod(types.NewFunc(pos, parent, name, sig))
458 }
459
460 return tname
461
462 case arrayTag:
463 t := new(types.Array)
464 if p.trackAllTypes {
465 p.record(t)
466 }
467
468 n := p.int64()
469 *t = *types.NewArray(p.typ(parent, nil), n)
470 return t
471
472 case sliceTag:
473 t := new(types.Slice)
474 if p.trackAllTypes {
475 p.record(t)
476 }
477
478 *t = *types.NewSlice(p.typ(parent, nil))
479 return t
480
481 case dddTag:
482 t := new(dddSlice)
483 if p.trackAllTypes {
484 p.record(t)
485 }
486
487 t.elem = p.typ(parent, nil)
488 return t
489
490 case structTag:
491 t := new(types.Struct)
492 if p.trackAllTypes {
493 p.record(t)
494 }
495
496 *t = *types.NewStruct(p.fieldList(parent))
497 return t
498
499 case pointerTag:
500 t := new(types.Pointer)
501 if p.trackAllTypes {
502 p.record(t)
503 }
504
505 *t = *types.NewPointer(p.typ(parent, nil))
506 return t
507
508 case signatureTag:
509 t := new(types.Signature)
510 if p.trackAllTypes {
511 p.record(t)
512 }
513
514 params, isddd := p.paramList()
515 result, _ := p.paramList()
516 *t = *types.NewSignature(nil, params, result, isddd)
517 return t
518
519 case interfaceTag:
520
521
522
523
524
525
526 n := len(p.typList)
527 if p.trackAllTypes {
528 p.record(nil)
529 }
530
531 var embeddeds []types.Type
532 for n := p.int(); n > 0; n-- {
533 p.pos()
534 embeddeds = append(embeddeds, p.typ(parent, nil))
535 }
536
537 t := types.NewInterfaceType(p.methodList(parent, tname), embeddeds)
538 p.interfaceList = append(p.interfaceList, t)
539 if p.trackAllTypes {
540 p.typList[n] = t
541 }
542 return t
543
544 case mapTag:
545 t := new(types.Map)
546 if p.trackAllTypes {
547 p.record(t)
548 }
549
550 key := p.typ(parent, nil)
551 val := p.typ(parent, nil)
552 *t = *types.NewMap(key, val)
553 return t
554
555 case chanTag:
556 t := new(types.Chan)
557 if p.trackAllTypes {
558 p.record(t)
559 }
560
561 dir := chanDir(p.int())
562 val := p.typ(parent, nil)
563 *t = *types.NewChan(dir, val)
564 return t
565
566 default:
567 errorf("unexpected type tag %d", i)
568 panic("unreachable")
569 }
570 }
571
572 func chanDir(d int) types.ChanDir {
573
574 switch d {
575 case 1 :
576 return types.RecvOnly
577 case 2 :
578 return types.SendOnly
579 case 3 :
580 return types.SendRecv
581 default:
582 errorf("unexpected channel dir %d", d)
583 return 0
584 }
585 }
586
587 func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) {
588 if n := p.int(); n > 0 {
589 fields = make([]*types.Var, n)
590 tags = make([]string, n)
591 for i := range fields {
592 fields[i], tags[i] = p.field(parent)
593 }
594 }
595 return
596 }
597
598 func (p *importer) field(parent *types.Package) (*types.Var, string) {
599 pos := p.pos()
600 pkg, name, alias := p.fieldName(parent)
601 typ := p.typ(parent, nil)
602 tag := p.string()
603
604 anonymous := false
605 if name == "" {
606
607 switch typ := deref(typ).(type) {
608 case *types.Basic:
609 pkg = nil
610 name = typ.Name()
611 case *types.Named:
612 name = typ.Obj().Name()
613 default:
614 errorf("named base type expected")
615 }
616 anonymous = true
617 } else if alias {
618
619 anonymous = true
620 }
621
622 return types.NewField(pos, pkg, name, typ, anonymous), tag
623 }
624
625 func (p *importer) methodList(parent *types.Package, baseType *types.Named) (methods []*types.Func) {
626 if n := p.int(); n > 0 {
627 methods = make([]*types.Func, n)
628 for i := range methods {
629 methods[i] = p.method(parent, baseType)
630 }
631 }
632 return
633 }
634
635 func (p *importer) method(parent *types.Package, baseType *types.Named) *types.Func {
636 pos := p.pos()
637 pkg, name, _ := p.fieldName(parent)
638
639
640
641
642 var recv *types.Var
643 if baseType != nil {
644 recv = types.NewVar(token.NoPos, parent, "", baseType)
645 }
646 params, isddd := p.paramList()
647 result, _ := p.paramList()
648 sig := types.NewSignature(recv, params, result, isddd)
649 return types.NewFunc(pos, pkg, name, sig)
650 }
651
652 func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) {
653 name = p.string()
654 pkg = parent
655 if pkg == nil {
656
657 pkg = p.pkgList[0]
658 }
659 if p.version == 0 && name == "_" {
660
661 return
662 }
663 switch name {
664 case "":
665
666 case "?":
667
668 name = ""
669 pkg = p.pkg()
670 case "@":
671
672 name = p.string()
673 alias = true
674 fallthrough
675 default:
676 if !token.IsExported(name) {
677 pkg = p.pkg()
678 }
679 }
680 return
681 }
682
683 func (p *importer) paramList() (*types.Tuple, bool) {
684 n := p.int()
685 if n == 0 {
686 return nil, false
687 }
688
689 named := true
690 if n < 0 {
691 n = -n
692 named = false
693 }
694
695 params := make([]*types.Var, n)
696 isddd := false
697 for i := range params {
698 params[i], isddd = p.param(named)
699 }
700 return types.NewTuple(params...), isddd
701 }
702
703 func (p *importer) param(named bool) (*types.Var, bool) {
704 t := p.typ(nil, nil)
705 td, isddd := t.(*dddSlice)
706 if isddd {
707 t = types.NewSlice(td.elem)
708 }
709
710 var pkg *types.Package
711 var name string
712 if named {
713 name = p.string()
714 if name == "" {
715 errorf("expected named parameter")
716 }
717 if name != "_" {
718 pkg = p.pkg()
719 }
720 if i := strings.Index(name, "ยท"); i > 0 {
721 name = name[:i]
722 }
723 }
724
725
726 p.string()
727
728 return types.NewVar(token.NoPos, pkg, name, t), isddd
729 }
730
731 func (p *importer) value() constant.Value {
732 switch tag := p.tagOrIndex(); tag {
733 case falseTag:
734 return constant.MakeBool(false)
735 case trueTag:
736 return constant.MakeBool(true)
737 case int64Tag:
738 return constant.MakeInt64(p.int64())
739 case floatTag:
740 return p.float()
741 case complexTag:
742 re := p.float()
743 im := p.float()
744 return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
745 case stringTag:
746 return constant.MakeString(p.string())
747 case unknownTag:
748 return constant.MakeUnknown()
749 default:
750 errorf("unexpected value tag %d", tag)
751 panic("unreachable")
752 }
753 }
754
755 func (p *importer) float() constant.Value {
756 sign := p.int()
757 if sign == 0 {
758 return constant.MakeInt64(0)
759 }
760
761 exp := p.int()
762 mant := []byte(p.string())
763
764
765 for len(mant) > 0 && mant[0] == 0 {
766 mant = mant[1:]
767 }
768
769
770
771
772 for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
773 mant[i], mant[j] = mant[j], mant[i]
774 }
775
776
777
778 exp -= len(mant) << 3
779 if len(mant) > 0 {
780 for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
781 exp++
782 }
783 }
784
785 x := constant.MakeFromBytes(mant)
786 switch {
787 case exp < 0:
788 d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
789 x = constant.BinaryOp(x, token.QUO, d)
790 case exp > 0:
791 x = constant.Shift(x, token.SHL, uint(exp))
792 }
793
794 if sign < 0 {
795 x = constant.UnaryOp(token.SUB, x, 0)
796 }
797 return x
798 }
799
800
801
802
803 func (p *importer) tagOrIndex() int {
804 if p.debugFormat {
805 p.marker('t')
806 }
807
808 return int(p.rawInt64())
809 }
810
811 func (p *importer) int() int {
812 x := p.int64()
813 if int64(int(x)) != x {
814 errorf("exported integer too large")
815 }
816 return int(x)
817 }
818
819 func (p *importer) int64() int64 {
820 if p.debugFormat {
821 p.marker('i')
822 }
823
824 return p.rawInt64()
825 }
826
827 func (p *importer) path() string {
828 if p.debugFormat {
829 p.marker('p')
830 }
831
832
833 i := p.rawInt64()
834 if i >= 0 {
835 return p.pathList[i]
836 }
837
838 a := make([]string, -i)
839 for n := range a {
840 a[n] = p.string()
841 }
842 s := strings.Join(a, "/")
843 p.pathList = append(p.pathList, s)
844 return s
845 }
846
847 func (p *importer) string() string {
848 if p.debugFormat {
849 p.marker('s')
850 }
851
852
853 i := p.rawInt64()
854 if i >= 0 {
855 return p.strList[i]
856 }
857
858 if n := int(-i); n <= cap(p.buf) {
859 p.buf = p.buf[:n]
860 } else {
861 p.buf = make([]byte, n)
862 }
863 for i := range p.buf {
864 p.buf[i] = p.rawByte()
865 }
866 s := string(p.buf)
867 p.strList = append(p.strList, s)
868 return s
869 }
870
871 func (p *importer) marker(want byte) {
872 if got := p.rawByte(); got != want {
873 errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
874 }
875
876 pos := p.read
877 if n := int(p.rawInt64()); n != pos {
878 errorf("incorrect position: got %d; want %d", n, pos)
879 }
880 }
881
882
883 func (p *importer) rawInt64() int64 {
884 i, err := binary.ReadVarint(p)
885 if err != nil {
886 errorf("read error: %v", err)
887 }
888 return i
889 }
890
891
892 func (p *importer) rawStringln(b byte) string {
893 p.buf = p.buf[:0]
894 for b != '\n' {
895 p.buf = append(p.buf, b)
896 b = p.rawByte()
897 }
898 return string(p.buf)
899 }
900
901
902 func (p *importer) ReadByte() (byte, error) {
903 return p.rawByte(), nil
904 }
905
906
907
908
909 func (p *importer) rawByte() byte {
910 b := p.data[0]
911 r := 1
912 if b == '|' {
913 b = p.data[1]
914 r = 2
915 switch b {
916 case 'S':
917 b = '$'
918 case '|':
919
920 default:
921 errorf("unexpected escape sequence in export data")
922 }
923 }
924 p.data = p.data[r:]
925 p.read += r
926 return b
927
928 }
929
930
931
932
933
934 const (
935
936 packageTag = -(iota + 1)
937 constTag
938 typeTag
939 varTag
940 funcTag
941 endTag
942
943
944 namedTag
945 arrayTag
946 sliceTag
947 dddTag
948 structTag
949 pointerTag
950 signatureTag
951 interfaceTag
952 mapTag
953 chanTag
954
955
956 falseTag
957 trueTag
958 int64Tag
959 floatTag
960 fractionTag
961 complexTag
962 stringTag
963 nilTag
964 unknownTag
965
966
967 aliasTag
968 )
969
970 var predeclared = []types.Type{
971
972 types.Typ[types.Bool],
973 types.Typ[types.Int],
974 types.Typ[types.Int8],
975 types.Typ[types.Int16],
976 types.Typ[types.Int32],
977 types.Typ[types.Int64],
978 types.Typ[types.Uint],
979 types.Typ[types.Uint8],
980 types.Typ[types.Uint16],
981 types.Typ[types.Uint32],
982 types.Typ[types.Uint64],
983 types.Typ[types.Uintptr],
984 types.Typ[types.Float32],
985 types.Typ[types.Float64],
986 types.Typ[types.Complex64],
987 types.Typ[types.Complex128],
988 types.Typ[types.String],
989
990
991 types.Universe.Lookup("byte").Type(),
992 types.Universe.Lookup("rune").Type(),
993
994
995 types.Universe.Lookup("error").Type(),
996
997
998 types.Typ[types.UntypedBool],
999 types.Typ[types.UntypedInt],
1000 types.Typ[types.UntypedRune],
1001 types.Typ[types.UntypedFloat],
1002 types.Typ[types.UntypedComplex],
1003 types.Typ[types.UntypedString],
1004 types.Typ[types.UntypedNil],
1005
1006
1007 types.Typ[types.UnsafePointer],
1008
1009
1010 types.Typ[types.Invalid],
1011
1012
1013 anyType{},
1014 }
1015
1016 type anyType struct{}
1017
1018 func (t anyType) Underlying() types.Type { return t }
1019 func (t anyType) String() string { return "any" }
1020
View as plain text