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