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 the number of bytes consumed 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, pkg *types.Package, err error) {
66 const currentVersion = 0
69 if e := recover(); e != nil {
70 if version > currentVersion {
71 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
73 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
78 r := &intReader{bytes.NewReader(data), path}
80 version = int(r.uint64())
84 errorf("unknown iexport format version %d", version)
87 sLen := int64(r.uint64())
88 dLen := int64(r.uint64())
90 whence, _ := r.Seek(0, io.SeekCurrent)
91 stringData := data[whence : whence+sLen]
92 declData := data[whence+sLen : whence+sLen+dLen]
93 r.Seek(sLen+dLen, io.SeekCurrent)
98 stringData: stringData,
99 stringCache: make(map[uint64]string),
100 pkgCache: make(map[uint64]*types.Package),
103 pkgIndex: make(map[*types.Package]map[string]uint64),
104 typCache: make(map[uint64]types.Type),
108 files: make(map[string]*token.File),
112 for i, pt := range predeclared() {
113 p.typCache[uint64(i)] = pt
116 pkgList := make([]*types.Package, r.uint64())
117 for i := range pkgList {
118 pkgPathOff := r.uint64()
119 pkgPath := p.stringAt(pkgPathOff)
120 pkgName := p.stringAt(r.uint64())
121 _ = r.uint64() // package height; unused by go/types
126 pkg := imports[pkgPath]
128 pkg = types.NewPackage(pkgPath, pkgName)
129 imports[pkgPath] = pkg
130 } else if pkg.Name() != pkgName {
131 errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
134 p.pkgCache[pkgPathOff] = pkg
136 nameIndex := make(map[string]uint64)
137 for nSyms := r.uint64(); nSyms > 0; nSyms-- {
138 name := p.stringAt(r.uint64())
139 nameIndex[name] = r.uint64()
142 p.pkgIndex[pkg] = nameIndex
145 var localpkg *types.Package
146 for _, pkg := range pkgList {
147 if pkg.Path() == path {
152 names := make([]string, 0, len(p.pkgIndex[localpkg]))
153 for name := range p.pkgIndex[localpkg] {
154 names = append(names, name)
157 for _, name := range names {
158 p.doDecl(localpkg, name)
161 for _, typ := range p.interfaceList {
165 // record all referenced packages as imports
166 list := append(([]*types.Package)(nil), pkgList[1:]...)
167 sort.Sort(byPath(list))
168 localpkg.SetImports(list)
170 // package was imported completely and without errors
171 localpkg.MarkComplete()
173 consumed, _ := r.Seek(0, io.SeekCurrent)
174 return int(consumed), localpkg, nil
177 type iimporter struct {
181 stringCache map[uint64]string
182 pkgCache map[uint64]*types.Package
185 pkgIndex map[*types.Package]map[string]uint64
186 typCache map[uint64]types.Type
189 interfaceList []*types.Interface
192 func (p *iimporter) doDecl(pkg *types.Package, name string) {
193 // See if we've already imported this declaration.
194 if obj := pkg.Scope().Lookup(name); obj != nil {
198 off, ok := p.pkgIndex[pkg][name]
200 errorf("%v.%v not in index", pkg, name)
203 r := &importReader{p: p, currPkg: pkg}
204 r.declReader.Reset(p.declData[off:])
209 func (p *iimporter) stringAt(off uint64) string {
210 if s, ok := p.stringCache[off]; ok {
214 slen, n := binary.Uvarint(p.stringData[off:])
216 errorf("varint failed")
218 spos := off + uint64(n)
219 s := string(p.stringData[spos : spos+slen])
220 p.stringCache[off] = s
224 func (p *iimporter) pkgAt(off uint64) *types.Package {
225 if pkg, ok := p.pkgCache[off]; ok {
228 path := p.stringAt(off)
229 errorf("missing package %q in %q", path, p.ipath)
233 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
234 if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
238 if off < predeclReserved {
239 errorf("predeclared type missing from cache: %v", off)
242 r := &importReader{p: p}
243 r.declReader.Reset(p.declData[off-predeclReserved:])
246 if base == nil || !isInterface(t) {
252 type importReader struct {
254 declReader bytes.Reader
255 currPkg *types.Package
260 func (r *importReader) obj(name string) {
268 r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
271 typ, val := r.value()
273 r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
276 sig := r.signature(nil)
278 r.declare(types.NewFunc(pos, r.currPkg, name, sig))
281 // Types can be recursive. We need to setup a stub
282 // declaration before recursing.
283 obj := types.NewTypeName(pos, r.currPkg, name, nil)
284 named := types.NewNamed(obj, nil, nil)
287 underlying := r.p.typAt(r.uint64(), named).Underlying()
288 named.SetUnderlying(underlying)
290 if !isInterface(underlying) {
291 for n := r.uint64(); n > 0; n-- {
295 msig := r.signature(recv)
297 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
304 r.declare(types.NewVar(pos, r.currPkg, name, typ))
307 errorf("unexpected tag: %v", tag)
311 func (r *importReader) declare(obj types.Object) {
312 obj.Pkg().Scope().Insert(obj)
315 func (r *importReader) value() (typ types.Type, val constant.Value) {
318 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
319 case types.IsBoolean:
320 val = constant.MakeBool(r.bool())
323 val = constant.MakeString(r.string())
325 case types.IsInteger:
331 case types.IsComplex:
334 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
337 if b.Kind() == types.Invalid {
338 val = constant.MakeUnknown()
341 errorf("unexpected type %v", typ) // panics
348 func intSize(b *types.Basic) (signed bool, maxBytes uint) {
349 if (b.Info() & types.IsUntyped) != 0 {
354 case types.Float32, types.Complex64:
356 case types.Float64, types.Complex128:
360 signed = (b.Info() & types.IsUnsigned) == 0
362 case types.Int8, types.Uint8:
364 case types.Int16, types.Uint16:
366 case types.Int32, types.Uint32:
375 func (r *importReader) mpint(b *types.Basic) constant.Value {
376 signed, maxBytes := intSize(b)
378 maxSmall := 256 - maxBytes
380 maxSmall = 256 - 2*maxBytes
386 n, _ := r.declReader.ReadByte()
387 if uint(n) < maxSmall {
395 return constant.MakeInt64(v)
402 if v < 1 || uint(v) > maxBytes {
403 errorf("weird decoding: %v, %v => %v", n, signed, v)
406 buf := make([]byte, v)
407 io.ReadFull(&r.declReader, buf)
409 // convert to little endian
410 // TODO(gri) go/constant should have a more direct conversion function
411 // (e.g., once it supports a big.Float based implementation)
412 for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
413 buf[i], buf[j] = buf[j], buf[i]
416 x := constant.MakeFromBytes(buf)
417 if signed && n&1 != 0 {
418 x = constant.UnaryOp(token.SUB, x, 0)
423 func (r *importReader) mpfloat(b *types.Basic) constant.Value {
425 if constant.Sign(x) == 0 {
432 x = constant.Shift(x, token.SHL, uint(exp))
434 d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
435 x = constant.BinaryOp(x, token.QUO, d)
440 func (r *importReader) ident() string {
444 func (r *importReader) qualifiedIdent() (*types.Package, string) {
450 func (r *importReader) pos() token.Pos {
452 if delta != deltaNewFile {
454 } else if l := r.int64(); l == -1 {
455 r.prevLine += deltaNewFile
457 r.prevFile = r.string()
461 if r.prevFile == "" && r.prevLine == 0 {
465 return r.p.fake.pos(r.prevFile, int(r.prevLine))
468 func (r *importReader) typ() types.Type {
469 return r.p.typAt(r.uint64(), nil)
472 func isInterface(t types.Type) bool {
473 _, ok := t.(*types.Interface)
477 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
478 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
480 func (r *importReader) doType(base *types.Named) types.Type {
481 switch k := r.kind(); k {
483 errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
487 pkg, name := r.qualifiedIdent()
488 r.p.doDecl(pkg, name)
489 return pkg.Scope().Lookup(name).(*types.TypeName).Type()
491 return types.NewPointer(r.typ())
493 return types.NewSlice(r.typ())
496 return types.NewArray(r.typ(), int64(n))
498 dir := chanDir(int(r.uint64()))
499 return types.NewChan(dir, r.typ())
501 return types.NewMap(r.typ(), r.typ())
504 return r.signature(nil)
509 fields := make([]*types.Var, r.uint64())
510 tags := make([]string, len(fields))
511 for i := range fields {
518 fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
521 return types.NewStruct(fields, tags)
526 embeddeds := make([]types.Type, r.uint64())
527 for i := range embeddeds {
529 embeddeds[i] = r.typ()
532 methods := make([]*types.Func, r.uint64())
533 for i := range methods {
537 // TODO(mdempsky): Matches bimport.go, but I
538 // don't agree with this.
541 recv = types.NewVar(token.NoPos, r.currPkg, "", base)
544 msig := r.signature(recv)
545 methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
548 typ := newInterface(methods, embeddeds)
549 r.p.interfaceList = append(r.p.interfaceList, typ)
554 func (r *importReader) kind() itag {
555 return itag(r.uint64())
558 func (r *importReader) signature(recv *types.Var) *types.Signature {
559 params := r.paramList()
560 results := r.paramList()
561 variadic := params.Len() > 0 && r.bool()
562 return types.NewSignature(recv, params, results, variadic)
565 func (r *importReader) paramList() *types.Tuple {
566 xs := make([]*types.Var, r.uint64())
570 return types.NewTuple(xs...)
573 func (r *importReader) param() *types.Var {
577 return types.NewParam(pos, r.currPkg, name, typ)
580 func (r *importReader) bool() bool {
581 return r.uint64() != 0
584 func (r *importReader) int64() int64 {
585 n, err := binary.ReadVarint(&r.declReader)
587 errorf("readVarint: %v", err)
592 func (r *importReader) uint64() uint64 {
593 n, err := binary.ReadUvarint(&r.declReader)
595 errorf("readUvarint: %v", err)
600 func (r *importReader) byte() byte {
601 x, err := r.declReader.ReadByte()
603 errorf("declReader.ReadByte: %v", err)