github.com/yukk001/go1.10.8@v0.0.0-20190813125351-6df2d3982e20/src/cmd/compile/internal/gc/bimport.go (about)

     1  // Copyright 2015 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  // Binary package import.
     6  // See bexport.go for the export data format and how
     7  // to make a format change.
     8  
     9  package gc
    10  
    11  import (
    12  	"bufio"
    13  	"cmd/compile/internal/types"
    14  	"cmd/internal/src"
    15  	"encoding/binary"
    16  	"fmt"
    17  	"math/big"
    18  	"strconv"
    19  	"strings"
    20  )
    21  
    22  // The overall structure of Import is symmetric to Export: For each
    23  // export method in bexport.go there is a matching and symmetric method
    24  // in bimport.go. Changing the export format requires making symmetric
    25  // changes to bimport.go and bexport.go.
    26  
    27  type importer struct {
    28  	in      *bufio.Reader
    29  	imp     *types.Pkg // imported package
    30  	buf     []byte     // reused for reading strings
    31  	version int        // export format version
    32  
    33  	// object lists, in order of deserialization
    34  	strList       []string
    35  	pathList      []string
    36  	pkgList       []*types.Pkg
    37  	typList       []*types.Type
    38  	funcList      []*Node // nil entry means already declared
    39  	trackAllTypes bool
    40  
    41  	// for delayed type verification
    42  	cmpList []struct{ pt, t *types.Type }
    43  
    44  	// position encoding
    45  	posInfoFormat bool
    46  	prevFile      string
    47  	prevLine      int
    48  	posBase       *src.PosBase
    49  
    50  	// debugging support
    51  	debugFormat bool
    52  	read        int // bytes read
    53  }
    54  
    55  // Import populates imp from the serialized package data read from in.
    56  func Import(imp *types.Pkg, in *bufio.Reader) {
    57  	inimport = true
    58  	defer func() { inimport = false }()
    59  
    60  	p := importer{
    61  		in:       in,
    62  		imp:      imp,
    63  		version:  -1,           // unknown version
    64  		strList:  []string{""}, // empty string is mapped to 0
    65  		pathList: []string{""}, // empty path is mapped to 0
    66  	}
    67  
    68  	// read version info
    69  	var versionstr string
    70  	if b := p.rawByte(); b == 'c' || b == 'd' {
    71  		// Go1.7 encoding; first byte encodes low-level
    72  		// encoding format (compact vs debug).
    73  		// For backward-compatibility only (avoid problems with
    74  		// old installed packages). Newly compiled packages use
    75  		// the extensible format string.
    76  		// TODO(gri) Remove this support eventually; after Go1.8.
    77  		if b == 'd' {
    78  			p.debugFormat = true
    79  		}
    80  		p.trackAllTypes = p.rawByte() == 'a'
    81  		p.posInfoFormat = p.bool()
    82  		versionstr = p.string()
    83  		if versionstr == "v1" {
    84  			p.version = 0
    85  		}
    86  	} else {
    87  		// Go1.8 extensible encoding
    88  		// read version string and extract version number (ignore anything after the version number)
    89  		versionstr = p.rawStringln(b)
    90  		if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
    91  			if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
    92  				p.version = v
    93  			}
    94  		}
    95  	}
    96  
    97  	// read version specific flags - extend as necessary
    98  	switch p.version {
    99  	// case 6:
   100  	// 	...
   101  	//	fallthrough
   102  	case 5, 4, 3, 2, 1:
   103  		p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
   104  		p.trackAllTypes = p.bool()
   105  		p.posInfoFormat = p.bool()
   106  	case 0:
   107  		// Go1.7 encoding format - nothing to do here
   108  	default:
   109  		p.formatErrorf("unknown export format version %d (%q)", p.version, versionstr)
   110  	}
   111  
   112  	// --- generic export data ---
   113  
   114  	// populate typList with predeclared "known" types
   115  	p.typList = append(p.typList, predeclared()...)
   116  
   117  	// read package data
   118  	p.pkg()
   119  
   120  	// defer some type-checking until all types are read in completely
   121  	tcok := typecheckok
   122  	typecheckok = true
   123  	defercheckwidth()
   124  
   125  	// read objects
   126  
   127  	// phase 1
   128  	objcount := 0
   129  	for {
   130  		tag := p.tagOrIndex()
   131  		if tag == endTag {
   132  			break
   133  		}
   134  		p.obj(tag)
   135  		objcount++
   136  	}
   137  
   138  	// self-verification
   139  	if count := p.int(); count != objcount {
   140  		p.formatErrorf("got %d objects; want %d", objcount, count)
   141  	}
   142  
   143  	// --- compiler-specific export data ---
   144  
   145  	// read compiler-specific flags
   146  
   147  	// phase 2
   148  	objcount = 0
   149  	for {
   150  		tag := p.tagOrIndex()
   151  		if tag == endTag {
   152  			break
   153  		}
   154  		p.obj(tag)
   155  		objcount++
   156  	}
   157  
   158  	// self-verification
   159  	if count := p.int(); count != objcount {
   160  		p.formatErrorf("got %d objects; want %d", objcount, count)
   161  	}
   162  
   163  	// read inlineable functions bodies
   164  	if dclcontext != PEXTERN {
   165  		p.formatErrorf("unexpected context %d", dclcontext)
   166  	}
   167  
   168  	objcount = 0
   169  	for i0 := -1; ; {
   170  		i := p.int() // index of function with inlineable body
   171  		if i < 0 {
   172  			break
   173  		}
   174  
   175  		// don't process the same function twice
   176  		if i <= i0 {
   177  			p.formatErrorf("index not increasing: %d <= %d", i, i0)
   178  		}
   179  		i0 = i
   180  
   181  		if funcdepth != 0 {
   182  			p.formatErrorf("unexpected Funcdepth %d", funcdepth)
   183  		}
   184  
   185  		// Note: In the original code, funchdr and funcbody are called for
   186  		// all functions (that were not yet imported). Now, we are calling
   187  		// them only for functions with inlineable bodies. funchdr does
   188  		// parameter renaming which doesn't matter if we don't have a body.
   189  
   190  		inlCost := p.int()
   191  		if f := p.funcList[i]; f != nil && f.Func.Inl.Len() == 0 {
   192  			// function not yet imported - read body and set it
   193  			funchdr(f)
   194  			body := p.stmtList()
   195  			if body == nil {
   196  				// Make sure empty body is not interpreted as
   197  				// no inlineable body (see also parser.fnbody)
   198  				// (not doing so can cause significant performance
   199  				// degradation due to unnecessary calls to empty
   200  				// functions).
   201  				body = []*Node{nod(OEMPTY, nil, nil)}
   202  			}
   203  			f.Func.Inl.Set(body)
   204  			f.Func.InlCost = int32(inlCost)
   205  			if Debug['E'] > 0 && Debug['m'] > 2 && f.Func.Inl.Len() != 0 {
   206  				if Debug['m'] > 3 {
   207  					fmt.Printf("inl body for %v: %+v\n", f, f.Func.Inl)
   208  				} else {
   209  					fmt.Printf("inl body for %v: %v\n", f, f.Func.Inl)
   210  				}
   211  			}
   212  			funcbody()
   213  		} else {
   214  			// function already imported - read body but discard declarations
   215  			dclcontext = PDISCARD // throw away any declarations
   216  			p.stmtList()
   217  			dclcontext = PEXTERN
   218  		}
   219  
   220  		objcount++
   221  	}
   222  
   223  	// self-verification
   224  	if count := p.int(); count != objcount {
   225  		p.formatErrorf("got %d functions; want %d", objcount, count)
   226  	}
   227  
   228  	if dclcontext != PEXTERN {
   229  		p.formatErrorf("unexpected context %d", dclcontext)
   230  	}
   231  
   232  	p.verifyTypes()
   233  
   234  	// --- end of export data ---
   235  
   236  	typecheckok = tcok
   237  	resumecheckwidth()
   238  
   239  	if debug_dclstack != 0 {
   240  		testdclstack()
   241  	}
   242  }
   243  
   244  func (p *importer) formatErrorf(format string, args ...interface{}) {
   245  	if debugFormat {
   246  		Fatalf(format, args...)
   247  	}
   248  
   249  	yyerror("cannot import %q due to version skew - reinstall package (%s)",
   250  		p.imp.Path, fmt.Sprintf(format, args...))
   251  	errorexit()
   252  }
   253  
   254  func (p *importer) verifyTypes() {
   255  	for _, pair := range p.cmpList {
   256  		pt := pair.pt
   257  		t := pair.t
   258  		if !eqtype(pt.Orig, t) {
   259  			p.formatErrorf("inconsistent definition for type %v during import\n\t%L (in %q)\n\t%L (in %q)", pt.Sym, pt, pt.Sym.Importdef.Path, t, p.imp.Path)
   260  		}
   261  	}
   262  }
   263  
   264  // numImport tracks how often a package with a given name is imported.
   265  // It is used to provide a better error message (by using the package
   266  // path to disambiguate) if a package that appears multiple times with
   267  // the same name appears in an error message.
   268  var numImport = make(map[string]int)
   269  
   270  func (p *importer) pkg() *types.Pkg {
   271  	// if the package was seen before, i is its index (>= 0)
   272  	i := p.tagOrIndex()
   273  	if i >= 0 {
   274  		return p.pkgList[i]
   275  	}
   276  
   277  	// otherwise, i is the package tag (< 0)
   278  	if i != packageTag {
   279  		p.formatErrorf("expected package tag, found tag = %d", i)
   280  	}
   281  
   282  	// read package data
   283  	name := p.string()
   284  	var path string
   285  	if p.version >= 5 {
   286  		path = p.path()
   287  	} else {
   288  		path = p.string()
   289  	}
   290  
   291  	// we should never see an empty package name
   292  	if name == "" {
   293  		p.formatErrorf("empty package name for path %q", path)
   294  	}
   295  
   296  	// we should never see a bad import path
   297  	if isbadimport(path, true) {
   298  		p.formatErrorf("bad package path %q for package %s", path, name)
   299  	}
   300  
   301  	// an empty path denotes the package we are currently importing;
   302  	// it must be the first package we see
   303  	if (path == "") != (len(p.pkgList) == 0) {
   304  		p.formatErrorf("package path %q for pkg index %d", path, len(p.pkgList))
   305  	}
   306  
   307  	// add package to pkgList
   308  	pkg := p.imp
   309  	if path != "" {
   310  		pkg = types.NewPkg(path, "")
   311  	}
   312  	if pkg.Name == "" {
   313  		pkg.Name = name
   314  		numImport[name]++
   315  	} else if pkg.Name != name {
   316  		yyerror("conflicting package names %s and %s for path %q", pkg.Name, name, path)
   317  	}
   318  	if myimportpath != "" && path == myimportpath {
   319  		yyerror("import %q: package depends on %q (import cycle)", p.imp.Path, path)
   320  		errorexit()
   321  	}
   322  	p.pkgList = append(p.pkgList, pkg)
   323  
   324  	return pkg
   325  }
   326  
   327  func idealType(typ *types.Type) *types.Type {
   328  	if typ.IsUntyped() {
   329  		// canonicalize ideal types
   330  		typ = types.Types[TIDEAL]
   331  	}
   332  	return typ
   333  }
   334  
   335  func (p *importer) obj(tag int) {
   336  	switch tag {
   337  	case constTag:
   338  		pos := p.pos()
   339  		sym := p.qualifiedName()
   340  		typ := p.typ()
   341  		val := p.value(typ)
   342  		importconst(p.imp, sym, idealType(typ), npos(pos, nodlit(val)))
   343  
   344  	case aliasTag:
   345  		pos := p.pos()
   346  		sym := p.qualifiedName()
   347  		typ := p.typ()
   348  		importalias(pos, p.imp, sym, typ)
   349  
   350  	case typeTag:
   351  		p.typ()
   352  
   353  	case varTag:
   354  		pos := p.pos()
   355  		sym := p.qualifiedName()
   356  		typ := p.typ()
   357  		importvar(pos, p.imp, sym, typ)
   358  
   359  	case funcTag:
   360  		pos := p.pos()
   361  		sym := p.qualifiedName()
   362  		params := p.paramList()
   363  		result := p.paramList()
   364  
   365  		sig := functypefield(nil, params, result)
   366  		importsym(p.imp, sym, ONAME)
   367  		if old := asNode(sym.Def); old != nil && old.Op == ONAME {
   368  			// function was imported before (via another import)
   369  			if !eqtype(sig, old.Type) {
   370  				p.formatErrorf("inconsistent definition for func %v during import\n\t%v\n\t%v", sym, old.Type, sig)
   371  			}
   372  			n := asNode(old.Type.Nname())
   373  			p.funcList = append(p.funcList, n)
   374  			break
   375  		}
   376  
   377  		n := newfuncnamel(pos, sym)
   378  		n.Type = sig
   379  		// TODO(mdempsky): Stop clobbering n.Pos in declare.
   380  		savedlineno := lineno
   381  		lineno = pos
   382  		declare(n, PFUNC)
   383  		lineno = savedlineno
   384  		p.funcList = append(p.funcList, n)
   385  		importlist = append(importlist, n)
   386  
   387  		sig.SetNname(asTypesNode(n))
   388  
   389  		if Debug['E'] > 0 {
   390  			fmt.Printf("import [%q] func %v \n", p.imp.Path, n)
   391  		}
   392  
   393  	default:
   394  		p.formatErrorf("unexpected object (tag = %d)", tag)
   395  	}
   396  }
   397  
   398  func (p *importer) pos() src.XPos {
   399  	if !p.posInfoFormat {
   400  		return src.NoXPos
   401  	}
   402  
   403  	file := p.prevFile
   404  	line := p.prevLine
   405  	delta := p.int()
   406  	line += delta
   407  	if p.version >= 5 {
   408  		if delta == deltaNewFile {
   409  			if n := p.int(); n >= 0 {
   410  				// file changed
   411  				file = p.path()
   412  				line = n
   413  			}
   414  		}
   415  	} else {
   416  		if delta == 0 {
   417  			if n := p.int(); n >= 0 {
   418  				// file changed
   419  				file = p.prevFile[:n] + p.string()
   420  				line = p.int()
   421  			}
   422  		}
   423  	}
   424  	if file != p.prevFile {
   425  		p.prevFile = file
   426  		p.posBase = src.NewFileBase(file, file)
   427  	}
   428  	p.prevLine = line
   429  
   430  	pos := src.MakePos(p.posBase, uint(line), 0)
   431  	xpos := Ctxt.PosTable.XPos(pos)
   432  	return xpos
   433  }
   434  
   435  func (p *importer) path() string {
   436  	// if the path was seen before, i is its index (>= 0)
   437  	// (the empty string is at index 0)
   438  	i := p.int()
   439  	if i >= 0 {
   440  		return p.pathList[i]
   441  	}
   442  	// otherwise, i is the negative path length (< 0)
   443  	a := make([]string, -i)
   444  	for n := range a {
   445  		a[n] = p.string()
   446  	}
   447  	s := strings.Join(a, "/")
   448  	p.pathList = append(p.pathList, s)
   449  	return s
   450  }
   451  
   452  func (p *importer) newtyp(etype types.EType) *types.Type {
   453  	t := types.New(etype)
   454  	if p.trackAllTypes {
   455  		p.typList = append(p.typList, t)
   456  	}
   457  	return t
   458  }
   459  
   460  // importtype declares that pt, an imported named type, has underlying type t.
   461  func (p *importer) importtype(pt, t *types.Type) {
   462  	if pt.Etype == TFORW {
   463  		copytype(asNode(pt.Nod), t)
   464  		pt.Sym.Importdef = p.imp
   465  		pt.Sym.Lastlineno = lineno
   466  		declare(asNode(pt.Nod), PEXTERN)
   467  		checkwidth(pt)
   468  	} else {
   469  		// pt.Orig and t must be identical.
   470  		if p.trackAllTypes {
   471  			// If we track all types, t may not be fully set up yet.
   472  			// Collect the types and verify identity later.
   473  			p.cmpList = append(p.cmpList, struct{ pt, t *types.Type }{pt, t})
   474  		} else if !eqtype(pt.Orig, t) {
   475  			yyerror("inconsistent definition for type %v during import\n\t%L (in %q)\n\t%L (in %q)", pt.Sym, pt, pt.Sym.Importdef.Path, t, p.imp.Path)
   476  		}
   477  	}
   478  
   479  	if Debug['E'] != 0 {
   480  		fmt.Printf("import type %v %L\n", pt, t)
   481  	}
   482  }
   483  
   484  func (p *importer) typ() *types.Type {
   485  	// if the type was seen before, i is its index (>= 0)
   486  	i := p.tagOrIndex()
   487  	if i >= 0 {
   488  		return p.typList[i]
   489  	}
   490  
   491  	// otherwise, i is the type tag (< 0)
   492  	var t *types.Type
   493  	switch i {
   494  	case namedTag:
   495  		pos := p.pos()
   496  		tsym := p.qualifiedName()
   497  
   498  		t = pkgtype(pos, p.imp, tsym)
   499  		p.typList = append(p.typList, t)
   500  		dup := !t.IsKind(types.TFORW) // type already imported
   501  
   502  		// read underlying type
   503  		t0 := p.typ()
   504  		// TODO(mdempsky): Stop clobbering n.Pos in declare.
   505  		savedlineno := lineno
   506  		lineno = pos
   507  		p.importtype(t, t0)
   508  		lineno = savedlineno
   509  
   510  		// interfaces don't have associated methods
   511  		if t0.IsInterface() {
   512  			break
   513  		}
   514  
   515  		// set correct import context (since p.typ() may be called
   516  		// while importing the body of an inlined function)
   517  		savedContext := dclcontext
   518  		dclcontext = PEXTERN
   519  
   520  		// read associated methods
   521  		for i := p.int(); i > 0; i-- {
   522  			mpos := p.pos()
   523  			sym := p.fieldSym()
   524  
   525  			// during import unexported method names should be in the type's package
   526  			if !exportname(sym.Name) && sym.Pkg != tsym.Pkg {
   527  				Fatalf("imported method name %+v in wrong package %s\n", sym, tsym.Pkg.Name)
   528  			}
   529  
   530  			recv := p.paramList() // TODO(gri) do we need a full param list for the receiver?
   531  			params := p.paramList()
   532  			result := p.paramList()
   533  			nointerface := p.bool()
   534  
   535  			mt := functypefield(recv[0], params, result)
   536  			oldm := addmethod(sym, mt, false, nointerface)
   537  
   538  			if dup {
   539  				// An earlier import already declared this type and its methods.
   540  				// Discard the duplicate method declaration.
   541  				n := asNode(oldm.Type.Nname())
   542  				p.funcList = append(p.funcList, n)
   543  				continue
   544  			}
   545  
   546  			n := newfuncnamel(mpos, methodname(sym, recv[0].Type))
   547  			n.Type = mt
   548  			n.SetClass(PFUNC)
   549  			checkwidth(n.Type)
   550  			p.funcList = append(p.funcList, n)
   551  			importlist = append(importlist, n)
   552  
   553  			// (comment from parser.go)
   554  			// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
   555  			// (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
   556  			// out by typecheck's lookdot as this $$.ttype. So by providing
   557  			// this back link here we avoid special casing there.
   558  			mt.SetNname(asTypesNode(n))
   559  
   560  			if Debug['E'] > 0 {
   561  				fmt.Printf("import [%q] meth %v \n", p.imp.Path, n)
   562  			}
   563  		}
   564  
   565  		dclcontext = savedContext
   566  
   567  	case arrayTag:
   568  		t = p.newtyp(TARRAY)
   569  		bound := p.int64()
   570  		elem := p.typ()
   571  		t.Extra = &types.Array{Elem: elem, Bound: bound}
   572  
   573  	case sliceTag:
   574  		t = p.newtyp(TSLICE)
   575  		elem := p.typ()
   576  		t.Extra = types.Slice{Elem: elem}
   577  
   578  	case dddTag:
   579  		t = p.newtyp(TDDDFIELD)
   580  		t.Extra = types.DDDField{T: p.typ()}
   581  
   582  	case structTag:
   583  		t = p.newtyp(TSTRUCT)
   584  		t.SetFields(p.fieldList())
   585  		checkwidth(t)
   586  
   587  	case pointerTag:
   588  		t = p.newtyp(types.Tptr)
   589  		t.Extra = types.Ptr{Elem: p.typ()}
   590  
   591  	case signatureTag:
   592  		t = p.newtyp(TFUNC)
   593  		params := p.paramList()
   594  		result := p.paramList()
   595  		functypefield0(t, nil, params, result)
   596  
   597  	case interfaceTag:
   598  		if ml := p.methodList(); len(ml) == 0 {
   599  			t = types.Types[TINTER]
   600  		} else {
   601  			t = p.newtyp(TINTER)
   602  			t.SetInterface(ml)
   603  		}
   604  
   605  	case mapTag:
   606  		t = p.newtyp(TMAP)
   607  		mt := t.MapType()
   608  		mt.Key = p.typ()
   609  		mt.Val = p.typ()
   610  
   611  	case chanTag:
   612  		t = p.newtyp(TCHAN)
   613  		ct := t.ChanType()
   614  		ct.Dir = types.ChanDir(p.int())
   615  		ct.Elem = p.typ()
   616  
   617  	default:
   618  		p.formatErrorf("unexpected type (tag = %d)", i)
   619  	}
   620  
   621  	if t == nil {
   622  		p.formatErrorf("nil type (type tag = %d)", i)
   623  	}
   624  
   625  	return t
   626  }
   627  
   628  func (p *importer) qualifiedName() *types.Sym {
   629  	name := p.string()
   630  	pkg := p.pkg()
   631  	return pkg.Lookup(name)
   632  }
   633  
   634  func (p *importer) fieldList() (fields []*types.Field) {
   635  	if n := p.int(); n > 0 {
   636  		fields = make([]*types.Field, n)
   637  		for i := range fields {
   638  			fields[i] = p.field()
   639  		}
   640  	}
   641  	return
   642  }
   643  
   644  func (p *importer) field() *types.Field {
   645  	pos := p.pos()
   646  	sym, alias := p.fieldName()
   647  	typ := p.typ()
   648  	note := p.string()
   649  
   650  	f := types.NewField()
   651  	if sym.Name == "" {
   652  		// anonymous field: typ must be T or *T and T must be a type name
   653  		s := typ.Sym
   654  		if s == nil && typ.IsPtr() {
   655  			s = typ.Elem().Sym // deref
   656  		}
   657  		sym = sym.Pkg.Lookup(s.Name)
   658  		f.Embedded = 1
   659  	} else if alias {
   660  		// anonymous field: we have an explicit name because it's a type alias
   661  		f.Embedded = 1
   662  	}
   663  
   664  	f.Sym = sym
   665  	f.Nname = asTypesNode(newnamel(pos, sym))
   666  	f.Type = typ
   667  	f.Note = note
   668  
   669  	return f
   670  }
   671  
   672  func (p *importer) methodList() (methods []*types.Field) {
   673  	for n := p.int(); n > 0; n-- {
   674  		f := types.NewField()
   675  		f.Nname = asTypesNode(newname(nblank.Sym))
   676  		asNode(f.Nname).Pos = p.pos()
   677  		f.Type = p.typ()
   678  		methods = append(methods, f)
   679  	}
   680  
   681  	for n := p.int(); n > 0; n-- {
   682  		methods = append(methods, p.method())
   683  	}
   684  
   685  	return
   686  }
   687  
   688  func (p *importer) method() *types.Field {
   689  	pos := p.pos()
   690  	sym := p.methodName()
   691  	params := p.paramList()
   692  	result := p.paramList()
   693  
   694  	f := types.NewField()
   695  	f.Sym = sym
   696  	f.Nname = asTypesNode(newnamel(pos, sym))
   697  	f.Type = functypefield(fakeRecvField(), params, result)
   698  	return f
   699  }
   700  
   701  func (p *importer) fieldName() (*types.Sym, bool) {
   702  	name := p.string()
   703  	if p.version == 0 && name == "_" {
   704  		// version 0 didn't export a package for _ field names
   705  		// but used the builtin package instead
   706  		return builtinpkg.Lookup(name), false
   707  	}
   708  	pkg := localpkg
   709  	alias := false
   710  	switch name {
   711  	case "":
   712  		// 1) field name matches base type name and is exported: nothing to do
   713  	case "?":
   714  		// 2) field name matches base type name and is not exported: need package
   715  		name = ""
   716  		pkg = p.pkg()
   717  	case "@":
   718  		// 3) field name doesn't match base type name (alias name): need name and possibly package
   719  		name = p.string()
   720  		alias = true
   721  		fallthrough
   722  	default:
   723  		if !exportname(name) {
   724  			pkg = p.pkg()
   725  		}
   726  	}
   727  	return pkg.Lookup(name), alias
   728  }
   729  
   730  func (p *importer) methodName() *types.Sym {
   731  	name := p.string()
   732  	if p.version == 0 && name == "_" {
   733  		// version 0 didn't export a package for _ method names
   734  		// but used the builtin package instead
   735  		return builtinpkg.Lookup(name)
   736  	}
   737  	pkg := localpkg
   738  	if !exportname(name) {
   739  		pkg = p.pkg()
   740  	}
   741  	return pkg.Lookup(name)
   742  }
   743  
   744  func (p *importer) paramList() []*types.Field {
   745  	i := p.int()
   746  	if i == 0 {
   747  		return nil
   748  	}
   749  	// negative length indicates unnamed parameters
   750  	named := true
   751  	if i < 0 {
   752  		i = -i
   753  		named = false
   754  	}
   755  	// i > 0
   756  	fs := make([]*types.Field, i)
   757  	for i := range fs {
   758  		fs[i] = p.param(named)
   759  	}
   760  	return fs
   761  }
   762  
   763  func (p *importer) param(named bool) *types.Field {
   764  	f := types.NewField()
   765  	f.Type = p.typ()
   766  	if f.Type.Etype == TDDDFIELD {
   767  		// TDDDFIELD indicates wrapped ... slice type
   768  		f.Type = types.NewSlice(f.Type.DDDField())
   769  		f.SetIsddd(true)
   770  	}
   771  
   772  	if named {
   773  		name := p.string()
   774  		if name == "" {
   775  			p.formatErrorf("expected named parameter")
   776  		}
   777  		// TODO(gri) Supply function/method package rather than
   778  		// encoding the package for each parameter repeatedly.
   779  		pkg := localpkg
   780  		if name != "_" {
   781  			pkg = p.pkg()
   782  		}
   783  		f.Sym = pkg.Lookup(name)
   784  		f.Nname = asTypesNode(newname(f.Sym))
   785  	}
   786  
   787  	// TODO(gri) This is compiler-specific (escape info).
   788  	// Move into compiler-specific section eventually?
   789  	f.Note = p.string()
   790  
   791  	return f
   792  }
   793  
   794  func (p *importer) value(typ *types.Type) (x Val) {
   795  	switch tag := p.tagOrIndex(); tag {
   796  	case falseTag:
   797  		x.U = false
   798  
   799  	case trueTag:
   800  		x.U = true
   801  
   802  	case int64Tag:
   803  		u := new(Mpint)
   804  		u.SetInt64(p.int64())
   805  		u.Rune = typ == types.Idealrune
   806  		x.U = u
   807  
   808  	case floatTag:
   809  		f := newMpflt()
   810  		p.float(f)
   811  		if typ == types.Idealint || typ.IsInteger() {
   812  			// uncommon case: large int encoded as float
   813  			u := new(Mpint)
   814  			u.SetFloat(f)
   815  			x.U = u
   816  			break
   817  		}
   818  		x.U = f
   819  
   820  	case complexTag:
   821  		u := new(Mpcplx)
   822  		p.float(&u.Real)
   823  		p.float(&u.Imag)
   824  		x.U = u
   825  
   826  	case stringTag:
   827  		x.U = p.string()
   828  
   829  	case unknownTag:
   830  		p.formatErrorf("unknown constant (importing package with errors)")
   831  
   832  	case nilTag:
   833  		x.U = new(NilVal)
   834  
   835  	default:
   836  		p.formatErrorf("unexpected value tag %d", tag)
   837  	}
   838  
   839  	// verify ideal type
   840  	if typ.IsUntyped() && untype(x.Ctype()) != typ {
   841  		p.formatErrorf("value %v and type %v don't match", x, typ)
   842  	}
   843  
   844  	return
   845  }
   846  
   847  func (p *importer) float(x *Mpflt) {
   848  	sign := p.int()
   849  	if sign == 0 {
   850  		x.SetFloat64(0)
   851  		return
   852  	}
   853  
   854  	exp := p.int()
   855  	mant := new(big.Int).SetBytes([]byte(p.string()))
   856  
   857  	m := x.Val.SetInt(mant)
   858  	m.SetMantExp(m, exp-mant.BitLen())
   859  	if sign < 0 {
   860  		m.Neg(m)
   861  	}
   862  }
   863  
   864  // ----------------------------------------------------------------------------
   865  // Inlined function bodies
   866  
   867  // Approach: Read nodes and use them to create/declare the same data structures
   868  // as done originally by the (hidden) parser by closely following the parser's
   869  // original code. In other words, "parsing" the import data (which happens to
   870  // be encoded in binary rather textual form) is the best way at the moment to
   871  // re-establish the syntax tree's invariants. At some future point we might be
   872  // able to avoid this round-about way and create the rewritten nodes directly,
   873  // possibly avoiding a lot of duplicate work (name resolution, type checking).
   874  //
   875  // Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their
   876  // unrefined nodes (since this is what the importer uses). The respective case
   877  // entries are unreachable in the importer.
   878  
   879  func (p *importer) stmtList() []*Node {
   880  	var list []*Node
   881  	for {
   882  		n := p.node()
   883  		if n == nil {
   884  			break
   885  		}
   886  		// OBLOCK nodes may be created when importing ODCL nodes - unpack them
   887  		if n.Op == OBLOCK {
   888  			list = append(list, n.List.Slice()...)
   889  		} else {
   890  			list = append(list, n)
   891  		}
   892  	}
   893  	return list
   894  }
   895  
   896  func (p *importer) exprList() []*Node {
   897  	var list []*Node
   898  	for {
   899  		n := p.expr()
   900  		if n == nil {
   901  			break
   902  		}
   903  		list = append(list, n)
   904  	}
   905  	return list
   906  }
   907  
   908  func (p *importer) elemList() []*Node {
   909  	c := p.int()
   910  	list := make([]*Node, c)
   911  	for i := range list {
   912  		s := p.fieldSym()
   913  		list[i] = nodSym(OSTRUCTKEY, p.expr(), s)
   914  	}
   915  	return list
   916  }
   917  
   918  func (p *importer) expr() *Node {
   919  	n := p.node()
   920  	if n != nil && n.Op == OBLOCK {
   921  		Fatalf("unexpected block node: %v", n)
   922  	}
   923  	return n
   924  }
   925  
   926  func npos(pos src.XPos, n *Node) *Node {
   927  	n.Pos = pos
   928  	return n
   929  }
   930  
   931  // TODO(gri) split into expr and stmt
   932  func (p *importer) node() *Node {
   933  	switch op := p.op(); op {
   934  	// expressions
   935  	// case OPAREN:
   936  	// 	unreachable - unpacked by exporter
   937  
   938  	// case ODDDARG:
   939  	//	unimplemented
   940  
   941  	case OLITERAL:
   942  		pos := p.pos()
   943  		typ := p.typ()
   944  		n := npos(pos, nodlit(p.value(typ)))
   945  		if !typ.IsUntyped() {
   946  			// Type-checking simplifies unsafe.Pointer(uintptr(c))
   947  			// to unsafe.Pointer(c) which then cannot type-checked
   948  			// again. Re-introduce explicit uintptr(c) conversion.
   949  			// (issue 16317).
   950  			if typ.IsUnsafePtr() {
   951  				n = nodl(pos, OCONV, n, nil)
   952  				n.Type = types.Types[TUINTPTR]
   953  			}
   954  			n = nodl(pos, OCONV, n, nil)
   955  			n.Type = typ
   956  		}
   957  		return n
   958  
   959  	case ONAME:
   960  		return npos(p.pos(), mkname(p.sym()))
   961  
   962  	// case OPACK, ONONAME:
   963  	// 	unreachable - should have been resolved by typechecking
   964  
   965  	case OTYPE:
   966  		return npos(p.pos(), typenod(p.typ()))
   967  
   968  	// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
   969  	//      unreachable - should have been resolved by typechecking
   970  
   971  	// case OCLOSURE:
   972  	//	unimplemented
   973  
   974  	case OPTRLIT:
   975  		pos := p.pos()
   976  		n := npos(pos, p.expr())
   977  		if !p.bool() /* !implicit, i.e. '&' operator */ {
   978  			if n.Op == OCOMPLIT {
   979  				// Special case for &T{...}: turn into (*T){...}.
   980  				n.Right = nodl(pos, OIND, n.Right, nil)
   981  				n.Right.SetImplicit(true)
   982  			} else {
   983  				n = nodl(pos, OADDR, n, nil)
   984  			}
   985  		}
   986  		return n
   987  
   988  	case OSTRUCTLIT:
   989  		// TODO(mdempsky): Export position information for OSTRUCTKEY nodes.
   990  		savedlineno := lineno
   991  		lineno = p.pos()
   992  		n := nodl(lineno, OCOMPLIT, nil, typenod(p.typ()))
   993  		n.List.Set(p.elemList()) // special handling of field names
   994  		lineno = savedlineno
   995  		return n
   996  
   997  	// case OARRAYLIT, OSLICELIT, OMAPLIT:
   998  	// 	unreachable - mapped to case OCOMPLIT below by exporter
   999  
  1000  	case OCOMPLIT:
  1001  		n := nodl(p.pos(), OCOMPLIT, nil, typenod(p.typ()))
  1002  		n.List.Set(p.exprList())
  1003  		return n
  1004  
  1005  	case OKEY:
  1006  		pos := p.pos()
  1007  		left, right := p.exprsOrNil()
  1008  		return nodl(pos, OKEY, left, right)
  1009  
  1010  	// case OSTRUCTKEY:
  1011  	//	unreachable - handled in case OSTRUCTLIT by elemList
  1012  
  1013  	// case OCALLPART:
  1014  	//	unimplemented
  1015  
  1016  	// case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
  1017  	// 	unreachable - mapped to case OXDOT below by exporter
  1018  
  1019  	case OXDOT:
  1020  		// see parser.new_dotname
  1021  		return npos(p.pos(), nodSym(OXDOT, p.expr(), p.fieldSym()))
  1022  
  1023  	// case ODOTTYPE, ODOTTYPE2:
  1024  	// 	unreachable - mapped to case ODOTTYPE below by exporter
  1025  
  1026  	case ODOTTYPE:
  1027  		n := nodl(p.pos(), ODOTTYPE, p.expr(), nil)
  1028  		n.Type = p.typ()
  1029  		return n
  1030  
  1031  	// case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
  1032  	// 	unreachable - mapped to cases below by exporter
  1033  
  1034  	case OINDEX:
  1035  		return nodl(p.pos(), op, p.expr(), p.expr())
  1036  
  1037  	case OSLICE, OSLICE3:
  1038  		n := nodl(p.pos(), op, p.expr(), nil)
  1039  		low, high := p.exprsOrNil()
  1040  		var max *Node
  1041  		if n.Op.IsSlice3() {
  1042  			max = p.expr()
  1043  		}
  1044  		n.SetSliceBounds(low, high, max)
  1045  		return n
  1046  
  1047  	// case OCONV, OCONVIFACE, OCONVNOP, OARRAYBYTESTR, OARRAYRUNESTR, OSTRARRAYBYTE, OSTRARRAYRUNE, ORUNESTR:
  1048  	// 	unreachable - mapped to OCONV case below by exporter
  1049  
  1050  	case OCONV:
  1051  		n := nodl(p.pos(), OCONV, p.expr(), nil)
  1052  		n.Type = p.typ()
  1053  		return n
  1054  
  1055  	case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
  1056  		n := npos(p.pos(), builtinCall(op))
  1057  		n.List.Set(p.exprList())
  1058  		if op == OAPPEND {
  1059  			n.SetIsddd(p.bool())
  1060  		}
  1061  		return n
  1062  
  1063  	// case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
  1064  	// 	unreachable - mapped to OCALL case below by exporter
  1065  
  1066  	case OCALL:
  1067  		n := nodl(p.pos(), OCALL, p.expr(), nil)
  1068  		n.List.Set(p.exprList())
  1069  		n.SetIsddd(p.bool())
  1070  		return n
  1071  
  1072  	case OMAKEMAP, OMAKECHAN, OMAKESLICE:
  1073  		n := npos(p.pos(), builtinCall(OMAKE))
  1074  		n.List.Append(typenod(p.typ()))
  1075  		n.List.Append(p.exprList()...)
  1076  		return n
  1077  
  1078  	// unary expressions
  1079  	case OPLUS, OMINUS, OADDR, OCOM, OIND, ONOT, ORECV:
  1080  		return nodl(p.pos(), op, p.expr(), nil)
  1081  
  1082  	// binary expressions
  1083  	case OADD, OAND, OANDAND, OANDNOT, ODIV, OEQ, OGE, OGT, OLE, OLT,
  1084  		OLSH, OMOD, OMUL, ONE, OOR, OOROR, ORSH, OSEND, OSUB, OXOR:
  1085  		return nodl(p.pos(), op, p.expr(), p.expr())
  1086  
  1087  	case OADDSTR:
  1088  		pos := p.pos()
  1089  		list := p.exprList()
  1090  		x := npos(pos, list[0])
  1091  		for _, y := range list[1:] {
  1092  			x = nodl(pos, OADD, x, y)
  1093  		}
  1094  		return x
  1095  
  1096  	// case OCMPSTR, OCMPIFACE:
  1097  	// 	unreachable - mapped to std comparison operators by exporter
  1098  
  1099  	case ODCLCONST:
  1100  		// TODO(gri) these should not be exported in the first place
  1101  		return nodl(p.pos(), OEMPTY, nil, nil)
  1102  
  1103  	// --------------------------------------------------------------------
  1104  	// statements
  1105  	case ODCL:
  1106  		if p.version < 2 {
  1107  			// versions 0 and 1 exported a bool here but it
  1108  			// was always false - simply ignore in this case
  1109  			p.bool()
  1110  		}
  1111  		pos := p.pos()
  1112  		lhs := dclname(p.sym())
  1113  		typ := typenod(p.typ())
  1114  		return npos(pos, liststmt(variter([]*Node{lhs}, typ, nil))) // TODO(gri) avoid list creation
  1115  
  1116  	// case ODCLFIELD:
  1117  	//	unimplemented
  1118  
  1119  	// case OAS, OASWB:
  1120  	// 	unreachable - mapped to OAS case below by exporter
  1121  
  1122  	case OAS:
  1123  		return nodl(p.pos(), OAS, p.expr(), p.expr())
  1124  
  1125  	case OASOP:
  1126  		n := nodl(p.pos(), OASOP, nil, nil)
  1127  		n.Etype = types.EType(p.int())
  1128  		n.Left = p.expr()
  1129  		if !p.bool() {
  1130  			n.Right = nodintconst(1)
  1131  			n.SetImplicit(true)
  1132  		} else {
  1133  			n.Right = p.expr()
  1134  		}
  1135  		return n
  1136  
  1137  	// case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
  1138  	// 	unreachable - mapped to OAS2 case below by exporter
  1139  
  1140  	case OAS2:
  1141  		n := nodl(p.pos(), OAS2, nil, nil)
  1142  		n.List.Set(p.exprList())
  1143  		n.Rlist.Set(p.exprList())
  1144  		return n
  1145  
  1146  	case ORETURN:
  1147  		n := nodl(p.pos(), ORETURN, nil, nil)
  1148  		n.List.Set(p.exprList())
  1149  		return n
  1150  
  1151  	// case ORETJMP:
  1152  	// 	unreachable - generated by compiler for trampolin routines (not exported)
  1153  
  1154  	case OPROC, ODEFER:
  1155  		return nodl(p.pos(), op, p.expr(), nil)
  1156  
  1157  	case OIF:
  1158  		n := nodl(p.pos(), OIF, nil, nil)
  1159  		n.Ninit.Set(p.stmtList())
  1160  		n.Left = p.expr()
  1161  		n.Nbody.Set(p.stmtList())
  1162  		n.Rlist.Set(p.stmtList())
  1163  		return n
  1164  
  1165  	case OFOR:
  1166  		n := nodl(p.pos(), OFOR, nil, nil)
  1167  		n.Ninit.Set(p.stmtList())
  1168  		n.Left, n.Right = p.exprsOrNil()
  1169  		n.Nbody.Set(p.stmtList())
  1170  		return n
  1171  
  1172  	case ORANGE:
  1173  		n := nodl(p.pos(), ORANGE, nil, nil)
  1174  		n.List.Set(p.stmtList())
  1175  		n.Right = p.expr()
  1176  		n.Nbody.Set(p.stmtList())
  1177  		return n
  1178  
  1179  	case OSELECT, OSWITCH:
  1180  		n := nodl(p.pos(), op, nil, nil)
  1181  		n.Ninit.Set(p.stmtList())
  1182  		n.Left, _ = p.exprsOrNil()
  1183  		n.List.Set(p.stmtList())
  1184  		return n
  1185  
  1186  	// case OCASE, OXCASE:
  1187  	// 	unreachable - mapped to OXCASE case below by exporter
  1188  
  1189  	case OXCASE:
  1190  		n := nodl(p.pos(), OXCASE, nil, nil)
  1191  		n.List.Set(p.exprList())
  1192  		// TODO(gri) eventually we must declare variables for type switch
  1193  		// statements (type switch statements are not yet exported)
  1194  		n.Nbody.Set(p.stmtList())
  1195  		return n
  1196  
  1197  	// case OFALL:
  1198  	// 	unreachable - mapped to OXFALL case below by exporter
  1199  
  1200  	case OFALL:
  1201  		n := nodl(p.pos(), OFALL, nil, nil)
  1202  		return n
  1203  
  1204  	case OBREAK, OCONTINUE:
  1205  		pos := p.pos()
  1206  		left, _ := p.exprsOrNil()
  1207  		if left != nil {
  1208  			left = newname(left.Sym)
  1209  		}
  1210  		return nodl(pos, op, left, nil)
  1211  
  1212  	// case OEMPTY:
  1213  	// 	unreachable - not emitted by exporter
  1214  
  1215  	case OGOTO, OLABEL:
  1216  		return nodl(p.pos(), op, newname(p.expr().Sym), nil)
  1217  
  1218  	case OEND:
  1219  		return nil
  1220  
  1221  	default:
  1222  		Fatalf("cannot import %v (%d) node\n"+
  1223  			"==> please file an issue and assign to gri@\n", op, int(op))
  1224  		panic("unreachable") // satisfy compiler
  1225  	}
  1226  }
  1227  
  1228  func builtinCall(op Op) *Node {
  1229  	return nod(OCALL, mkname(builtinpkg.Lookup(goopnames[op])), nil)
  1230  }
  1231  
  1232  func (p *importer) exprsOrNil() (a, b *Node) {
  1233  	ab := p.int()
  1234  	if ab&1 != 0 {
  1235  		a = p.expr()
  1236  	}
  1237  	if ab&2 != 0 {
  1238  		b = p.expr()
  1239  	}
  1240  	return
  1241  }
  1242  
  1243  func (p *importer) fieldSym() *types.Sym {
  1244  	name := p.string()
  1245  	pkg := localpkg
  1246  	if !exportname(name) {
  1247  		pkg = p.pkg()
  1248  	}
  1249  	return pkg.Lookup(name)
  1250  }
  1251  
  1252  func (p *importer) sym() *types.Sym {
  1253  	name := p.string()
  1254  	pkg := localpkg
  1255  	if name != "_" {
  1256  		pkg = p.pkg()
  1257  	}
  1258  	linkname := p.string()
  1259  	sym := pkg.Lookup(name)
  1260  	sym.Linkname = linkname
  1261  	return sym
  1262  }
  1263  
  1264  func (p *importer) bool() bool {
  1265  	return p.int() != 0
  1266  }
  1267  
  1268  func (p *importer) op() Op {
  1269  	return Op(p.int())
  1270  }
  1271  
  1272  // ----------------------------------------------------------------------------
  1273  // Low-level decoders
  1274  
  1275  func (p *importer) tagOrIndex() int {
  1276  	if p.debugFormat {
  1277  		p.marker('t')
  1278  	}
  1279  
  1280  	return int(p.rawInt64())
  1281  }
  1282  
  1283  func (p *importer) int() int {
  1284  	x := p.int64()
  1285  	if int64(int(x)) != x {
  1286  		p.formatErrorf("exported integer too large")
  1287  	}
  1288  	return int(x)
  1289  }
  1290  
  1291  func (p *importer) int64() int64 {
  1292  	if p.debugFormat {
  1293  		p.marker('i')
  1294  	}
  1295  
  1296  	return p.rawInt64()
  1297  }
  1298  
  1299  func (p *importer) string() string {
  1300  	if p.debugFormat {
  1301  		p.marker('s')
  1302  	}
  1303  	// if the string was seen before, i is its index (>= 0)
  1304  	// (the empty string is at index 0)
  1305  	i := p.rawInt64()
  1306  	if i >= 0 {
  1307  		return p.strList[i]
  1308  	}
  1309  	// otherwise, i is the negative string length (< 0)
  1310  	if n := int(-i); n <= cap(p.buf) {
  1311  		p.buf = p.buf[:n]
  1312  	} else {
  1313  		p.buf = make([]byte, n)
  1314  	}
  1315  	for i := range p.buf {
  1316  		p.buf[i] = p.rawByte()
  1317  	}
  1318  	s := string(p.buf)
  1319  	p.strList = append(p.strList, s)
  1320  	return s
  1321  }
  1322  
  1323  func (p *importer) marker(want byte) {
  1324  	if got := p.rawByte(); got != want {
  1325  		p.formatErrorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
  1326  	}
  1327  
  1328  	pos := p.read
  1329  	if n := int(p.rawInt64()); n != pos {
  1330  		p.formatErrorf("incorrect position: got %d; want %d", n, pos)
  1331  	}
  1332  }
  1333  
  1334  // rawInt64 should only be used by low-level decoders.
  1335  func (p *importer) rawInt64() int64 {
  1336  	i, err := binary.ReadVarint(p)
  1337  	if err != nil {
  1338  		p.formatErrorf("read error: %v", err)
  1339  	}
  1340  	return i
  1341  }
  1342  
  1343  // rawStringln should only be used to read the initial version string.
  1344  func (p *importer) rawStringln(b byte) string {
  1345  	p.buf = p.buf[:0]
  1346  	for b != '\n' {
  1347  		p.buf = append(p.buf, b)
  1348  		b = p.rawByte()
  1349  	}
  1350  	return string(p.buf)
  1351  }
  1352  
  1353  // needed for binary.ReadVarint in rawInt64
  1354  func (p *importer) ReadByte() (byte, error) {
  1355  	return p.rawByte(), nil
  1356  }
  1357  
  1358  // rawByte is the bottleneck interface for reading from p.in.
  1359  // It unescapes '|' 'S' to '$' and '|' '|' to '|'.
  1360  // rawByte should only be used by low-level decoders.
  1361  func (p *importer) rawByte() byte {
  1362  	c, err := p.in.ReadByte()
  1363  	p.read++
  1364  	if err != nil {
  1365  		p.formatErrorf("read error: %v", err)
  1366  	}
  1367  	if c == '|' {
  1368  		c, err = p.in.ReadByte()
  1369  		p.read++
  1370  		if err != nil {
  1371  			p.formatErrorf("read error: %v", err)
  1372  		}
  1373  		switch c {
  1374  		case 'S':
  1375  			c = '$'
  1376  		case '|':
  1377  			// nothing to do
  1378  		default:
  1379  			p.formatErrorf("unexpected escape sequence in export data")
  1380  		}
  1381  	}
  1382  	return c
  1383  }