github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/importer/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 importer 6 7 import ( 8 "github.com/go-asm/go/cmd/compile/base" 9 "github.com/go-asm/go/cmd/compile/syntax" 10 "github.com/go-asm/go/cmd/compile/types2" 11 "github.com/go-asm/go/cmd/src" 12 "github.com/go-asm/go/pkgbits" 13 ) 14 15 type pkgReader struct { 16 pkgbits.PkgDecoder 17 18 ctxt *types2.Context 19 imports map[string]*types2.Package 20 21 posBases []*syntax.PosBase 22 pkgs []*types2.Package 23 typs []types2.Type 24 } 25 26 func ReadPackage(ctxt *types2.Context, imports map[string]*types2.Package, input pkgbits.PkgDecoder) *types2.Package { 27 pr := pkgReader{ 28 PkgDecoder: input, 29 30 ctxt: ctxt, 31 imports: imports, 32 33 posBases: make([]*syntax.PosBase, input.NumElems(pkgbits.RelocPosBase)), 34 pkgs: make([]*types2.Package, input.NumElems(pkgbits.RelocPkg)), 35 typs: make([]types2.Type, input.NumElems(pkgbits.RelocType)), 36 } 37 38 r := pr.newReader(pkgbits.RelocMeta, pkgbits.PublicRootIdx, pkgbits.SyncPublic) 39 pkg := r.pkg() 40 r.Bool() // TODO(mdempsky): Remove; was "has init" 41 42 for i, n := 0, r.Len(); i < n; i++ { 43 // As if r.obj(), but avoiding the Scope.Lookup call, 44 // to avoid eager loading of imports. 45 r.Sync(pkgbits.SyncObject) 46 assert(!r.Bool()) 47 r.p.objIdx(r.Reloc(pkgbits.RelocObj)) 48 assert(r.Len() == 0) 49 } 50 51 r.Sync(pkgbits.SyncEOF) 52 53 pkg.MarkComplete() 54 return pkg 55 } 56 57 type reader struct { 58 pkgbits.Decoder 59 60 p *pkgReader 61 62 dict *readerDict 63 } 64 65 type readerDict struct { 66 bounds []typeInfo 67 68 tparams []*types2.TypeParam 69 70 derived []derivedInfo 71 derivedTypes []types2.Type 72 } 73 74 type readerTypeBound struct { 75 derived bool 76 boundIdx int 77 } 78 79 func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { 80 return &reader{ 81 Decoder: pr.NewDecoder(k, idx, marker), 82 p: pr, 83 } 84 } 85 86 func (pr *pkgReader) tempReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { 87 return &reader{ 88 Decoder: pr.TempDecoder(k, idx, marker), 89 p: pr, 90 } 91 } 92 93 func (pr *pkgReader) retireReader(r *reader) { 94 pr.RetireDecoder(&r.Decoder) 95 } 96 97 // @@@ Positions 98 99 func (r *reader) pos() syntax.Pos { 100 r.Sync(pkgbits.SyncPos) 101 if !r.Bool() { 102 return syntax.Pos{} 103 } 104 105 // TODO(mdempsky): Delta encoding. 106 posBase := r.posBase() 107 line := r.Uint() 108 col := r.Uint() 109 return syntax.MakePos(posBase, line, col) 110 } 111 112 func (r *reader) posBase() *syntax.PosBase { 113 return r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase)) 114 } 115 116 func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *syntax.PosBase { 117 if b := pr.posBases[idx]; b != nil { 118 return b 119 } 120 var b *syntax.PosBase 121 { 122 r := pr.tempReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) 123 124 filename := r.String() 125 126 if r.Bool() { 127 b = syntax.NewTrimmedFileBase(filename, true) 128 } else { 129 pos := r.pos() 130 line := r.Uint() 131 col := r.Uint() 132 b = syntax.NewLineBase(pos, filename, true, line, col) 133 } 134 pr.retireReader(r) 135 } 136 137 pr.posBases[idx] = b 138 return b 139 } 140 141 // @@@ Packages 142 143 func (r *reader) pkg() *types2.Package { 144 r.Sync(pkgbits.SyncPkg) 145 return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg)) 146 } 147 148 func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types2.Package { 149 // TODO(mdempsky): Consider using some non-nil pointer to indicate 150 // the universe scope, so we don't need to keep re-reading it. 151 if pkg := pr.pkgs[idx]; pkg != nil { 152 return pkg 153 } 154 155 pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg() 156 pr.pkgs[idx] = pkg 157 return pkg 158 } 159 160 func (r *reader) doPkg() *types2.Package { 161 path := r.String() 162 switch path { 163 case "": 164 path = r.p.PkgPath() 165 case "builtin": 166 return nil // universe 167 case "unsafe": 168 return types2.Unsafe 169 } 170 171 if pkg := r.p.imports[path]; pkg != nil { 172 return pkg 173 } 174 175 name := r.String() 176 pkg := types2.NewPackage(path, name) 177 r.p.imports[path] = pkg 178 179 // TODO(mdempsky): The list of imported packages is important for 180 // go/types, but we could probably skip populating it for types2. 181 imports := make([]*types2.Package, r.Len()) 182 for i := range imports { 183 imports[i] = r.pkg() 184 } 185 pkg.SetImports(imports) 186 187 return pkg 188 } 189 190 // @@@ Types 191 192 func (r *reader) typ() types2.Type { 193 return r.p.typIdx(r.typInfo(), r.dict) 194 } 195 196 func (r *reader) typInfo() typeInfo { 197 r.Sync(pkgbits.SyncType) 198 if r.Bool() { 199 return typeInfo{idx: pkgbits.Index(r.Len()), derived: true} 200 } 201 return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false} 202 } 203 204 func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict) types2.Type { 205 idx := info.idx 206 var where *types2.Type 207 if info.derived { 208 where = &dict.derivedTypes[idx] 209 idx = dict.derived[idx].idx 210 } else { 211 where = &pr.typs[idx] 212 } 213 214 if typ := *where; typ != nil { 215 return typ 216 } 217 218 var typ types2.Type 219 { 220 r := pr.tempReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) 221 r.dict = dict 222 223 typ = r.doTyp() 224 assert(typ != nil) 225 pr.retireReader(r) 226 } 227 228 // See comment in pkgReader.typIdx explaining how this happens. 229 if prev := *where; prev != nil { 230 return prev 231 } 232 233 *where = typ 234 return typ 235 } 236 237 func (r *reader) doTyp() (res types2.Type) { 238 switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag { 239 default: 240 base.FatalfAt(src.NoXPos, "unhandled type tag: %v", tag) 241 panic("unreachable") 242 243 case pkgbits.TypeBasic: 244 return types2.Typ[r.Len()] 245 246 case pkgbits.TypeNamed: 247 obj, targs := r.obj() 248 name := obj.(*types2.TypeName) 249 if len(targs) != 0 { 250 t, _ := types2.Instantiate(r.p.ctxt, name.Type(), targs, false) 251 return t 252 } 253 return name.Type() 254 255 case pkgbits.TypeTypeParam: 256 return r.dict.tparams[r.Len()] 257 258 case pkgbits.TypeArray: 259 len := int64(r.Uint64()) 260 return types2.NewArray(r.typ(), len) 261 case pkgbits.TypeChan: 262 dir := types2.ChanDir(r.Len()) 263 return types2.NewChan(dir, r.typ()) 264 case pkgbits.TypeMap: 265 return types2.NewMap(r.typ(), r.typ()) 266 case pkgbits.TypePointer: 267 return types2.NewPointer(r.typ()) 268 case pkgbits.TypeSignature: 269 return r.signature(nil, nil, nil) 270 case pkgbits.TypeSlice: 271 return types2.NewSlice(r.typ()) 272 case pkgbits.TypeStruct: 273 return r.structType() 274 case pkgbits.TypeInterface: 275 return r.interfaceType() 276 case pkgbits.TypeUnion: 277 return r.unionType() 278 } 279 } 280 281 func (r *reader) structType() *types2.Struct { 282 fields := make([]*types2.Var, r.Len()) 283 var tags []string 284 for i := range fields { 285 pos := r.pos() 286 pkg, name := r.selector() 287 ftyp := r.typ() 288 tag := r.String() 289 embedded := r.Bool() 290 291 fields[i] = types2.NewField(pos, pkg, name, ftyp, embedded) 292 if tag != "" { 293 for len(tags) < i { 294 tags = append(tags, "") 295 } 296 tags = append(tags, tag) 297 } 298 } 299 return types2.NewStruct(fields, tags) 300 } 301 302 func (r *reader) unionType() *types2.Union { 303 terms := make([]*types2.Term, r.Len()) 304 for i := range terms { 305 terms[i] = types2.NewTerm(r.Bool(), r.typ()) 306 } 307 return types2.NewUnion(terms) 308 } 309 310 func (r *reader) interfaceType() *types2.Interface { 311 methods := make([]*types2.Func, r.Len()) 312 embeddeds := make([]types2.Type, r.Len()) 313 implicit := len(methods) == 0 && len(embeddeds) == 1 && r.Bool() 314 315 for i := range methods { 316 pos := r.pos() 317 pkg, name := r.selector() 318 mtyp := r.signature(nil, nil, nil) 319 methods[i] = types2.NewFunc(pos, pkg, name, mtyp) 320 } 321 322 for i := range embeddeds { 323 embeddeds[i] = r.typ() 324 } 325 326 iface := types2.NewInterfaceType(methods, embeddeds) 327 if implicit { 328 iface.MarkImplicit() 329 } 330 return iface 331 } 332 333 func (r *reader) signature(recv *types2.Var, rtparams, tparams []*types2.TypeParam) *types2.Signature { 334 r.Sync(pkgbits.SyncSignature) 335 336 params := r.params() 337 results := r.params() 338 variadic := r.Bool() 339 340 return types2.NewSignatureType(recv, rtparams, tparams, params, results, variadic) 341 } 342 343 func (r *reader) params() *types2.Tuple { 344 r.Sync(pkgbits.SyncParams) 345 params := make([]*types2.Var, r.Len()) 346 for i := range params { 347 params[i] = r.param() 348 } 349 return types2.NewTuple(params...) 350 } 351 352 func (r *reader) param() *types2.Var { 353 r.Sync(pkgbits.SyncParam) 354 355 pos := r.pos() 356 pkg, name := r.localIdent() 357 typ := r.typ() 358 359 return types2.NewParam(pos, pkg, name, typ) 360 } 361 362 // @@@ Objects 363 364 func (r *reader) obj() (types2.Object, []types2.Type) { 365 r.Sync(pkgbits.SyncObject) 366 367 assert(!r.Bool()) 368 369 pkg, name := r.p.objIdx(r.Reloc(pkgbits.RelocObj)) 370 obj := pkg.Scope().Lookup(name) 371 372 targs := make([]types2.Type, r.Len()) 373 for i := range targs { 374 targs[i] = r.typ() 375 } 376 377 return obj, targs 378 } 379 380 func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) { 381 var objPkg *types2.Package 382 var objName string 383 var tag pkgbits.CodeObj 384 { 385 rname := pr.tempReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) 386 387 objPkg, objName = rname.qualifiedIdent() 388 assert(objName != "") 389 390 tag = pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) 391 pr.retireReader(rname) 392 } 393 394 if tag == pkgbits.ObjStub { 395 base.Assertf(objPkg == nil || objPkg == types2.Unsafe, "unexpected stub package: %v", objPkg) 396 return objPkg, objName 397 } 398 399 objPkg.Scope().InsertLazy(objName, func() types2.Object { 400 dict := pr.objDictIdx(idx) 401 402 r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1) 403 r.dict = dict 404 405 switch tag { 406 default: 407 panic("weird") 408 409 case pkgbits.ObjAlias: 410 pos := r.pos() 411 typ := r.typ() 412 return types2.NewTypeName(pos, objPkg, objName, typ) 413 414 case pkgbits.ObjConst: 415 pos := r.pos() 416 typ := r.typ() 417 val := r.Value() 418 return types2.NewConst(pos, objPkg, objName, typ, val) 419 420 case pkgbits.ObjFunc: 421 pos := r.pos() 422 tparams := r.typeParamNames() 423 sig := r.signature(nil, nil, tparams) 424 return types2.NewFunc(pos, objPkg, objName, sig) 425 426 case pkgbits.ObjType: 427 pos := r.pos() 428 429 return types2.NewTypeNameLazy(pos, objPkg, objName, func(named *types2.Named) (tparams []*types2.TypeParam, underlying types2.Type, methods []*types2.Func) { 430 tparams = r.typeParamNames() 431 432 // TODO(mdempsky): Rewrite receiver types to underlying is an 433 // Interface? The go/types importer does this (I think because 434 // unit tests expected that), but cmd/compile doesn't care 435 // about it, so maybe we can avoid worrying about that here. 436 underlying = r.typ().Underlying() 437 438 methods = make([]*types2.Func, r.Len()) 439 for i := range methods { 440 methods[i] = r.method() 441 } 442 443 return 444 }) 445 446 case pkgbits.ObjVar: 447 pos := r.pos() 448 typ := r.typ() 449 return types2.NewVar(pos, objPkg, objName, typ) 450 } 451 }) 452 453 return objPkg, objName 454 } 455 456 func (pr *pkgReader) objDictIdx(idx pkgbits.Index) *readerDict { 457 var dict readerDict 458 { 459 r := pr.tempReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) 460 461 if implicits := r.Len(); implicits != 0 { 462 base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits) 463 } 464 465 dict.bounds = make([]typeInfo, r.Len()) 466 for i := range dict.bounds { 467 dict.bounds[i] = r.typInfo() 468 } 469 470 dict.derived = make([]derivedInfo, r.Len()) 471 dict.derivedTypes = make([]types2.Type, len(dict.derived)) 472 for i := range dict.derived { 473 dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()} 474 } 475 476 pr.retireReader(r) 477 } 478 // function references follow, but reader doesn't need those 479 480 return &dict 481 } 482 483 func (r *reader) typeParamNames() []*types2.TypeParam { 484 r.Sync(pkgbits.SyncTypeParamNames) 485 486 // Note: This code assumes it only processes objects without 487 // implement type parameters. This is currently fine, because 488 // reader is only used to read in exported declarations, which are 489 // always package scoped. 490 491 if len(r.dict.bounds) == 0 { 492 return nil 493 } 494 495 // Careful: Type parameter lists may have cycles. To allow for this, 496 // we construct the type parameter list in two passes: first we 497 // create all the TypeNames and TypeParams, then we construct and 498 // set the bound type. 499 500 r.dict.tparams = make([]*types2.TypeParam, len(r.dict.bounds)) 501 for i := range r.dict.bounds { 502 pos := r.pos() 503 pkg, name := r.localIdent() 504 505 tname := types2.NewTypeName(pos, pkg, name, nil) 506 r.dict.tparams[i] = types2.NewTypeParam(tname, nil) 507 } 508 509 for i, bound := range r.dict.bounds { 510 r.dict.tparams[i].SetConstraint(r.p.typIdx(bound, r.dict)) 511 } 512 513 return r.dict.tparams 514 } 515 516 func (r *reader) method() *types2.Func { 517 r.Sync(pkgbits.SyncMethod) 518 pos := r.pos() 519 pkg, name := r.selector() 520 521 rtparams := r.typeParamNames() 522 sig := r.signature(r.param(), rtparams, nil) 523 524 _ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go. 525 return types2.NewFunc(pos, pkg, name, sig) 526 } 527 528 func (r *reader) qualifiedIdent() (*types2.Package, string) { return r.ident(pkgbits.SyncSym) } 529 func (r *reader) localIdent() (*types2.Package, string) { return r.ident(pkgbits.SyncLocalIdent) } 530 func (r *reader) selector() (*types2.Package, string) { return r.ident(pkgbits.SyncSelector) } 531 532 func (r *reader) ident(marker pkgbits.SyncMarker) (*types2.Package, string) { 533 r.Sync(marker) 534 return r.pkg(), r.String() 535 }