github.com/llvm-mirror/llgo@v0.0.0-20190322182713-bf6f0a60fce1/third_party/gotools/go/importer/export.go (about)

     1  // Copyright 2013 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 importer
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/binary"
    10  	"fmt"
    11  	"go/ast"
    12  	"strings"
    13  
    14  	"llvm.org/llgo/third_party/gotools/go/exact"
    15  	"llvm.org/llgo/third_party/gotools/go/types"
    16  )
    17  
    18  // debugging support
    19  const (
    20  	debug = false // emit debugging data
    21  	trace = false // print emitted data
    22  )
    23  
    24  // format returns a byte indicating the low-level encoding/decoding format
    25  // (debug vs product).
    26  func format() byte {
    27  	if debug {
    28  		return 'd'
    29  	}
    30  	return 'p'
    31  }
    32  
    33  // ExportData serializes the interface (exported package objects)
    34  // of package pkg and returns the corresponding data. The export
    35  // format is described elsewhere (TODO).
    36  func ExportData(pkg *types.Package) []byte {
    37  	p := exporter{
    38  		data:     append([]byte(magic), format()),
    39  		pkgIndex: make(map[*types.Package]int),
    40  		typIndex: make(map[types.Type]int),
    41  	}
    42  
    43  	// populate typIndex with predeclared types
    44  	for _, t := range predeclared {
    45  		p.typIndex[t] = len(p.typIndex)
    46  	}
    47  
    48  	if trace {
    49  		p.tracef("export %s\n", pkg.Name())
    50  		defer p.tracef("\n")
    51  	}
    52  
    53  	p.string(version)
    54  
    55  	p.pkg(pkg)
    56  
    57  	// collect exported objects from package scope
    58  	var list []types.Object
    59  	scope := pkg.Scope()
    60  	for _, name := range scope.Names() {
    61  		if exported(name) {
    62  			list = append(list, scope.Lookup(name))
    63  		}
    64  	}
    65  
    66  	// write objects
    67  	p.int(len(list))
    68  	for _, obj := range list {
    69  		p.obj(obj)
    70  	}
    71  
    72  	return p.data
    73  }
    74  
    75  type exporter struct {
    76  	data     []byte
    77  	pkgIndex map[*types.Package]int
    78  	typIndex map[types.Type]int
    79  
    80  	// tracing support
    81  	indent string
    82  }
    83  
    84  func (p *exporter) pkg(pkg *types.Package) {
    85  	if trace {
    86  		p.tracef("package { ")
    87  		defer p.tracef("} ")
    88  	}
    89  
    90  	if pkg == nil {
    91  		panic("unexpected nil pkg")
    92  	}
    93  
    94  	// if the package was seen before, write its index (>= 0)
    95  	if i, ok := p.pkgIndex[pkg]; ok {
    96  		p.int(i)
    97  		return
    98  	}
    99  	p.pkgIndex[pkg] = len(p.pkgIndex)
   100  
   101  	// otherwise, write the package tag (< 0) and package data
   102  	p.int(packageTag)
   103  	p.string(pkg.Name())
   104  	p.string(pkg.Path())
   105  }
   106  
   107  func (p *exporter) obj(obj types.Object) {
   108  	if trace {
   109  		p.tracef("object %s {\n", obj.Name())
   110  		defer p.tracef("}\n")
   111  	}
   112  
   113  	switch obj := obj.(type) {
   114  	case *types.Const:
   115  		p.int(constTag)
   116  		p.string(obj.Name())
   117  		p.typ(obj.Type())
   118  		p.value(obj.Val())
   119  	case *types.TypeName:
   120  		p.int(typeTag)
   121  		// name is written by corresponding named type
   122  		p.typ(obj.Type().(*types.Named))
   123  	case *types.Var:
   124  		p.int(varTag)
   125  		p.string(obj.Name())
   126  		p.typ(obj.Type())
   127  	case *types.Func:
   128  		p.int(funcTag)
   129  		p.string(obj.Name())
   130  		p.typ(obj.Type())
   131  	default:
   132  		panic(fmt.Sprintf("unexpected object type %T", obj))
   133  	}
   134  }
   135  
   136  func (p *exporter) value(x exact.Value) {
   137  	if trace {
   138  		p.tracef("value { ")
   139  		defer p.tracef("} ")
   140  	}
   141  
   142  	switch kind := x.Kind(); kind {
   143  	case exact.Bool:
   144  		tag := falseTag
   145  		if exact.BoolVal(x) {
   146  			tag = trueTag
   147  		}
   148  		p.int(tag)
   149  	case exact.Int:
   150  		if i, ok := exact.Int64Val(x); ok {
   151  			p.int(int64Tag)
   152  			p.int64(i)
   153  			return
   154  		}
   155  		p.int(floatTag)
   156  		p.float(x)
   157  	case exact.Float:
   158  		p.int(fractionTag)
   159  		p.fraction(x)
   160  	case exact.Complex:
   161  		p.int(complexTag)
   162  		p.fraction(exact.Real(x))
   163  		p.fraction(exact.Imag(x))
   164  	case exact.String:
   165  		p.int(stringTag)
   166  		p.string(exact.StringVal(x))
   167  	default:
   168  		panic(fmt.Sprintf("unexpected value kind %d", kind))
   169  	}
   170  }
   171  
   172  func (p *exporter) float(x exact.Value) {
   173  	sign := exact.Sign(x)
   174  	p.int(sign)
   175  	if sign == 0 {
   176  		return
   177  	}
   178  
   179  	p.ufloat(x)
   180  }
   181  
   182  func (p *exporter) fraction(x exact.Value) {
   183  	sign := exact.Sign(x)
   184  	p.int(sign)
   185  	if sign == 0 {
   186  		return
   187  	}
   188  
   189  	p.ufloat(exact.Num(x))
   190  	p.ufloat(exact.Denom(x))
   191  }
   192  
   193  // ufloat writes abs(x) in form of a binary exponent
   194  // followed by its mantissa bytes; x must be != 0.
   195  func (p *exporter) ufloat(x exact.Value) {
   196  	mant := exact.Bytes(x)
   197  	exp8 := -1
   198  	for i, b := range mant {
   199  		if b != 0 {
   200  			exp8 = i
   201  			break
   202  		}
   203  	}
   204  	if exp8 < 0 {
   205  		panic(fmt.Sprintf("%s has no mantissa", x))
   206  	}
   207  	p.int(exp8 * 8)
   208  	p.bytes(mant[exp8:])
   209  }
   210  
   211  func (p *exporter) typ(typ types.Type) {
   212  	if trace {
   213  		p.tracef("type {\n")
   214  		defer p.tracef("}\n")
   215  	}
   216  
   217  	// if the type was seen before, write its index (>= 0)
   218  	if i, ok := p.typIndex[typ]; ok {
   219  		p.int(i)
   220  		return
   221  	}
   222  	p.typIndex[typ] = len(p.typIndex)
   223  
   224  	// otherwise, write the type tag (< 0) and type data
   225  	switch t := typ.(type) {
   226  	case *types.Array:
   227  		p.int(arrayTag)
   228  		p.int64(t.Len())
   229  		p.typ(t.Elem())
   230  
   231  	case *types.Slice:
   232  		p.int(sliceTag)
   233  		p.typ(t.Elem())
   234  
   235  	case *types.Struct:
   236  		p.int(structTag)
   237  		n := t.NumFields()
   238  		p.int(n)
   239  		for i := 0; i < n; i++ {
   240  			p.field(t.Field(i))
   241  			p.string(t.Tag(i))
   242  		}
   243  
   244  	case *types.Pointer:
   245  		p.int(pointerTag)
   246  		p.typ(t.Elem())
   247  
   248  	case *types.Signature:
   249  		p.int(signatureTag)
   250  		p.signature(t)
   251  
   252  	case *types.Interface:
   253  		p.int(interfaceTag)
   254  
   255  		// write embedded interfaces
   256  		m := t.NumEmbeddeds()
   257  		p.int(m)
   258  		for i := 0; i < m; i++ {
   259  			p.typ(t.Embedded(i))
   260  		}
   261  
   262  		// write methods
   263  		n := t.NumExplicitMethods()
   264  		p.int(n)
   265  		for i := 0; i < n; i++ {
   266  			m := t.ExplicitMethod(i)
   267  			p.qualifiedName(m.Pkg(), m.Name())
   268  			p.typ(m.Type())
   269  		}
   270  
   271  	case *types.Map:
   272  		p.int(mapTag)
   273  		p.typ(t.Key())
   274  		p.typ(t.Elem())
   275  
   276  	case *types.Chan:
   277  		p.int(chanTag)
   278  		p.int(int(t.Dir()))
   279  		p.typ(t.Elem())
   280  
   281  	case *types.Named:
   282  		p.int(namedTag)
   283  
   284  		// write type object
   285  		obj := t.Obj()
   286  		p.string(obj.Name())
   287  		p.pkg(obj.Pkg())
   288  
   289  		// write underlying type
   290  		p.typ(t.Underlying())
   291  
   292  		// write associated methods
   293  		n := t.NumMethods()
   294  		p.int(n)
   295  		for i := 0; i < n; i++ {
   296  			m := t.Method(i)
   297  			p.string(m.Name())
   298  			p.typ(m.Type())
   299  		}
   300  
   301  	default:
   302  		panic("unreachable")
   303  	}
   304  }
   305  
   306  func (p *exporter) field(f *types.Var) {
   307  	// anonymous fields have "" name
   308  	name := ""
   309  	if !f.Anonymous() {
   310  		name = f.Name()
   311  	}
   312  
   313  	// qualifiedName will always emit the field package for
   314  	// anonymous fields because "" is not an exported name.
   315  	p.qualifiedName(f.Pkg(), name)
   316  	p.typ(f.Type())
   317  }
   318  
   319  func (p *exporter) qualifiedName(pkg *types.Package, name string) {
   320  	p.string(name)
   321  	// exported names don't need package
   322  	if !exported(name) {
   323  		if pkg == nil {
   324  			panic(fmt.Sprintf("nil package for unexported qualified name %s", name))
   325  		}
   326  		p.pkg(pkg)
   327  	}
   328  }
   329  
   330  func (p *exporter) signature(sig *types.Signature) {
   331  	// We need the receiver information (T vs *T)
   332  	// for methods associated with named types.
   333  	// We do not record interface receiver types in the
   334  	// export data because 1) the importer can derive them
   335  	// from the interface type and 2) they create cycles
   336  	// in the type graph.
   337  	if recv := sig.Recv(); recv != nil {
   338  		if _, ok := recv.Type().Underlying().(*types.Interface); !ok {
   339  			// 1-element tuple
   340  			p.int(1)
   341  			p.param(recv)
   342  		} else {
   343  			// 0-element tuple
   344  			p.int(0)
   345  		}
   346  	} else {
   347  		// 0-element tuple
   348  		p.int(0)
   349  	}
   350  	p.tuple(sig.Params())
   351  	p.tuple(sig.Results())
   352  	if sig.Variadic() {
   353  		p.int(1)
   354  	} else {
   355  		p.int(0)
   356  	}
   357  }
   358  
   359  func (p *exporter) param(v *types.Var) {
   360  	p.string(v.Name())
   361  	p.typ(v.Type())
   362  }
   363  
   364  func (p *exporter) tuple(t *types.Tuple) {
   365  	n := t.Len()
   366  	p.int(n)
   367  	for i := 0; i < n; i++ {
   368  		p.param(t.At(i))
   369  	}
   370  }
   371  
   372  // ----------------------------------------------------------------------------
   373  // encoders
   374  
   375  func (p *exporter) string(s string) {
   376  	p.bytes([]byte(s)) // (could be inlined if extra allocation matters)
   377  }
   378  
   379  func (p *exporter) int(x int) {
   380  	p.int64(int64(x))
   381  }
   382  
   383  func (p *exporter) int64(x int64) {
   384  	if debug {
   385  		p.marker('i')
   386  	}
   387  
   388  	if trace {
   389  		p.tracef("%d ", x)
   390  	}
   391  
   392  	p.rawInt64(x)
   393  }
   394  
   395  func (p *exporter) bytes(b []byte) {
   396  	if debug {
   397  		p.marker('b')
   398  	}
   399  
   400  	if trace {
   401  		p.tracef("%q ", b)
   402  	}
   403  
   404  	p.rawInt64(int64(len(b)))
   405  	if len(b) > 0 {
   406  		p.data = append(p.data, b...)
   407  	}
   408  }
   409  
   410  // marker emits a marker byte and position information which makes
   411  // it easy for a reader to detect if it is "out of sync". Used for
   412  // debug format only.
   413  func (p *exporter) marker(m byte) {
   414  	if debug {
   415  		p.data = append(p.data, m)
   416  		p.rawInt64(int64(len(p.data)))
   417  	}
   418  }
   419  
   420  // rawInt64 should only be used by low-level encoders
   421  func (p *exporter) rawInt64(x int64) {
   422  	var tmp [binary.MaxVarintLen64]byte
   423  	n := binary.PutVarint(tmp[:], x)
   424  	p.data = append(p.data, tmp[:n]...)
   425  }
   426  
   427  // utility functions
   428  
   429  func (p *exporter) tracef(format string, args ...interface{}) {
   430  	// rewrite format string to take care of indentation
   431  	const indent = ".  "
   432  	if strings.IndexAny(format, "{}\n") >= 0 {
   433  		var buf bytes.Buffer
   434  		for i := 0; i < len(format); i++ {
   435  			// no need to deal with runes
   436  			ch := format[i]
   437  			switch ch {
   438  			case '{':
   439  				p.indent += indent
   440  			case '}':
   441  				p.indent = p.indent[:len(p.indent)-len(indent)]
   442  				if i+1 < len(format) && format[i+1] == '\n' {
   443  					buf.WriteByte('\n')
   444  					buf.WriteString(p.indent)
   445  					buf.WriteString("} ")
   446  					i++
   447  					continue
   448  				}
   449  			}
   450  			buf.WriteByte(ch)
   451  			if ch == '\n' {
   452  				buf.WriteString(p.indent)
   453  			}
   454  		}
   455  		format = buf.String()
   456  	}
   457  	fmt.Printf(format, args...)
   458  }
   459  
   460  func exported(name string) bool {
   461  	return ast.IsExported(name)
   462  }