Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/compile/internal/importer/iimport.go

Documentation: cmd/compile/internal/importer

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

View as plain text