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