github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/go/internal/gcimporter/bimport.go (about) 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 package gcimporter 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 "go/constant" 11 "go/token" 12 "go/types" 13 "sort" 14 "strconv" 15 "strings" 16 "unicode" 17 "unicode/utf8" 18 ) 19 20 type importer struct { 21 imports map[string]*types.Package 22 data []byte 23 path string 24 buf []byte // for reading strings 25 version int // export format version 26 27 // object lists 28 strList []string // in order of appearance 29 pkgList []*types.Package // in order of appearance 30 typList []types.Type // in order of appearance 31 trackAllTypes bool 32 33 // position encoding 34 posInfoFormat bool 35 prevFile string 36 prevLine int 37 38 // debugging support 39 debugFormat bool 40 read int // bytes read 41 } 42 43 // BImportData imports a package from the serialized package data 44 // and returns the number of bytes consumed and a reference to the package. 45 // If the export data version is not recognized or the format is otherwise 46 // compromised, an error is returned. 47 func BImportData(imports map[string]*types.Package, data []byte, path string) (_ int, _ *types.Package, err error) { 48 // catch panics and return them as errors 49 defer func() { 50 if e := recover(); e != nil { 51 // The package (filename) causing the problem is added to this 52 // error by a wrapper in the caller (Import in gcimporter.go). 53 err = fmt.Errorf("cannot import, possibly version skew (%v) - reinstall package", e) 54 } 55 }() 56 57 p := importer{ 58 imports: imports, 59 data: data, 60 path: path, 61 version: -1, // unknown version 62 strList: []string{""}, // empty string is mapped to 0 63 } 64 65 // read version info 66 var versionstr string 67 if b := p.rawByte(); b == 'c' || b == 'd' { 68 // Go1.7 encoding; first byte encodes low-level 69 // encoding format (compact vs debug). 70 // For backward-compatibility only (avoid problems with 71 // old installed packages). Newly compiled packages use 72 // the extensible format string. 73 // TODO(gri) Remove this support eventually; after Go1.8. 74 if b == 'd' { 75 p.debugFormat = true 76 } 77 p.trackAllTypes = p.rawByte() == 'a' 78 p.posInfoFormat = p.int() != 0 79 versionstr = p.string() 80 if versionstr == "v1" { 81 p.version = 0 82 } 83 } else { 84 // Go1.8 extensible encoding 85 // read version string and extract version number (ignore anything after the version number) 86 versionstr = p.rawStringln(b) 87 if s := strings.SplitN(versionstr, " ", 3); len(s) >= 2 && s[0] == "version" { 88 if v, err := strconv.Atoi(s[1]); err == nil && v > 0 { 89 p.version = v 90 } 91 } 92 } 93 94 // read version specific flags - extend as necessary 95 switch p.version { 96 // case 2: 97 // ... 98 // fallthrough 99 case 1: 100 p.debugFormat = p.rawStringln(p.rawByte()) == "debug" 101 p.trackAllTypes = p.int() != 0 102 p.posInfoFormat = p.int() != 0 103 case 0: 104 // Go1.7 encoding format - nothing to do here 105 default: 106 errorf("unknown export format version %d (%q)", p.version, versionstr) 107 } 108 109 // --- generic export data --- 110 111 // populate typList with predeclared "known" types 112 p.typList = append(p.typList, predeclared...) 113 114 // read package data 115 pkg := p.pkg() 116 117 // read objects of phase 1 only (see cmd/compiler/internal/gc/bexport.go) 118 objcount := 0 119 for { 120 tag := p.tagOrIndex() 121 if tag == endTag { 122 break 123 } 124 p.obj(tag) 125 objcount++ 126 } 127 128 // self-verification 129 if count := p.int(); count != objcount { 130 errorf("got %d objects; want %d", objcount, count) 131 } 132 133 // ignore compiler-specific import data 134 135 // complete interfaces 136 for _, typ := range p.typList { 137 // If we only record named types (!p.trackAllTypes), 138 // we must check the underlying types here. If we 139 // track all types, the Underlying() method call is 140 // not needed. 141 // TODO(gri) Remove if p.trackAllTypes is gone. 142 if it, ok := typ.Underlying().(*types.Interface); ok { 143 it.Complete() 144 } 145 } 146 147 // record all referenced packages as imports 148 list := append(([]*types.Package)(nil), p.pkgList[1:]...) 149 sort.Sort(byPath(list)) 150 pkg.SetImports(list) 151 152 // package was imported completely and without errors 153 pkg.MarkComplete() 154 155 return p.read, pkg, nil 156 } 157 158 func errorf(format string, args ...interface{}) { 159 panic(fmt.Sprintf(format, args...)) 160 } 161 162 func (p *importer) pkg() *types.Package { 163 // if the package was seen before, i is its index (>= 0) 164 i := p.tagOrIndex() 165 if i >= 0 { 166 return p.pkgList[i] 167 } 168 169 // otherwise, i is the package tag (< 0) 170 if i != packageTag { 171 errorf("unexpected package tag %d", i) 172 } 173 174 // read package data 175 name := p.string() 176 path := p.string() 177 178 // we should never see an empty package name 179 if name == "" { 180 errorf("empty package name in import") 181 } 182 183 // an empty path denotes the package we are currently importing; 184 // it must be the first package we see 185 if (path == "") != (len(p.pkgList) == 0) { 186 errorf("package path %q for pkg index %d", path, len(p.pkgList)) 187 } 188 189 // if the package was imported before, use that one; otherwise create a new one 190 if path == "" { 191 path = p.path 192 } 193 pkg := p.imports[path] 194 if pkg == nil { 195 pkg = types.NewPackage(path, name) 196 p.imports[path] = pkg 197 } else if pkg.Name() != name { 198 errorf("conflicting names %s and %s for package %q", pkg.Name(), name, path) 199 } 200 p.pkgList = append(p.pkgList, pkg) 201 202 return pkg 203 } 204 205 func (p *importer) declare(obj types.Object) { 206 pkg := obj.Pkg() 207 if alt := pkg.Scope().Insert(obj); alt != nil { 208 // This could only trigger if we import a (non-type) object a second time. 209 // This should never happen because 1) we only import a package once; and 210 // b) we ignore compiler-specific export data which may contain functions 211 // whose inlined function bodies refer to other functions that were already 212 // imported. 213 // (See also the comment in cmd/compile/internal/gc/bimport.go importer.obj, 214 // switch case importing functions). 215 errorf("inconsistent import:\n\t%v\npreviously imported as:\n\t%v\n", alt, obj) 216 } 217 } 218 219 func (p *importer) obj(tag int) { 220 switch tag { 221 case constTag: 222 p.pos() 223 pkg, name := p.qualifiedName() 224 typ := p.typ(nil) 225 val := p.value() 226 p.declare(types.NewConst(token.NoPos, pkg, name, typ, val)) 227 228 case typeTag: 229 _ = p.typ(nil) 230 231 case varTag: 232 p.pos() 233 pkg, name := p.qualifiedName() 234 typ := p.typ(nil) 235 p.declare(types.NewVar(token.NoPos, pkg, name, typ)) 236 237 case funcTag: 238 p.pos() 239 pkg, name := p.qualifiedName() 240 params, isddd := p.paramList() 241 result, _ := p.paramList() 242 sig := types.NewSignature(nil, params, result, isddd) 243 p.declare(types.NewFunc(token.NoPos, pkg, name, sig)) 244 245 default: 246 errorf("unexpected object tag %d", tag) 247 } 248 } 249 250 func (p *importer) pos() { 251 if !p.posInfoFormat { 252 return 253 } 254 255 file := p.prevFile 256 line := p.prevLine 257 if delta := p.int(); delta != 0 { 258 // line changed 259 line += delta 260 } else if n := p.int(); n >= 0 { 261 // file changed 262 file = p.prevFile[:n] + p.string() 263 p.prevFile = file 264 line = p.int() 265 } 266 p.prevLine = line 267 268 // TODO(gri) register new position 269 } 270 271 func (p *importer) qualifiedName() (pkg *types.Package, name string) { 272 name = p.string() 273 pkg = p.pkg() 274 return 275 } 276 277 func (p *importer) record(t types.Type) { 278 p.typList = append(p.typList, t) 279 } 280 281 // A dddSlice is a types.Type representing ...T parameters. 282 // It only appears for parameter types and does not escape 283 // the importer. 284 type dddSlice struct { 285 elem types.Type 286 } 287 288 func (t *dddSlice) Underlying() types.Type { return t } 289 func (t *dddSlice) String() string { return "..." + t.elem.String() } 290 291 // parent is the package which declared the type; parent == nil means 292 // the package currently imported. The parent package is needed for 293 // exported struct fields and interface methods which don't contain 294 // explicit package information in the export data. 295 func (p *importer) typ(parent *types.Package) types.Type { 296 // if the type was seen before, i is its index (>= 0) 297 i := p.tagOrIndex() 298 if i >= 0 { 299 return p.typList[i] 300 } 301 302 // otherwise, i is the type tag (< 0) 303 switch i { 304 case namedTag: 305 // read type object 306 p.pos() 307 parent, name := p.qualifiedName() 308 scope := parent.Scope() 309 obj := scope.Lookup(name) 310 311 // if the object doesn't exist yet, create and insert it 312 if obj == nil { 313 obj = types.NewTypeName(token.NoPos, parent, name, nil) 314 scope.Insert(obj) 315 } 316 317 if _, ok := obj.(*types.TypeName); !ok { 318 errorf("pkg = %s, name = %s => %s", parent, name, obj) 319 } 320 321 // associate new named type with obj if it doesn't exist yet 322 t0 := types.NewNamed(obj.(*types.TypeName), nil, nil) 323 324 // but record the existing type, if any 325 t := obj.Type().(*types.Named) 326 p.record(t) 327 328 // read underlying type 329 t0.SetUnderlying(p.typ(parent)) 330 331 // interfaces don't have associated methods 332 if types.IsInterface(t0) { 333 return t 334 } 335 336 // read associated methods 337 for i := p.int(); i > 0; i-- { 338 // TODO(gri) replace this with something closer to fieldName 339 p.pos() 340 name := p.string() 341 if !exported(name) { 342 p.pkg() 343 } 344 345 recv, _ := p.paramList() // TODO(gri) do we need a full param list for the receiver? 346 params, isddd := p.paramList() 347 result, _ := p.paramList() 348 p.int() // go:nointerface pragma - discarded 349 350 sig := types.NewSignature(recv.At(0), params, result, isddd) 351 t0.AddMethod(types.NewFunc(token.NoPos, parent, name, sig)) 352 } 353 354 return t 355 356 case arrayTag: 357 t := new(types.Array) 358 if p.trackAllTypes { 359 p.record(t) 360 } 361 362 n := p.int64() 363 *t = *types.NewArray(p.typ(parent), n) 364 return t 365 366 case sliceTag: 367 t := new(types.Slice) 368 if p.trackAllTypes { 369 p.record(t) 370 } 371 372 *t = *types.NewSlice(p.typ(parent)) 373 return t 374 375 case dddTag: 376 t := new(dddSlice) 377 if p.trackAllTypes { 378 p.record(t) 379 } 380 381 t.elem = p.typ(parent) 382 return t 383 384 case structTag: 385 t := new(types.Struct) 386 if p.trackAllTypes { 387 p.record(t) 388 } 389 390 *t = *types.NewStruct(p.fieldList(parent)) 391 return t 392 393 case pointerTag: 394 t := new(types.Pointer) 395 if p.trackAllTypes { 396 p.record(t) 397 } 398 399 *t = *types.NewPointer(p.typ(parent)) 400 return t 401 402 case signatureTag: 403 t := new(types.Signature) 404 if p.trackAllTypes { 405 p.record(t) 406 } 407 408 params, isddd := p.paramList() 409 result, _ := p.paramList() 410 *t = *types.NewSignature(nil, params, result, isddd) 411 return t 412 413 case interfaceTag: 414 // Create a dummy entry in the type list. This is safe because we 415 // cannot expect the interface type to appear in a cycle, as any 416 // such cycle must contain a named type which would have been 417 // first defined earlier. 418 n := len(p.typList) 419 if p.trackAllTypes { 420 p.record(nil) 421 } 422 423 // no embedded interfaces with gc compiler 424 if p.int() != 0 { 425 errorf("unexpected embedded interface") 426 } 427 428 t := types.NewInterface(p.methodList(parent), nil) 429 if p.trackAllTypes { 430 p.typList[n] = t 431 } 432 return t 433 434 case mapTag: 435 t := new(types.Map) 436 if p.trackAllTypes { 437 p.record(t) 438 } 439 440 key := p.typ(parent) 441 val := p.typ(parent) 442 *t = *types.NewMap(key, val) 443 return t 444 445 case chanTag: 446 t := new(types.Chan) 447 if p.trackAllTypes { 448 p.record(t) 449 } 450 451 var dir types.ChanDir 452 // tag values must match the constants in cmd/compile/internal/gc/go.go 453 switch d := p.int(); d { 454 case 1 /* Crecv */ : 455 dir = types.RecvOnly 456 case 2 /* Csend */ : 457 dir = types.SendOnly 458 case 3 /* Cboth */ : 459 dir = types.SendRecv 460 default: 461 errorf("unexpected channel dir %d", d) 462 } 463 val := p.typ(parent) 464 *t = *types.NewChan(dir, val) 465 return t 466 467 default: 468 errorf("unexpected type tag %d", i) 469 panic("unreachable") 470 } 471 } 472 473 func (p *importer) fieldList(parent *types.Package) (fields []*types.Var, tags []string) { 474 if n := p.int(); n > 0 { 475 fields = make([]*types.Var, n) 476 tags = make([]string, n) 477 for i := range fields { 478 fields[i] = p.field(parent) 479 tags[i] = p.string() 480 } 481 } 482 return 483 } 484 485 func (p *importer) field(parent *types.Package) *types.Var { 486 p.pos() 487 pkg, name := p.fieldName(parent) 488 typ := p.typ(parent) 489 490 anonymous := false 491 if name == "" { 492 // anonymous field - typ must be T or *T and T must be a type name 493 switch typ := deref(typ).(type) { 494 case *types.Basic: // basic types are named types 495 pkg = nil // // objects defined in Universe scope have no package 496 name = typ.Name() 497 case *types.Named: 498 name = typ.Obj().Name() 499 default: 500 errorf("anonymous field expected") 501 } 502 anonymous = true 503 } 504 505 return types.NewField(token.NoPos, pkg, name, typ, anonymous) 506 } 507 508 func (p *importer) methodList(parent *types.Package) (methods []*types.Func) { 509 if n := p.int(); n > 0 { 510 methods = make([]*types.Func, n) 511 for i := range methods { 512 methods[i] = p.method(parent) 513 } 514 } 515 return 516 } 517 518 func (p *importer) method(parent *types.Package) *types.Func { 519 p.pos() 520 pkg, name := p.fieldName(parent) 521 params, isddd := p.paramList() 522 result, _ := p.paramList() 523 sig := types.NewSignature(nil, params, result, isddd) 524 return types.NewFunc(token.NoPos, pkg, name, sig) 525 } 526 527 func (p *importer) fieldName(parent *types.Package) (*types.Package, string) { 528 name := p.string() 529 pkg := parent 530 if pkg == nil { 531 // use the imported package instead 532 pkg = p.pkgList[0] 533 } 534 if p.version == 0 && name == "_" { 535 // version 0 didn't export a package for _ fields 536 return pkg, name 537 } 538 if name != "" && !exported(name) { 539 if name == "?" { 540 name = "" 541 } 542 pkg = p.pkg() 543 } 544 return pkg, name 545 } 546 547 func (p *importer) paramList() (*types.Tuple, bool) { 548 n := p.int() 549 if n == 0 { 550 return nil, false 551 } 552 // negative length indicates unnamed parameters 553 named := true 554 if n < 0 { 555 n = -n 556 named = false 557 } 558 // n > 0 559 params := make([]*types.Var, n) 560 isddd := false 561 for i := range params { 562 params[i], isddd = p.param(named) 563 } 564 return types.NewTuple(params...), isddd 565 } 566 567 func (p *importer) param(named bool) (*types.Var, bool) { 568 t := p.typ(nil) 569 td, isddd := t.(*dddSlice) 570 if isddd { 571 t = types.NewSlice(td.elem) 572 } 573 574 var pkg *types.Package 575 var name string 576 if named { 577 name = p.string() 578 if name == "" { 579 errorf("expected named parameter") 580 } 581 if name != "_" { 582 pkg = p.pkg() 583 } 584 if i := strings.Index(name, "ยท"); i > 0 { 585 name = name[:i] // cut off gc-specific parameter numbering 586 } 587 } 588 589 // read and discard compiler-specific info 590 p.string() 591 592 return types.NewVar(token.NoPos, pkg, name, t), isddd 593 } 594 595 func exported(name string) bool { 596 ch, _ := utf8.DecodeRuneInString(name) 597 return unicode.IsUpper(ch) 598 } 599 600 func (p *importer) value() constant.Value { 601 switch tag := p.tagOrIndex(); tag { 602 case falseTag: 603 return constant.MakeBool(false) 604 case trueTag: 605 return constant.MakeBool(true) 606 case int64Tag: 607 return constant.MakeInt64(p.int64()) 608 case floatTag: 609 return p.float() 610 case complexTag: 611 re := p.float() 612 im := p.float() 613 return constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 614 case stringTag: 615 return constant.MakeString(p.string()) 616 default: 617 errorf("unexpected value tag %d", tag) 618 panic("unreachable") 619 } 620 } 621 622 func (p *importer) float() constant.Value { 623 sign := p.int() 624 if sign == 0 { 625 return constant.MakeInt64(0) 626 } 627 628 exp := p.int() 629 mant := []byte(p.string()) // big endian 630 631 // remove leading 0's if any 632 for len(mant) > 0 && mant[0] == 0 { 633 mant = mant[1:] 634 } 635 636 // convert to little endian 637 // TODO(gri) go/constant should have a more direct conversion function 638 // (e.g., once it supports a big.Float based implementation) 639 for i, j := 0, len(mant)-1; i < j; i, j = i+1, j-1 { 640 mant[i], mant[j] = mant[j], mant[i] 641 } 642 643 // adjust exponent (constant.MakeFromBytes creates an integer value, 644 // but mant represents the mantissa bits such that 0.5 <= mant < 1.0) 645 exp -= len(mant) << 3 646 if len(mant) > 0 { 647 for msd := mant[len(mant)-1]; msd&0x80 == 0; msd <<= 1 { 648 exp++ 649 } 650 } 651 652 x := constant.MakeFromBytes(mant) 653 switch { 654 case exp < 0: 655 d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp)) 656 x = constant.BinaryOp(x, token.QUO, d) 657 case exp > 0: 658 x = constant.Shift(x, token.SHL, uint(exp)) 659 } 660 661 if sign < 0 { 662 x = constant.UnaryOp(token.SUB, x, 0) 663 } 664 return x 665 } 666 667 // ---------------------------------------------------------------------------- 668 // Low-level decoders 669 670 func (p *importer) tagOrIndex() int { 671 if p.debugFormat { 672 p.marker('t') 673 } 674 675 return int(p.rawInt64()) 676 } 677 678 func (p *importer) int() int { 679 x := p.int64() 680 if int64(int(x)) != x { 681 errorf("exported integer too large") 682 } 683 return int(x) 684 } 685 686 func (p *importer) int64() int64 { 687 if p.debugFormat { 688 p.marker('i') 689 } 690 691 return p.rawInt64() 692 } 693 694 func (p *importer) string() string { 695 if p.debugFormat { 696 p.marker('s') 697 } 698 // if the string was seen before, i is its index (>= 0) 699 // (the empty string is at index 0) 700 i := p.rawInt64() 701 if i >= 0 { 702 return p.strList[i] 703 } 704 // otherwise, i is the negative string length (< 0) 705 if n := int(-i); n <= cap(p.buf) { 706 p.buf = p.buf[:n] 707 } else { 708 p.buf = make([]byte, n) 709 } 710 for i := range p.buf { 711 p.buf[i] = p.rawByte() 712 } 713 s := string(p.buf) 714 p.strList = append(p.strList, s) 715 return s 716 } 717 718 func (p *importer) marker(want byte) { 719 if got := p.rawByte(); got != want { 720 errorf("incorrect marker: got %c; want %c (pos = %d)", got, want, p.read) 721 } 722 723 pos := p.read 724 if n := int(p.rawInt64()); n != pos { 725 errorf("incorrect position: got %d; want %d", n, pos) 726 } 727 } 728 729 // rawInt64 should only be used by low-level decoders. 730 func (p *importer) rawInt64() int64 { 731 i, err := binary.ReadVarint(p) 732 if err != nil { 733 errorf("read error: %v", err) 734 } 735 return i 736 } 737 738 // rawStringln should only be used to read the initial version string. 739 func (p *importer) rawStringln(b byte) string { 740 p.buf = p.buf[:0] 741 for b != '\n' { 742 p.buf = append(p.buf, b) 743 b = p.rawByte() 744 } 745 return string(p.buf) 746 } 747 748 // needed for binary.ReadVarint in rawInt64 749 func (p *importer) ReadByte() (byte, error) { 750 return p.rawByte(), nil 751 } 752 753 // byte is the bottleneck interface for reading p.data. 754 // It unescapes '|' 'S' to '$' and '|' '|' to '|'. 755 // rawByte should only be used by low-level decoders. 756 func (p *importer) rawByte() byte { 757 b := p.data[0] 758 r := 1 759 if b == '|' { 760 b = p.data[1] 761 r = 2 762 switch b { 763 case 'S': 764 b = '$' 765 case '|': 766 // nothing to do 767 default: 768 errorf("unexpected escape sequence in export data") 769 } 770 } 771 p.data = p.data[r:] 772 p.read += r 773 return b 774 775 } 776 777 // ---------------------------------------------------------------------------- 778 // Export format 779 780 // Tags. Must be < 0. 781 const ( 782 // Objects 783 packageTag = -(iota + 1) 784 constTag 785 typeTag 786 varTag 787 funcTag 788 endTag 789 790 // Types 791 namedTag 792 arrayTag 793 sliceTag 794 dddTag 795 structTag 796 pointerTag 797 signatureTag 798 interfaceTag 799 mapTag 800 chanTag 801 802 // Values 803 falseTag 804 trueTag 805 int64Tag 806 floatTag 807 fractionTag // not used by gc 808 complexTag 809 stringTag 810 unknownTag // not used by gc (only appears in packages with errors) 811 ) 812 813 var predeclared = []types.Type{ 814 // basic types 815 types.Typ[types.Bool], 816 types.Typ[types.Int], 817 types.Typ[types.Int8], 818 types.Typ[types.Int16], 819 types.Typ[types.Int32], 820 types.Typ[types.Int64], 821 types.Typ[types.Uint], 822 types.Typ[types.Uint8], 823 types.Typ[types.Uint16], 824 types.Typ[types.Uint32], 825 types.Typ[types.Uint64], 826 types.Typ[types.Uintptr], 827 types.Typ[types.Float32], 828 types.Typ[types.Float64], 829 types.Typ[types.Complex64], 830 types.Typ[types.Complex128], 831 types.Typ[types.String], 832 833 // aliases 834 types.Universe.Lookup("byte").Type(), 835 types.Universe.Lookup("rune").Type(), 836 837 // error 838 types.Universe.Lookup("error").Type(), 839 840 // untyped types 841 types.Typ[types.UntypedBool], 842 types.Typ[types.UntypedInt], 843 types.Typ[types.UntypedRune], 844 types.Typ[types.UntypedFloat], 845 types.Typ[types.UntypedComplex], 846 types.Typ[types.UntypedString], 847 types.Typ[types.UntypedNil], 848 849 // package unsafe 850 types.Typ[types.UnsafePointer], 851 852 // invalid type 853 types.Typ[types.Invalid], // only appears in packages with errors 854 855 // used internally by gc; never used by this package or in .a files 856 anyType{}, 857 } 858 859 type anyType struct{} 860 861 func (t anyType) Underlying() types.Type { return t } 862 func (t anyType) String() string { return "any" }