github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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  	"unicode"
    15  	"unicode/utf8"
    16  )
    17  
    18  // BImportData imports a package from the serialized package data
    19  // and returns the number of bytes consumed and a reference to the package.
    20  // If data is obviously malformed, an error is returned but in
    21  // general it is not recommended to call BImportData on untrusted data.
    22  func BImportData(imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
    23  	p := importer{
    24  		imports: imports,
    25  		data:    data,
    26  	}
    27  	p.buf = p.bufarray[:]
    28  
    29  	// read low-level encoding format
    30  	switch format := p.byte(); format {
    31  	case 'c':
    32  		// compact format - nothing to do
    33  	case 'd':
    34  		p.debugFormat = true
    35  	default:
    36  		return p.read, nil, fmt.Errorf("invalid encoding format in export data: got %q; want 'c' or 'd'", format)
    37  	}
    38  
    39  	// --- generic export data ---
    40  
    41  	if v := p.string(); v != "v0" {
    42  		return p.read, nil, fmt.Errorf("unknown version: %s", v)
    43  	}
    44  
    45  	// populate typList with predeclared "known" types
    46  	p.typList = append(p.typList, predeclared...)
    47  
    48  	// read package data
    49  	// TODO(gri) clean this up
    50  	i := p.tagOrIndex()
    51  	if i != packageTag {
    52  		panic(fmt.Sprintf("package tag expected, got %d", i))
    53  	}
    54  	name := p.string()
    55  	if s := p.string(); s != "" {
    56  		panic(fmt.Sprintf("empty path expected, got %s", s))
    57  	}
    58  	pkg := p.imports[path]
    59  	if pkg == nil {
    60  		pkg = types.NewPackage(path, name)
    61  		p.imports[path] = pkg
    62  	}
    63  	p.pkgList = append(p.pkgList, pkg)
    64  
    65  	if debug && p.pkgList[0] != pkg {
    66  		panic("imported packaged not found in pkgList[0]")
    67  	}
    68  
    69  	// read compiler-specific flags
    70  	p.string() // discard
    71  
    72  	// read consts
    73  	for i := p.int(); i > 0; i-- {
    74  		name := p.string()
    75  		typ := p.typ()
    76  		val := p.value()
    77  		p.declare(types.NewConst(token.NoPos, pkg, name, typ, val))
    78  	}
    79  
    80  	// read vars
    81  	for i := p.int(); i > 0; i-- {
    82  		name := p.string()
    83  		typ := p.typ()
    84  		p.declare(types.NewVar(token.NoPos, pkg, name, typ))
    85  	}
    86  
    87  	// read funcs
    88  	for i := p.int(); i > 0; i-- {
    89  		name := p.string()
    90  		sig := p.typ().(*types.Signature)
    91  		p.int() // read and discard index of inlined function body
    92  		p.declare(types.NewFunc(token.NoPos, pkg, name, sig))
    93  	}
    94  
    95  	// read types
    96  	for i := p.int(); i > 0; i-- {
    97  		// name is parsed as part of named type and the
    98  		// type object is added to scope via respective
    99  		// named type
   100  		_ = p.typ().(*types.Named)
   101  	}
   102  
   103  	// ignore compiler-specific import data
   104  
   105  	// complete interfaces
   106  	for _, typ := range p.typList {
   107  		if it, ok := typ.(*types.Interface); ok {
   108  			it.Complete()
   109  		}
   110  	}
   111  
   112  	// record all referenced packages as imports
   113  	list := append(([]*types.Package)(nil), p.pkgList[1:]...)
   114  	sort.Sort(byPath(list))
   115  	pkg.SetImports(list)
   116  
   117  	// package was imported completely and without errors
   118  	pkg.MarkComplete()
   119  
   120  	return p.read, pkg, nil
   121  }
   122  
   123  type importer struct {
   124  	imports  map[string]*types.Package
   125  	data     []byte
   126  	buf      []byte   // for reading strings
   127  	bufarray [64]byte // initial underlying array for buf, large enough to avoid allocation when compiling std lib
   128  	pkgList  []*types.Package
   129  	typList  []types.Type
   130  
   131  	debugFormat bool
   132  	read        int // bytes read
   133  }
   134  
   135  func (p *importer) declare(obj types.Object) {
   136  	if alt := p.pkgList[0].Scope().Insert(obj); alt != nil {
   137  		// This can only happen if we import a package a second time.
   138  		panic(fmt.Sprintf("%s already declared", alt.Name()))
   139  	}
   140  }
   141  
   142  func (p *importer) pkg() *types.Package {
   143  	// if the package was seen before, i is its index (>= 0)
   144  	i := p.tagOrIndex()
   145  	if i >= 0 {
   146  		return p.pkgList[i]
   147  	}
   148  
   149  	// otherwise, i is the package tag (< 0)
   150  	if i != packageTag {
   151  		panic(fmt.Sprintf("unexpected package tag %d", i))
   152  	}
   153  
   154  	// read package data
   155  	name := p.string()
   156  	path := p.string()
   157  
   158  	// we should never see an empty package name
   159  	if name == "" {
   160  		panic("empty package name in import")
   161  	}
   162  
   163  	// we should never see an empty import path
   164  	if path == "" {
   165  		panic("empty import path")
   166  	}
   167  
   168  	// if the package was imported before, use that one; otherwise create a new one
   169  	pkg := p.imports[path]
   170  	if pkg == nil {
   171  		pkg = types.NewPackage(path, name)
   172  		p.imports[path] = pkg
   173  	}
   174  	p.pkgList = append(p.pkgList, pkg)
   175  
   176  	return pkg
   177  }
   178  
   179  func (p *importer) record(t types.Type) {
   180  	p.typList = append(p.typList, t)
   181  }
   182  
   183  // A dddSlice is a types.Type representing ...T parameters.
   184  // It only appears for parameter types and does not escape
   185  // the importer.
   186  type dddSlice struct {
   187  	elem types.Type
   188  }
   189  
   190  func (t *dddSlice) Underlying() types.Type { return t }
   191  func (t *dddSlice) String() string         { return "..." + t.elem.String() }
   192  
   193  func (p *importer) typ() types.Type {
   194  	// if the type was seen before, i is its index (>= 0)
   195  	i := p.tagOrIndex()
   196  	if i >= 0 {
   197  		return p.typList[i]
   198  	}
   199  
   200  	// otherwise, i is the type tag (< 0)
   201  	switch i {
   202  	case namedTag:
   203  		// read type object
   204  		name := p.string()
   205  		tpkg := p.pkg()
   206  		scope := tpkg.Scope()
   207  		obj := scope.Lookup(name)
   208  
   209  		// if the object doesn't exist yet, create and insert it
   210  		if obj == nil {
   211  			obj = types.NewTypeName(token.NoPos, tpkg, name, nil)
   212  			scope.Insert(obj)
   213  		}
   214  
   215  		if _, ok := obj.(*types.TypeName); !ok {
   216  			panic(fmt.Sprintf("pkg = %s, name = %s => %s", tpkg, name, obj))
   217  		}
   218  
   219  		// associate new named type with obj if it doesn't exist yet
   220  		t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
   221  
   222  		// but record the existing type, if any
   223  		t := obj.Type().(*types.Named)
   224  		p.record(t)
   225  
   226  		// read underlying type
   227  		t0.SetUnderlying(p.typ())
   228  
   229  		// interfaces don't have associated methods
   230  		if _, ok := t0.Underlying().(*types.Interface); ok {
   231  			return t
   232  		}
   233  
   234  		// read associated methods
   235  		for i := p.int(); i > 0; i-- {
   236  			name := p.string()
   237  			recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
   238  			params, isddd := p.paramList()
   239  			result, _ := p.paramList()
   240  			p.int() // read and discard index of inlined function body
   241  			sig := types.NewSignature(recv.At(0), params, result, isddd)
   242  			t0.AddMethod(types.NewFunc(token.NoPos, tpkg, name, sig))
   243  		}
   244  
   245  		return t
   246  
   247  	case arrayTag:
   248  		t := new(types.Array)
   249  		p.record(t)
   250  
   251  		n := p.int64()
   252  		*t = *types.NewArray(p.typ(), n)
   253  		return t
   254  
   255  	case sliceTag:
   256  		t := new(types.Slice)
   257  		p.record(t)
   258  
   259  		*t = *types.NewSlice(p.typ())
   260  		return t
   261  
   262  	case dddTag:
   263  		t := new(dddSlice)
   264  		p.record(t)
   265  
   266  		t.elem = p.typ()
   267  		return t
   268  
   269  	case structTag:
   270  		t := new(types.Struct)
   271  		p.record(t)
   272  
   273  		n := p.int()
   274  		fields := make([]*types.Var, n)
   275  		tags := make([]string, n)
   276  		for i := range fields {
   277  			fields[i] = p.field()
   278  			tags[i] = p.string()
   279  		}
   280  		*t = *types.NewStruct(fields, tags)
   281  		return t
   282  
   283  	case pointerTag:
   284  		t := new(types.Pointer)
   285  		p.record(t)
   286  
   287  		*t = *types.NewPointer(p.typ())
   288  		return t
   289  
   290  	case signatureTag:
   291  		t := new(types.Signature)
   292  		p.record(t)
   293  
   294  		params, isddd := p.paramList()
   295  		result, _ := p.paramList()
   296  		*t = *types.NewSignature(nil, params, result, isddd)
   297  		return t
   298  
   299  	case interfaceTag:
   300  		// Create a dummy entry in the type list. This is safe because we
   301  		// cannot expect the interface type to appear in a cycle, as any
   302  		// such cycle must contain a named type which would have been
   303  		// first defined earlier.
   304  		n := len(p.typList)
   305  		p.record(nil)
   306  
   307  		// no embedded interfaces with gc compiler
   308  		if p.int() != 0 {
   309  			panic("unexpected embedded interface")
   310  		}
   311  
   312  		// read methods
   313  		methods := make([]*types.Func, p.int())
   314  		for i := range methods {
   315  			pkg, name := p.fieldName()
   316  			params, isddd := p.paramList()
   317  			result, _ := p.paramList()
   318  			sig := types.NewSignature(nil, params, result, isddd)
   319  			methods[i] = types.NewFunc(token.NoPos, pkg, name, sig)
   320  		}
   321  
   322  		t := types.NewInterface(methods, nil)
   323  		p.typList[n] = t
   324  		return t
   325  
   326  	case mapTag:
   327  		t := new(types.Map)
   328  		p.record(t)
   329  
   330  		key := p.typ()
   331  		val := p.typ()
   332  		*t = *types.NewMap(key, val)
   333  		return t
   334  
   335  	case chanTag:
   336  		t := new(types.Chan)
   337  		p.record(t)
   338  
   339  		var dir types.ChanDir
   340  		// tag values must match the constants in cmd/compile/internal/gc/go.go
   341  		switch d := p.int(); d {
   342  		case 1 /* Crecv */ :
   343  			dir = types.RecvOnly
   344  		case 2 /* Csend */ :
   345  			dir = types.SendOnly
   346  		case 3 /* Cboth */ :
   347  			dir = types.SendRecv
   348  		default:
   349  			panic(fmt.Sprintf("unexpected channel dir %d", d))
   350  		}
   351  		val := p.typ()
   352  		*t = *types.NewChan(dir, val)
   353  		return t
   354  
   355  	default:
   356  		panic(fmt.Sprintf("unexpected type tag %d", i))
   357  	}
   358  }
   359  
   360  func (p *importer) field() *types.Var {
   361  	pkg, name := p.fieldName()
   362  	typ := p.typ()
   363  
   364  	anonymous := false
   365  	if name == "" {
   366  		// anonymous field - typ must be T or *T and T must be a type name
   367  		switch typ := deref(typ).(type) {
   368  		case *types.Basic: // basic types are named types
   369  			name = typ.Name()
   370  		case *types.Named:
   371  			pkg = p.pkgList[0]
   372  			name = typ.Obj().Name()
   373  		default:
   374  			panic("anonymous field expected")
   375  		}
   376  		anonymous = true
   377  	}
   378  
   379  	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
   380  }
   381  
   382  func (p *importer) fieldName() (*types.Package, string) {
   383  	name := p.string()
   384  	if name == "" {
   385  		return nil, "" // anonymous field
   386  	}
   387  	pkg := p.pkgList[0]
   388  	if name == "?" || name != "_" && !exported(name) {
   389  		if name == "?" {
   390  			name = ""
   391  		}
   392  		pkg = p.pkg()
   393  	}
   394  	return pkg, name
   395  }
   396  
   397  func (p *importer) paramList() (*types.Tuple, bool) {
   398  	n := p.int()
   399  	if n == 0 {
   400  		return nil, false
   401  	}
   402  	// negative length indicates unnamed parameters
   403  	named := true
   404  	if n < 0 {
   405  		n = -n
   406  		named = false
   407  	}
   408  	// n > 0
   409  	params := make([]*types.Var, n)
   410  	isddd := false
   411  	for i := range params {
   412  		params[i], isddd = p.param(named)
   413  	}
   414  	return types.NewTuple(params...), isddd
   415  }
   416  
   417  func (p *importer) param(named bool) (*types.Var, bool) {
   418  	t := p.typ()
   419  	td, isddd := t.(*dddSlice)
   420  	if isddd {
   421  		t = types.NewSlice(td.elem)
   422  	}
   423  
   424  	var name string
   425  	if named {
   426  		name = p.string()
   427  		if name == "" {
   428  			panic("expected named parameter")
   429  		}
   430  	}
   431  
   432  	// read and discard compiler-specific info
   433  	p.string()
   434  
   435  	return types.NewVar(token.NoPos, nil, name, t), isddd
   436  }
   437  
   438  func exported(name string) bool {
   439  	ch, _ := utf8.DecodeRuneInString(name)
   440  	return unicode.IsUpper(ch)
   441  }
   442  
   443  func (p *importer) value() constant.Value {
   444  	switch tag := p.tagOrIndex(); tag {
   445  	case falseTag:
   446  		return constant.MakeBool(false)
   447  	case trueTag:
   448  		return constant.MakeBool(true)
   449  	case int64Tag:
   450  		return constant.MakeInt64(p.int64())
   451  	case floatTag:
   452  		return p.float()
   453  	case complexTag:
   454  		re := p.float()
   455  		im := p.float()
   456  		return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
   457  	case stringTag:
   458  		return constant.MakeString(p.string())
   459  	default:
   460  		panic(fmt.Sprintf("unexpected value tag %d", tag))
   461  	}
   462  }
   463  
   464  func (p *importer) float() constant.Value {
   465  	sign := p.int()
   466  	if sign == 0 {
   467  		return constant.MakeInt64(0)
   468  	}
   469  
   470  	exp := p.int()
   471  	mant := []byte(p.string()) // big endian
   472  
   473  	// remove leading 0's if any
   474  	for len(mant) > 0 && mant[0] == 0 {
   475  		mant = mant[1:]
   476  	}
   477  
   478  	// convert to little endian
   479  	// TODO(gri) go/constant should have a more direct conversion function
   480  	//           (e.g., once it supports a big.Float based implementation)
   481  	for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
   482  		mant[i], mant[j] = mant[j], mant[i]
   483  	}
   484  
   485  	// adjust exponent (constant.MakeFromBytes creates an integer value,
   486  	// but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
   487  	exp -= len(mant) << 3
   488  	if len(mant) > 0 {
   489  		for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
   490  			exp++
   491  		}
   492  	}
   493  
   494  	x := constant.MakeFromBytes(mant)
   495  	switch {
   496  	case exp < 0:
   497  		d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
   498  		x = constant.BinaryOp(x, token.QUO, d)
   499  	case exp > 0:
   500  		x = constant.Shift(x, token.SHL, uint(exp))
   501  	}
   502  
   503  	if sign < 0 {
   504  		x = constant.UnaryOp(token.SUB, x, 0)
   505  	}
   506  	return x
   507  }
   508  
   509  // ----------------------------------------------------------------------------
   510  // Low-level decoders
   511  
   512  func (p *importer) tagOrIndex() int {
   513  	if p.debugFormat {
   514  		p.marker('t')
   515  	}
   516  
   517  	return int(p.rawInt64())
   518  }
   519  
   520  func (p *importer) int() int {
   521  	x := p.int64()
   522  	if int64(int(x)) != x {
   523  		panic("exported integer too large")
   524  	}
   525  	return int(x)
   526  }
   527  
   528  func (p *importer) int64() int64 {
   529  	if p.debugFormat {
   530  		p.marker('i')
   531  	}
   532  
   533  	return p.rawInt64()
   534  }
   535  
   536  func (p *importer) string() string {
   537  	if p.debugFormat {
   538  		p.marker('s')
   539  	}
   540  
   541  	if n := int(p.rawInt64()); n > 0 {
   542  		if cap(p.buf) < n {
   543  			p.buf = make([]byte, n)
   544  		} else {
   545  			p.buf = p.buf[:n]
   546  		}
   547  		for i := 0; i < n; i++ {
   548  			p.buf[i] = p.byte()
   549  		}
   550  		return string(p.buf)
   551  	}
   552  
   553  	return ""
   554  }
   555  
   556  func (p *importer) marker(want byte) {
   557  	if got := p.byte(); got != want {
   558  		panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read))
   559  	}
   560  
   561  	pos := p.read
   562  	if n := int(p.rawInt64()); n != pos {
   563  		panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos))
   564  	}
   565  }
   566  
   567  // rawInt64 should only be used by low-level decoders
   568  func (p *importer) rawInt64() int64 {
   569  	i, err := binary.ReadVarint(p)
   570  	if err != nil {
   571  		panic(fmt.Sprintf("read error: %v", err))
   572  	}
   573  	return i
   574  }
   575  
   576  // needed for binary.ReadVarint in rawInt64
   577  func (p *importer) ReadByte() (byte, error) {
   578  	return p.byte(), nil
   579  }
   580  
   581  // byte is the bottleneck interface for reading p.data.
   582  // It unescapes '|' 'S' to '$' and '|' '|' to '|'.
   583  func (p *importer) byte() byte {
   584  	b := p.data[0]
   585  	r := 1
   586  	if b == '|' {
   587  		b = p.data[1]
   588  		r = 2
   589  		switch b {
   590  		case 'S':
   591  			b = '$'
   592  		case '|':
   593  			// nothing to do
   594  		default:
   595  			panic("unexpected escape sequence in export data")
   596  		}
   597  	}
   598  	p.data = p.data[r:]
   599  	p.read += r
   600  	return b
   601  
   602  }
   603  
   604  // ----------------------------------------------------------------------------
   605  // Export format
   606  
   607  // Tags. Must be < 0.
   608  const (
   609  	// Packages
   610  	packageTag = -(iota + 1)
   611  
   612  	// Types
   613  	namedTag
   614  	arrayTag
   615  	sliceTag
   616  	dddTag
   617  	structTag
   618  	pointerTag
   619  	signatureTag
   620  	interfaceTag
   621  	mapTag
   622  	chanTag
   623  
   624  	// Values
   625  	falseTag
   626  	trueTag
   627  	int64Tag
   628  	floatTag
   629  	fractionTag // not used by gc
   630  	complexTag
   631  	stringTag
   632  )
   633  
   634  var predeclared = []types.Type{
   635  	// basic types
   636  	types.Typ[types.Bool],
   637  	types.Typ[types.Int],
   638  	types.Typ[types.Int8],
   639  	types.Typ[types.Int16],
   640  	types.Typ[types.Int32],
   641  	types.Typ[types.Int64],
   642  	types.Typ[types.Uint],
   643  	types.Typ[types.Uint8],
   644  	types.Typ[types.Uint16],
   645  	types.Typ[types.Uint32],
   646  	types.Typ[types.Uint64],
   647  	types.Typ[types.Uintptr],
   648  	types.Typ[types.Float32],
   649  	types.Typ[types.Float64],
   650  	types.Typ[types.Complex64],
   651  	types.Typ[types.Complex128],
   652  	types.Typ[types.String],
   653  
   654  	// aliases
   655  	types.Universe.Lookup("byte").Type(),
   656  	types.Universe.Lookup("rune").Type(),
   657  
   658  	// error
   659  	types.Universe.Lookup("error").Type(),
   660  
   661  	// untyped types
   662  	types.Typ[types.UntypedBool],
   663  	types.Typ[types.UntypedInt],
   664  	types.Typ[types.UntypedRune],
   665  	types.Typ[types.UntypedFloat],
   666  	types.Typ[types.UntypedComplex],
   667  	types.Typ[types.UntypedString],
   668  	types.Typ[types.UntypedNil],
   669  
   670  	// package unsafe
   671  	types.Typ[types.UnsafePointer],
   672  }