]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgo/go/go/internal/gcimporter/iimport.go
libgo: update to Go1.14beta1
[thirdparty/gcc.git] / libgo / go / go / internal / gcimporter / iimport.go
CommitLineData
dd931d9b
ILT
1// Copyright 2018 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// Indexed package import.
6// See cmd/compile/internal/gc/iexport.go for the export data format.
7
8package gcimporter
9
10import (
11 "bytes"
12 "encoding/binary"
13 "fmt"
14 "go/constant"
15 "go/token"
16 "go/types"
17 "io"
18 "sort"
19)
20
21type intReader struct {
22 *bytes.Reader
23 path string
24}
25
26func (r *intReader) int64() int64 {
27 i, err := binary.ReadVarint(r.Reader)
28 if err != nil {
29 errorf("import %q: read varint error: %v", r.path, err)
30 }
31 return i
32}
33
34func (r *intReader) uint64() uint64 {
35 i, err := binary.ReadUvarint(r.Reader)
36 if err != nil {
37 errorf("import %q: read varint error: %v", r.path, err)
38 }
39 return i
40}
41
42const predeclReserved = 32
43
44type itag uint64
45
46const (
47 // Types
48 definedType itag = iota
49 pointerType
50 sliceType
51 arrayType
52 chanType
53 mapType
54 signatureType
55 structType
56 interfaceType
57)
58
59// iImportData imports a package from the serialized package data
60// and returns the number of bytes consumed and a reference to the package.
61// If the export data version is not recognized or the format is otherwise
62// compromised, an error is returned.
63func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
5a8ea165
ILT
64 const currentVersion = 1
65 version := int64(-1)
dd931d9b
ILT
66 defer func() {
67 if e := recover(); e != nil {
68 if version > currentVersion {
69 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e)
70 } else {
71 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e)
72 }
73 }
74 }()
75
76 r := &intReader{bytes.NewReader(data), path}
77
5a8ea165 78 version = int64(r.uint64())
dd931d9b 79 switch version {
5a8ea165 80 case currentVersion, 0:
dd931d9b
ILT
81 default:
82 errorf("unknown iexport format version %d", version)
83 }
84
85 sLen := int64(r.uint64())
86 dLen := int64(r.uint64())
87
88 whence, _ := r.Seek(0, io.SeekCurrent)
89 stringData := data[whence : whence+sLen]
90 declData := data[whence+sLen : whence+sLen+dLen]
91 r.Seek(sLen+dLen, io.SeekCurrent)
92
93 p := iimporter{
5a8ea165
ILT
94 ipath: path,
95 version: int(version),
dd931d9b
ILT
96
97 stringData: stringData,
98 stringCache: make(map[uint64]string),
99 pkgCache: make(map[uint64]*types.Package),
100
101 declData: declData,
102 pkgIndex: make(map[*types.Package]map[string]uint64),
103 typCache: make(map[uint64]types.Type),
104
105 fake: fakeFileSet{
106 fset: fset,
107 files: make(map[string]*token.File),
108 },
109 }
110
111 for i, pt := range predeclared {
112 p.typCache[uint64(i)] = pt
113 }
114
115 pkgList := make([]*types.Package, r.uint64())
116 for i := range pkgList {
117 pkgPathOff := r.uint64()
118 pkgPath := p.stringAt(pkgPathOff)
119 pkgName := p.stringAt(r.uint64())
120 _ = r.uint64() // package height; unused by go/types
121
122 if pkgPath == "" {
123 pkgPath = path
124 }
125 pkg := imports[pkgPath]
126 if pkg == nil {
127 pkg = types.NewPackage(pkgPath, pkgName)
128 imports[pkgPath] = pkg
129 } else if pkg.Name() != pkgName {
130 errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path)
131 }
132
133 p.pkgCache[pkgPathOff] = pkg
134
135 nameIndex := make(map[string]uint64)
136 for nSyms := r.uint64(); nSyms > 0; nSyms-- {
137 name := p.stringAt(r.uint64())
138 nameIndex[name] = r.uint64()
139 }
140
141 p.pkgIndex[pkg] = nameIndex
142 pkgList[i] = pkg
143 }
144
145 localpkg := pkgList[0]
146
147 names := make([]string, 0, len(p.pkgIndex[localpkg]))
148 for name := range p.pkgIndex[localpkg] {
149 names = append(names, name)
150 }
151 sort.Strings(names)
152 for _, name := range names {
153 p.doDecl(localpkg, name)
154 }
155
156 for _, typ := range p.interfaceList {
157 typ.Complete()
158 }
159
160 // record all referenced packages as imports
161 list := append(([]*types.Package)(nil), pkgList[1:]...)
162 sort.Sort(byPath(list))
163 localpkg.SetImports(list)
164
165 // package was imported completely and without errors
166 localpkg.MarkComplete()
167
168 consumed, _ := r.Seek(0, io.SeekCurrent)
169 return int(consumed), localpkg, nil
170}
171
172type iimporter struct {
5a8ea165
ILT
173 ipath string
174 version int
dd931d9b
ILT
175
176 stringData []byte
177 stringCache map[uint64]string
178 pkgCache map[uint64]*types.Package
179
180 declData []byte
181 pkgIndex map[*types.Package]map[string]uint64
182 typCache map[uint64]types.Type
183
184 fake fakeFileSet
185 interfaceList []*types.Interface
186}
187
188func (p *iimporter) doDecl(pkg *types.Package, name string) {
189 // See if we've already imported this declaration.
190 if obj := pkg.Scope().Lookup(name); obj != nil {
191 return
192 }
193
194 off, ok := p.pkgIndex[pkg][name]
195 if !ok {
196 errorf("%v.%v not in index", pkg, name)
197 }
198
199 r := &importReader{p: p, currPkg: pkg}
200 r.declReader.Reset(p.declData[off:])
201
202 r.obj(name)
203}
204
205func (p *iimporter) stringAt(off uint64) string {
206 if s, ok := p.stringCache[off]; ok {
207 return s
208 }
209
210 slen, n := binary.Uvarint(p.stringData[off:])
211 if n <= 0 {
212 errorf("varint failed")
213 }
214 spos := off + uint64(n)
215 s := string(p.stringData[spos : spos+slen])
216 p.stringCache[off] = s
217 return s
218}
219
220func (p *iimporter) pkgAt(off uint64) *types.Package {
221 if pkg, ok := p.pkgCache[off]; ok {
222 return pkg
223 }
224 path := p.stringAt(off)
225 errorf("missing package %q in %q", path, p.ipath)
226 return nil
227}
228
229func (p *iimporter) typAt(off uint64, base *types.Named) types.Type {
230 if t, ok := p.typCache[off]; ok && (base == nil || !isInterface(t)) {
231 return t
232 }
233
234 if off < predeclReserved {
235 errorf("predeclared type missing from cache: %v", off)
236 }
237
238 r := &importReader{p: p}
239 r.declReader.Reset(p.declData[off-predeclReserved:])
240 t := r.doType(base)
241
242 if base == nil || !isInterface(t) {
243 p.typCache[off] = t
244 }
245 return t
246}
247
248type importReader struct {
249 p *iimporter
250 declReader bytes.Reader
251 currPkg *types.Package
252 prevFile string
253 prevLine int64
5a8ea165 254 prevColumn int64
dd931d9b
ILT
255}
256
257func (r *importReader) obj(name string) {
258 tag := r.byte()
259 pos := r.pos()
260
261 switch tag {
262 case 'A':
263 typ := r.typ()
264
265 r.declare(types.NewTypeName(pos, r.currPkg, name, typ))
266
267 case 'C':
268 typ, val := r.value()
269
270 r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
271
272 case 'F':
273 sig := r.signature(nil)
274
275 r.declare(types.NewFunc(pos, r.currPkg, name, sig))
276
277 case 'T':
278 // Types can be recursive. We need to setup a stub
279 // declaration before recursing.
280 obj := types.NewTypeName(pos, r.currPkg, name, nil)
281 named := types.NewNamed(obj, nil, nil)
282 r.declare(obj)
283
284 underlying := r.p.typAt(r.uint64(), named).Underlying()
285 named.SetUnderlying(underlying)
286
287 if !isInterface(underlying) {
288 for n := r.uint64(); n > 0; n-- {
289 mpos := r.pos()
290 mname := r.ident()
291 recv := r.param()
292 msig := r.signature(recv)
293
294 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
295 }
296 }
297
298 case 'V':
299 typ := r.typ()
300
301 r.declare(types.NewVar(pos, r.currPkg, name, typ))
302
303 default:
304 errorf("unexpected tag: %v", tag)
305 }
306}
307
308func (r *importReader) declare(obj types.Object) {
309 obj.Pkg().Scope().Insert(obj)
310}
311
312func (r *importReader) value() (typ types.Type, val constant.Value) {
313 typ = r.typ()
314
315 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
316 case types.IsBoolean:
317 val = constant.MakeBool(r.bool())
318
319 case types.IsString:
320 val = constant.MakeString(r.string())
321
322 case types.IsInteger:
323 val = r.mpint(b)
324
325 case types.IsFloat:
326 val = r.mpfloat(b)
327
328 case types.IsComplex:
329 re := r.mpfloat(b)
330 im := r.mpfloat(b)
331 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im))
332
333 default:
334 errorf("unexpected type %v", typ) // panics
335 panic("unreachable")
336 }
337
338 return
339}
340
341func intSize(b *types.Basic) (signed bool, maxBytes uint) {
342 if (b.Info() & types.IsUntyped) != 0 {
343 return true, 64
344 }
345
346 switch b.Kind() {
347 case types.Float32, types.Complex64:
348 return true, 3
349 case types.Float64, types.Complex128:
350 return true, 7
351 }
352
353 signed = (b.Info() & types.IsUnsigned) == 0
354 switch b.Kind() {
355 case types.Int8, types.Uint8:
356 maxBytes = 1
357 case types.Int16, types.Uint16:
358 maxBytes = 2
359 case types.Int32, types.Uint32:
360 maxBytes = 4
361 default:
362 maxBytes = 8
363 }
364
365 return
366}
367
368func (r *importReader) mpint(b *types.Basic) constant.Value {
369 signed, maxBytes := intSize(b)
370
371 maxSmall := 256 - maxBytes
372 if signed {
373 maxSmall = 256 - 2*maxBytes
374 }
375 if maxBytes == 1 {
376 maxSmall = 256
377 }
378
379 n, _ := r.declReader.ReadByte()
380 if uint(n) < maxSmall {
381 v := int64(n)
382 if signed {
383 v >>= 1
384 if n&1 != 0 {
385 v = ^v
386 }
387 }
388 return constant.MakeInt64(v)
389 }
390
391 v := -n
392 if signed {
393 v = -(n &^ 1) >> 1
394 }
395 if v < 1 || uint(v) > maxBytes {
396 errorf("weird decoding: %v, %v => %v", n, signed, v)
397 }
398
399 buf := make([]byte, v)
400 io.ReadFull(&r.declReader, buf)
401
402 // convert to little endian
403 // TODO(gri) go/constant should have a more direct conversion function
404 // (e.g., once it supports a big.Float based implementation)
405 for i, j := 0, len(buf)-1; i < j; i, j = i+1, j-1 {
406 buf[i], buf[j] = buf[j], buf[i]
407 }
408
409 x := constant.MakeFromBytes(buf)
410 if signed && n&1 != 0 {
411 x = constant.UnaryOp(token.SUB, x, 0)
412 }
413 return x
414}
415
416func (r *importReader) mpfloat(b *types.Basic) constant.Value {
417 x := r.mpint(b)
418 if constant.Sign(x) == 0 {
419 return x
420 }
421
422 exp := r.int64()
423 switch {
424 case exp > 0:
425 x = constant.Shift(x, token.SHL, uint(exp))
426 case exp < 0:
427 d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
428 x = constant.BinaryOp(x, token.QUO, d)
429 }
430 return x
431}
432
433func (r *importReader) ident() string {
434 return r.string()
435}
436
437func (r *importReader) qualifiedIdent() (*types.Package, string) {
438 name := r.string()
439 pkg := r.pkg()
440 return pkg, name
441}
442
443func (r *importReader) pos() token.Pos {
5a8ea165
ILT
444 if r.p.version >= 1 {
445 r.posv1()
446 } else {
447 r.posv0()
448 }
449
450 if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 {
451 return token.NoPos
452 }
453 return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn))
454}
455
456func (r *importReader) posv0() {
dd931d9b
ILT
457 delta := r.int64()
458 if delta != deltaNewFile {
459 r.prevLine += delta
460 } else if l := r.int64(); l == -1 {
461 r.prevLine += deltaNewFile
462 } else {
463 r.prevFile = r.string()
464 r.prevLine = l
465 }
5a8ea165 466}
dd931d9b 467
5a8ea165
ILT
468func (r *importReader) posv1() {
469 delta := r.int64()
470 r.prevColumn += delta >> 1
471 if delta&1 != 0 {
472 delta = r.int64()
473 r.prevLine += delta >> 1
474 if delta&1 != 0 {
475 r.prevFile = r.string()
476 }
dd931d9b 477 }
dd931d9b
ILT
478}
479
480func (r *importReader) typ() types.Type {
481 return r.p.typAt(r.uint64(), nil)
482}
483
484func isInterface(t types.Type) bool {
485 _, ok := t.(*types.Interface)
486 return ok
487}
488
489func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) }
490func (r *importReader) string() string { return r.p.stringAt(r.uint64()) }
491
492func (r *importReader) doType(base *types.Named) types.Type {
493 switch k := r.kind(); k {
494 default:
495 errorf("unexpected kind tag in %q: %v", r.p.ipath, k)
496 return nil
497
498 case definedType:
499 pkg, name := r.qualifiedIdent()
500 r.p.doDecl(pkg, name)
501 return pkg.Scope().Lookup(name).(*types.TypeName).Type()
502 case pointerType:
503 return types.NewPointer(r.typ())
504 case sliceType:
505 return types.NewSlice(r.typ())
506 case arrayType:
507 n := r.uint64()
508 return types.NewArray(r.typ(), int64(n))
509 case chanType:
510 dir := chanDir(int(r.uint64()))
511 return types.NewChan(dir, r.typ())
512 case mapType:
513 return types.NewMap(r.typ(), r.typ())
514 case signatureType:
515 r.currPkg = r.pkg()
516 return r.signature(nil)
517
518 case structType:
519 r.currPkg = r.pkg()
520
521 fields := make([]*types.Var, r.uint64())
522 tags := make([]string, len(fields))
523 for i := range fields {
524 fpos := r.pos()
525 fname := r.ident()
526 ftyp := r.typ()
527 emb := r.bool()
528 tag := r.string()
529
530 fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb)
531 tags[i] = tag
532 }
533 return types.NewStruct(fields, tags)
534
535 case interfaceType:
536 r.currPkg = r.pkg()
537
538 embeddeds := make([]types.Type, r.uint64())
539 for i := range embeddeds {
540 _ = r.pos()
541 embeddeds[i] = r.typ()
542 }
543
544 methods := make([]*types.Func, r.uint64())
545 for i := range methods {
546 mpos := r.pos()
547 mname := r.ident()
548
549 // TODO(mdempsky): Matches bimport.go, but I
550 // don't agree with this.
551 var recv *types.Var
552 if base != nil {
553 recv = types.NewVar(token.NoPos, r.currPkg, "", base)
554 }
555
556 msig := r.signature(recv)
557 methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig)
558 }
559
560 typ := types.NewInterfaceType(methods, embeddeds)
561 r.p.interfaceList = append(r.p.interfaceList, typ)
562 return typ
563 }
564}
565
566func (r *importReader) kind() itag {
567 return itag(r.uint64())
568}
569
570func (r *importReader) signature(recv *types.Var) *types.Signature {
571 params := r.paramList()
572 results := r.paramList()
573 variadic := params.Len() > 0 && r.bool()
574 return types.NewSignature(recv, params, results, variadic)
575}
576
577func (r *importReader) paramList() *types.Tuple {
578 xs := make([]*types.Var, r.uint64())
579 for i := range xs {
580 xs[i] = r.param()
581 }
582 return types.NewTuple(xs...)
583}
584
585func (r *importReader) param() *types.Var {
586 pos := r.pos()
587 name := r.ident()
588 typ := r.typ()
589 return types.NewParam(pos, r.currPkg, name, typ)
590}
591
592func (r *importReader) bool() bool {
593 return r.uint64() != 0
594}
595
596func (r *importReader) int64() int64 {
597 n, err := binary.ReadVarint(&r.declReader)
598 if err != nil {
599 errorf("readVarint: %v", err)
600 }
601 return n
602}
603
604func (r *importReader) uint64() uint64 {
605 n, err := binary.ReadUvarint(&r.declReader)
606 if err != nil {
607 errorf("readUvarint: %v", err)
608 }
609 return n
610}
611
612func (r *importReader) byte() byte {
613 x, err := r.declReader.ReadByte()
614 if err != nil {
615 errorf("declReader.ReadByte: %v", err)
616 }
617 return x
618}