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