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