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