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