github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/internal/gcimporter/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  // This file is a copy of $GOROOT/src/go/internal/gcimporter/bimport.go.
     6  
     7  package gcimporter
     8  
     9  import (
    10  	"encoding/binary"
    11  	"fmt"
    12  	"go/constant"
    13  	"go/token"
    14  	"go/types"
    15  	"sort"
    16  	"strconv"
    17  	"strings"
    18  	"sync"
    19  	"unicode"
    20  	"unicode/utf8"
    21  )
    22  
    23  type importer struct {
    24  	imports    map[string]*types.Package
    25  	data       []byte
    26  	importpath string
    27  	buf        []byte // for reading strings
    28  	version    int    // export format version
    29  
    30  	// object lists
    31  	strList       []string           // in order of appearance
    32  	pathList      []string           // in order of appearance
    33  	pkgList       []*types.Package   // in order of appearance
    34  	typList       []types.Type       // in order of appearance
    35  	interfaceList []*types.Interface // for delayed completion only
    36  	trackAllTypes bool
    37  
    38  	// position encoding
    39  	posInfoFormat bool
    40  	prevFile      string
    41  	prevLine      int
    42  	fake          fakeFileSet
    43  
    44  	// debugging support
    45  	debugFormat bool
    46  	read        int // bytes read
    47  }
    48  
    49  // BImportData imports a package from the serialized package data
    50  // and returns the number of bytes consumed and a reference to the package.
    51  // If the export data version is not recognized or the format is otherwise
    52  // compromised, an error is returned.
    53  func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
    54  	// catch panics and return them as errors
    55  	const currentVersion = 6
    56  	version := -1 // unknown version
    57  	defer func() {
    58  		if e := recover(); e != nil {
    59  			// Return a (possibly nil or incomplete) package unchanged (see #16088).
    60  			if version > currentVersion {
    61  				err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
    62  			} else {
    63  				err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
    64  			}
    65  		}
    66  	}()
    67  
    68  	p := importer{
    69  		imports:    imports,
    70  		data:       data,
    71  		importpath: path,
    72  		version:    version,
    73  		strList:    []string{""}, // empty string is mapped to 0
    74  		pathList:   []string{""}, // empty string is mapped to 0
    75  		fake: fakeFileSet{
    76  			fset:  fset,
    77  			files: make(map[string]*fileInfo),
    78  		},
    79  	}
    80  	defer p.fake.setLines() // set lines for files in fset
    81  
    82  	// read version info
    83  	var versionstr string
    84  	if b := p.rawByte(); b == 'c' || b == 'd' {
    85  		// Go1.7 encoding; first byte encodes low-level
    86  		// encoding format (compact vs debug).
    87  		// For backward-compatibility only (avoid problems with
    88  		// old installed packages). Newly compiled packages use
    89  		// the extensible format string.
    90  		// TODO(gri) Remove this support eventually; after Go1.8.
    91  		if b == 'd' {
    92  			p.debugFormat = true
    93  		}
    94  		p.trackAllTypes = p.rawByte() == 'a'
    95  		p.posInfoFormat = p.int() != 0
    96  		versionstr = p.string()
    97  		if versionstr == "v1" {
    98  			version = 0
    99  		}
   100  	} else {
   101  		// Go1.8 extensible encoding
   102  		// read version string and extract version number (ignore anything after the version number)
   103  		versionstr = p.rawStringln(b)
   104  		if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" {
   105  			if v, err := strconv.Atoi(s[1]); err == nil && v > 0 {
   106  				version = v
   107  			}
   108  		}
   109  	}
   110  	p.version = version
   111  
   112  	// read version specific flags - extend as necessary
   113  	switch p.version {
   114  	// case currentVersion:
   115  	// 	...
   116  	//	fallthrough
   117  	case currentVersion, 5, 4, 3, 2, 1:
   118  		p.debugFormat = p.rawStringln(p.rawByte()) == "debug"
   119  		p.trackAllTypes = p.int() != 0
   120  		p.posInfoFormat = p.int() != 0
   121  	case 0:
   122  		// Go1.7 encoding format - nothing to do here
   123  	default:
   124  		errorf("unknown bexport format version %d (%q)", p.version, versionstr)
   125  	}
   126  
   127  	// --- generic export data ---
   128  
   129  	// populate typList with predeclared "known" types
   130  	p.typList = append(p.typList, predeclared()...)
   131  
   132  	// read package data
   133  	pkg = p.pkg()
   134  
   135  	// read objects of phase 1 only (see cmd/compile/internal/gc/bexport.go)
   136  	objcount := 0
   137  	for {
   138  		tag := p.tagOrIndex()
   139  		if tag == endTag {
   140  			break
   141  		}
   142  		p.obj(tag)
   143  		objcount++
   144  	}
   145  
   146  	// self-verification
   147  	if count := p.int(); count != objcount {
   148  		errorf("got %d objects; want %d", objcount, count)
   149  	}
   150  
   151  	// ignore compiler-specific import data
   152  
   153  	// complete interfaces
   154  	// TODO(gri) re-investigate if we still need to do this in a delayed fashion
   155  	for _, typ := range p.interfaceList {
   156  		typ.Complete()
   157  	}
   158  
   159  	// record all referenced packages as imports
   160  	list := append(([]*types.Package)(nil), p.pkgList[1:]...)
   161  	sort.Sort(byPath(list))
   162  	pkg.SetImports(list)
   163  
   164  	// package was imported completely and without errors
   165  	pkg.MarkComplete()
   166  
   167  	return p.read, pkg, nil
   168  }
   169  
   170  func errorf(format string, args ...interface{}) {
   171  	panic(fmt.Sprintf(format, args...))
   172  }
   173  
   174  func (p *importer) pkg() *types.Package {
   175  	// if the package was seen before, i is its index (>= 0)
   176  	i := p.tagOrIndex()
   177  	if i >= 0 {
   178  		return p.pkgList[i]
   179  	}
   180  
   181  	// otherwise, i is the package tag (< 0)
   182  	if i != packageTag {
   183  		errorf("unexpected package tag %d version %d", i, p.version)
   184  	}
   185  
   186  	// read package data
   187  	name := p.string()
   188  	var path string
   189  	if p.version >= 5 {
   190  		path = p.path()
   191  	} else {
   192  		path = p.string()
   193  	}
   194  	if p.version >= 6 {
   195  		p.int() // package height; unused by go/types
   196  	}
   197  
   198  	// we should never see an empty package name
   199  	if name == "" {
   200  		errorf("empty package name in import")
   201  	}
   202  
   203  	// an empty path denotes the package we are currently importing;
   204  	// it must be the first package we see
   205  	if (path == "") != (len(p.pkgList) == 0) {
   206  		errorf("package path %q for pkg index %d", path, len(p.pkgList))
   207  	}
   208  
   209  	// if the package was imported before, use that one; otherwise create a new one
   210  	if path == "" {
   211  		path = p.importpath
   212  	}
   213  	pkg := p.imports[path]
   214  	if pkg == nil {
   215  		pkg = types.NewPackage(path, name)
   216  		p.imports[path] = pkg
   217  	} else if pkg.Name() != name {
   218  		errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path)
   219  	}
   220  	p.pkgList = append(p.pkgList, pkg)
   221  
   222  	return pkg
   223  }
   224  
   225  // objTag returns the tag value for each object kind.
   226  func objTag(obj types.Object) int {
   227  	switch obj.(type) {
   228  	case *types.Const:
   229  		return constTag
   230  	case *types.TypeName:
   231  		return typeTag
   232  	case *types.Var:
   233  		return varTag
   234  	case *types.Func:
   235  		return funcTag
   236  	default:
   237  		errorf("unexpected object: %v (%T)", obj, obj) // panics
   238  		panic("unreachable")
   239  	}
   240  }
   241  
   242  func sameObj(a, b types.Object) bool {
   243  	// Because unnamed types are not canonicalized, we cannot simply compare types for
   244  	// (pointer) identity.
   245  	// Ideally we'd check equality of constant values as well, but this is good enough.
   246  	return objTag(a) == objTag(b) && types.Identical(a.Type(), b.Type())
   247  }
   248  
   249  func (p *importer) declare(obj types.Object) {
   250  	pkg := obj.Pkg()
   251  	if alt := pkg.Scope().Insert(obj); alt != nil {
   252  		// This can only trigger if we import a (non-type) object a second time.
   253  		// Excluding type aliases, this cannot happen because 1) we only import a package
   254  		// once; and b) we ignore compiler-specific export data which may contain
   255  		// functions whose inlined function bodies refer to other functions that
   256  		// were already imported.
   257  		// However, type aliases require reexporting the original type, so we need
   258  		// to allow it (see also the comment in cmd/compile/internal/gc/bimport.go,
   259  		// method importer.obj, switch case importing functions).
   260  		// TODO(gri) review/update this comment once the gc compiler handles type aliases.
   261  		if !sameObj(obj, alt) {
   262  			errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
   263  		}
   264  	}
   265  }
   266  
   267  func (p *importer) obj(tag int) {
   268  	switch tag {
   269  	case constTag:
   270  		pos := p.pos()
   271  		pkg, name := p.qualifiedName()
   272  		typ := p.typ(nil, nil)
   273  		val := p.value()
   274  		p.declare(types.NewConst(pos, pkg, name, typ, val))
   275  
   276  	case aliasTag:
   277  		// TODO(gri) verify type alias hookup is correct
   278  		pos := p.pos()
   279  		pkg, name := p.qualifiedName()
   280  		typ := p.typ(nil, nil)
   281  		p.declare(types.NewTypeName(pos, pkg, name, typ))
   282  
   283  	case typeTag:
   284  		p.typ(nil, nil)
   285  
   286  	case varTag:
   287  		pos := p.pos()
   288  		pkg, name := p.qualifiedName()
   289  		typ := p.typ(nil, nil)
   290  		p.declare(types.NewVar(pos, pkg, name, typ))
   291  
   292  	case funcTag:
   293  		pos := p.pos()
   294  		pkg, name := p.qualifiedName()
   295  		params, isddd := p.paramList()
   296  		result, _ := p.paramList()
   297  		sig := types.NewSignature(nil, params, result, isddd)
   298  		p.declare(types.NewFunc(pos, pkg, name, sig))
   299  
   300  	default:
   301  		errorf("unexpected object tag %d", tag)
   302  	}
   303  }
   304  
   305  const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go
   306  
   307  func (p *importer) pos() token.Pos {
   308  	if !p.posInfoFormat {
   309  		return token.NoPos
   310  	}
   311  
   312  	file := p.prevFile
   313  	line := p.prevLine
   314  	delta := p.int()
   315  	line += delta
   316  	if p.version >= 5 {
   317  		if delta == deltaNewFile {
   318  			if n := p.int(); n >= 0 {
   319  				// file changed
   320  				file = p.path()
   321  				line = n
   322  			}
   323  		}
   324  	} else {
   325  		if delta == 0 {
   326  			if n := p.int(); n >= 0 {
   327  				// file changed
   328  				file = p.prevFile[:n] + p.string()
   329  				line = p.int()
   330  			}
   331  		}
   332  	}
   333  	p.prevFile = file
   334  	p.prevLine = line
   335  
   336  	return p.fake.pos(file, line, 0)
   337  }
   338  
   339  // Synthesize a token.Pos
   340  type fakeFileSet struct {
   341  	fset  *token.FileSet
   342  	files map[string]*fileInfo
   343  }
   344  
   345  type fileInfo struct {
   346  	file     *token.File
   347  	lastline int
   348  }
   349  
   350  const maxlines = 64 * 1024
   351  
   352  func (s *fakeFileSet) pos(file string, line, column int) token.Pos {
   353  	// TODO(mdempsky): Make use of column.
   354  
   355  	// Since we don't know the set of needed file positions, we reserve maxlines
   356  	// positions per file. We delay calling token.File.SetLines until all
   357  	// positions have been calculated (by way of fakeFileSet.setLines), so that
   358  	// we can avoid setting unnecessary lines. See also golang/go#46586.
   359  	f := s.files[file]
   360  	if f == nil {
   361  		f = &fileInfo{file: s.fset.AddFile(file, -1, maxlines)}
   362  		s.files[file] = f
   363  	}
   364  	if line > maxlines {
   365  		line = 1
   366  	}
   367  	if line > f.lastline {
   368  		f.lastline = line
   369  	}
   370  
   371  	// Return a fake position assuming that f.file consists only of newlines.
   372  	return token.Pos(f.file.Base() + line - 1)
   373  }
   374  
   375  func (s *fakeFileSet) setLines() {
   376  	fakeLinesOnce.Do(func() {
   377  		fakeLines = make([]int, maxlines)
   378  		for i := range fakeLines {
   379  			fakeLines[i] = i
   380  		}
   381  	})
   382  	for _, f := range s.files {
   383  		f.file.SetLines(fakeLines[:f.lastline])
   384  	}
   385  }
   386  
   387  var (
   388  	fakeLines     []int
   389  	fakeLinesOnce sync.Once
   390  )
   391  
   392  func (p *importer) qualifiedName() (pkg *types.Package, name string) {
   393  	name = p.string()
   394  	pkg = p.pkg()
   395  	return
   396  }
   397  
   398  func (p *importer) record(t types.Type) {
   399  	p.typList = append(p.typList, t)
   400  }
   401  
   402  // A dddSlice is a types.Type representing ...T parameters.
   403  // It only appears for parameter types and does not escape
   404  // the importer.
   405  type dddSlice struct {
   406  	elem types.Type
   407  }
   408  
   409  func (t *dddSlice) Underlying() types.Type { return t }
   410  func (t *dddSlice) String() string         { return "..." + t.elem.String() }
   411  
   412  // parent is the package which declared the type; parent == nil means
   413  // the package currently imported. The parent package is needed for
   414  // exported struct fields and interface methods which don't contain
   415  // explicit package information in the export data.
   416  //
   417  // A non-nil tname is used as the "owner" of the result type; i.e.,
   418  // the result type is the underlying type of tname. tname is used
   419  // to give interface methods a named receiver type where possible.
   420  func (p *importer) typ(parent *types.Package, tname *types.Named) types.Type {
   421  	// if the type was seen before, i is its index (>= 0)
   422  	i := p.tagOrIndex()
   423  	if i >= 0 {
   424  		return p.typList[i]
   425  	}
   426  
   427  	// otherwise, i is the type tag (< 0)
   428  	switch i {
   429  	case namedTag:
   430  		// read type object
   431  		pos := p.pos()
   432  		parent, name := p.qualifiedName()
   433  		scope := parent.Scope()
   434  		obj := scope.Lookup(name)
   435  
   436  		// if the object doesn't exist yet, create and insert it
   437  		if obj == nil {
   438  			obj = types.NewTypeName(pos, parent, name, nil)
   439  			scope.Insert(obj)
   440  		}
   441  
   442  		if _, ok := obj.(*types.TypeName); !ok {
   443  			errorf("pkg = %s, name = %s => %s", parent, name, obj)
   444  		}
   445  
   446  		// associate new named type with obj if it doesn't exist yet
   447  		t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
   448  
   449  		// but record the existing type, if any
   450  		tname := obj.Type().(*types.Named) // tname is either t0 or the existing type
   451  		p.record(tname)
   452  
   453  		// read underlying type
   454  		t0.SetUnderlying(p.typ(parent, t0))
   455  
   456  		// interfaces don't have associated methods
   457  		if types.IsInterface(t0) {
   458  			return tname
   459  		}
   460  
   461  		// read associated methods
   462  		for i := p.int(); i > 0; i-- {
   463  			// TODO(gri) replace this with something closer to fieldName
   464  			pos := p.pos()
   465  			name := p.string()
   466  			if !exported(name) {
   467  				p.pkg()
   468  			}
   469  
   470  			recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
   471  			params, isddd := p.paramList()
   472  			result, _ := p.paramList()
   473  			p.int() // go:nointerface pragma - discarded
   474  
   475  			sig := types.NewSignature(recv.At(0), params, result, isddd)
   476  			t0.AddMethod(types.NewFunc(pos, parent, name, sig))
   477  		}
   478  
   479  		return tname
   480  
   481  	case arrayTag:
   482  		t := new(types.Array)
   483  		if p.trackAllTypes {
   484  			p.record(t)
   485  		}
   486  
   487  		n := p.int64()
   488  		*t = *types.NewArray(p.typ(parent, nil), n)
   489  		return t
   490  
   491  	case sliceTag:
   492  		t := new(types.Slice)
   493  		if p.trackAllTypes {
   494  			p.record(t)
   495  		}
   496  
   497  		*t = *types.NewSlice(p.typ(parent, nil))
   498  		return t
   499  
   500  	case dddTag:
   501  		t := new(dddSlice)
   502  		if p.trackAllTypes {
   503  			p.record(t)
   504  		}
   505  
   506  		t.elem = p.typ(parent, nil)
   507  		return t
   508  
   509  	case structTag:
   510  		t := new(types.Struct)
   511  		if p.trackAllTypes {
   512  			p.record(t)
   513  		}
   514  
   515  		*t = *types.NewStruct(p.fieldList(parent))
   516  		return t
   517  
   518  	case pointerTag:
   519  		t := new(types.Pointer)
   520  		if p.trackAllTypes {
   521  			p.record(t)
   522  		}
   523  
   524  		*t = *types.NewPointer(p.typ(parent, nil))
   525  		return t
   526  
   527  	case signatureTag:
   528  		t := new(types.Signature)
   529  		if p.trackAllTypes {
   530  			p.record(t)
   531  		}
   532  
   533  		params, isddd := p.paramList()
   534  		result, _ := p.paramList()
   535  		*t = *types.NewSignature(nil, params, result, isddd)
   536  		return t
   537  
   538  	case interfaceTag:
   539  		// Create a dummy entry in the type list. This is safe because we
   540  		// cannot expect the interface type to appear in a cycle, as any
   541  		// such cycle must contain a named type which would have been
   542  		// first defined earlier.
   543  		// TODO(gri) Is this still true now that we have type aliases?
   544  		// See issue #23225.
   545  		n := len(p.typList)
   546  		if p.trackAllTypes {
   547  			p.record(nil)
   548  		}
   549  
   550  		var embeddeds []types.Type
   551  		for n := p.int(); n > 0; n-- {
   552  			p.pos()
   553  			embeddeds = append(embeddeds, p.typ(parent, nil))
   554  		}
   555  
   556  		t := newInterface(p.methodList(parent, tname), embeddeds)
   557  		p.interfaceList = append(p.interfaceList, t)
   558  		if p.trackAllTypes {
   559  			p.typList[n] = t
   560  		}
   561  		return t
   562  
   563  	case mapTag:
   564  		t := new(types.Map)
   565  		if p.trackAllTypes {
   566  			p.record(t)
   567  		}
   568  
   569  		key := p.typ(parent, nil)
   570  		val := p.typ(parent, nil)
   571  		*t = *types.NewMap(key, val)
   572  		return t
   573  
   574  	case chanTag:
   575  		t := new(types.Chan)
   576  		if p.trackAllTypes {
   577  			p.record(t)
   578  		}
   579  
   580  		dir := chanDir(p.int())
   581  		val := p.typ(parent, nil)
   582  		*t = *types.NewChan(dir, val)
   583  		return t
   584  
   585  	default:
   586  		errorf("unexpected type tag %d", i) // panics
   587  		panic("unreachable")
   588  	}
   589  }
   590  
   591  func chanDir(d int) types.ChanDir {
   592  	// tag values must match the constants in cmd/compile/internal/gc/go.go
   593  	switch d {
   594  	case 1 /* Crecv */ :
   595  		return types.RecvOnly
   596  	case 2 /* Csend */ :
   597  		return types.SendOnly
   598  	case 3 /* Cboth */ :
   599  		return types.SendRecv
   600  	default:
   601  		errorf("unexpected channel dir %d", d)
   602  		return 0
   603  	}
   604  }
   605  
   606  func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) {
   607  	if n := p.int(); n > 0 {
   608  		fields = make([]*types.Var, n)
   609  		tags = make([]string, n)
   610  		for i := range fields {
   611  			fields[i], tags[i] = p.field(parent)
   612  		}
   613  	}
   614  	return
   615  }
   616  
   617  func (p *importer) field(parent *types.Package) (*types.Var, string) {
   618  	pos := p.pos()
   619  	pkg, name, alias := p.fieldName(parent)
   620  	typ := p.typ(parent, nil)
   621  	tag := p.string()
   622  
   623  	anonymous := false
   624  	if name == "" {
   625  		// anonymous field - typ must be T or *T and T must be a type name
   626  		switch typ := deref(typ).(type) {
   627  		case *types.Basic: // basic types are named types
   628  			pkg = nil // // objects defined in Universe scope have no package
   629  			name = typ.Name()
   630  		case *types.Named:
   631  			name = typ.Obj().Name()
   632  		default:
   633  			errorf("named base type expected")
   634  		}
   635  		anonymous = true
   636  	} else if alias {
   637  		// anonymous field: we have an explicit name because it's an alias
   638  		anonymous = true
   639  	}
   640  
   641  	return types.NewField(pos, pkg, name, typ, anonymous), tag
   642  }
   643  
   644  func (p *importer) methodList(parent *types.Package, baseType *types.Named) (methods []*types.Func) {
   645  	if n := p.int(); n > 0 {
   646  		methods = make([]*types.Func, n)
   647  		for i := range methods {
   648  			methods[i] = p.method(parent, baseType)
   649  		}
   650  	}
   651  	return
   652  }
   653  
   654  func (p *importer) method(parent *types.Package, baseType *types.Named) *types.Func {
   655  	pos := p.pos()
   656  	pkg, name, _ := p.fieldName(parent)
   657  	// If we don't have a baseType, use a nil receiver.
   658  	// A receiver using the actual interface type (which
   659  	// we don't know yet) will be filled in when we call
   660  	// types.Interface.Complete.
   661  	var recv *types.Var
   662  	if baseType != nil {
   663  		recv = types.NewVar(token.NoPos, parent, "", baseType)
   664  	}
   665  	params, isddd := p.paramList()
   666  	result, _ := p.paramList()
   667  	sig := types.NewSignature(recv, params, result, isddd)
   668  	return types.NewFunc(pos, pkg, name, sig)
   669  }
   670  
   671  func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) {
   672  	name = p.string()
   673  	pkg = parent
   674  	if pkg == nil {
   675  		// use the imported package instead
   676  		pkg = p.pkgList[0]
   677  	}
   678  	if p.version == 0 && name == "_" {
   679  		// version 0 didn't export a package for _ fields
   680  		return
   681  	}
   682  	switch name {
   683  	case "":
   684  		// 1) field name matches base type name and is exported: nothing to do
   685  	case "?":
   686  		// 2) field name matches base type name and is not exported: need package
   687  		name = ""
   688  		pkg = p.pkg()
   689  	case "@":
   690  		// 3) field name doesn't match type name (alias)
   691  		name = p.string()
   692  		alias = true
   693  		fallthrough
   694  	default:
   695  		if !exported(name) {
   696  			pkg = p.pkg()
   697  		}
   698  	}
   699  	return
   700  }
   701  
   702  func (p *importer) paramList() (*types.Tuple, bool) {
   703  	n := p.int()
   704  	if n == 0 {
   705  		return nil, false
   706  	}
   707  	// negative length indicates unnamed parameters
   708  	named := true
   709  	if n < 0 {
   710  		n = -n
   711  		named = false
   712  	}
   713  	// n > 0
   714  	params := make([]*types.Var, n)
   715  	isddd := false
   716  	for i := range params {
   717  		params[i], isddd = p.param(named)
   718  	}
   719  	return types.NewTuple(params...), isddd
   720  }
   721  
   722  func (p *importer) param(named bool) (*types.Var, bool) {
   723  	t := p.typ(nil, nil)
   724  	td, isddd := t.(*dddSlice)
   725  	if isddd {
   726  		t = types.NewSlice(td.elem)
   727  	}
   728  
   729  	var pkg *types.Package
   730  	var name string
   731  	if named {
   732  		name = p.string()
   733  		if name == "" {
   734  			errorf("expected named parameter")
   735  		}
   736  		if name != "_" {
   737  			pkg = p.pkg()
   738  		}
   739  		if i := strings.Index(name, "ยท"); i > 0 {
   740  			name = name[:i] // cut off gc-specific parameter numbering
   741  		}
   742  	}
   743  
   744  	// read and discard compiler-specific info
   745  	p.string()
   746  
   747  	return types.NewVar(token.NoPos, pkg, name, t), isddd
   748  }
   749  
   750  func exported(name string) bool {
   751  	ch, _ := utf8.DecodeRuneInString(name)
   752  	return unicode.IsUpper(ch)
   753  }
   754  
   755  func (p *importer) value() constant.Value {
   756  	switch tag := p.tagOrIndex(); tag {
   757  	case falseTag:
   758  		return constant.MakeBool(false)
   759  	case trueTag:
   760  		return constant.MakeBool(true)
   761  	case int64Tag:
   762  		return constant.MakeInt64(p.int64())
   763  	case floatTag:
   764  		return p.float()
   765  	case complexTag:
   766  		re := p.float()
   767  		im := p.float()
   768  		return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
   769  	case stringTag:
   770  		return constant.MakeString(p.string())
   771  	case unknownTag:
   772  		return constant.MakeUnknown()
   773  	default:
   774  		errorf("unexpected value tag %d", tag) // panics
   775  		panic("unreachable")
   776  	}
   777  }
   778  
   779  func (p *importer) float() constant.Value {
   780  	sign := p.int()
   781  	if sign == 0 {
   782  		return constant.MakeInt64(0)
   783  	}
   784  
   785  	exp := p.int()
   786  	mant := []byte(p.string()) // big endian
   787  
   788  	// remove leading 0's if any
   789  	for len(mant) > 0 && mant[0] == 0 {
   790  		mant = mant[1:]
   791  	}
   792  
   793  	// convert to little endian
   794  	// TODO(gri) go/constant should have a more direct conversion function
   795  	//           (e.g., once it supports a big.Float based implementation)
   796  	for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
   797  		mant[i], mant[j] = mant[j], mant[i]
   798  	}
   799  
   800  	// adjust exponent (constant.MakeFromBytes creates an integer value,
   801  	// but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
   802  	exp -= len(mant) << 3
   803  	if len(mant) > 0 {
   804  		for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
   805  			exp++
   806  		}
   807  	}
   808  
   809  	x := constant.MakeFromBytes(mant)
   810  	switch {
   811  	case exp < 0:
   812  		d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
   813  		x = constant.BinaryOp(x, token.QUO, d)
   814  	case exp > 0:
   815  		x = constant.Shift(x, token.SHL, uint(exp))
   816  	}
   817  
   818  	if sign < 0 {
   819  		x = constant.UnaryOp(token.SUB, x, 0)
   820  	}
   821  	return x
   822  }
   823  
   824  // ----------------------------------------------------------------------------
   825  // Low-level decoders
   826  
   827  func (p *importer) tagOrIndex() int {
   828  	if p.debugFormat {
   829  		p.marker('t')
   830  	}
   831  
   832  	return int(p.rawInt64())
   833  }
   834  
   835  func (p *importer) int() int {
   836  	x := p.int64()
   837  	if int64(int(x)) != x {
   838  		errorf("exported integer too large")
   839  	}
   840  	return int(x)
   841  }
   842  
   843  func (p *importer) int64() int64 {
   844  	if p.debugFormat {
   845  		p.marker('i')
   846  	}
   847  
   848  	return p.rawInt64()
   849  }
   850  
   851  func (p *importer) path() string {
   852  	if p.debugFormat {
   853  		p.marker('p')
   854  	}
   855  	// if the path was seen before, i is its index (>= 0)
   856  	// (the empty string is at index 0)
   857  	i := p.rawInt64()
   858  	if i >= 0 {
   859  		return p.pathList[i]
   860  	}
   861  	// otherwise, i is the negative path length (< 0)
   862  	a := make([]string, -i)
   863  	for n := range a {
   864  		a[n] = p.string()
   865  	}
   866  	s := strings.Join(a, "/")
   867  	p.pathList = append(p.pathList, s)
   868  	return s
   869  }
   870  
   871  func (p *importer) string() string {
   872  	if p.debugFormat {
   873  		p.marker('s')
   874  	}
   875  	// if the string was seen before, i is its index (>= 0)
   876  	// (the empty string is at index 0)
   877  	i := p.rawInt64()
   878  	if i >= 0 {
   879  		return p.strList[i]
   880  	}
   881  	// otherwise, i is the negative string length (< 0)
   882  	if n := int(-i); n <= cap(p.buf) {
   883  		p.buf = p.buf[:n]
   884  	} else {
   885  		p.buf = make([]byte, n)
   886  	}
   887  	for i := range p.buf {
   888  		p.buf[i] = p.rawByte()
   889  	}
   890  	s := string(p.buf)
   891  	p.strList = append(p.strList, s)
   892  	return s
   893  }
   894  
   895  func (p *importer) marker(want byte) {
   896  	if got := p.rawByte(); got != want {
   897  		errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
   898  	}
   899  
   900  	pos := p.read
   901  	if n := int(p.rawInt64()); n != pos {
   902  		errorf("incorrect position: got %d; want %d", n, pos)
   903  	}
   904  }
   905  
   906  // rawInt64 should only be used by low-level decoders.
   907  func (p *importer) rawInt64() int64 {
   908  	i, err := binary.ReadVarint(p)
   909  	if err != nil {
   910  		errorf("read error: %v", err)
   911  	}
   912  	return i
   913  }
   914  
   915  // rawStringln should only be used to read the initial version string.
   916  func (p *importer) rawStringln(b byte) string {
   917  	p.buf = p.buf[:0]
   918  	for b != '\n' {
   919  		p.buf = append(p.buf, b)
   920  		b = p.rawByte()
   921  	}
   922  	return string(p.buf)
   923  }
   924  
   925  // needed for binary.ReadVarint in rawInt64
   926  func (p *importer) ReadByte() (byte, error) {
   927  	return p.rawByte(), nil
   928  }
   929  
   930  // byte is the bottleneck interface for reading p.data.
   931  // It unescapes '|' 'S' to '$' and '|' '|' to '|'.
   932  // rawByte should only be used by low-level decoders.
   933  func (p *importer) rawByte() byte {
   934  	b := p.data[0]
   935  	r := 1
   936  	if b == '|' {
   937  		b = p.data[1]
   938  		r = 2
   939  		switch b {
   940  		case 'S':
   941  			b = '$'
   942  		case '|':
   943  			// nothing to do
   944  		default:
   945  			errorf("unexpected escape sequence in export data")
   946  		}
   947  	}
   948  	p.data = p.data[r:]
   949  	p.read += r
   950  	return b
   951  
   952  }
   953  
   954  // ----------------------------------------------------------------------------
   955  // Export format
   956  
   957  // Tags. Must be < 0.
   958  const (
   959  	// Objects
   960  	packageTag = -(iota + 1)
   961  	constTag
   962  	typeTag
   963  	varTag
   964  	funcTag
   965  	endTag
   966  
   967  	// Types
   968  	namedTag
   969  	arrayTag
   970  	sliceTag
   971  	dddTag
   972  	structTag
   973  	pointerTag
   974  	signatureTag
   975  	interfaceTag
   976  	mapTag
   977  	chanTag
   978  
   979  	// Values
   980  	falseTag
   981  	trueTag
   982  	int64Tag
   983  	floatTag
   984  	fractionTag // not used by gc
   985  	complexTag
   986  	stringTag
   987  	nilTag     // only used by gc (appears in exported inlined function bodies)
   988  	unknownTag // not used by gc (only appears in packages with errors)
   989  
   990  	// Type aliases
   991  	aliasTag
   992  )
   993  
   994  var predeclOnce sync.Once
   995  var predecl []types.Type // initialized lazily
   996  
   997  func predeclared() []types.Type {
   998  	predeclOnce.Do(func() {
   999  		// initialize lazily to be sure that all
  1000  		// elements have been initialized before
  1001  		predecl = []types.Type{ // basic types
  1002  			types.Typ[types.Bool],
  1003  			types.Typ[types.Int],
  1004  			types.Typ[types.Int8],
  1005  			types.Typ[types.Int16],
  1006  			types.Typ[types.Int32],
  1007  			types.Typ[types.Int64],
  1008  			types.Typ[types.Uint],
  1009  			types.Typ[types.Uint8],
  1010  			types.Typ[types.Uint16],
  1011  			types.Typ[types.Uint32],
  1012  			types.Typ[types.Uint64],
  1013  			types.Typ[types.Uintptr],
  1014  			types.Typ[types.Float32],
  1015  			types.Typ[types.Float64],
  1016  			types.Typ[types.Complex64],
  1017  			types.Typ[types.Complex128],
  1018  			types.Typ[types.String],
  1019  
  1020  			// basic type aliases
  1021  			types.Universe.Lookup("byte").Type(),
  1022  			types.Universe.Lookup("rune").Type(),
  1023  
  1024  			// error
  1025  			types.Universe.Lookup("error").Type(),
  1026  
  1027  			// untyped types
  1028  			types.Typ[types.UntypedBool],
  1029  			types.Typ[types.UntypedInt],
  1030  			types.Typ[types.UntypedRune],
  1031  			types.Typ[types.UntypedFloat],
  1032  			types.Typ[types.UntypedComplex],
  1033  			types.Typ[types.UntypedString],
  1034  			types.Typ[types.UntypedNil],
  1035  
  1036  			// package unsafe
  1037  			types.Typ[types.UnsafePointer],
  1038  
  1039  			// invalid type
  1040  			types.Typ[types.Invalid], // only appears in packages with errors
  1041  
  1042  			// used internally by gc; never used by this package or in .a files
  1043  			anyType{},
  1044  		}
  1045  		predecl = append(predecl, additionalPredeclared()...)
  1046  	})
  1047  	return predecl
  1048  }
  1049  
  1050  type anyType struct{}
  1051  
  1052  func (t anyType) Underlying() types.Type { return t }
  1053  func (t anyType) String() string         { return "any" }