Black Lives Matter. Support the Equal Justice Initiative.

Source file src/go/internal/gcimporter/iimport.go

Documentation: go/internal/gcimporter

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

View as plain text