...
Run Format

Source file src/go/internal/gcimporter/bimport.go

Documentation: go/internal/gcimporter

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

View as plain text