...

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

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

View as plain text