github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/go/internal/gcimporter/iimport.go (about)

     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.
     4  
     5  // Indexed package import.
     6  // See cmd/compile/internal/gc/iexport.go for the export data format.
     7  
     8  package gcimporter
     9  
    10  import (
    11  	"bytes"
    12  	"encoding/binary"
    13  	"fmt"
    14  	"go/constant"
    15  	"go/token"
    16  	"go/types"
    17  	"io"
    18  	"sort"
    19  )
    20  
    21  type intReader struct {
    22  	*bytes.Reader
    23  	path string
    24  }
    25  
    26  func (r *intReader) int64() int64 {
    27  	i, err := binary.ReadVarint(r.Reader)
    28  	if err != nil {
    29  		errorf("import %q: read varint error: %v", r.path, err)
    30  	}
    31  	return i
    32  }
    33  
    34  func (r *intReader) uint64() uint64 {
    35  	i, err := binary.ReadUvarint(r.Reader)
    36  	if err != nil {
    37  		errorf("import %q: read varint error: %v", r.path, err)
    38  	}
    39  	return i
    40  }
    41  
    42  const predeclReserved = 32
    43  
    44  type itag uint64
    45  
    46  const (
    47  	// Types
    48  	definedType itag = iota
    49  	pointerType
    50  	sliceType
    51  	arrayType
    52  	chanType
    53  	mapType
    54  	signatureType
    55  	structType
    56  	interfaceType
    57  )
    58  
    59  // iImportData imports a package from the serialized package data
    60  // and returns the number of bytes consumed and a reference to the package.
    61  // If the export data version is not recognized or the format is otherwise
    62  // compromised, an error is returned.
    63  func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
    64  	const currentVersion = 0
    65  	version := -1
    66  	defer func() {
    67  		if e := recover(); e != nil {
    68  			if version > currentVersion {
    69  				err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
    70  			} else {
    71  				err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
    72  			}
    73  		}
    74  	}()
    75  
    76  	r := &intReader{bytes.NewReader(data), path}
    77  
    78  	version = int(r.uint64())
    79  	switch version {
    80  	case currentVersion:
    81  	default:
    82  		errorf("unknown iexport format version %d", version)
    83  	}
    84  
    85  	sLen := int64(r.uint64())
    86  	dLen := int64(r.uint64())
    87  
    88  	whence, _ := r.Seek(0, io.SeekCurrent)
    89  	stringData := data[whence : whence+sLen]
    90  	declData := data[whence+sLen : whence+sLen+dLen]
    91  	r.Seek(sLen+dLen, io.SeekCurrent)
    92  
    93  	p := iimporter{
    94  		ipath: path,
    95  
    96  		stringData:  stringData,
    97  		stringCache: make(map[uint64]string),
    98  		pkgCache:    make(map[uint64]*types.Package),
    99  
   100  		declData: declData,
   101  		pkgIndex: make(map[*types.Package]map[string]uint64),
   102  		typCache: make(map[uint64]types.Type),
   103  
   104  		fake: fakeFileSet{
   105  			fset:  fset,
   106  			files: make(map[string]*token.File),
   107  		},
   108  	}
   109  
   110  	for i, pt := range predeclared {
   111  		p.typCache[uint64(i)] = pt
   112  	}
   113  
   114  	pkgList := make([]*types.Package, r.uint64())
   115  	for i := range pkgList {
   116  		pkgPathOff := r.uint64()
   117  		pkgPath := p.stringAt(pkgPathOff)
   118  		pkgName := p.stringAt(r.uint64())
   119  		_ = r.uint64() // package height; unused by go/types
   120  
   121  		if pkgPath == "" {
   122  			pkgPath = path
   123  		}
   124  		pkg := imports[pkgPath]
   125  		if pkg == nil {
   126  			pkg = types.NewPackage(pkgPath, pkgName)
   127  			imports[pkgPath] = pkg
   128  		} else if pkg.Name() != pkgName {
   129  			errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
   130  		}
   131  
   132  		p.pkgCache[pkgPathOff] = pkg
   133  
   134  		nameIndex := make(map[string]uint64)
   135  		for nSyms := r.uint64(); nSyms > 0; nSyms-- {
   136  			name := p.stringAt(r.uint64())
   137  			nameIndex[name] = r.uint64()
   138  		}
   139  
   140  		p.pkgIndex[pkg] = nameIndex
   141  		pkgList[i] = pkg
   142  	}
   143  
   144  	localpkg := pkgList[0]
   145  
   146  	names := make([]string, 0, len(p.pkgIndex[localpkg]))
   147  	for name := range p.pkgIndex[localpkg] {
   148  		names = append(names, name)
   149  	}
   150  	sort.Strings(names)
   151  	for _, name := range names {
   152  		p.doDecl(localpkg, name)
   153  	}
   154  
   155  	for _, typ := range p.interfaceList {
   156  		typ.Complete()
   157  	}
   158  
   159  	// record all referenced packages as imports
   160  	list := append(([]*types.Package)(nil), pkgList[1:]...)
   161  	sort.Sort(byPath(list))
   162  	localpkg.SetImports(list)
   163  
   164  	// package was imported completely and without errors
   165  	localpkg.MarkComplete()
   166  
   167  	consumed, _ := r.Seek(0, io.SeekCurrent)
   168  	return int(consumed), localpkg, nil
   169  }
   170  
   171  type iimporter struct {
   172  	ipath string
   173  
   174  	stringData  []byte
   175  	stringCache map[uint64]string
   176  	pkgCache    map[uint64]*types.Package
   177  
   178  	declData []byte
   179  	pkgIndex map[*types.Package]map[string]uint64
   180  	typCache map[uint64]types.Type
   181  
   182  	fake          fakeFileSet
   183  	interfaceList []*types.Interface
   184  }
   185  
   186  func (p *iimporter) doDecl(pkg *types.Package, name string) {
   187  	// See if we've already imported this declaration.
   188  	if obj := pkg.Scope().Lookup(name); obj != nil {
   189  		return
   190  	}
   191  
   192  	off, ok := p.pkgIndex[pkg][name]
   193  	if !ok {
   194  		errorf("%v.%v not in index", pkg, name)
   195  	}
   196  
   197  	r := &importReader{p: p, currPkg: pkg}
   198  	r.declReader.Reset(p.declData[off:])
   199  
   200  	r.obj(name)
   201  }
   202  
   203  func (p *iimporter) stringAt(off uint64) string {
   204  	if s, ok := p.stringCache[off]; ok {
   205  		return s
   206  	}
   207  
   208  	slen, n := binary.Uvarint(p.stringData[off:])
   209  	if n <= 0 {
   210  		errorf("varint failed")
   211  	}
   212  	spos := off + uint64(n)
   213  	s := string(p.stringData[spos : spos+slen])
   214  	p.stringCache[off] = s
   215  	return s
   216  }
   217  
   218  func (p *iimporter) pkgAt(off uint64) *types.Package {
   219  	if pkg, ok := p.pkgCache[off]; ok {
   220  		return pkg
   221  	}
   222  	path := p.stringAt(off)
   223  	errorf("missing package %q in %q", path, p.ipath)
   224  	return nil
   225  }
   226  
   227  func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
   228  	if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
   229  		return t
   230  	}
   231  
   232  	if off < predeclReserved {
   233  		errorf("predeclared type missing from cache: %v", off)
   234  	}
   235  
   236  	r := &importReader{p: p}
   237  	r.declReader.Reset(p.declData[off-predeclReserved:])
   238  	t := r.doType(base)
   239  
   240  	if base == nil || !isInterface(t) {
   241  		p.typCache[off] = t
   242  	}
   243  	return t
   244  }
   245  
   246  type importReader struct {
   247  	p          *iimporter
   248  	declReader bytes.Reader
   249  	currPkg    *types.Package
   250  	prevFile   string
   251  	prevLine   int64
   252  }
   253  
   254  func (r *importReader) obj(name string) {
   255  	tag := r.byte()
   256  	pos := r.pos()
   257  
   258  	switch tag {
   259  	case 'A':
   260  		typ := r.typ()
   261  
   262  		r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
   263  
   264  	case 'C':
   265  		typ, val := r.value()
   266  
   267  		r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
   268  
   269  	case 'F':
   270  		sig := r.signature(nil)
   271  
   272  		r.declare(types.NewFunc(pos, r.currPkg, name, sig))
   273  
   274  	case 'T':
   275  		// Types can be recursive. We need to setup a stub
   276  		// declaration before recursing.
   277  		obj := types.NewTypeName(pos, r.currPkg, name, nil)
   278  		named := types.NewNamed(obj, nil, nil)
   279  		r.declare(obj)
   280  
   281  		underlying := r.p.typAt(r.uint64(), named).Underlying()
   282  		named.SetUnderlying(underlying)
   283  
   284  		if !isInterface(underlying) {
   285  			for n := r.uint64(); n > 0; n-- {
   286  				mpos := r.pos()
   287  				mname := r.ident()
   288  				recv := r.param()
   289  				msig := r.signature(recv)
   290  
   291  				named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
   292  			}
   293  		}
   294  
   295  	case 'V':
   296  		typ := r.typ()
   297  
   298  		r.declare(types.NewVar(pos, r.currPkg, name, typ))
   299  
   300  	default:
   301  		errorf("unexpected tag: %v", tag)
   302  	}
   303  }
   304  
   305  func (r *importReader) declare(obj types.Object) {
   306  	obj.Pkg().Scope().Insert(obj)
   307  }
   308  
   309  func (r *importReader) value() (typ types.Type, val constant.Value) {
   310  	typ = r.typ()
   311  
   312  	switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
   313  	case types.IsBoolean:
   314  		val = constant.MakeBool(r.bool())
   315  
   316  	case types.IsString:
   317  		val = constant.MakeString(r.string())
   318  
   319  	case types.IsInteger:
   320  		val = r.mpint(b)
   321  
   322  	case types.IsFloat:
   323  		val = r.mpfloat(b)
   324  
   325  	case types.IsComplex:
   326  		re := r.mpfloat(b)
   327  		im := r.mpfloat(b)
   328  		val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
   329  
   330  	default:
   331  		errorf("unexpected type %v", typ) // panics
   332  		panic("unreachable")
   333  	}
   334  
   335  	return
   336  }
   337  
   338  func intSize(b *types.Basic) (signed bool, maxBytes uint) {
   339  	if (b.Info() & types.IsUntyped) != 0 {
   340  		return true, 64
   341  	}
   342  
   343  	switch b.Kind() {
   344  	case types.Float32, types.Complex64:
   345  		return true, 3
   346  	case types.Float64, types.Complex128:
   347  		return true, 7
   348  	}
   349  
   350  	signed = (b.Info() & types.IsUnsigned) == 0
   351  	switch b.Kind() {
   352  	case types.Int8, types.Uint8:
   353  		maxBytes = 1
   354  	case types.Int16, types.Uint16:
   355  		maxBytes = 2
   356  	case types.Int32, types.Uint32:
   357  		maxBytes = 4
   358  	default:
   359  		maxBytes = 8
   360  	}
   361  
   362  	return
   363  }
   364  
   365  func (r *importReader) mpint(b *types.Basic) constant.Value {
   366  	signed, maxBytes := intSize(b)
   367  
   368  	maxSmall := 256 - maxBytes
   369  	if signed {
   370  		maxSmall = 256 - 2*maxBytes
   371  	}
   372  	if maxBytes == 1 {
   373  		maxSmall = 256
   374  	}
   375  
   376  	n, _ := r.declReader.ReadByte()
   377  	if uint(n) < maxSmall {
   378  		v := int64(n)
   379  		if signed {
   380  			v >>= 1
   381  			if n&1 != 0 {
   382  				v = ^v
   383  			}
   384  		}
   385  		return constant.MakeInt64(v)
   386  	}
   387  
   388  	v := -n
   389  	if signed {
   390  		v = -(n &^ 1) >> 1
   391  	}
   392  	if v < 1 || uint(v) > maxBytes {
   393  		errorf("weird decoding: %v, %v => %v", n, signed, v)
   394  	}
   395  
   396  	buf := make([]byte, v)
   397  	io.ReadFull(&r.declReader, buf)
   398  
   399  	// convert to little endian
   400  	// TODO(gri) go/constant should have a more direct conversion function
   401  	//           (e.g., once it supports a big.Float based implementation)
   402  	for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
   403  		buf[i], buf[j] = buf[j], buf[i]
   404  	}
   405  
   406  	x := constant.MakeFromBytes(buf)
   407  	if signed && n&1 != 0 {
   408  		x = constant.UnaryOp(token.SUB, x, 0)
   409  	}
   410  	return x
   411  }
   412  
   413  func (r *importReader) mpfloat(b *types.Basic) constant.Value {
   414  	x := r.mpint(b)
   415  	if constant.Sign(x) == 0 {
   416  		return x
   417  	}
   418  
   419  	exp := r.int64()
   420  	switch {
   421  	case exp > 0:
   422  		x = constant.Shift(x, token.SHL, uint(exp))
   423  	case exp < 0:
   424  		d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
   425  		x = constant.BinaryOp(x, token.QUO, d)
   426  	}
   427  	return x
   428  }
   429  
   430  func (r *importReader) ident() string {
   431  	return r.string()
   432  }
   433  
   434  func (r *importReader) qualifiedIdent() (*types.Package, string) {
   435  	name := r.string()
   436  	pkg := r.pkg()
   437  	return pkg, name
   438  }
   439  
   440  func (r *importReader) pos() token.Pos {
   441  	delta := r.int64()
   442  	if delta != deltaNewFile {
   443  		r.prevLine += delta
   444  	} else if l := r.int64(); l == -1 {
   445  		r.prevLine += deltaNewFile
   446  	} else {
   447  		r.prevFile = r.string()
   448  		r.prevLine = l
   449  	}
   450  
   451  	if r.prevFile == "" && r.prevLine == 0 {
   452  		return token.NoPos
   453  	}
   454  
   455  	return r.p.fake.pos(r.prevFile, int(r.prevLine))
   456  }
   457  
   458  func (r *importReader) typ() types.Type {
   459  	return r.p.typAt(r.uint64(), nil)
   460  }
   461  
   462  func isInterface(t types.Type) bool {
   463  	_, ok := t.(*types.Interface)
   464  	return ok
   465  }
   466  
   467  func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
   468  func (r *importReader) string() string      { return r.p.stringAt(r.uint64()) }
   469  
   470  func (r *importReader) doType(base *types.Named) types.Type {
   471  	switch k := r.kind(); k {
   472  	default:
   473  		errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
   474  		return nil
   475  
   476  	case definedType:
   477  		pkg, name := r.qualifiedIdent()
   478  		r.p.doDecl(pkg, name)
   479  		return pkg.Scope().Lookup(name).(*types.TypeName).Type()
   480  	case pointerType:
   481  		return types.NewPointer(r.typ())
   482  	case sliceType:
   483  		return types.NewSlice(r.typ())
   484  	case arrayType:
   485  		n := r.uint64()
   486  		return types.NewArray(r.typ(), int64(n))
   487  	case chanType:
   488  		dir := chanDir(int(r.uint64()))
   489  		return types.NewChan(dir, r.typ())
   490  	case mapType:
   491  		return types.NewMap(r.typ(), r.typ())
   492  	case signatureType:
   493  		r.currPkg = r.pkg()
   494  		return r.signature(nil)
   495  
   496  	case structType:
   497  		r.currPkg = r.pkg()
   498  
   499  		fields := make([]*types.Var, r.uint64())
   500  		tags := make([]string, len(fields))
   501  		for i := range fields {
   502  			fpos := r.pos()
   503  			fname := r.ident()
   504  			ftyp := r.typ()
   505  			emb := r.bool()
   506  			tag := r.string()
   507  
   508  			fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
   509  			tags[i] = tag
   510  		}
   511  		return types.NewStruct(fields, tags)
   512  
   513  	case interfaceType:
   514  		r.currPkg = r.pkg()
   515  
   516  		embeddeds := make([]types.Type, r.uint64())
   517  		for i := range embeddeds {
   518  			_ = r.pos()
   519  			embeddeds[i] = r.typ()
   520  		}
   521  
   522  		methods := make([]*types.Func, r.uint64())
   523  		for i := range methods {
   524  			mpos := r.pos()
   525  			mname := r.ident()
   526  
   527  			// TODO(mdempsky): Matches bimport.go, but I
   528  			// don't agree with this.
   529  			var recv *types.Var
   530  			if base != nil {
   531  				recv = types.NewVar(token.NoPos, r.currPkg, "", base)
   532  			}
   533  
   534  			msig := r.signature(recv)
   535  			methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
   536  		}
   537  
   538  		typ := types.NewInterfaceType(methods, embeddeds)
   539  		r.p.interfaceList = append(r.p.interfaceList, typ)
   540  		return typ
   541  	}
   542  }
   543  
   544  func (r *importReader) kind() itag {
   545  	return itag(r.uint64())
   546  }
   547  
   548  func (r *importReader) signature(recv *types.Var) *types.Signature {
   549  	params := r.paramList()
   550  	results := r.paramList()
   551  	variadic := params.Len() > 0 && r.bool()
   552  	return types.NewSignature(recv, params, results, variadic)
   553  }
   554  
   555  func (r *importReader) paramList() *types.Tuple {
   556  	xs := make([]*types.Var, r.uint64())
   557  	for i := range xs {
   558  		xs[i] = r.param()
   559  	}
   560  	return types.NewTuple(xs...)
   561  }
   562  
   563  func (r *importReader) param() *types.Var {
   564  	pos := r.pos()
   565  	name := r.ident()
   566  	typ := r.typ()
   567  	return types.NewParam(pos, r.currPkg, name, typ)
   568  }
   569  
   570  func (r *importReader) bool() bool {
   571  	return r.uint64() != 0
   572  }
   573  
   574  func (r *importReader) int64() int64 {
   575  	n, err := binary.ReadVarint(&r.declReader)
   576  	if err != nil {
   577  		errorf("readVarint: %v", err)
   578  	}
   579  	return n
   580  }
   581  
   582  func (r *importReader) uint64() uint64 {
   583  	n, err := binary.ReadUvarint(&r.declReader)
   584  	if err != nil {
   585  		errorf("readUvarint: %v", err)
   586  	}
   587  	return n
   588  }
   589  
   590  func (r *importReader) byte() byte {
   591  	x, err := r.declReader.ReadByte()
   592  	if err != nil {
   593  		errorf("declReader.ReadByte: %v", err)
   594  	}
   595  	return x
   596  }