Home | History | Annotate | Download | only in gcimporter
      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" }
    992