blob: 2045f5517b123e3240d8b893351b6f6e34eb36d4 [file] [log] [blame]
Dan Willemsen38f2dba2016-07-08 14:54:35 -07001// 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
5package gcimporter
6
7import (
8 "encoding/binary"
9 "fmt"
10 "go/constant"
11 "go/token"
12 "go/types"
13 "sort"
Dan Willemsenebae3022017-01-13 23:01:08 -080014 "strconv"
Dan Willemsen38f2dba2016-07-08 14:54:35 -070015 "strings"
Dan Willemsenebae3022017-01-13 23:01:08 -080016 "sync"
Dan Willemsen38f2dba2016-07-08 14:54:35 -070017 "unicode"
18 "unicode/utf8"
19)
20
21type importer struct {
Dan Willemsend2797482017-07-26 13:13:13 -070022 imports map[string]*types.Package
23 data []byte
24 importpath string
25 buf []byte // for reading strings
26 version int // export format version
Dan Willemsen38f2dba2016-07-08 14:54:35 -070027
28 // object lists
Dan Willemsend2797482017-07-26 13:13:13 -070029 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
Dan Willemsen38f2dba2016-07-08 14:54:35 -070034 trackAllTypes bool
35
36 // position encoding
37 posInfoFormat bool
38 prevFile string
39 prevLine int
Dan Willemsenebae3022017-01-13 23:01:08 -080040 fset *token.FileSet
41 files map[string]*token.File
Dan Willemsen38f2dba2016-07-08 14:54:35 -070042
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.
Dan Willemsenebae3022017-01-13 23:01:08 -080050// If the export data version is not recognized or the format is otherwise
51// compromised, an error is returned.
Dan Willemsend2797482017-07-26 13:13:13 -070052func BImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
Dan Willemsenebae3022017-01-13 23:01:08 -080053 // 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).
Dan Willemsend2797482017-07-26 13:13:13 -070058 // Return a (possibly nil or incomplete) package unchanged (see #16088).
Dan Willemsenebae3022017-01-13 23:01:08 -080059 err = fmt.Errorf("cannot import, possibly version skew (%v) - reinstall package", e)
60 }
61 }()
62
Dan Willemsen38f2dba2016-07-08 14:54:35 -070063 p := importer{
Dan Willemsend2797482017-07-26 13:13:13 -070064 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),
Dan Willemsen38f2dba2016-07-08 14:54:35 -070072 }
73
Dan Willemsenebae3022017-01-13 23:01:08 -080074 // 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 {
Dan Willemsend2797482017-07-26 13:13:13 -0700105 // case 6:
Dan Willemsenebae3022017-01-13 23:01:08 -0800106 // ...
107 // fallthrough
Dan Willemsend2797482017-07-26 13:13:13 -0700108 case 5, 4, 3, 2, 1:
Dan Willemsenebae3022017-01-13 23:01:08 -0800109 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
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700114 default:
Dan Willemsenebae3022017-01-13 23:01:08 -0800115 errorf("unknown export format version %d (%q)", p.version, versionstr)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700116 }
117
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700118 // --- generic export data ---
119
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700120 // populate typList with predeclared "known" types
121 p.typList = append(p.typList, predeclared...)
122
123 // read package data
Dan Willemsend2797482017-07-26 13:13:13 -0700124 pkg = p.pkg()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700125
126 // read objects of phase 1 only (see cmd/compiler/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 {
Dan Willemsenebae3022017-01-13 23:01:08 -0800139 errorf("got %d objects; want %d", objcount, count)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700140 }
141
142 // ignore compiler-specific import data
143
144 // complete interfaces
Dan Willemsend2797482017-07-26 13:13:13 -0700145 // TODO(gri) re-investigate if we still need to do this in a delayed fashion
146 for _, typ := range p.interfaceList {
147 typ.Complete()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700148 }
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
Dan Willemsenebae3022017-01-13 23:01:08 -0800161func errorf(format string, args ...interface{}) {
162 panic(fmt.Sprintf(format, args...))
163}
164
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700165func (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 {
Dan Willemsend2797482017-07-26 13:13:13 -0700174 errorf("unexpected package tag %d version %d", i, p.version)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700175 }
176
177 // read package data
178 name := p.string()
Dan Willemsend2797482017-07-26 13:13:13 -0700179 var path string
180 if p.version >= 5 {
181 path = p.path()
182 } else {
183 path = p.string()
184 }
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700185
186 // we should never see an empty package name
187 if name == "" {
Dan Willemsenebae3022017-01-13 23:01:08 -0800188 errorf("empty package name in import")
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700189 }
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) {
Dan Willemsenebae3022017-01-13 23:01:08 -0800194 errorf("package path %q for pkg index %d", path, len(p.pkgList))
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700195 }
196
197 // if the package was imported before, use that one; otherwise create a new one
198 if path == "" {
Dan Willemsend2797482017-07-26 13:13:13 -0700199 path = p.importpath
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700200 }
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 {
Dan Willemsenebae3022017-01-13 23:01:08 -0800206 errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700207 }
208 p.pkgList = append(p.pkgList, pkg)
209
210 return pkg
211}
212
Dan Willemsenebae3022017-01-13 23:01:08 -0800213// objTag returns the tag value for each object kind.
Dan Willemsenebae3022017-01-13 23:01:08 -0800214func 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
Dan Willemsenebae3022017-01-13 23:01:08 -0800224 default:
225 errorf("unexpected object: %v (%T)", obj, obj) // panics
226 panic("unreachable")
227 }
228}
229
230func 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
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700237func (p *importer) declare(obj types.Object) {
238 pkg := obj.Pkg()
239 if alt := pkg.Scope().Insert(obj); alt != nil {
Dan Willemsenebae3022017-01-13 23:01:08 -0800240 // This can only trigger if we import a (non-type) object a second time.
Dan Willemsend2797482017-07-26 13:13:13 -0700241 // Excluding type aliases, this cannot happen because 1) we only import a package
Dan Willemsenebae3022017-01-13 23:01:08 -0800242 // 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.
Dan Willemsend2797482017-07-26 13:13:13 -0700245 // However, type aliases require reexporting the original type, so we need
Dan Willemsenebae3022017-01-13 23:01:08 -0800246 // to allow it (see also the comment in cmd/compile/internal/gc/bimport.go,
247 // method importer.obj, switch case importing functions).
Dan Willemsend2797482017-07-26 13:13:13 -0700248 // TODO(gri) review/update this comment once the gc compiler handles type aliases.
Dan Willemsenebae3022017-01-13 23:01:08 -0800249 if !sameObj(obj, alt) {
250 errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", obj, alt)
251 }
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700252 }
253}
254
255func (p *importer) obj(tag int) {
256 switch tag {
257 case constTag:
Dan Willemsenebae3022017-01-13 23:01:08 -0800258 pos := p.pos()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700259 pkg, name := p.qualifiedName()
260 typ := p.typ(nil)
261 val := p.value()
Dan Willemsenebae3022017-01-13 23:01:08 -0800262 p.declare(types.NewConst(pos, pkg, name, typ, val))
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700263
Dan Willemsend2797482017-07-26 13:13:13 -0700264 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
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700271 case typeTag:
Dan Willemsenebae3022017-01-13 23:01:08 -0800272 p.typ(nil)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700273
274 case varTag:
Dan Willemsenebae3022017-01-13 23:01:08 -0800275 pos := p.pos()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700276 pkg, name := p.qualifiedName()
277 typ := p.typ(nil)
Dan Willemsenebae3022017-01-13 23:01:08 -0800278 p.declare(types.NewVar(pos, pkg, name, typ))
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700279
280 case funcTag:
Dan Willemsenebae3022017-01-13 23:01:08 -0800281 pos := p.pos()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700282 pkg, name := p.qualifiedName()
283 params, isddd := p.paramList()
284 result, _ := p.paramList()
285 sig := types.NewSignature(nil, params, result, isddd)
Dan Willemsenebae3022017-01-13 23:01:08 -0800286 p.declare(types.NewFunc(pos, pkg, name, sig))
287
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700288 default:
Dan Willemsenebae3022017-01-13 23:01:08 -0800289 errorf("unexpected object tag %d", tag)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700290 }
291}
292
Dan Willemsend2797482017-07-26 13:13:13 -0700293const deltaNewFile = -64 // see cmd/compile/internal/gc/bexport.go
294
Dan Willemsenebae3022017-01-13 23:01:08 -0800295func (p *importer) pos() token.Pos {
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700296 if !p.posInfoFormat {
Dan Willemsenebae3022017-01-13 23:01:08 -0800297 return token.NoPos
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700298 }
299
300 file := p.prevFile
301 line := p.prevLine
Dan Willemsend2797482017-07-26 13:13:13 -0700302 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 }
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700320 }
Dan Willemsend2797482017-07-26 13:13:13 -0700321 p.prevFile = file
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700322 p.prevLine = line
323
Dan Willemsenebae3022017-01-13 23:01:08 -0800324 // 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)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700351}
352
Dan Willemsenebae3022017-01-13 23:01:08 -0800353var (
354 fakeLines []int
355 fakeLinesOnce sync.Once
356)
357
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700358func (p *importer) qualifiedName() (pkg *types.Package, name string) {
359 name = p.string()
Dan Willemsend2797482017-07-26 13:13:13 -0700360 pkg = p.pkg()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700361 return
362}
363
364func (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.
371type dddSlice struct {
372 elem types.Type
373}
374
375func (t *dddSlice) Underlying() types.Type { return t }
376func (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.
382func (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
Dan Willemsenebae3022017-01-13 23:01:08 -0800393 pos := p.pos()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700394 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 {
Dan Willemsenebae3022017-01-13 23:01:08 -0800400 obj = types.NewTypeName(pos, parent, name, nil)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700401 scope.Insert(obj)
402 }
403
404 if _, ok := obj.(*types.TypeName); !ok {
Dan Willemsenebae3022017-01-13 23:01:08 -0800405 errorf("pkg = %s, name = %s => %s", parent, name, obj)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700406 }
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
Dan Willemsenebae3022017-01-13 23:01:08 -0800426 pos := p.pos()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700427 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()
Dan Willemsenebae3022017-01-13 23:01:08 -0800435 p.int() // go:nointerface pragma - discarded
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700436
437 sig := types.NewSignature(recv.At(0), params, result, isddd)
Dan Willemsenebae3022017-01-13 23:01:08 -0800438 t0.AddMethod(types.NewFunc(pos, parent, name, sig))
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700439 }
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
Dan Willemsend2797482017-07-26 13:13:13 -0700510 var embeddeds []*types.Named
511 for n := p.int(); n > 0; n-- {
512 p.pos()
513 embeddeds = append(embeddeds, p.typ(parent).(*types.Named))
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700514 }
515
Dan Willemsend2797482017-07-26 13:13:13 -0700516 t := types.NewInterface(p.methodList(parent), embeddeds)
517 p.interfaceList = append(p.interfaceList, t)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700518 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:
Dan Willemsenebae3022017-01-13 23:01:08 -0800550 errorf("unexpected channel dir %d", d)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700551 }
552 val := p.typ(parent)
553 *t = *types.NewChan(dir, val)
554 return t
555
556 default:
Dan Willemsenebae3022017-01-13 23:01:08 -0800557 errorf("unexpected type tag %d", i) // panics
558 panic("unreachable")
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700559 }
560}
561
562func (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 {
Dan Willemsend2797482017-07-26 13:13:13 -0700567 fields[i], tags[i] = p.field(parent)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700568 }
569 }
570 return
571}
572
Dan Willemsend2797482017-07-26 13:13:13 -0700573func (p *importer) field(parent *types.Package) (*types.Var, string) {
Dan Willemsenebae3022017-01-13 23:01:08 -0800574 pos := p.pos()
Dan Willemsend2797482017-07-26 13:13:13 -0700575 pkg, name, alias := p.fieldName(parent)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700576 typ := p.typ(parent)
Dan Willemsend2797482017-07-26 13:13:13 -0700577 tag := p.string()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700578
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:
Dan Willemsend2797482017-07-26 13:13:13 -0700589 errorf("named base type expected")
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700590 }
591 anonymous = true
Dan Willemsend2797482017-07-26 13:13:13 -0700592 } else if alias {
593 // anonymous field: we have an explicit name because it's an alias
594 anonymous = true
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700595 }
596
Dan Willemsend2797482017-07-26 13:13:13 -0700597 return types.NewField(pos, pkg, name, typ, anonymous), tag
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700598}
599
600func (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
610func (p *importer) method(parent *types.Package) *types.Func {
Dan Willemsenebae3022017-01-13 23:01:08 -0800611 pos := p.pos()
Dan Willemsend2797482017-07-26 13:13:13 -0700612 pkg, name, _ := p.fieldName(parent)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700613 params, isddd := p.paramList()
614 result, _ := p.paramList()
615 sig := types.NewSignature(nil, params, result, isddd)
Dan Willemsenebae3022017-01-13 23:01:08 -0800616 return types.NewFunc(pos, pkg, name, sig)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700617}
618
Dan Willemsend2797482017-07-26 13:13:13 -0700619func (p *importer) fieldName(parent *types.Package) (pkg *types.Package, name string, alias bool) {
620 name = p.string()
621 pkg = parent
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700622 if pkg == nil {
623 // use the imported package instead
624 pkg = p.pkgList[0]
625 }
Dan Willemsenebae3022017-01-13 23:01:08 -0800626 if p.version == 0 && name == "_" {
627 // version 0 didn't export a package for _ fields
Dan Willemsend2797482017-07-26 13:13:13 -0700628 return
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700629 }
Dan Willemsend2797482017-07-26 13:13:13 -0700630 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 = ""
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700636 pkg = p.pkg()
Dan Willemsend2797482017-07-26 13:13:13 -0700637 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 }
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700646 }
Dan Willemsend2797482017-07-26 13:13:13 -0700647 return
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700648}
649
650func (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
670func (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 == "" {
Dan Willemsenebae3022017-01-13 23:01:08 -0800682 errorf("expected named parameter")
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700683 }
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
698func exported(name string) bool {
699 ch, _ := utf8.DecodeRuneInString(name)
700 return unicode.IsUpper(ch)
701}
702
703func (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())
Dan Willemsenebae3022017-01-13 23:01:08 -0800719 case unknownTag:
720 return constant.MakeUnknown()
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700721 default:
Dan Willemsenebae3022017-01-13 23:01:08 -0800722 errorf("unexpected value tag %d", tag) // panics
723 panic("unreachable")
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700724 }
725}
726
727func (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
775func (p *importer) tagOrIndex() int {
776 if p.debugFormat {
777 p.marker('t')
778 }
779
780 return int(p.rawInt64())
781}
782
783func (p *importer) int() int {
784 x := p.int64()
785 if int64(int(x)) != x {
Dan Willemsenebae3022017-01-13 23:01:08 -0800786 errorf("exported integer too large")
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700787 }
788 return int(x)
789}
790
791func (p *importer) int64() int64 {
792 if p.debugFormat {
793 p.marker('i')
794 }
795
796 return p.rawInt64()
797}
798
Dan Willemsend2797482017-07-26 13:13:13 -0700799func (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
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700819func (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
843func (p *importer) marker(want byte) {
844 if got := p.rawByte(); got != want {
Dan Willemsenebae3022017-01-13 23:01:08 -0800845 errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700846 }
847
848 pos := p.read
849 if n := int(p.rawInt64()); n != pos {
Dan Willemsenebae3022017-01-13 23:01:08 -0800850 errorf("incorrect position: got %d; want %d", n, pos)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700851 }
852}
853
Dan Willemsenebae3022017-01-13 23:01:08 -0800854// rawInt64 should only be used by low-level decoders.
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700855func (p *importer) rawInt64() int64 {
856 i, err := binary.ReadVarint(p)
857 if err != nil {
Dan Willemsenebae3022017-01-13 23:01:08 -0800858 errorf("read error: %v", err)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700859 }
860 return i
861}
862
Dan Willemsenebae3022017-01-13 23:01:08 -0800863// rawStringln should only be used to read the initial version string.
864func (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
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700873// needed for binary.ReadVarint in rawInt64
874func (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.
881func (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:
Dan Willemsenebae3022017-01-13 23:01:08 -0800893 errorf("unexpected escape sequence in export data")
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700894 }
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.
906const (
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
Dan Willemsenebae3022017-01-13 23:01:08 -0800935 nilTag // only used by gc (appears in exported inlined function bodies)
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700936 unknownTag // not used by gc (only appears in packages with errors)
Dan Willemsenebae3022017-01-13 23:01:08 -0800937
Dan Willemsend2797482017-07-26 13:13:13 -0700938 // Type aliases
Dan Willemsenebae3022017-01-13 23:01:08 -0800939 aliasTag
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700940)
941
942var 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
Dan Willemsend2797482017-07-26 13:13:13 -0700962 // basic type aliases
Dan Willemsen38f2dba2016-07-08 14:54:35 -0700963 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
988type anyType struct{}
989
990func (t anyType) Underlying() types.Type { return t }
991func (t anyType) String() string { return "any" }