github.com/bir3/gocompiler@v0.3.205/src/go/internal/gcimporter/ureader.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gcimporter 6 7 import ( 8 "github.com/bir3/gocompiler/src/go/token" 9 "github.com/bir3/gocompiler/src/go/types" 10 "github.com/bir3/gocompiler/src/internal/pkgbits" 11 ) 12 13 // A pkgReader holds the shared state for reading a unified IR package 14 // description. 15 type pkgReader struct { 16 pkgbits.PkgDecoder 17 18 fake fakeFileSet 19 20 ctxt *types.Context 21 imports map[string]*types.Package // previously imported packages, indexed by path 22 23 // lazily initialized arrays corresponding to the unified IR 24 // PosBase, Pkg, and Type sections, respectively. 25 posBases []string // position bases (i.e., file names) 26 pkgs []*types.Package 27 typs []types.Type 28 29 // laterFns holds functions that need to be invoked at the end of 30 // import reading. 31 laterFns []func() 32 33 // ifaces holds a list of constructed Interfaces, which need to have 34 // Complete called after importing is done. 35 ifaces []*types.Interface 36 } 37 38 // later adds a function to be invoked at the end of import reading. 39 func (pr *pkgReader) later(fn func()) { 40 pr.laterFns = append(pr.laterFns, fn) 41 } 42 43 // readUnifiedPackage reads a package description from the given 44 // unified IR export data decoder. 45 func readUnifiedPackage(fset *token.FileSet, ctxt *types.Context, imports map[string]*types.Package, input pkgbits.PkgDecoder) *types.Package { 46 pr := pkgReader{ 47 PkgDecoder: input, 48 49 fake: fakeFileSet{ 50 fset: fset, 51 files: make(map[string]*fileInfo), 52 }, 53 54 ctxt: ctxt, 55 imports: imports, 56 57 posBases: make([]string, input.NumElems(pkgbits.RelocPosBase)), 58 pkgs: make([]*types.Package, input.NumElems(pkgbits.RelocPkg)), 59 typs: make([]types.Type, input.NumElems(pkgbits.RelocType)), 60 } 61 defer pr.fake.setLines() 62 63 r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) 64 pkg := r.pkg() 65 r.Bool() // TODO(mdempsky): Remove; was "has init" 66 67 for i, n := 0, r.Len(); i < n; i++ { 68 // As if r.obj(), but avoiding the Scope.Lookup call, 69 // to avoid eager loading of imports. 70 r.Sync(pkgbits.SyncObject) 71 assert(!r.Bool()) 72 r.p.objIdx(r.Reloc(pkgbits.RelocObj)) 73 assert(r.Len() == 0) 74 } 75 76 r.Sync(pkgbits.SyncEOF) 77 78 for _, fn := range pr.laterFns { 79 fn() 80 } 81 82 for _, iface := range pr.ifaces { 83 iface.Complete() 84 } 85 86 pkg.MarkComplete() 87 return pkg 88 } 89 90 // A reader holds the state for reading a single unified IR element 91 // within a package. 92 type reader struct { 93 pkgbits.Decoder 94 95 p *pkgReader 96 97 dict *readerDict 98 } 99 100 // A readerDict holds the state for type parameters that parameterize 101 // the current unified IR element. 102 type readerDict struct { 103 // bounds is a slice of typeInfos corresponding to the underlying 104 // bounds of the element's type parameters. 105 bounds []typeInfo 106 107 // tparams is a slice of the constructed TypeParams for the element. 108 tparams []*types.TypeParam 109 110 // devived is a slice of types derived from tparams, which may be 111 // instantiated while reading the current element. 112 derived []derivedInfo 113 derivedTypes []types.Type // lazily instantiated from derived 114 } 115 116 func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { 117 return &reader{ 118 Decoder: pr.NewDecoder(k, idx, marker), 119 p: pr, 120 } 121 } 122 123 func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { 124 return &reader{ 125 Decoder: pr.TempDecoder(k, idx, marker), 126 p: pr, 127 } 128 } 129 130 func (pr *pkgReader) retireReader(r *reader) { 131 pr.RetireDecoder(&r.Decoder) 132 } 133 134 // @@@ Positions 135 136 func (r *reader) pos() token.Pos { 137 r.Sync(pkgbits.SyncPos) 138 if !r.Bool() { 139 return token.NoPos 140 } 141 142 // TODO(mdempsky): Delta encoding. 143 posBase := r.posBase() 144 line := r.Uint() 145 col := r.Uint() 146 return r.p.fake.pos(posBase, int(line), int(col)) 147 } 148 149 func (r *reader) posBase() string { 150 return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase)) 151 } 152 153 func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) string { 154 if b := pr.posBases[idx]; b != "" { 155 return b 156 } 157 158 var filename string 159 { 160 r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) 161 162 // Within types2, position bases have a lot more details (e.g., 163 // keeping track of where //line directives appeared exactly). 164 // 165 // For go/types, we just track the file name. 166 167 filename = r.String() 168 169 if r.Bool() { // file base 170 // Was: "b = token.NewTrimmedFileBase(filename, true)" 171 } else { // line base 172 pos := r.pos() 173 line := r.Uint() 174 col := r.Uint() 175 176 // Was: "b = token.NewLineBase(pos, filename, true, line, col)" 177 _, _, _ = pos, line, col 178 } 179 pr.retireReader(r) 180 } 181 b := filename 182 pr.posBases[idx] = b 183 return b 184 } 185 186 // @@@ Packages 187 188 func (r *reader) pkg() *types.Package { 189 r.Sync(pkgbits.SyncPkg) 190 return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg)) 191 } 192 193 func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Package { 194 // TODO(mdempsky): Consider using some non-nil pointer to indicate 195 // the universe scope, so we don't need to keep re-reading it. 196 if pkg := pr.pkgs[idx]; pkg != nil { 197 return pkg 198 } 199 200 pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg() 201 pr.pkgs[idx] = pkg 202 return pkg 203 } 204 205 func (r *reader) doPkg() *types.Package { 206 path := r.String() 207 switch path { 208 case "": 209 path = r.p.PkgPath() 210 case "builtin": 211 return nil // universe 212 case "unsafe": 213 return types.Unsafe 214 } 215 216 if pkg := r.p.imports[path]; pkg != nil { 217 return pkg 218 } 219 220 name := r.String() 221 222 pkg := types.NewPackage(path, name) 223 r.p.imports[path] = pkg 224 225 imports := make([]*types.Package, r.Len()) 226 for i := range imports { 227 imports[i] = r.pkg() 228 } 229 230 // The documentation for (*types.Package).Imports requires 231 // flattening the import graph when reading from export data, as 232 // obviously incorrect as that is. 233 // 234 // TODO(mdempsky): Remove this if go.dev/issue/54096 is accepted. 235 pkg.SetImports(flattenImports(imports)) 236 237 return pkg 238 } 239 240 // flattenImports returns the transitive closure of all imported 241 // packages rooted from pkgs. 242 func flattenImports(pkgs []*types.Package) []*types.Package { 243 var res []*types.Package 244 seen := make(map[*types.Package]struct{}) 245 for _, pkg := range pkgs { 246 if _, ok := seen[pkg]; ok { 247 continue 248 } 249 seen[pkg] = struct{}{} 250 res = append(res, pkg) 251 252 // pkg.Imports() is already flattened. 253 for _, pkg := range pkg.Imports() { 254 if _, ok := seen[pkg]; ok { 255 continue 256 } 257 seen[pkg] = struct{}{} 258 res = append(res, pkg) 259 } 260 } 261 return res 262 } 263 264 // @@@ Types 265 266 func (r *reader) typ() types.Type { 267 return r.p.typIdx(r.typInfo(), r.dict) 268 } 269 270 func (r *reader) typInfo() typeInfo { 271 r.Sync(pkgbits.SyncType) 272 if r.Bool() { 273 return typeInfo{idx: pkgbits.Index(r.Len()), derived: true} 274 } 275 return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false} 276 } 277 278 func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types.Type { 279 idx := info.idx 280 var where *types.Type 281 if info.derived { 282 where = &dict.derivedTypes[idx] 283 idx = dict.derived[idx].idx 284 } else { 285 where = &pr.typs[idx] 286 } 287 288 if typ := *where; typ != nil { 289 return typ 290 } 291 292 var typ types.Type 293 { 294 r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) 295 r.dict = dict 296 297 typ = r.doTyp() 298 assert(typ != nil) 299 pr.retireReader(r) 300 } 301 // See comment in pkgReader.typIdx explaining how this happens. 302 if prev := *where; prev != nil { 303 return prev 304 } 305 306 *where = typ 307 return typ 308 } 309 310 func (r *reader) doTyp() (res types.Type) { 311 switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag { 312 default: 313 errorf("unhandled type tag: %v", tag) 314 panic("unreachable") 315 316 case pkgbits.TypeBasic: 317 return types.Typ[r.Len()] 318 319 case pkgbits.TypeNamed: 320 obj, targs := r.obj() 321 name := obj.(*types.TypeName) 322 if len(targs) != 0 { 323 t, _ := types.Instantiate(r.p.ctxt, name.Type(), targs, false) 324 return t 325 } 326 return name.Type() 327 328 case pkgbits.TypeTypeParam: 329 return r.dict.tparams[r.Len()] 330 331 case pkgbits.TypeArray: 332 len := int64(r.Uint64()) 333 return types.NewArray(r.typ(), len) 334 case pkgbits.TypeChan: 335 dir := types.ChanDir(r.Len()) 336 return types.NewChan(dir, r.typ()) 337 case pkgbits.TypeMap: 338 return types.NewMap(r.typ(), r.typ()) 339 case pkgbits.TypePointer: 340 return types.NewPointer(r.typ()) 341 case pkgbits.TypeSignature: 342 return r.signature(nil, nil, nil) 343 case pkgbits.TypeSlice: 344 return types.NewSlice(r.typ()) 345 case pkgbits.TypeStruct: 346 return r.structType() 347 case pkgbits.TypeInterface: 348 return r.interfaceType() 349 case pkgbits.TypeUnion: 350 return r.unionType() 351 } 352 } 353 354 func (r *reader) structType() *types.Struct { 355 fields := make([]*types.Var, r.Len()) 356 var tags []string 357 for i := range fields { 358 pos := r.pos() 359 pkg, name := r.selector() 360 ftyp := r.typ() 361 tag := r.String() 362 embedded := r.Bool() 363 364 fields[i] = types.NewField(pos, pkg, name, ftyp, embedded) 365 if tag != "" { 366 for len(tags) < i { 367 tags = append(tags, "") 368 } 369 tags = append(tags, tag) 370 } 371 } 372 return types.NewStruct(fields, tags) 373 } 374 375 func (r *reader) unionType() *types.Union { 376 terms := make([]*types.Term, r.Len()) 377 for i := range terms { 378 terms[i] = types.NewTerm(r.Bool(), r.typ()) 379 } 380 return types.NewUnion(terms) 381 } 382 383 func (r *reader) interfaceType() *types.Interface { 384 methods := make([]*types.Func, r.Len()) 385 embeddeds := make([]types.Type, r.Len()) 386 implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool() 387 388 for i := range methods { 389 pos := r.pos() 390 pkg, name := r.selector() 391 mtyp := r.signature(nil, nil, nil) 392 methods[i] = types.NewFunc(pos, pkg, name, mtyp) 393 } 394 395 for i := range embeddeds { 396 embeddeds[i] = r.typ() 397 } 398 399 iface := types.NewInterfaceType(methods, embeddeds) 400 if implicit { 401 iface.MarkImplicit() 402 } 403 404 // We need to call iface.Complete(), but if there are any embedded 405 // defined types, then we may not have set their underlying 406 // interface type yet. So we need to defer calling Complete until 407 // after we've called SetUnderlying everywhere. 408 // 409 // TODO(mdempsky): After CL 424876 lands, it should be safe to call 410 // iface.Complete() immediately. 411 r.p.ifaces = append(r.p.ifaces, iface) 412 413 return iface 414 } 415 416 func (r *reader) signature(recv *types.Var, rtparams, tparams []*types.TypeParam) *types.Signature { 417 r.Sync(pkgbits.SyncSignature) 418 419 params := r.params() 420 results := r.params() 421 variadic := r.Bool() 422 423 return types.NewSignatureType(recv, rtparams, tparams, params, results, variadic) 424 } 425 426 func (r *reader) params() *types.Tuple { 427 r.Sync(pkgbits.SyncParams) 428 429 params := make([]*types.Var, r.Len()) 430 for i := range params { 431 params[i] = r.param() 432 } 433 434 return types.NewTuple(params...) 435 } 436 437 func (r *reader) param() *types.Var { 438 r.Sync(pkgbits.SyncParam) 439 440 pos := r.pos() 441 pkg, name := r.localIdent() 442 typ := r.typ() 443 444 return types.NewParam(pos, pkg, name, typ) 445 } 446 447 // @@@ Objects 448 449 func (r *reader) obj() (types.Object, []types.Type) { 450 r.Sync(pkgbits.SyncObject) 451 452 assert(!r.Bool()) 453 454 pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj)) 455 obj := pkgScope(pkg).Lookup(name) 456 457 targs := make([]types.Type, r.Len()) 458 for i := range targs { 459 targs[i] = r.typ() 460 } 461 462 return obj, targs 463 } 464 465 func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) { 466 467 var objPkg *types.Package 468 var objName string 469 var tag pkgbits.CodeObj 470 { 471 rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) 472 473 objPkg, objName = rname.qualifiedIdent() 474 assert(objName != "") 475 476 tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) 477 pr.retireReader(rname) 478 } 479 480 if tag == pkgbits.ObjStub { 481 assert(objPkg == nil || objPkg == types.Unsafe) 482 return objPkg, objName 483 } 484 485 // Ignore local types promoted to global scope (#55110). 486 if _, suffix := splitVargenSuffix(objName); suffix != "" { 487 return objPkg, objName 488 } 489 490 if objPkg.Scope().Lookup(objName) == nil { 491 dict := pr.objDictIdx(idx) 492 493 r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1) 494 r.dict = dict 495 496 declare := func(obj types.Object) { 497 objPkg.Scope().Insert(obj) 498 } 499 500 switch tag { 501 default: 502 panic("weird") 503 504 case pkgbits.ObjAlias: 505 pos := r.pos() 506 typ := r.typ() 507 declare(types.NewTypeName(pos, objPkg, objName, typ)) 508 509 case pkgbits.ObjConst: 510 pos := r.pos() 511 typ := r.typ() 512 val := r.Value() 513 declare(types.NewConst(pos, objPkg, objName, typ, val)) 514 515 case pkgbits.ObjFunc: 516 pos := r.pos() 517 tparams := r.typeParamNames() 518 sig := r.signature(nil, nil, tparams) 519 declare(types.NewFunc(pos, objPkg, objName, sig)) 520 521 case pkgbits.ObjType: 522 pos := r.pos() 523 524 obj := types.NewTypeName(pos, objPkg, objName, nil) 525 named := types.NewNamed(obj, nil, nil) 526 declare(obj) 527 528 named.SetTypeParams(r.typeParamNames()) 529 530 underlying := r.typ().Underlying() 531 532 // If the underlying type is an interface, we need to 533 // duplicate its methods so we can replace the receiver 534 // parameter's type (#49906). 535 if iface, ok := underlying.(*types.Interface); ok && iface.NumExplicitMethods() != 0 { 536 methods := make([]*types.Func, iface.NumExplicitMethods()) 537 for i := range methods { 538 fn := iface.ExplicitMethod(i) 539 sig := fn.Type().(*types.Signature) 540 541 recv := types.NewVar(fn.Pos(), fn.Pkg(), "", named) 542 methods[i] = types.NewFunc(fn.Pos(), fn.Pkg(), fn.Name(), types.NewSignature(recv, sig.Params(), sig.Results(), sig.Variadic())) 543 } 544 545 embeds := make([]types.Type, iface.NumEmbeddeds()) 546 for i := range embeds { 547 embeds[i] = iface.EmbeddedType(i) 548 } 549 550 newIface := types.NewInterfaceType(methods, embeds) 551 r.p.ifaces = append(r.p.ifaces, newIface) 552 underlying = newIface 553 } 554 555 named.SetUnderlying(underlying) 556 557 for i, n := 0, r.Len(); i < n; i++ { 558 named.AddMethod(r.method()) 559 } 560 561 case pkgbits.ObjVar: 562 pos := r.pos() 563 typ := r.typ() 564 declare(types.NewVar(pos, objPkg, objName, typ)) 565 } 566 } 567 568 return objPkg, objName 569 } 570 571 func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict { 572 573 var dict readerDict 574 575 { 576 r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) 577 if implicits := r.Len(); implicits != 0 { 578 errorf("unexpected object with %v implicit type parameter(s)", implicits) 579 } 580 581 dict.bounds = make([]typeInfo, r.Len()) 582 for i := range dict.bounds { 583 dict.bounds[i] = r.typInfo() 584 } 585 586 dict.derived = make([]derivedInfo, r.Len()) 587 dict.derivedTypes = make([]types.Type, len(dict.derived)) 588 for i := range dict.derived { 589 dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()} 590 } 591 592 pr.retireReader(r) 593 } 594 // function references follow, but reader doesn't need those 595 596 return &dict 597 } 598 599 func (r *reader) typeParamNames() []*types.TypeParam { 600 r.Sync(pkgbits.SyncTypeParamNames) 601 602 // Note: This code assumes it only processes objects without 603 // implement type parameters. This is currently fine, because 604 // reader is only used to read in exported declarations, which are 605 // always package scoped. 606 607 if len(r.dict.bounds) == 0 { 608 return nil 609 } 610 611 // Careful: Type parameter lists may have cycles. To allow for this, 612 // we construct the type parameter list in two passes: first we 613 // create all the TypeNames and TypeParams, then we construct and 614 // set the bound type. 615 616 r.dict.tparams = make([]*types.TypeParam, len(r.dict.bounds)) 617 for i := range r.dict.bounds { 618 pos := r.pos() 619 pkg, name := r.localIdent() 620 621 tname := types.NewTypeName(pos, pkg, name, nil) 622 r.dict.tparams[i] = types.NewTypeParam(tname, nil) 623 } 624 625 typs := make([]types.Type, len(r.dict.bounds)) 626 for i, bound := range r.dict.bounds { 627 typs[i] = r.p.typIdx(bound, r.dict) 628 } 629 630 // TODO(mdempsky): This is subtle, elaborate further. 631 // 632 // We have to save tparams outside of the closure, because 633 // typeParamNames() can be called multiple times with the same 634 // dictionary instance. 635 // 636 // Also, this needs to happen later to make sure SetUnderlying has 637 // been called. 638 // 639 // TODO(mdempsky): Is it safe to have a single "later" slice or do 640 // we need to have multiple passes? See comments on CL 386002 and 641 // go.dev/issue/52104. 642 tparams := r.dict.tparams 643 r.p.later(func() { 644 for i, typ := range typs { 645 tparams[i].SetConstraint(typ) 646 } 647 }) 648 649 return r.dict.tparams 650 } 651 652 func (r *reader) method() *types.Func { 653 r.Sync(pkgbits.SyncMethod) 654 pos := r.pos() 655 pkg, name := r.selector() 656 657 rparams := r.typeParamNames() 658 sig := r.signature(r.param(), rparams, nil) 659 660 _ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go. 661 return types.NewFunc(pos, pkg, name, sig) 662 } 663 664 func (r *reader) qualifiedIdent() (*types.Package, string) { return r.ident(pkgbits.SyncSym) } 665 func (r *reader) localIdent() (*types.Package, string) { return r.ident(pkgbits.SyncLocalIdent) } 666 func (r *reader) selector() (*types.Package, string) { return r.ident(pkgbits.SyncSelector) } 667 668 func (r *reader) ident(marker pkgbits.SyncMarker) (*types.Package, string) { 669 r.Sync(marker) 670 return r.pkg(), r.String() 671 } 672 673 // pkgScope returns pkg.Scope(). 674 // If pkg is nil, it returns types.Universe instead. 675 // 676 // TODO(mdempsky): Remove after x/tools can depend on Go 1.19. 677 func pkgScope(pkg *types.Package) *types.Scope { 678 if pkg != nil { 679 return pkg.Scope() 680 } 681 return types.Universe 682 }