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