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