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

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Indexed package import.
     6  // See iexport.go for the export data format.
     7  
     8  package gc
     9  
    10  import (
    11  	"cmd/compile/internal/types"
    12  	"cmd/internal/bio"
    13  	"cmd/internal/src"
    14  	"encoding/binary"
    15  	"fmt"
    16  	"math/big"
    17  	"os"
    18  	"strings"
    19  )
    20  
    21  // An iimporterAndOffset identifies an importer and an offset within
    22  // its data section.
    23  type iimporterAndOffset struct {
    24  	p   *iimporter
    25  	off uint64
    26  }
    27  
    28  var (
    29  	// declImporter maps from imported identifiers to an importer
    30  	// and offset where that identifier's declaration can be read.
    31  	declImporter = map[*types.Sym]iimporterAndOffset{}
    32  
    33  	// inlineImporter is like declImporter, but for inline bodies
    34  	// for function and method symbols.
    35  	inlineImporter = map[*types.Sym]iimporterAndOffset{}
    36  )
    37  
    38  func expandDecl(n *Node) {
    39  	if n.Op != ONONAME {
    40  		return
    41  	}
    42  
    43  	r := importReaderFor(n, declImporter)
    44  	if r == nil {
    45  		// Can happen if user tries to reference an undeclared name.
    46  		return
    47  	}
    48  
    49  	r.doDecl(n)
    50  }
    51  
    52  func expandInline(fn *Node) {
    53  	if fn.Func.Inl.Body != nil {
    54  		return
    55  	}
    56  
    57  	r := importReaderFor(fn, inlineImporter)
    58  	if r == nil {
    59  		Fatalf("missing import reader for %v", fn)
    60  	}
    61  
    62  	r.doInline(fn)
    63  }
    64  
    65  func importReaderFor(n *Node, importers map[*types.Sym]iimporterAndOffset) *importReader {
    66  	x, ok := importers[n.Sym]
    67  	if !ok {
    68  		return nil
    69  	}
    70  
    71  	return x.p.newReader(x.off, n.Sym.Pkg)
    72  }
    73  
    74  type intReader struct {
    75  	*bio.Reader
    76  	pkg *types.Pkg
    77  }
    78  
    79  func (r *intReader) int64() int64 {
    80  	i, err := binary.ReadVarint(r.Reader)
    81  	if err != nil {
    82  		yyerror("import %q: read error: %v", r.pkg.Path, err)
    83  		errorexit()
    84  	}
    85  	return i
    86  }
    87  
    88  func (r *intReader) uint64() uint64 {
    89  	i, err := binary.ReadUvarint(r.Reader)
    90  	if err != nil {
    91  		yyerror("import %q: read error: %v", r.pkg.Path, err)
    92  		errorexit()
    93  	}
    94  	return i
    95  }
    96  
    97  func iimport(pkg *types.Pkg, in *bio.Reader) {
    98  	ir := &intReader{in, pkg}
    99  
   100  	version := ir.uint64()
   101  	if version != iexportVersion {
   102  		yyerror("import %q: unknown export format version %d", pkg.Path, version)
   103  		errorexit()
   104  	}
   105  
   106  	sLen := ir.uint64()
   107  	dLen := ir.uint64()
   108  
   109  	// Map string (and data) section into memory as a single large
   110  	// string. This reduces heap fragmentation and allows
   111  	// returning individual substrings very efficiently.
   112  	data, err := mapFile(in.File(), in.Offset(), int64(sLen+dLen))
   113  	if err != nil {
   114  		yyerror("import %q: mapping input: %v", pkg.Path, err)
   115  		errorexit()
   116  	}
   117  	stringData := data[:sLen]
   118  	declData := data[sLen:]
   119  
   120  	in.Seek(int64(sLen+dLen), os.SEEK_CUR)
   121  
   122  	p := &iimporter{
   123  		ipkg: pkg,
   124  
   125  		pkgCache:     map[uint64]*types.Pkg{},
   126  		posBaseCache: map[uint64]*src.PosBase{},
   127  		typCache:     map[uint64]*types.Type{},
   128  
   129  		stringData: stringData,
   130  		declData:   declData,
   131  	}
   132  
   133  	for i, pt := range predeclared() {
   134  		p.typCache[uint64(i)] = pt
   135  	}
   136  
   137  	// Declaration index.
   138  	for nPkgs := ir.uint64(); nPkgs > 0; nPkgs-- {
   139  		pkg := p.pkgAt(ir.uint64())
   140  		pkgName := p.stringAt(ir.uint64())
   141  		pkgHeight := int(ir.uint64())
   142  		if pkg.Name == "" {
   143  			pkg.Name = pkgName
   144  			pkg.Height = pkgHeight
   145  			numImport[pkgName]++
   146  
   147  			// TODO(mdempsky): This belongs somewhere else.
   148  			pkg.Lookup("_").Def = asTypesNode(nblank)
   149  		} else {
   150  			if pkg.Name != pkgName {
   151  				Fatalf("conflicting package names %v and %v for path %q", pkg.Name, pkgName, pkg.Path)
   152  			}
   153  			if pkg.Height != pkgHeight {
   154  				Fatalf("conflicting package heights %v and %v for path %q", pkg.Height, pkgHeight, pkg.Path)
   155  			}
   156  		}
   157  
   158  		for nSyms := ir.uint64(); nSyms > 0; nSyms-- {
   159  			s := pkg.Lookup(p.stringAt(ir.uint64()))
   160  			off := ir.uint64()
   161  
   162  			if _, ok := declImporter[s]; ok {
   163  				continue
   164  			}
   165  			declImporter[s] = iimporterAndOffset{p, off}
   166  
   167  			// Create stub declaration. If used, this will
   168  			// be overwritten by expandDecl.
   169  			if s.Def != nil {
   170  				Fatalf("unexpected definition for %v: %v", s, asNode(s.Def))
   171  			}
   172  			s.Def = asTypesNode(npos(src.NoXPos, dclname(s)))
   173  		}
   174  	}
   175  
   176  	// Inline body index.
   177  	for nPkgs := ir.uint64(); nPkgs > 0; nPkgs-- {
   178  		pkg := p.pkgAt(ir.uint64())
   179  
   180  		for nSyms := ir.uint64(); nSyms > 0; nSyms-- {
   181  			s := pkg.Lookup(p.stringAt(ir.uint64()))
   182  			off := ir.uint64()
   183  
   184  			if _, ok := inlineImporter[s]; ok {
   185  				continue
   186  			}
   187  			inlineImporter[s] = iimporterAndOffset{p, off}
   188  		}
   189  	}
   190  }
   191  
   192  type iimporter struct {
   193  	ipkg *types.Pkg
   194  
   195  	pkgCache     map[uint64]*types.Pkg
   196  	posBaseCache map[uint64]*src.PosBase
   197  	typCache     map[uint64]*types.Type
   198  
   199  	stringData string
   200  	declData   string
   201  }
   202  
   203  func (p *iimporter) stringAt(off uint64) string {
   204  	var x [binary.MaxVarintLen64]byte
   205  	n := copy(x[:], p.stringData[off:])
   206  
   207  	slen, n := binary.Uvarint(x[:n])
   208  	if n <= 0 {
   209  		Fatalf("varint failed")
   210  	}
   211  	spos := off + uint64(n)
   212  	return p.stringData[spos : spos+slen]
   213  }
   214  
   215  func (p *iimporter) posBaseAt(off uint64) *src.PosBase {
   216  	if posBase, ok := p.posBaseCache[off]; ok {
   217  		return posBase
   218  	}
   219  
   220  	file := p.stringAt(off)
   221  	posBase := src.NewFileBase(file, file)
   222  	p.posBaseCache[off] = posBase
   223  	return posBase
   224  }
   225  
   226  func (p *iimporter) pkgAt(off uint64) *types.Pkg {
   227  	if pkg, ok := p.pkgCache[off]; ok {
   228  		return pkg
   229  	}
   230  
   231  	pkg := p.ipkg
   232  	if pkgPath := p.stringAt(off); pkgPath != "" {
   233  		pkg = types.NewPkg(pkgPath, "")
   234  	}
   235  	p.pkgCache[off] = pkg
   236  	return pkg
   237  }
   238  
   239  // An importReader keeps state for reading an individual imported
   240  // object (declaration or inline body).
   241  type importReader struct {
   242  	strings.Reader
   243  	p *iimporter
   244  
   245  	currPkg  *types.Pkg
   246  	prevBase *src.PosBase
   247  	prevLine int64
   248  }
   249  
   250  func (p *iimporter) newReader(off uint64, pkg *types.Pkg) *importReader {
   251  	r := &importReader{
   252  		p:       p,
   253  		currPkg: pkg,
   254  	}
   255  	// (*strings.Reader).Reset wasn't added until Go 1.7, and we
   256  	// need to build with Go 1.4.
   257  	r.Reader = *strings.NewReader(p.declData[off:])
   258  	return r
   259  }
   260  
   261  func (r *importReader) string() string        { return r.p.stringAt(r.uint64()) }
   262  func (r *importReader) posBase() *src.PosBase { return r.p.posBaseAt(r.uint64()) }
   263  func (r *importReader) pkg() *types.Pkg       { return r.p.pkgAt(r.uint64()) }
   264  
   265  func (r *importReader) setPkg() {
   266  	r.currPkg = r.pkg()
   267  }
   268  
   269  func (r *importReader) doDecl(n *Node) {
   270  	if n.Op != ONONAME {
   271  		Fatalf("doDecl: unexpected Op for %v: %v", n.Sym, n.Op)
   272  	}
   273  
   274  	tag := r.byte()
   275  	pos := r.pos()
   276  
   277  	switch tag {
   278  	case 'A':
   279  		typ := r.typ()
   280  
   281  		importalias(r.p.ipkg, pos, n.Sym, typ)
   282  
   283  	case 'C':
   284  		typ, val := r.value()
   285  
   286  		importconst(r.p.ipkg, pos, n.Sym, typ, val)
   287  
   288  	case 'F':
   289  		typ := r.signature(nil)
   290  
   291  		importfunc(r.p.ipkg, pos, n.Sym, typ)
   292  		r.funcExt(n)
   293  
   294  	case 'T':
   295  		// Types can be recursive. We need to setup a stub
   296  		// declaration before recursing.
   297  		t := importtype(r.p.ipkg, pos, n.Sym)
   298  
   299  		// We also need to defer width calculations until
   300  		// after the underlying type has been assigned.
   301  		//
   302  		// TODO(mdempsky): Add nesting support directly to
   303  		// {defer,resume}checkwidth? Width calculations are
   304  		// already deferred during initial typechecking, but
   305  		// not when we're expanding inline function bodies, so
   306  		// we currently need to handle both cases here.
   307  		deferring := defercalc != 0
   308  		if !deferring {
   309  			defercheckwidth()
   310  		}
   311  		underlying := r.typ()
   312  		copytype(typenod(t), underlying)
   313  		if !deferring {
   314  			resumecheckwidth()
   315  		}
   316  
   317  		if underlying.IsInterface() {
   318  			break
   319  		}
   320  
   321  		ms := make([]*types.Field, r.uint64())
   322  		for i := range ms {
   323  			mpos := r.pos()
   324  			msym := r.ident()
   325  			recv := r.param()
   326  			mtyp := r.signature(recv)
   327  
   328  			f := types.NewField()
   329  			f.Pos = mpos
   330  			f.Sym = msym
   331  			f.Type = mtyp
   332  			ms[i] = f
   333  
   334  			m := newfuncnamel(mpos, methodSym(recv.Type, msym))
   335  			m.Type = mtyp
   336  			m.SetClass(PFUNC)
   337  			// methodSym already marked m.Sym as a function.
   338  
   339  			// (comment from parser.go)
   340  			// inl.C's inlnode in on a dotmeth node expects to find the inlineable body as
   341  			// (dotmeth's type).Nname.Inl, and dotmeth's type has been pulled
   342  			// out by typecheck's lookdot as this $$.ttype. So by providing
   343  			// this back link here we avoid special casing there.
   344  			mtyp.SetNname(asTypesNode(m))
   345  		}
   346  		t.Methods().Set(ms)
   347  
   348  		for _, m := range ms {
   349  			r.methExt(m)
   350  		}
   351  
   352  	case 'V':
   353  		typ := r.typ()
   354  
   355  		importvar(r.p.ipkg, pos, n.Sym, typ)
   356  		r.varExt(n)
   357  
   358  	default:
   359  		Fatalf("unexpected tag: %v", tag)
   360  	}
   361  }
   362  
   363  func (p *importReader) value() (typ *types.Type, v Val) {
   364  	typ = p.typ()
   365  
   366  	switch constTypeOf(typ) {
   367  	case CTNIL:
   368  		v.U = &NilVal{}
   369  	case CTBOOL:
   370  		v.U = p.bool()
   371  	case CTSTR:
   372  		v.U = p.string()
   373  	case CTINT:
   374  		x := new(Mpint)
   375  		x.Rune = typ == types.Idealrune
   376  		p.mpint(&x.Val, typ)
   377  		v.U = x
   378  	case CTFLT:
   379  		x := newMpflt()
   380  		p.float(x, typ)
   381  		v.U = x
   382  	case CTCPLX:
   383  		x := newMpcmplx()
   384  		p.float(&x.Real, typ)
   385  		p.float(&x.Imag, typ)
   386  		v.U = x
   387  	}
   388  
   389  	typ = idealType(typ)
   390  	return
   391  }
   392  
   393  func (p *importReader) mpint(x *big.Int, typ *types.Type) {
   394  	signed, maxBytes := intSize(typ)
   395  
   396  	maxSmall := 256 - maxBytes
   397  	if signed {
   398  		maxSmall = 256 - 2*maxBytes
   399  	}
   400  	if maxBytes == 1 {
   401  		maxSmall = 256
   402  	}
   403  
   404  	n, _ := p.ReadByte()
   405  	if uint(n) < maxSmall {
   406  		v := int64(n)
   407  		if signed {
   408  			v >>= 1
   409  			if n&1 != 0 {
   410  				v = ^v
   411  			}
   412  		}
   413  		x.SetInt64(v)
   414  		return
   415  	}
   416  
   417  	v := -n
   418  	if signed {
   419  		v = -(n &^ 1) >> 1
   420  	}
   421  	if v < 1 || uint(v) > maxBytes {
   422  		Fatalf("weird decoding: %v, %v => %v", n, signed, v)
   423  	}
   424  	b := make([]byte, v)
   425  	p.Read(b)
   426  	x.SetBytes(b)
   427  	if signed && n&1 != 0 {
   428  		x.Neg(x)
   429  	}
   430  }
   431  
   432  func (p *importReader) float(x *Mpflt, typ *types.Type) {
   433  	var mant big.Int
   434  	p.mpint(&mant, typ)
   435  	m := x.Val.SetInt(&mant)
   436  	if m.Sign() == 0 {
   437  		return
   438  	}
   439  	m.SetMantExp(m, int(p.int64()))
   440  }
   441  
   442  func (r *importReader) ident() *types.Sym {
   443  	name := r.string()
   444  	if name == "" {
   445  		return nil
   446  	}
   447  	pkg := r.currPkg
   448  	if types.IsExported(name) {
   449  		pkg = localpkg
   450  	}
   451  	return pkg.Lookup(name)
   452  }
   453  
   454  func (r *importReader) qualifiedIdent() *types.Sym {
   455  	name := r.string()
   456  	pkg := r.pkg()
   457  	return pkg.Lookup(name)
   458  }
   459  
   460  func (r *importReader) pos() src.XPos {
   461  	delta := r.int64()
   462  	if delta != deltaNewFile {
   463  		r.prevLine += delta
   464  	} else if l := r.int64(); l == -1 {
   465  		r.prevLine += deltaNewFile
   466  	} else {
   467  		r.prevBase = r.posBase()
   468  		r.prevLine = l
   469  	}
   470  
   471  	if (r.prevBase == nil || r.prevBase.AbsFilename() == "") && r.prevLine == 0 {
   472  		// TODO(mdempsky): Remove once we reliably write
   473  		// position information for all nodes.
   474  		return src.NoXPos
   475  	}
   476  
   477  	if r.prevBase == nil {
   478  		Fatalf("missing posbase")
   479  	}
   480  	pos := src.MakePos(r.prevBase, uint(r.prevLine), 0)
   481  	return Ctxt.PosTable.XPos(pos)
   482  }
   483  
   484  func (r *importReader) typ() *types.Type {
   485  	return r.p.typAt(r.uint64())
   486  }
   487  
   488  func (p *iimporter) typAt(off uint64) *types.Type {
   489  	t, ok := p.typCache[off]
   490  	if !ok {
   491  		if off < predeclReserved {
   492  			Fatalf("predeclared type missing from cache: %d", off)
   493  		}
   494  		t = p.newReader(off-predeclReserved, nil).typ1()
   495  		p.typCache[off] = t
   496  	}
   497  	return t
   498  }
   499  
   500  func (r *importReader) typ1() *types.Type {
   501  	switch k := r.kind(); k {
   502  	default:
   503  		Fatalf("unexpected kind tag in %q: %v", r.p.ipkg.Path, k)
   504  		return nil
   505  
   506  	case definedType:
   507  		// We might be called from within doInline, in which
   508  		// case Sym.Def can point to declared parameters
   509  		// instead of the top-level types. Also, we don't
   510  		// support inlining functions with local defined
   511  		// types. Therefore, this must be a package-scope
   512  		// type.
   513  		n := asNode(r.qualifiedIdent().PkgDef())
   514  		if n.Op == ONONAME {
   515  			expandDecl(n)
   516  		}
   517  		if n.Op != OTYPE {
   518  			Fatalf("expected OTYPE, got %v: %v, %v", n.Op, n.Sym, n)
   519  		}
   520  		return n.Type
   521  	case pointerType:
   522  		return types.NewPtr(r.typ())
   523  	case sliceType:
   524  		return types.NewSlice(r.typ())
   525  	case arrayType:
   526  		n := r.uint64()
   527  		return types.NewArray(r.typ(), int64(n))
   528  	case chanType:
   529  		dir := types.ChanDir(r.uint64())
   530  		return types.NewChan(r.typ(), dir)
   531  	case mapType:
   532  		return types.NewMap(r.typ(), r.typ())
   533  
   534  	case signatureType:
   535  		r.setPkg()
   536  		return r.signature(nil)
   537  
   538  	case structType:
   539  		r.setPkg()
   540  
   541  		fs := make([]*types.Field, r.uint64())
   542  		for i := range fs {
   543  			pos := r.pos()
   544  			sym := r.ident()
   545  			typ := r.typ()
   546  			emb := r.bool()
   547  			note := r.string()
   548  
   549  			f := types.NewField()
   550  			f.Pos = pos
   551  			f.Sym = sym
   552  			f.Type = typ
   553  			if emb {
   554  				f.Embedded = 1
   555  			}
   556  			f.Note = note
   557  			fs[i] = f
   558  		}
   559  
   560  		t := types.New(TSTRUCT)
   561  		t.SetPkg(r.currPkg)
   562  		t.SetFields(fs)
   563  		return t
   564  
   565  	case interfaceType:
   566  		r.setPkg()
   567  
   568  		embeddeds := make([]*types.Field, r.uint64())
   569  		for i := range embeddeds {
   570  			pos := r.pos()
   571  			typ := r.typ()
   572  
   573  			f := types.NewField()
   574  			f.Pos = pos
   575  			f.Type = typ
   576  			embeddeds[i] = f
   577  		}
   578  
   579  		methods := make([]*types.Field, r.uint64())
   580  		for i := range methods {
   581  			pos := r.pos()
   582  			sym := r.ident()
   583  			typ := r.signature(fakeRecvField())
   584  
   585  			f := types.NewField()
   586  			f.Pos = pos
   587  			f.Sym = sym
   588  			f.Type = typ
   589  			methods[i] = f
   590  		}
   591  
   592  		t := types.New(TINTER)
   593  		t.SetPkg(r.currPkg)
   594  		t.SetInterface(append(embeddeds, methods...))
   595  
   596  		// Ensure we expand the interface in the frontend (#25055).
   597  		checkwidth(t)
   598  
   599  		return t
   600  	}
   601  }
   602  
   603  func (r *importReader) kind() itag {
   604  	return itag(r.uint64())
   605  }
   606  
   607  func (r *importReader) signature(recv *types.Field) *types.Type {
   608  	params := r.paramList()
   609  	results := r.paramList()
   610  	if n := len(params); n > 0 {
   611  		params[n-1].SetIsDDD(r.bool())
   612  	}
   613  	t := functypefield(recv, params, results)
   614  	t.SetPkg(r.currPkg)
   615  	return t
   616  }
   617  
   618  func (r *importReader) paramList() []*types.Field {
   619  	fs := make([]*types.Field, r.uint64())
   620  	for i := range fs {
   621  		fs[i] = r.param()
   622  	}
   623  	return fs
   624  }
   625  
   626  func (r *importReader) param() *types.Field {
   627  	f := types.NewField()
   628  	f.Pos = r.pos()
   629  	f.Sym = r.ident()
   630  	f.Type = r.typ()
   631  	return f
   632  }
   633  
   634  func (r *importReader) bool() bool {
   635  	return r.uint64() != 0
   636  }
   637  
   638  func (r *importReader) int64() int64 {
   639  	n, err := binary.ReadVarint(r)
   640  	if err != nil {
   641  		Fatalf("readVarint: %v", err)
   642  	}
   643  	return n
   644  }
   645  
   646  func (r *importReader) uint64() uint64 {
   647  	n, err := binary.ReadUvarint(r)
   648  	if err != nil {
   649  		Fatalf("readVarint: %v", err)
   650  	}
   651  	return n
   652  }
   653  
   654  func (r *importReader) byte() byte {
   655  	x, err := r.ReadByte()
   656  	if err != nil {
   657  		Fatalf("declReader.ReadByte: %v", err)
   658  	}
   659  	return x
   660  }
   661  
   662  // Compiler-specific extensions.
   663  
   664  func (r *importReader) varExt(n *Node) {
   665  	r.linkname(n.Sym)
   666  }
   667  
   668  func (r *importReader) funcExt(n *Node) {
   669  	r.linkname(n.Sym)
   670  
   671  	// Escape analysis.
   672  	for _, fs := range types.RecvsParams {
   673  		for _, f := range fs(n.Type).FieldSlice() {
   674  			f.Note = r.string()
   675  		}
   676  	}
   677  
   678  	// Inline body.
   679  	if u := r.uint64(); u > 0 {
   680  		n.Func.Inl = &Inline{
   681  			Cost: int32(u - 1),
   682  		}
   683  		n.Func.Endlineno = r.pos()
   684  	}
   685  }
   686  
   687  func (r *importReader) methExt(m *types.Field) {
   688  	if r.bool() {
   689  		m.SetNointerface(true)
   690  	}
   691  	r.funcExt(asNode(m.Type.Nname()))
   692  }
   693  
   694  func (r *importReader) linkname(s *types.Sym) {
   695  	s.Linkname = r.string()
   696  }
   697  
   698  func (r *importReader) doInline(n *Node) {
   699  	if len(n.Func.Inl.Body) != 0 {
   700  		Fatalf("%v already has inline body", n)
   701  	}
   702  
   703  	funchdr(n)
   704  	body := r.stmtList()
   705  	funcbody()
   706  	if body == nil {
   707  		//
   708  		// Make sure empty body is not interpreted as
   709  		// no inlineable body (see also parser.fnbody)
   710  		// (not doing so can cause significant performance
   711  		// degradation due to unnecessary calls to empty
   712  		// functions).
   713  		body = []*Node{}
   714  	}
   715  	n.Func.Inl.Body = body
   716  
   717  	importlist = append(importlist, n)
   718  
   719  	if Debug['E'] > 0 && Debug['m'] > 2 {
   720  		if Debug['m'] > 3 {
   721  			fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body))
   722  		} else {
   723  			fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body))
   724  		}
   725  	}
   726  }
   727  
   728  // ----------------------------------------------------------------------------
   729  // Inlined function bodies
   730  
   731  // Approach: Read nodes and use them to create/declare the same data structures
   732  // as done originally by the (hidden) parser by closely following the parser's
   733  // original code. In other words, "parsing" the import data (which happens to
   734  // be encoded in binary rather textual form) is the best way at the moment to
   735  // re-establish the syntax tree's invariants. At some future point we might be
   736  // able to avoid this round-about way and create the rewritten nodes directly,
   737  // possibly avoiding a lot of duplicate work (name resolution, type checking).
   738  //
   739  // Refined nodes (e.g., ODOTPTR as a refinement of OXDOT) are exported as their
   740  // unrefined nodes (since this is what the importer uses). The respective case
   741  // entries are unreachable in the importer.
   742  
   743  func (r *importReader) stmtList() []*Node {
   744  	var list []*Node
   745  	for {
   746  		n := r.node()
   747  		if n == nil {
   748  			break
   749  		}
   750  		// OBLOCK nodes may be created when importing ODCL nodes - unpack them
   751  		if n.Op == OBLOCK {
   752  			list = append(list, n.List.Slice()...)
   753  		} else {
   754  			list = append(list, n)
   755  		}
   756  
   757  	}
   758  	return list
   759  }
   760  
   761  func (r *importReader) exprList() []*Node {
   762  	var list []*Node
   763  	for {
   764  		n := r.expr()
   765  		if n == nil {
   766  			break
   767  		}
   768  		list = append(list, n)
   769  	}
   770  	return list
   771  }
   772  
   773  func (r *importReader) expr() *Node {
   774  	n := r.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 (r *importReader) node() *Node {
   783  	switch op := r.op(); op {
   784  	// expressions
   785  	// case OPAREN:
   786  	// 	unreachable - unpacked by exporter
   787  
   788  	// case ODDDARG:
   789  	//	unimplemented
   790  
   791  	case OLITERAL:
   792  		pos := r.pos()
   793  		typ, val := r.value()
   794  
   795  		n := npos(pos, nodlit(val))
   796  		n.Type = typ
   797  		return n
   798  
   799  	case ONONAME:
   800  		return mkname(r.qualifiedIdent())
   801  
   802  	case ONAME:
   803  		return mkname(r.ident())
   804  
   805  	// case OPACK, ONONAME:
   806  	// 	unreachable - should have been resolved by typechecking
   807  
   808  	case OTYPE:
   809  		return typenod(r.typ())
   810  
   811  	// case OTARRAY, OTMAP, OTCHAN, OTSTRUCT, OTINTER, OTFUNC:
   812  	//      unreachable - should have been resolved by typechecking
   813  
   814  	// case OCLOSURE:
   815  	//	unimplemented
   816  
   817  	case OPTRLIT:
   818  		pos := r.pos()
   819  		n := npos(pos, r.expr())
   820  		if !r.bool() /* !implicit, i.e. '&' operator */ {
   821  			if n.Op == OCOMPLIT {
   822  				// Special case for &T{...}: turn into (*T){...}.
   823  				n.Right = nodl(pos, ODEREF, n.Right, nil)
   824  				n.Right.SetImplicit(true)
   825  			} else {
   826  				n = nodl(pos, OADDR, n, nil)
   827  			}
   828  		}
   829  		return n
   830  
   831  	case OSTRUCTLIT:
   832  		// TODO(mdempsky): Export position information for OSTRUCTKEY nodes.
   833  		savedlineno := lineno
   834  		lineno = r.pos()
   835  		n := nodl(lineno, OCOMPLIT, nil, typenod(r.typ()))
   836  		n.List.Set(r.elemList()) // special handling of field names
   837  		lineno = savedlineno
   838  		return n
   839  
   840  	// case OARRAYLIT, OSLICELIT, OMAPLIT:
   841  	// 	unreachable - mapped to case OCOMPLIT below by exporter
   842  
   843  	case OCOMPLIT:
   844  		n := nodl(r.pos(), OCOMPLIT, nil, typenod(r.typ()))
   845  		n.List.Set(r.exprList())
   846  		return n
   847  
   848  	case OKEY:
   849  		pos := r.pos()
   850  		left, right := r.exprsOrNil()
   851  		return nodl(pos, OKEY, left, right)
   852  
   853  	// case OSTRUCTKEY:
   854  	//	unreachable - handled in case OSTRUCTLIT by elemList
   855  
   856  	// case OCALLPART:
   857  	//	unimplemented
   858  
   859  	// case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
   860  	// 	unreachable - mapped to case OXDOT below by exporter
   861  
   862  	case OXDOT:
   863  		// see parser.new_dotname
   864  		return npos(r.pos(), nodSym(OXDOT, r.expr(), r.ident()))
   865  
   866  	// case ODOTTYPE, ODOTTYPE2:
   867  	// 	unreachable - mapped to case ODOTTYPE below by exporter
   868  
   869  	case ODOTTYPE:
   870  		n := nodl(r.pos(), ODOTTYPE, r.expr(), nil)
   871  		n.Type = r.typ()
   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 nodl(r.pos(), op, r.expr(), r.expr())
   879  
   880  	case OSLICE, OSLICE3:
   881  		n := nodl(r.pos(), op, r.expr(), nil)
   882  		low, high := r.exprsOrNil()
   883  		var max *Node
   884  		if n.Op.IsSlice3() {
   885  			max = r.expr()
   886  		}
   887  		n.SetSliceBounds(low, high, max)
   888  		return n
   889  
   890  	// case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR:
   891  	// 	unreachable - mapped to OCONV case below by exporter
   892  
   893  	case OCONV:
   894  		n := nodl(r.pos(), OCONV, r.expr(), nil)
   895  		n.Type = r.typ()
   896  		return n
   897  
   898  	case OCOPY, OCOMPLEX, OREAL, OIMAG, OAPPEND, OCAP, OCLOSE, ODELETE, OLEN, OMAKE, ONEW, OPANIC, ORECOVER, OPRINT, OPRINTN:
   899  		n := npos(r.pos(), builtinCall(op))
   900  		n.List.Set(r.exprList())
   901  		if op == OAPPEND {
   902  			n.SetIsDDD(r.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 := nodl(r.pos(), OCALL, r.expr(), nil)
   911  		n.List.Set(r.exprList())
   912  		n.SetIsDDD(r.bool())
   913  		return n
   914  
   915  	case OMAKEMAP, OMAKECHAN, OMAKESLICE:
   916  		n := npos(r.pos(), builtinCall(OMAKE))
   917  		n.List.Append(typenod(r.typ()))
   918  		n.List.Append(r.exprList()...)
   919  		return n
   920  
   921  	// unary expressions
   922  	case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
   923  		return nodl(r.pos(), op, r.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 nodl(r.pos(), op, r.expr(), r.expr())
   929  
   930  	case OADDSTR:
   931  		pos := r.pos()
   932  		list := r.exprList()
   933  		x := npos(pos, list[0])
   934  		for _, y := range list[1:] {
   935  			x = nodl(pos, OADD, x, y)
   936  		}
   937  		return x
   938  
   939  	// --------------------------------------------------------------------
   940  	// statements
   941  	case ODCL:
   942  		pos := r.pos()
   943  		lhs := npos(pos, dclname(r.ident()))
   944  		typ := typenod(r.typ())
   945  		return npos(pos, liststmt(variter([]*Node{lhs}, typ, nil))) // TODO(gri) avoid list creation
   946  
   947  	// case ODCLFIELD:
   948  	//	unimplemented
   949  
   950  	// case OAS, OASWB:
   951  	// 	unreachable - mapped to OAS case below by exporter
   952  
   953  	case OAS:
   954  		return nodl(r.pos(), OAS, r.expr(), r.expr())
   955  
   956  	case OASOP:
   957  		n := nodl(r.pos(), OASOP, nil, nil)
   958  		n.SetSubOp(r.op())
   959  		n.Left = r.expr()
   960  		if !r.bool() {
   961  			n.Right = nodintconst(1)
   962  			n.SetImplicit(true)
   963  		} else {
   964  			n.Right = r.expr()
   965  		}
   966  		return n
   967  
   968  	// case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
   969  	// 	unreachable - mapped to OAS2 case below by exporter
   970  
   971  	case OAS2:
   972  		n := nodl(r.pos(), OAS2, nil, nil)
   973  		n.List.Set(r.exprList())
   974  		n.Rlist.Set(r.exprList())
   975  		return n
   976  
   977  	case ORETURN:
   978  		n := nodl(r.pos(), ORETURN, nil, nil)
   979  		n.List.Set(r.exprList())
   980  		return n
   981  
   982  	// case ORETJMP:
   983  	// 	unreachable - generated by compiler for trampolin routines (not exported)
   984  
   985  	case OGO, ODEFER:
   986  		return nodl(r.pos(), op, r.expr(), nil)
   987  
   988  	case OIF:
   989  		n := nodl(r.pos(), OIF, nil, nil)
   990  		n.Ninit.Set(r.stmtList())
   991  		n.Left = r.expr()
   992  		n.Nbody.Set(r.stmtList())
   993  		n.Rlist.Set(r.stmtList())
   994  		return n
   995  
   996  	case OFOR:
   997  		n := nodl(r.pos(), OFOR, nil, nil)
   998  		n.Ninit.Set(r.stmtList())
   999  		n.Left, n.Right = r.exprsOrNil()
  1000  		n.Nbody.Set(r.stmtList())
  1001  		return n
  1002  
  1003  	case ORANGE:
  1004  		n := nodl(r.pos(), ORANGE, nil, nil)
  1005  		n.List.Set(r.stmtList())
  1006  		n.Right = r.expr()
  1007  		n.Nbody.Set(r.stmtList())
  1008  		return n
  1009  
  1010  	case OSELECT, OSWITCH:
  1011  		n := nodl(r.pos(), op, nil, nil)
  1012  		n.Ninit.Set(r.stmtList())
  1013  		n.Left, _ = r.exprsOrNil()
  1014  		n.List.Set(r.stmtList())
  1015  		return n
  1016  
  1017  	// case OCASE, OXCASE:
  1018  	// 	unreachable - mapped to OXCASE case below by exporter
  1019  
  1020  	case OXCASE:
  1021  		n := nodl(r.pos(), OXCASE, nil, nil)
  1022  		n.List.Set(r.exprList())
  1023  		// TODO(gri) eventually we must declare variables for type switch
  1024  		// statements (type switch statements are not yet exported)
  1025  		n.Nbody.Set(r.stmtList())
  1026  		return n
  1027  
  1028  	// case OFALL:
  1029  	// 	unreachable - mapped to OXFALL case below by exporter
  1030  
  1031  	case OFALL:
  1032  		n := nodl(r.pos(), OFALL, nil, nil)
  1033  		return n
  1034  
  1035  	case OBREAK, OCONTINUE:
  1036  		pos := r.pos()
  1037  		left, _ := r.exprsOrNil()
  1038  		if left != nil {
  1039  			left = newname(left.Sym)
  1040  		}
  1041  		return nodl(pos, op, left, nil)
  1042  
  1043  	// case OEMPTY:
  1044  	// 	unreachable - not emitted by exporter
  1045  
  1046  	case OGOTO, OLABEL:
  1047  		n := nodl(r.pos(), op, nil, nil)
  1048  		n.Sym = lookup(r.string())
  1049  		return n
  1050  
  1051  	case OEND:
  1052  		return nil
  1053  
  1054  	default:
  1055  		Fatalf("cannot import %v (%d) node\n"+
  1056  			"\t==> please file an issue and assign to gri@", op, int(op))
  1057  		panic("unreachable") // satisfy compiler
  1058  	}
  1059  }
  1060  
  1061  func (r *importReader) op() Op {
  1062  	return Op(r.uint64())
  1063  }
  1064  
  1065  func (r *importReader) elemList() []*Node {
  1066  	c := r.uint64()
  1067  	list := make([]*Node, c)
  1068  	for i := range list {
  1069  		s := r.ident()
  1070  		list[i] = nodSym(OSTRUCTKEY, r.expr(), s)
  1071  	}
  1072  	return list
  1073  }
  1074  
  1075  func (r *importReader) exprsOrNil() (a, b *Node) {
  1076  	ab := r.uint64()
  1077  	if ab&1 != 0 {
  1078  		a = r.expr()
  1079  	}
  1080  	if ab&2 != 0 {
  1081  		b = r.node()
  1082  	}
  1083  	return
  1084  }