github.com/aloncn/graphics-go@v0.0.1/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(nil)
    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(nil)
    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(nil).(*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(nil).(*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  // parent is the package which declared the type; parent == nil means
   194  // the package currently imported. The parent package is needed for
   195  // exported struct fields and interface methods which don't contain
   196  // explicit package information in the export data.
   197  func (p *importer) typ(parent *types.Package) types.Type {
   198  	// if the type was seen before, i is its index (>= 0)
   199  	i := p.tagOrIndex()
   200  	if i >= 0 {
   201  		return p.typList[i]
   202  	}
   203  
   204  	// otherwise, i is the type tag (< 0)
   205  	switch i {
   206  	case namedTag:
   207  		// read type object
   208  		name := p.string()
   209  		parent = p.pkg()
   210  		scope := parent.Scope()
   211  		obj := scope.Lookup(name)
   212  
   213  		// if the object doesn't exist yet, create and insert it
   214  		if obj == nil {
   215  			obj = types.NewTypeName(token.NoPos, parent, name, nil)
   216  			scope.Insert(obj)
   217  		}
   218  
   219  		if _, ok := obj.(*types.TypeName); !ok {
   220  			panic(fmt.Sprintf("pkg = %s, name = %s => %s", parent, name, obj))
   221  		}
   222  
   223  		// associate new named type with obj if it doesn't exist yet
   224  		t0 := types.NewNamed(obj.(*types.TypeName), nil, nil)
   225  
   226  		// but record the existing type, if any
   227  		t := obj.Type().(*types.Named)
   228  		p.record(t)
   229  
   230  		// read underlying type
   231  		t0.SetUnderlying(p.typ(parent))
   232  
   233  		// interfaces don't have associated methods
   234  		if _, ok := t0.Underlying().(*types.Interface); ok {
   235  			return t
   236  		}
   237  
   238  		// read associated methods
   239  		for i := p.int(); i > 0; i-- {
   240  			name := p.string()
   241  			recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver?
   242  			params, isddd := p.paramList()
   243  			result, _ := p.paramList()
   244  			p.int() // read and discard index of inlined function body
   245  			sig := types.NewSignature(recv.At(0), params, result, isddd)
   246  			t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig))
   247  		}
   248  
   249  		return t
   250  
   251  	case arrayTag:
   252  		t := new(types.Array)
   253  		p.record(t)
   254  
   255  		n := p.int64()
   256  		*t = *types.NewArray(p.typ(parent), n)
   257  		return t
   258  
   259  	case sliceTag:
   260  		t := new(types.Slice)
   261  		p.record(t)
   262  
   263  		*t = *types.NewSlice(p.typ(parent))
   264  		return t
   265  
   266  	case dddTag:
   267  		t := new(dddSlice)
   268  		p.record(t)
   269  
   270  		t.elem = p.typ(parent)
   271  		return t
   272  
   273  	case structTag:
   274  		t := new(types.Struct)
   275  		p.record(t)
   276  
   277  		n := p.int()
   278  		fields := make([]*types.Var, n)
   279  		tags := make([]string, n)
   280  		for i := range fields {
   281  			fields[i] = p.field(parent)
   282  			tags[i] = p.string()
   283  		}
   284  		*t = *types.NewStruct(fields, tags)
   285  		return t
   286  
   287  	case pointerTag:
   288  		t := new(types.Pointer)
   289  		p.record(t)
   290  
   291  		*t = *types.NewPointer(p.typ(parent))
   292  		return t
   293  
   294  	case signatureTag:
   295  		t := new(types.Signature)
   296  		p.record(t)
   297  
   298  		params, isddd := p.paramList()
   299  		result, _ := p.paramList()
   300  		*t = *types.NewSignature(nil, params, result, isddd)
   301  		return t
   302  
   303  	case interfaceTag:
   304  		// Create a dummy entry in the type list. This is safe because we
   305  		// cannot expect the interface type to appear in a cycle, as any
   306  		// such cycle must contain a named type which would have been
   307  		// first defined earlier.
   308  		n := len(p.typList)
   309  		p.record(nil)
   310  
   311  		// no embedded interfaces with gc compiler
   312  		if p.int() != 0 {
   313  			panic("unexpected embedded interface")
   314  		}
   315  
   316  		// read methods
   317  		methods := make([]*types.Func, p.int())
   318  		for i := range methods {
   319  			pkg, name := p.fieldName(parent)
   320  			params, isddd := p.paramList()
   321  			result, _ := p.paramList()
   322  			sig := types.NewSignature(nil, params, result, isddd)
   323  			methods[i] = types.NewFunc(token.NoPos, pkg, name, sig)
   324  		}
   325  
   326  		t := types.NewInterface(methods, nil)
   327  		p.typList[n] = t
   328  		return t
   329  
   330  	case mapTag:
   331  		t := new(types.Map)
   332  		p.record(t)
   333  
   334  		key := p.typ(parent)
   335  		val := p.typ(parent)
   336  		*t = *types.NewMap(key, val)
   337  		return t
   338  
   339  	case chanTag:
   340  		t := new(types.Chan)
   341  		p.record(t)
   342  
   343  		var dir types.ChanDir
   344  		// tag values must match the constants in cmd/compile/internal/gc/go.go
   345  		switch d := p.int(); d {
   346  		case 1 /* Crecv */ :
   347  			dir = types.RecvOnly
   348  		case 2 /* Csend */ :
   349  			dir = types.SendOnly
   350  		case 3 /* Cboth */ :
   351  			dir = types.SendRecv
   352  		default:
   353  			panic(fmt.Sprintf("unexpected channel dir %d", d))
   354  		}
   355  		val := p.typ(parent)
   356  		*t = *types.NewChan(dir, val)
   357  		return t
   358  
   359  	default:
   360  		panic(fmt.Sprintf("unexpected type tag %d", i))
   361  	}
   362  }
   363  
   364  func (p *importer) field(parent *types.Package) *types.Var {
   365  	pkg, name := p.fieldName(parent)
   366  	typ := p.typ(parent)
   367  
   368  	anonymous := false
   369  	if name == "" {
   370  		// anonymous field - typ must be T or *T and T must be a type name
   371  		switch typ := deref(typ).(type) {
   372  		case *types.Basic: // basic types are named types
   373  			pkg = nil // // objects defined in Universe scope have no package
   374  			name = typ.Name()
   375  		case *types.Named:
   376  			name = typ.Obj().Name()
   377  		default:
   378  			panic("anonymous field expected")
   379  		}
   380  		anonymous = true
   381  	}
   382  
   383  	return types.NewField(token.NoPos, pkg, name, typ, anonymous)
   384  }
   385  
   386  func (p *importer) fieldName(parent *types.Package) (*types.Package, string) {
   387  	pkg := parent
   388  	if pkg == nil {
   389  		// use the imported package instead
   390  		pkg = p.pkgList[0]
   391  	}
   392  	name := p.string()
   393  	if name == "" {
   394  		return pkg, "" // anonymous
   395  	}
   396  	if name == "?" || name != "_" && !exported(name) {
   397  		// explicitly qualified field
   398  		if name == "?" {
   399  			name = "" // anonymous
   400  		}
   401  		pkg = p.pkg()
   402  	}
   403  	return pkg, name
   404  }
   405  
   406  func (p *importer) paramList() (*types.Tuple, bool) {
   407  	n := p.int()
   408  	if n == 0 {
   409  		return nil, false
   410  	}
   411  	// negative length indicates unnamed parameters
   412  	named := true
   413  	if n < 0 {
   414  		n = -n
   415  		named = false
   416  	}
   417  	// n > 0
   418  	params := make([]*types.Var, n)
   419  	isddd := false
   420  	for i := range params {
   421  		params[i], isddd = p.param(named)
   422  	}
   423  	return types.NewTuple(params...), isddd
   424  }
   425  
   426  func (p *importer) param(named bool) (*types.Var, bool) {
   427  	t := p.typ(nil)
   428  	td, isddd := t.(*dddSlice)
   429  	if isddd {
   430  		t = types.NewSlice(td.elem)
   431  	}
   432  
   433  	var name string
   434  	if named {
   435  		name = p.string()
   436  		if name == "" {
   437  			panic("expected named parameter")
   438  		}
   439  	}
   440  
   441  	// read and discard compiler-specific info
   442  	p.string()
   443  
   444  	return types.NewVar(token.NoPos, nil, name, t), isddd
   445  }
   446  
   447  func exported(name string) bool {
   448  	ch, _ := utf8.DecodeRuneInString(name)
   449  	return unicode.IsUpper(ch)
   450  }
   451  
   452  func (p *importer) value() constant.Value {
   453  	switch tag := p.tagOrIndex(); tag {
   454  	case falseTag:
   455  		return constant.MakeBool(false)
   456  	case trueTag:
   457  		return constant.MakeBool(true)
   458  	case int64Tag:
   459  		return constant.MakeInt64(p.int64())
   460  	case floatTag:
   461  		return p.float()
   462  	case complexTag:
   463  		re := p.float()
   464  		im := p.float()
   465  		return constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
   466  	case stringTag:
   467  		return constant.MakeString(p.string())
   468  	default:
   469  		panic(fmt.Sprintf("unexpected value tag %d", tag))
   470  	}
   471  }
   472  
   473  func (p *importer) float() constant.Value {
   474  	sign := p.int()
   475  	if sign == 0 {
   476  		return constant.MakeInt64(0)
   477  	}
   478  
   479  	exp := p.int()
   480  	mant := []byte(p.string()) // big endian
   481  
   482  	// remove leading 0's if any
   483  	for len(mant) > 0 && mant[0] == 0 {
   484  		mant = mant[1:]
   485  	}
   486  
   487  	// convert to little endian
   488  	// TODO(gri) go/constant should have a more direct conversion function
   489  	//           (e.g., once it supports a big.Float based implementation)
   490  	for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 {
   491  		mant[i], mant[j] = mant[j], mant[i]
   492  	}
   493  
   494  	// adjust exponent (constant.MakeFromBytes creates an integer value,
   495  	// but mant represents the mantissa bits such that 0.5 <= mant < 1.0)
   496  	exp -= len(mant) << 3
   497  	if len(mant) > 0 {
   498  		for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 {
   499  			exp++
   500  		}
   501  	}
   502  
   503  	x := constant.MakeFromBytes(mant)
   504  	switch {
   505  	case exp < 0:
   506  		d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
   507  		x = constant.BinaryOp(x, token.QUO, d)
   508  	case exp > 0:
   509  		x = constant.Shift(x, token.SHL, uint(exp))
   510  	}
   511  
   512  	if sign < 0 {
   513  		x = constant.UnaryOp(token.SUB, x, 0)
   514  	}
   515  	return x
   516  }
   517  
   518  // ----------------------------------------------------------------------------
   519  // Low-level decoders
   520  
   521  func (p *importer) tagOrIndex() int {
   522  	if p.debugFormat {
   523  		p.marker('t')
   524  	}
   525  
   526  	return int(p.rawInt64())
   527  }
   528  
   529  func (p *importer) int() int {
   530  	x := p.int64()
   531  	if int64(int(x)) != x {
   532  		panic("exported integer too large")
   533  	}
   534  	return int(x)
   535  }
   536  
   537  func (p *importer) int64() int64 {
   538  	if p.debugFormat {
   539  		p.marker('i')
   540  	}
   541  
   542  	return p.rawInt64()
   543  }
   544  
   545  func (p *importer) string() string {
   546  	if p.debugFormat {
   547  		p.marker('s')
   548  	}
   549  
   550  	if n := int(p.rawInt64()); n > 0 {
   551  		if cap(p.buf) < n {
   552  			p.buf = make([]byte, n)
   553  		} else {
   554  			p.buf = p.buf[:n]
   555  		}
   556  		for i := 0; i < n; i++ {
   557  			p.buf[i] = p.byte()
   558  		}
   559  		return string(p.buf)
   560  	}
   561  
   562  	return ""
   563  }
   564  
   565  func (p *importer) marker(want byte) {
   566  	if got := p.byte(); got != want {
   567  		panic(fmt.Sprintf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read))
   568  	}
   569  
   570  	pos := p.read
   571  	if n := int(p.rawInt64()); n != pos {
   572  		panic(fmt.Sprintf("incorrect position: got %d; want %d", n, pos))
   573  	}
   574  }
   575  
   576  // rawInt64 should only be used by low-level decoders
   577  func (p *importer) rawInt64() int64 {
   578  	i, err := binary.ReadVarint(p)
   579  	if err != nil {
   580  		panic(fmt.Sprintf("read error: %v", err))
   581  	}
   582  	return i
   583  }
   584  
   585  // needed for binary.ReadVarint in rawInt64
   586  func (p *importer) ReadByte() (byte, error) {
   587  	return p.byte(), nil
   588  }
   589  
   590  // byte is the bottleneck interface for reading p.data.
   591  // It unescapes '|' 'S' to '$' and '|' '|' to '|'.
   592  func (p *importer) byte() byte {
   593  	b := p.data[0]
   594  	r := 1
   595  	if b == '|' {
   596  		b = p.data[1]
   597  		r = 2
   598  		switch b {
   599  		case 'S':
   600  			b = '$'
   601  		case '|':
   602  			// nothing to do
   603  		default:
   604  			panic("unexpected escape sequence in export data")
   605  		}
   606  	}
   607  	p.data = p.data[r:]
   608  	p.read += r
   609  	return b
   610  
   611  }
   612  
   613  // ----------------------------------------------------------------------------
   614  // Export format
   615  
   616  // Tags. Must be < 0.
   617  const (
   618  	// Packages
   619  	packageTag = -(iota + 1)
   620  
   621  	// Types
   622  	namedTag
   623  	arrayTag
   624  	sliceTag
   625  	dddTag
   626  	structTag
   627  	pointerTag
   628  	signatureTag
   629  	interfaceTag
   630  	mapTag
   631  	chanTag
   632  
   633  	// Values
   634  	falseTag
   635  	trueTag
   636  	int64Tag
   637  	floatTag
   638  	fractionTag // not used by gc
   639  	complexTag
   640  	stringTag
   641  )
   642  
   643  var predeclared = []types.Type{
   644  	// basic types
   645  	types.Typ[types.Bool],
   646  	types.Typ[types.Int],
   647  	types.Typ[types.Int8],
   648  	types.Typ[types.Int16],
   649  	types.Typ[types.Int32],
   650  	types.Typ[types.Int64],
   651  	types.Typ[types.Uint],
   652  	types.Typ[types.Uint8],
   653  	types.Typ[types.Uint16],
   654  	types.Typ[types.Uint32],
   655  	types.Typ[types.Uint64],
   656  	types.Typ[types.Uintptr],
   657  	types.Typ[types.Float32],
   658  	types.Typ[types.Float64],
   659  	types.Typ[types.Complex64],
   660  	types.Typ[types.Complex128],
   661  	types.Typ[types.String],
   662  
   663  	// aliases
   664  	types.Universe.Lookup("byte").Type(),
   665  	types.Universe.Lookup("rune").Type(),
   666  
   667  	// error
   668  	types.Universe.Lookup("error").Type(),
   669  
   670  	// untyped types
   671  	types.Typ[types.UntypedBool],
   672  	types.Typ[types.UntypedInt],
   673  	types.Typ[types.UntypedRune],
   674  	types.Typ[types.UntypedFloat],
   675  	types.Typ[types.UntypedComplex],
   676  	types.Typ[types.UntypedString],
   677  	types.Typ[types.UntypedNil],
   678  
   679  	// package unsafe
   680  	types.Typ[types.UnsafePointer],
   681  }