1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Indexed package import.
6 // See cmd/compile/internal/gc/iexport.go for the export data format.
8 // This file is a copy of $GOROOT/src/go/internal/gcimporter/iimport.go.
23 type intReader struct {
28 func (r *intReader) int64() int64 {
29 i, err := binary.ReadVarint(r.Reader)
31 errorf("import %q: read varint error: %v", r.path, err)
36 func (r *intReader) uint64() uint64 {
37 i, err := binary.ReadUvarint(r.Reader)
39 errorf("import %q: read varint error: %v", r.path, err)
44 const predeclReserved = 32
50 definedType itag = iota
61 // IImportData imports a package from the serialized package data
62 // and returns 0 and a reference to the package.
63 // If the export data version is not recognized or the format is otherwise
64 // compromised, an error is returned.
65 func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
66 pkgs, err := iimportCommon(fset, imports, data, false, path)
70 return 0, pkgs[0], nil
73 // IImportBundle imports a set of packages from the serialized package bundle.
74 func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) {
75 return iimportCommon(fset, imports, data, true, "")
78 func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string) (pkgs []*types.Package, err error) {
79 const currentVersion = 1
82 if e := recover(); e != nil {
83 if version > currentVersion {
84 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
86 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
91 r := &intReader{bytes.NewReader(data), path}
94 bundleVersion := r.uint64()
95 switch bundleVersion {
98 errorf("unknown bundle format version %d", bundleVersion)
102 version = int64(r.uint64())
104 case currentVersion, 0:
106 errorf("unknown iexport format version %d", version)
109 sLen := int64(r.uint64())
110 dLen := int64(r.uint64())
112 whence, _ := r.Seek(0, io.SeekCurrent)
113 stringData := data[whence : whence+sLen]
114 declData := data[whence+sLen : whence+sLen+dLen]
115 r.Seek(sLen+dLen, io.SeekCurrent)
119 version: int(version),
121 stringData: stringData,
122 stringCache: make(map[uint64]string),
123 pkgCache: make(map[uint64]*types.Package),
126 pkgIndex: make(map[*types.Package]map[string]uint64),
127 typCache: make(map[uint64]types.Type),
131 files: make(map[string]*token.File),
135 for i, pt := range predeclared() {
136 p.typCache[uint64(i)] = pt
139 pkgList := make([]*types.Package, r.uint64())
140 for i := range pkgList {
141 pkgPathOff := r.uint64()
142 pkgPath := p.stringAt(pkgPathOff)
143 pkgName := p.stringAt(r.uint64())
144 _ = r.uint64() // package height; unused by go/types
149 pkg := imports[pkgPath]
151 pkg = types.NewPackage(pkgPath, pkgName)
152 imports[pkgPath] = pkg
153 } else if pkg.Name() != pkgName {
154 errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
157 p.pkgCache[pkgPathOff] = pkg
159 nameIndex := make(map[string]uint64)
160 for nSyms := r.uint64(); nSyms > 0; nSyms-- {
161 name := p.stringAt(r.uint64())
162 nameIndex[name] = r.uint64()
165 p.pkgIndex[pkg] = nameIndex
170 pkgs = make([]*types.Package, r.uint64())
171 for i := range pkgs {
172 pkg := p.pkgAt(r.uint64())
173 imps := make([]*types.Package, r.uint64())
174 for j := range imps {
175 imps[j] = p.pkgAt(r.uint64())
181 if len(pkgList) == 0 {
182 errorf("no packages found for %s", path)
187 // record all referenced packages as imports
188 list := append(([]*types.Package)(nil), pkgList[1:]...)
189 sort.Sort(byPath(list))
190 pkgs[0].SetImports(list)
193 for _, pkg := range pkgs {
198 names := make([]string, 0, len(p.pkgIndex[pkg]))
199 for name := range p.pkgIndex[pkg] {
200 names = append(names, name)
203 for _, name := range names {
207 // package was imported completely and without errors
211 for _, typ := range p.interfaceList {
218 type iimporter struct {
223 stringCache map[uint64]string
224 pkgCache map[uint64]*types.Package
227 pkgIndex map[*types.Package]map[string]uint64
228 typCache map[uint64]types.Type
231 interfaceList []*types.Interface
234 func (p *iimporter) doDecl(pkg *types.Package, name string) {
235 // See if we've already imported this declaration.
236 if obj := pkg.Scope().Lookup(name); obj != nil {
240 off, ok := p.pkgIndex[pkg][name]
242 errorf("%v.%v not in index", pkg, name)
245 r := &importReader{p: p, currPkg: pkg}
246 r.declReader.Reset(p.declData[off:])
251 func (p *iimporter) stringAt(off uint64) string {
252 if s, ok := p.stringCache[off]; ok {
256 slen, n := binary.Uvarint(p.stringData[off:])
258 errorf("varint failed")
260 spos := off + uint64(n)
261 s := string(p.stringData[spos : spos+slen])
262 p.stringCache[off] = s
266 func (p *iimporter) pkgAt(off uint64) *types.Package {
267 if pkg, ok := p.pkgCache[off]; ok {
270 path := p.stringAt(off)
271 errorf("missing package %q in %q", path, p.ipath)
275 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
276 if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
280 if off < predeclReserved {
281 errorf("predeclared type missing from cache: %v", off)
284 r := &importReader{p: p}
285 r.declReader.Reset(p.declData[off-predeclReserved:])
288 if base == nil || !isInterface(t) {
294 type importReader struct {
296 declReader bytes.Reader
297 currPkg *types.Package
303 func (r *importReader) obj(name string) {
311 r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
314 typ, val := r.value()
316 r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
319 sig := r.signature(nil)
321 r.declare(types.NewFunc(pos, r.currPkg, name, sig))
324 // Types can be recursive. We need to setup a stub
325 // declaration before recursing.
326 obj := types.NewTypeName(pos, r.currPkg, name, nil)
327 named := types.NewNamed(obj, nil, nil)
330 underlying := r.p.typAt(r.uint64(), named).Underlying()
331 named.SetUnderlying(underlying)
333 if !isInterface(underlying) {
334 for n := r.uint64(); n > 0; n-- {
338 msig := r.signature(recv)
340 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
347 r.declare(types.NewVar(pos, r.currPkg, name, typ))
350 errorf("unexpected tag: %v", tag)
354 func (r *importReader) declare(obj types.Object) {
355 obj.Pkg().Scope().Insert(obj)
358 func (r *importReader) value() (typ types.Type, val constant.Value) {
361 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
362 case types.IsBoolean:
363 val = constant.MakeBool(r.bool())
366 val = constant.MakeString(r.string())
368 case types.IsInteger:
374 case types.IsComplex:
377 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
380 if b.Kind() == types.Invalid {
381 val = constant.MakeUnknown()
384 errorf("unexpected type %v", typ) // panics
391 func intSize(b *types.Basic) (signed bool, maxBytes uint) {
392 if (b.Info() & types.IsUntyped) != 0 {
397 case types.Float32, types.Complex64:
399 case types.Float64, types.Complex128:
403 signed = (b.Info() & types.IsUnsigned) == 0
405 case types.Int8, types.Uint8:
407 case types.Int16, types.Uint16:
409 case types.Int32, types.Uint32:
418 func (r *importReader) mpint(b *types.Basic) constant.Value {
419 signed, maxBytes := intSize(b)
421 maxSmall := 256 - maxBytes
423 maxSmall = 256 - 2*maxBytes
429 n, _ := r.declReader.ReadByte()
430 if uint(n) < maxSmall {
438 return constant.MakeInt64(v)
445 if v < 1 || uint(v) > maxBytes {
446 errorf("weird decoding: %v, %v => %v", n, signed, v)
449 buf := make([]byte, v)
450 io.ReadFull(&r.declReader, buf)
452 // convert to little endian
453 // TODO(gri) go/constant should have a more direct conversion function
454 // (e.g., once it supports a big.Float based implementation)
455 for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
456 buf[i], buf[j] = buf[j], buf[i]
459 x := constant.MakeFromBytes(buf)
460 if signed && n&1 != 0 {
461 x = constant.UnaryOp(token.SUB, x, 0)
466 func (r *importReader) mpfloat(b *types.Basic) constant.Value {
468 if constant.Sign(x) == 0 {
475 x = constant.Shift(x, token.SHL, uint(exp))
477 d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
478 x = constant.BinaryOp(x, token.QUO, d)
483 func (r *importReader) ident() string {
487 func (r *importReader) qualifiedIdent() (*types.Package, string) {
493 func (r *importReader) pos() token.Pos {
494 if r.p.version >= 1 {
500 if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
503 return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
506 func (r *importReader) posv0() {
508 if delta != deltaNewFile {
510 } else if l := r.int64(); l == -1 {
511 r.prevLine += deltaNewFile
513 r.prevFile = r.string()
518 func (r *importReader) posv1() {
520 r.prevColumn += delta >> 1
523 r.prevLine += delta >> 1
525 r.prevFile = r.string()
530 func (r *importReader) typ() types.Type {
531 return r.p.typAt(r.uint64(), nil)
534 func isInterface(t types.Type) bool {
535 _, ok := t.(*types.Interface)
539 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
540 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
542 func (r *importReader) doType(base *types.Named) types.Type {
543 switch k := r.kind(); k {
545 errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
549 pkg, name := r.qualifiedIdent()
550 r.p.doDecl(pkg, name)
551 return pkg.Scope().Lookup(name).(*types.TypeName).Type()
553 return types.NewPointer(r.typ())
555 return types.NewSlice(r.typ())
558 return types.NewArray(r.typ(), int64(n))
560 dir := chanDir(int(r.uint64()))
561 return types.NewChan(dir, r.typ())
563 return types.NewMap(r.typ(), r.typ())
566 return r.signature(nil)
571 fields := make([]*types.Var, r.uint64())
572 tags := make([]string, len(fields))
573 for i := range fields {
580 fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
583 return types.NewStruct(fields, tags)
588 embeddeds := make([]types.Type, r.uint64())
589 for i := range embeddeds {
591 embeddeds[i] = r.typ()
594 methods := make([]*types.Func, r.uint64())
595 for i := range methods {
599 // TODO(mdempsky): Matches bimport.go, but I
600 // don't agree with this.
603 recv = types.NewVar(token.NoPos, r.currPkg, "", base)
606 msig := r.signature(recv)
607 methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
610 typ := newInterface(methods, embeddeds)
611 r.p.interfaceList = append(r.p.interfaceList, typ)
616 func (r *importReader) kind() itag {
617 return itag(r.uint64())
620 func (r *importReader) signature(recv *types.Var) *types.Signature {
621 params := r.paramList()
622 results := r.paramList()
623 variadic := params.Len() > 0 && r.bool()
624 return types.NewSignature(recv, params, results, variadic)
627 func (r *importReader) paramList() *types.Tuple {
628 xs := make([]*types.Var, r.uint64())
632 return types.NewTuple(xs...)
635 func (r *importReader) param() *types.Var {
639 return types.NewParam(pos, r.currPkg, name, typ)
642 func (r *importReader) bool() bool {
643 return r.uint64() != 0
646 func (r *importReader) int64() int64 {
647 n, err := binary.ReadVarint(&r.declReader)
649 errorf("readVarint: %v", err)
654 func (r *importReader) uint64() uint64 {
655 n, err := binary.ReadUvarint(&r.declReader)
657 errorf("readUvarint: %v", err)
662 func (r *importReader) byte() byte {
663 x, err := r.declReader.ReadByte()
665 errorf("declReader.ReadByte: %v", err)