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