GoPLS Viewer

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