github.com/bir3/gocompiler@v0.9.2202/src/go/internal/gcimporter/iimport.go (about) 1 // Copyright 2018 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 // Indexed package import. 6 // See cmd/compile/internal/gc/iexport.go for the export data format. 7 8 package gcimporter 9 10 import ( 11 "bufio" 12 "bytes" 13 "encoding/binary" 14 "fmt" 15 "github.com/bir3/gocompiler/src/go/constant" 16 "github.com/bir3/gocompiler/src/go/token" 17 "github.com/bir3/gocompiler/src/go/types" 18 "github.com/bir3/gocompiler/src/internal/saferio" 19 "io" 20 "math" 21 "math/big" 22 "sort" 23 "strings" 24 ) 25 26 type intReader struct { 27 *bufio.Reader 28 path string 29 } 30 31 func (r *intReader) int64() int64 { 32 i, err := binary.ReadVarint(r.Reader) 33 if err != nil { 34 errorf("import %q: read varint error: %v", r.path, err) 35 } 36 return i 37 } 38 39 func (r *intReader) uint64() uint64 { 40 i, err := binary.ReadUvarint(r.Reader) 41 if err != nil { 42 errorf("import %q: read varint error: %v", r.path, err) 43 } 44 return i 45 } 46 47 // Keep this in sync with constants in iexport.go. 48 const ( 49 iexportVersionGo1_11 = 0 50 iexportVersionPosCol = 1 51 iexportVersionGenerics = 2 52 iexportVersionGo1_18 = 2 53 54 iexportVersionCurrent = 2 55 ) 56 57 type ident struct { 58 pkg *types.Package 59 name string 60 } 61 62 const predeclReserved = 32 63 64 type itag uint64 65 66 const ( 67 // Types 68 definedType itag = iota 69 pointerType 70 sliceType 71 arrayType 72 chanType 73 mapType 74 signatureType 75 structType 76 interfaceType 77 typeParamType 78 instanceType 79 unionType 80 ) 81 82 // iImportData imports a package from the serialized package data 83 // and returns the number of bytes consumed and a reference to the package. 84 // If the export data version is not recognized or the format is otherwise 85 // compromised, an error is returned. 86 func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataReader *bufio.Reader, path string) (pkg *types.Package, err error) { 87 const currentVersion = iexportVersionCurrent 88 version := int64(-1) 89 defer func() { 90 if e := recover(); e != nil { 91 if version > currentVersion { 92 err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e) 93 } else { 94 err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e) 95 } 96 } 97 }() 98 99 r := &intReader{dataReader, path} 100 101 version = int64(r.uint64()) 102 switch version { 103 case iexportVersionGo1_18, iexportVersionPosCol, iexportVersionGo1_11: 104 default: 105 errorf("unknown iexport format version %d", version) 106 } 107 108 sLen := r.uint64() 109 dLen := r.uint64() 110 111 if sLen > math.MaxUint64-dLen { 112 errorf("lengths out of range (%d, %d)", sLen, dLen) 113 } 114 115 data, err := saferio.ReadData(r, sLen+dLen) 116 if err != nil { 117 errorf("cannot read %d bytes of stringData and declData: %s", sLen+dLen, err) 118 } 119 stringData := data[:sLen] 120 declData := data[sLen:] 121 122 p := iimporter{ 123 exportVersion: version, 124 ipath: path, 125 version: int(version), 126 127 stringData: stringData, 128 stringCache: make(map[uint64]string), 129 pkgCache: make(map[uint64]*types.Package), 130 131 declData: declData, 132 pkgIndex: make(map[*types.Package]map[string]uint64), 133 typCache: make(map[uint64]types.Type), 134 // Separate map for typeparams, keyed by their package and unique 135 // name (name with subscript). 136 tparamIndex: make(map[ident]*types.TypeParam), 137 138 fake: fakeFileSet{ 139 fset: fset, 140 files: make(map[string]*fileInfo), 141 }, 142 } 143 defer p.fake.setLines() // set lines for files in fset 144 145 for i, pt := range predeclared { 146 p.typCache[uint64(i)] = pt 147 } 148 149 pkgList := make([]*types.Package, r.uint64()) 150 for i := range pkgList { 151 pkgPathOff := r.uint64() 152 pkgPath := p.stringAt(pkgPathOff) 153 pkgName := p.stringAt(r.uint64()) 154 _ = r.uint64() // package height; unused by go/types 155 156 if pkgPath == "" { 157 pkgPath = path 158 } 159 pkg := imports[pkgPath] 160 if pkg == nil { 161 pkg = types.NewPackage(pkgPath, pkgName) 162 imports[pkgPath] = pkg 163 } else if pkg.Name() != pkgName { 164 errorf("conflicting names %s and %s for package %q", pkg.Name(), pkgName, path) 165 } 166 167 p.pkgCache[pkgPathOff] = pkg 168 169 nameIndex := make(map[string]uint64) 170 for nSyms := r.uint64(); nSyms > 0; nSyms-- { 171 name := p.stringAt(r.uint64()) 172 nameIndex[name] = r.uint64() 173 } 174 175 p.pkgIndex[pkg] = nameIndex 176 pkgList[i] = pkg 177 } 178 179 localpkg := pkgList[0] 180 181 names := make([]string, 0, len(p.pkgIndex[localpkg])) 182 for name := range p.pkgIndex[localpkg] { 183 names = append(names, name) 184 } 185 sort.Strings(names) 186 for _, name := range names { 187 p.doDecl(localpkg, name) 188 } 189 190 // SetConstraint can't be called if the constraint type is not yet complete. 191 // When type params are created in the 'P' case of (*importReader).obj(), 192 // the associated constraint type may not be complete due to recursion. 193 // Therefore, we defer calling SetConstraint there, and call it here instead 194 // after all types are complete. 195 for _, d := range p.later { 196 d.t.SetConstraint(d.constraint) 197 } 198 199 for _, typ := range p.interfaceList { 200 typ.Complete() 201 } 202 203 // record all referenced packages as imports 204 list := append(([]*types.Package)(nil), pkgList[1:]...) 205 sort.Sort(byPath(list)) 206 localpkg.SetImports(list) 207 208 // package was imported completely and without errors 209 localpkg.MarkComplete() 210 return localpkg, nil 211 } 212 213 type setConstraintArgs struct { 214 t *types.TypeParam 215 constraint types.Type 216 } 217 218 type iimporter struct { 219 exportVersion int64 220 ipath string 221 version int 222 223 stringData []byte 224 stringCache map[uint64]string 225 pkgCache map[uint64]*types.Package 226 227 declData []byte 228 pkgIndex map[*types.Package]map[string]uint64 229 typCache map[uint64]types.Type 230 tparamIndex map[ident]*types.TypeParam 231 232 fake fakeFileSet 233 interfaceList []*types.Interface 234 235 // Arguments for calls to SetConstraint that are deferred due to recursive types 236 later []setConstraintArgs 237 } 238 239 func (p *iimporter) doDecl(pkg *types.Package, name string) { 240 // See if we've already imported this declaration. 241 if obj := pkg.Scope().Lookup(name); obj != nil { 242 return 243 } 244 245 off, ok := p.pkgIndex[pkg][name] 246 if !ok { 247 errorf("%v.%v not in index", pkg, name) 248 } 249 250 r := &importReader{p: p, currPkg: pkg} 251 r.declReader.Reset(p.declData[off:]) 252 253 r.obj(name) 254 } 255 256 func (p *iimporter) stringAt(off uint64) string { 257 if s, ok := p.stringCache[off]; ok { 258 return s 259 } 260 261 slen, n := binary.Uvarint(p.stringData[off:]) 262 if n <= 0 { 263 errorf("varint failed") 264 } 265 spos := off + uint64(n) 266 s := string(p.stringData[spos : spos+slen]) 267 p.stringCache[off] = s 268 return s 269 } 270 271 func (p *iimporter) pkgAt(off uint64) *types.Package { 272 if pkg, ok := p.pkgCache[off]; ok { 273 return pkg 274 } 275 path := p.stringAt(off) 276 errorf("missing package %q in %q", path, p.ipath) 277 return nil 278 } 279 280 func (p *iimporter) typAt(off uint64, base *types.Named) types.Type { 281 if t, ok := p.typCache[off]; ok && canReuse(base, t) { 282 return t 283 } 284 285 if off < predeclReserved { 286 errorf("predeclared type missing from cache: %v", off) 287 } 288 289 r := &importReader{p: p} 290 r.declReader.Reset(p.declData[off-predeclReserved:]) 291 t := r.doType(base) 292 293 if canReuse(base, t) { 294 p.typCache[off] = t 295 } 296 return t 297 } 298 299 // canReuse reports whether the type rhs on the RHS of the declaration for def 300 // may be re-used. 301 // 302 // Specifically, if def is non-nil and rhs is an interface type with methods, it 303 // may not be re-used because we have a convention of setting the receiver type 304 // for interface methods to def. 305 func canReuse(def *types.Named, rhs types.Type) bool { 306 if def == nil { 307 return true 308 } 309 iface, _ := rhs.(*types.Interface) 310 if iface == nil { 311 return true 312 } 313 // Don't use iface.Empty() here as iface may not be complete. 314 return iface.NumEmbeddeds() == 0 && iface.NumExplicitMethods() == 0 315 } 316 317 type importReader struct { 318 p *iimporter 319 declReader bytes.Reader 320 currPkg *types.Package 321 prevFile string 322 prevLine int64 323 prevColumn int64 324 } 325 326 func (r *importReader) obj(name string) { 327 tag := r.byte() 328 pos := r.pos() 329 330 switch tag { 331 case 'A': 332 typ := r.typ() 333 334 r.declare(types.NewTypeName(pos, r.currPkg, name, typ)) 335 336 case 'C': 337 typ, val := r.value() 338 339 r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) 340 341 case 'F', 'G': 342 var tparams []*types.TypeParam 343 if tag == 'G' { 344 tparams = r.tparamList() 345 } 346 sig := r.signature(nil, nil, tparams) 347 r.declare(types.NewFunc(pos, r.currPkg, name, sig)) 348 349 case 'T', 'U': 350 // Types can be recursive. We need to setup a stub 351 // declaration before recurring. 352 obj := types.NewTypeName(pos, r.currPkg, name, nil) 353 named := types.NewNamed(obj, nil, nil) 354 // Declare obj before calling r.tparamList, so the new type name is recognized 355 // if used in the constraint of one of its own typeparams (see #48280). 356 r.declare(obj) 357 if tag == 'U' { 358 tparams := r.tparamList() 359 named.SetTypeParams(tparams) 360 } 361 362 underlying := r.p.typAt(r.uint64(), named).Underlying() 363 named.SetUnderlying(underlying) 364 365 if !isInterface(underlying) { 366 for n := r.uint64(); n > 0; n-- { 367 mpos := r.pos() 368 mname := r.ident() 369 recv := r.param() 370 371 // If the receiver has any targs, set those as the 372 // rparams of the method (since those are the 373 // typeparams being used in the method sig/body). 374 targs := baseType(recv.Type()).TypeArgs() 375 var rparams []*types.TypeParam 376 if targs.Len() > 0 { 377 rparams = make([]*types.TypeParam, targs.Len()) 378 for i := range rparams { 379 rparams[i], _ = targs.At(i).(*types.TypeParam) 380 } 381 } 382 msig := r.signature(recv, rparams, nil) 383 384 named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) 385 } 386 } 387 388 case 'P': 389 // We need to "declare" a typeparam in order to have a name that 390 // can be referenced recursively (if needed) in the type param's 391 // bound. 392 if r.p.exportVersion < iexportVersionGenerics { 393 errorf("unexpected type param type") 394 } 395 // Remove the "path" from the type param name that makes it unique, 396 // and revert any unique name used for blank typeparams. 397 name0 := tparamName(name) 398 tn := types.NewTypeName(pos, r.currPkg, name0, nil) 399 t := types.NewTypeParam(tn, nil) 400 // To handle recursive references to the typeparam within its 401 // bound, save the partial type in tparamIndex before reading the bounds. 402 id := ident{r.currPkg, name} 403 r.p.tparamIndex[id] = t 404 405 var implicit bool 406 if r.p.exportVersion >= iexportVersionGo1_18 { 407 implicit = r.bool() 408 } 409 constraint := r.typ() 410 if implicit { 411 iface, _ := constraint.(*types.Interface) 412 if iface == nil { 413 errorf("non-interface constraint marked implicit") 414 } 415 iface.MarkImplicit() 416 } 417 // The constraint type may not be complete, if we 418 // are in the middle of a type recursion involving type 419 // constraints. So, we defer SetConstraint until we have 420 // completely set up all types in ImportData. 421 r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint}) 422 423 case 'V': 424 typ := r.typ() 425 426 r.declare(types.NewVar(pos, r.currPkg, name, typ)) 427 428 default: 429 errorf("unexpected tag: %v", tag) 430 } 431 } 432 433 func (r *importReader) declare(obj types.Object) { 434 obj.Pkg().Scope().Insert(obj) 435 } 436 437 func (r *importReader) value() (typ types.Type, val constant.Value) { 438 typ = r.typ() 439 if r.p.exportVersion >= iexportVersionGo1_18 { 440 // TODO: add support for using the kind 441 _ = constant.Kind(r.int64()) 442 } 443 444 switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType { 445 case types.IsBoolean: 446 val = constant.MakeBool(r.bool()) 447 448 case types.IsString: 449 val = constant.MakeString(r.string()) 450 451 case types.IsInteger: 452 var x big.Int 453 r.mpint(&x, b) 454 val = constant.Make(&x) 455 456 case types.IsFloat: 457 val = r.mpfloat(b) 458 459 case types.IsComplex: 460 re := r.mpfloat(b) 461 im := r.mpfloat(b) 462 val = constant.BinaryOp(re, token.ADD, constant.MakeImag(im)) 463 464 default: 465 errorf("unexpected type %v", typ) // panics 466 panic("unreachable") 467 } 468 469 return 470 } 471 472 func intSize(b *types.Basic) (signed bool, maxBytes uint) { 473 if (b.Info() & types.IsUntyped) != 0 { 474 return true, 64 475 } 476 477 switch b.Kind() { 478 case types.Float32, types.Complex64: 479 return true, 3 480 case types.Float64, types.Complex128: 481 return true, 7 482 } 483 484 signed = (b.Info() & types.IsUnsigned) == 0 485 switch b.Kind() { 486 case types.Int8, types.Uint8: 487 maxBytes = 1 488 case types.Int16, types.Uint16: 489 maxBytes = 2 490 case types.Int32, types.Uint32: 491 maxBytes = 4 492 default: 493 maxBytes = 8 494 } 495 496 return 497 } 498 499 func (r *importReader) mpint(x *big.Int, typ *types.Basic) { 500 signed, maxBytes := intSize(typ) 501 502 maxSmall := 256 - maxBytes 503 if signed { 504 maxSmall = 256 - 2*maxBytes 505 } 506 if maxBytes == 1 { 507 maxSmall = 256 508 } 509 510 n, _ := r.declReader.ReadByte() 511 if uint(n) < maxSmall { 512 v := int64(n) 513 if signed { 514 v >>= 1 515 if n&1 != 0 { 516 v = ^v 517 } 518 } 519 x.SetInt64(v) 520 return 521 } 522 523 v := -n 524 if signed { 525 v = -(n &^ 1) >> 1 526 } 527 if v < 1 || uint(v) > maxBytes { 528 errorf("weird decoding: %v, %v => %v", n, signed, v) 529 } 530 b := make([]byte, v) 531 io.ReadFull(&r.declReader, b) 532 x.SetBytes(b) 533 if signed && n&1 != 0 { 534 x.Neg(x) 535 } 536 } 537 538 func (r *importReader) mpfloat(typ *types.Basic) constant.Value { 539 var mant big.Int 540 r.mpint(&mant, typ) 541 var f big.Float 542 f.SetInt(&mant) 543 if f.Sign() != 0 { 544 f.SetMantExp(&f, int(r.int64())) 545 } 546 return constant.Make(&f) 547 } 548 549 func (r *importReader) ident() string { 550 return r.string() 551 } 552 553 func (r *importReader) qualifiedIdent() (*types.Package, string) { 554 name := r.string() 555 pkg := r.pkg() 556 return pkg, name 557 } 558 559 func (r *importReader) pos() token.Pos { 560 if r.p.version >= 1 { 561 r.posv1() 562 } else { 563 r.posv0() 564 } 565 566 if r.prevFile == "" && r.prevLine == 0 && r.prevColumn == 0 { 567 return token.NoPos 568 } 569 return r.p.fake.pos(r.prevFile, int(r.prevLine), int(r.prevColumn)) 570 } 571 572 func (r *importReader) posv0() { 573 delta := r.int64() 574 if delta != deltaNewFile { 575 r.prevLine += delta 576 } else if l := r.int64(); l == -1 { 577 r.prevLine += deltaNewFile 578 } else { 579 r.prevFile = r.string() 580 r.prevLine = l 581 } 582 } 583 584 func (r *importReader) posv1() { 585 delta := r.int64() 586 r.prevColumn += delta >> 1 587 if delta&1 != 0 { 588 delta = r.int64() 589 r.prevLine += delta >> 1 590 if delta&1 != 0 { 591 r.prevFile = r.string() 592 } 593 } 594 } 595 596 func (r *importReader) typ() types.Type { 597 return r.p.typAt(r.uint64(), nil) 598 } 599 600 func isInterface(t types.Type) bool { 601 _, ok := t.(*types.Interface) 602 return ok 603 } 604 605 func (r *importReader) pkg() *types.Package { return r.p.pkgAt(r.uint64()) } 606 func (r *importReader) string() string { return r.p.stringAt(r.uint64()) } 607 608 func (r *importReader) doType(base *types.Named) types.Type { 609 switch k := r.kind(); k { 610 default: 611 errorf("unexpected kind tag in %q: %v", r.p.ipath, k) 612 return nil 613 614 case definedType: 615 pkg, name := r.qualifiedIdent() 616 r.p.doDecl(pkg, name) 617 return pkg.Scope().Lookup(name).(*types.TypeName).Type() 618 case pointerType: 619 return types.NewPointer(r.typ()) 620 case sliceType: 621 return types.NewSlice(r.typ()) 622 case arrayType: 623 n := r.uint64() 624 return types.NewArray(r.typ(), int64(n)) 625 case chanType: 626 dir := chanDir(int(r.uint64())) 627 return types.NewChan(dir, r.typ()) 628 case mapType: 629 return types.NewMap(r.typ(), r.typ()) 630 case signatureType: 631 r.currPkg = r.pkg() 632 return r.signature(nil, nil, nil) 633 634 case structType: 635 r.currPkg = r.pkg() 636 637 fields := make([]*types.Var, r.uint64()) 638 tags := make([]string, len(fields)) 639 for i := range fields { 640 fpos := r.pos() 641 fname := r.ident() 642 ftyp := r.typ() 643 emb := r.bool() 644 tag := r.string() 645 646 fields[i] = types.NewField(fpos, r.currPkg, fname, ftyp, emb) 647 tags[i] = tag 648 } 649 return types.NewStruct(fields, tags) 650 651 case interfaceType: 652 r.currPkg = r.pkg() 653 654 embeddeds := make([]types.Type, r.uint64()) 655 for i := range embeddeds { 656 _ = r.pos() 657 embeddeds[i] = r.typ() 658 } 659 660 methods := make([]*types.Func, r.uint64()) 661 for i := range methods { 662 mpos := r.pos() 663 mname := r.ident() 664 665 // TODO(mdempsky): Matches bimport.go, but I 666 // don't agree with this. 667 var recv *types.Var 668 if base != nil { 669 recv = types.NewVar(token.NoPos, r.currPkg, "", base) 670 } 671 672 msig := r.signature(recv, nil, nil) 673 methods[i] = types.NewFunc(mpos, r.currPkg, mname, msig) 674 } 675 676 typ := types.NewInterfaceType(methods, embeddeds) 677 r.p.interfaceList = append(r.p.interfaceList, typ) 678 return typ 679 680 case typeParamType: 681 if r.p.exportVersion < iexportVersionGenerics { 682 errorf("unexpected type param type") 683 } 684 pkg, name := r.qualifiedIdent() 685 id := ident{pkg, name} 686 if t, ok := r.p.tparamIndex[id]; ok { 687 // We're already in the process of importing this typeparam. 688 return t 689 } 690 // Otherwise, import the definition of the typeparam now. 691 r.p.doDecl(pkg, name) 692 return r.p.tparamIndex[id] 693 694 case instanceType: 695 if r.p.exportVersion < iexportVersionGenerics { 696 errorf("unexpected instantiation type") 697 } 698 // pos does not matter for instances: they are positioned on the original 699 // type. 700 _ = r.pos() 701 len := r.uint64() 702 targs := make([]types.Type, len) 703 for i := range targs { 704 targs[i] = r.typ() 705 } 706 baseType := r.typ() 707 // The imported instantiated type doesn't include any methods, so 708 // we must always use the methods of the base (orig) type. 709 // TODO provide a non-nil *Context 710 t, _ := types.Instantiate(nil, baseType, targs, false) 711 return t 712 713 case unionType: 714 if r.p.exportVersion < iexportVersionGenerics { 715 errorf("unexpected instantiation type") 716 } 717 terms := make([]*types.Term, r.uint64()) 718 for i := range terms { 719 terms[i] = types.NewTerm(r.bool(), r.typ()) 720 } 721 return types.NewUnion(terms) 722 } 723 } 724 725 func (r *importReader) kind() itag { 726 return itag(r.uint64()) 727 } 728 729 func (r *importReader) signature(recv *types.Var, rparams, tparams []*types.TypeParam) *types.Signature { 730 params := r.paramList() 731 results := r.paramList() 732 variadic := params.Len() > 0 && r.bool() 733 return types.NewSignatureType(recv, rparams, tparams, params, results, variadic) 734 } 735 736 func (r *importReader) tparamList() []*types.TypeParam { 737 n := r.uint64() 738 if n == 0 { 739 return nil 740 } 741 xs := make([]*types.TypeParam, n) 742 for i := range xs { 743 xs[i], _ = r.typ().(*types.TypeParam) 744 } 745 return xs 746 } 747 748 func (r *importReader) paramList() *types.Tuple { 749 xs := make([]*types.Var, r.uint64()) 750 for i := range xs { 751 xs[i] = r.param() 752 } 753 return types.NewTuple(xs...) 754 } 755 756 func (r *importReader) param() *types.Var { 757 pos := r.pos() 758 name := r.ident() 759 typ := r.typ() 760 return types.NewParam(pos, r.currPkg, name, typ) 761 } 762 763 func (r *importReader) bool() bool { 764 return r.uint64() != 0 765 } 766 767 func (r *importReader) int64() int64 { 768 n, err := binary.ReadVarint(&r.declReader) 769 if err != nil { 770 errorf("readVarint: %v", err) 771 } 772 return n 773 } 774 775 func (r *importReader) uint64() uint64 { 776 n, err := binary.ReadUvarint(&r.declReader) 777 if err != nil { 778 errorf("readUvarint: %v", err) 779 } 780 return n 781 } 782 783 func (r *importReader) byte() byte { 784 x, err := r.declReader.ReadByte() 785 if err != nil { 786 errorf("declReader.ReadByte: %v", err) 787 } 788 return x 789 } 790 791 func baseType(typ types.Type) *types.Named { 792 // pointer receivers are never types.Named types 793 if p, _ := typ.(*types.Pointer); p != nil { 794 typ = p.Elem() 795 } 796 // receiver base types are always (possibly generic) types.Named types 797 n, _ := typ.(*types.Named) 798 return n 799 } 800 801 const blankMarker = "$" 802 803 // tparamName returns the real name of a type parameter, after stripping its 804 // qualifying prefix and reverting blank-name encoding. See tparamExportName 805 // for details. 806 func tparamName(exportName string) string { 807 // Remove the "path" from the type param name that makes it unique. 808 ix := strings.LastIndex(exportName, ".") 809 if ix < 0 { 810 errorf("malformed type parameter export name %s: missing prefix", exportName) 811 } 812 name := exportName[ix+1:] 813 if strings.HasPrefix(name, blankMarker) { 814 return "_" 815 } 816 return name 817 }