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