1// UNREVIEWED 2 3// Copyright 2021 The Go Authors. All rights reserved. 4// Use of this source code is governed by a BSD-style 5// license that can be found in the LICENSE file. 6 7package noder 8 9import ( 10 "cmd/compile/internal/base" 11 "cmd/compile/internal/syntax" 12 "cmd/compile/internal/types2" 13 "cmd/internal/src" 14) 15 16type pkgReader2 struct { 17 pkgDecoder 18 19 ctxt *types2.Context 20 imports map[string]*types2.Package 21 22 posBases []*syntax.PosBase 23 pkgs []*types2.Package 24 typs []types2.Type 25} 26 27func readPackage2(ctxt *types2.Context, imports map[string]*types2.Package, input pkgDecoder) *types2.Package { 28 pr := pkgReader2{ 29 pkgDecoder: input, 30 31 ctxt: ctxt, 32 imports: imports, 33 34 posBases: make([]*syntax.PosBase, input.numElems(relocPosBase)), 35 pkgs: make([]*types2.Package, input.numElems(relocPkg)), 36 typs: make([]types2.Type, input.numElems(relocType)), 37 } 38 39 r := pr.newReader(relocMeta, publicRootIdx, syncPublic) 40 pkg := r.pkg() 41 r.bool() // has init 42 43 for i, n := 0, r.len(); i < n; i++ { 44 // As if r.obj(), but avoiding the Scope.Lookup call, 45 // to avoid eager loading of imports. 46 r.sync(syncObject) 47 assert(!r.bool()) 48 r.p.objIdx(r.reloc(relocObj)) 49 assert(r.len() == 0) 50 } 51 52 r.sync(syncEOF) 53 54 pkg.MarkComplete() 55 return pkg 56} 57 58type reader2 struct { 59 decoder 60 61 p *pkgReader2 62 63 dict *reader2Dict 64} 65 66type reader2Dict struct { 67 bounds []typeInfo 68 69 tparams []*types2.TypeParam 70 71 derived []derivedInfo 72 derivedTypes []types2.Type 73} 74 75type reader2TypeBound struct { 76 derived bool 77 boundIdx int 78} 79 80func (pr *pkgReader2) newReader(k reloc, idx int, marker syncMarker) *reader2 { 81 return &reader2{ 82 decoder: pr.newDecoder(k, idx, marker), 83 p: pr, 84 } 85} 86 87// @@@ Positions 88 89func (r *reader2) pos() syntax.Pos { 90 r.sync(syncPos) 91 if !r.bool() { 92 return syntax.Pos{} 93 } 94 95 // TODO(mdempsky): Delta encoding. 96 posBase := r.posBase() 97 line := r.uint() 98 col := r.uint() 99 return syntax.MakePos(posBase, line, col) 100} 101 102func (r *reader2) posBase() *syntax.PosBase { 103 return r.p.posBaseIdx(r.reloc(relocPosBase)) 104} 105 106func (pr *pkgReader2) posBaseIdx(idx int) *syntax.PosBase { 107 if b := pr.posBases[idx]; b != nil { 108 return b 109 } 110 111 r := pr.newReader(relocPosBase, idx, syncPosBase) 112 var b *syntax.PosBase 113 114 filename := r.string() 115 116 if r.bool() { 117 b = syntax.NewTrimmedFileBase(filename, true) 118 } else { 119 pos := r.pos() 120 line := r.uint() 121 col := r.uint() 122 b = syntax.NewLineBase(pos, filename, true, line, col) 123 } 124 125 pr.posBases[idx] = b 126 return b 127} 128 129// @@@ Packages 130 131func (r *reader2) pkg() *types2.Package { 132 r.sync(syncPkg) 133 return r.p.pkgIdx(r.reloc(relocPkg)) 134} 135 136func (pr *pkgReader2) pkgIdx(idx int) *types2.Package { 137 // TODO(mdempsky): Consider using some non-nil pointer to indicate 138 // the universe scope, so we don't need to keep re-reading it. 139 if pkg := pr.pkgs[idx]; pkg != nil { 140 return pkg 141 } 142 143 pkg := pr.newReader(relocPkg, idx, syncPkgDef).doPkg() 144 pr.pkgs[idx] = pkg 145 return pkg 146} 147 148func (r *reader2) doPkg() *types2.Package { 149 path := r.string() 150 if path == "builtin" { 151 return nil // universe 152 } 153 if path == "" { 154 path = r.p.pkgPath 155 } 156 157 if pkg := r.p.imports[path]; pkg != nil { 158 return pkg 159 } 160 161 name := r.string() 162 height := r.len() 163 164 pkg := types2.NewPackageHeight(path, name, height) 165 r.p.imports[path] = pkg 166 167 // TODO(mdempsky): The list of imported packages is important for 168 // go/types, but we could probably skip populating it for types2. 169 imports := make([]*types2.Package, r.len()) 170 for i := range imports { 171 imports[i] = r.pkg() 172 } 173 pkg.SetImports(imports) 174 175 return pkg 176} 177 178// @@@ Types 179 180func (r *reader2) typ() types2.Type { 181 return r.p.typIdx(r.typInfo(), r.dict) 182} 183 184func (r *reader2) typInfo() typeInfo { 185 r.sync(syncType) 186 if r.bool() { 187 return typeInfo{idx: r.len(), derived: true} 188 } 189 return typeInfo{idx: r.reloc(relocType), derived: false} 190} 191 192func (pr *pkgReader2) typIdx(info typeInfo, dict *reader2Dict) types2.Type { 193 idx := info.idx 194 var where *types2.Type 195 if info.derived { 196 where = &dict.derivedTypes[idx] 197 idx = dict.derived[idx].idx 198 } else { 199 where = &pr.typs[idx] 200 } 201 202 if typ := *where; typ != nil { 203 return typ 204 } 205 206 r := pr.newReader(relocType, idx, syncTypeIdx) 207 r.dict = dict 208 209 typ := r.doTyp() 210 assert(typ != nil) 211 212 // See comment in pkgReader.typIdx explaining how this happens. 213 if prev := *where; prev != nil { 214 return prev 215 } 216 217 *where = typ 218 return typ 219} 220 221func (r *reader2) doTyp() (res types2.Type) { 222 switch tag := codeType(r.code(syncType)); tag { 223 default: 224 base.FatalfAt(src.NoXPos, "unhandled type tag: %v", tag) 225 panic("unreachable") 226 227 case typeBasic: 228 return types2.Typ[r.len()] 229 230 case typeNamed: 231 obj, targs := r.obj() 232 name := obj.(*types2.TypeName) 233 if len(targs) != 0 { 234 t, _ := types2.Instantiate(r.p.ctxt, name.Type(), targs, false) 235 return t 236 } 237 return name.Type() 238 239 case typeTypeParam: 240 return r.dict.tparams[r.len()] 241 242 case typeArray: 243 len := int64(r.uint64()) 244 return types2.NewArray(r.typ(), len) 245 case typeChan: 246 dir := types2.ChanDir(r.len()) 247 return types2.NewChan(dir, r.typ()) 248 case typeMap: 249 return types2.NewMap(r.typ(), r.typ()) 250 case typePointer: 251 return types2.NewPointer(r.typ()) 252 case typeSignature: 253 return r.signature(nil) 254 case typeSlice: 255 return types2.NewSlice(r.typ()) 256 case typeStruct: 257 return r.structType() 258 case typeInterface: 259 return r.interfaceType() 260 case typeUnion: 261 return r.unionType() 262 } 263} 264 265func (r *reader2) structType() *types2.Struct { 266 fields := make([]*types2.Var, r.len()) 267 var tags []string 268 for i := range fields { 269 pos := r.pos() 270 pkg, name := r.selector() 271 ftyp := r.typ() 272 tag := r.string() 273 embedded := r.bool() 274 275 fields[i] = types2.NewField(pos, pkg, name, ftyp, embedded) 276 if tag != "" { 277 for len(tags) < i { 278 tags = append(tags, "") 279 } 280 tags = append(tags, tag) 281 } 282 } 283 return types2.NewStruct(fields, tags) 284} 285 286func (r *reader2) unionType() *types2.Union { 287 terms := make([]*types2.Term, r.len()) 288 for i := range terms { 289 terms[i] = types2.NewTerm(r.bool(), r.typ()) 290 } 291 return types2.NewUnion(terms) 292} 293 294func (r *reader2) interfaceType() *types2.Interface { 295 methods := make([]*types2.Func, r.len()) 296 embeddeds := make([]types2.Type, r.len()) 297 298 for i := range methods { 299 pos := r.pos() 300 pkg, name := r.selector() 301 mtyp := r.signature(nil) 302 methods[i] = types2.NewFunc(pos, pkg, name, mtyp) 303 } 304 305 for i := range embeddeds { 306 embeddeds[i] = r.typ() 307 } 308 309 return types2.NewInterfaceType(methods, embeddeds) 310} 311 312func (r *reader2) signature(recv *types2.Var) *types2.Signature { 313 r.sync(syncSignature) 314 315 params := r.params() 316 results := r.params() 317 variadic := r.bool() 318 319 return types2.NewSignatureType(recv, nil, nil, params, results, variadic) 320} 321 322func (r *reader2) params() *types2.Tuple { 323 r.sync(syncParams) 324 params := make([]*types2.Var, r.len()) 325 for i := range params { 326 params[i] = r.param() 327 } 328 return types2.NewTuple(params...) 329} 330 331func (r *reader2) param() *types2.Var { 332 r.sync(syncParam) 333 334 pos := r.pos() 335 pkg, name := r.localIdent() 336 typ := r.typ() 337 338 return types2.NewParam(pos, pkg, name, typ) 339} 340 341// @@@ Objects 342 343func (r *reader2) obj() (types2.Object, []types2.Type) { 344 r.sync(syncObject) 345 346 assert(!r.bool()) 347 348 pkg, name := r.p.objIdx(r.reloc(relocObj)) 349 obj := pkg.Scope().Lookup(name) 350 351 targs := make([]types2.Type, r.len()) 352 for i := range targs { 353 targs[i] = r.typ() 354 } 355 356 return obj, targs 357} 358 359func (pr *pkgReader2) objIdx(idx int) (*types2.Package, string) { 360 rname := pr.newReader(relocName, idx, syncObject1) 361 362 objPkg, objName := rname.qualifiedIdent() 363 assert(objName != "") 364 365 tag := codeObj(rname.code(syncCodeObj)) 366 367 if tag == objStub { 368 assert(objPkg == nil || objPkg == types2.Unsafe) 369 return objPkg, objName 370 } 371 372 dict := pr.objDictIdx(idx) 373 374 r := pr.newReader(relocObj, idx, syncObject1) 375 r.dict = dict 376 377 objPkg.Scope().InsertLazy(objName, func() types2.Object { 378 switch tag { 379 default: 380 panic("weird") 381 382 case objAlias: 383 pos := r.pos() 384 typ := r.typ() 385 return types2.NewTypeName(pos, objPkg, objName, typ) 386 387 case objConst: 388 pos := r.pos() 389 typ := r.typ() 390 val := r.value() 391 return types2.NewConst(pos, objPkg, objName, typ, val) 392 393 case objFunc: 394 pos := r.pos() 395 tparams := r.typeParamNames() 396 sig := r.signature(nil) 397 sig.SetTypeParams(tparams) 398 return types2.NewFunc(pos, objPkg, objName, sig) 399 400 case objType: 401 pos := r.pos() 402 403 return types2.NewTypeNameLazy(pos, objPkg, objName, func(named *types2.Named) (tparams []*types2.TypeParam, underlying types2.Type, methods []*types2.Func) { 404 tparams = r.typeParamNames() 405 406 // TODO(mdempsky): Rewrite receiver types to underlying is an 407 // Interface? The go/types importer does this (I think because 408 // unit tests expected that), but cmd/compile doesn't care 409 // about it, so maybe we can avoid worrying about that here. 410 underlying = r.typ().Underlying() 411 412 methods = make([]*types2.Func, r.len()) 413 for i := range methods { 414 methods[i] = r.method() 415 } 416 417 return 418 }) 419 420 case objVar: 421 pos := r.pos() 422 typ := r.typ() 423 return types2.NewVar(pos, objPkg, objName, typ) 424 } 425 }) 426 427 return objPkg, objName 428} 429 430func (pr *pkgReader2) objDictIdx(idx int) *reader2Dict { 431 r := pr.newReader(relocObjDict, idx, syncObject1) 432 433 var dict reader2Dict 434 435 if implicits := r.len(); implicits != 0 { 436 base.Fatalf("unexpected object with %v implicit type parameter(s)", implicits) 437 } 438 439 dict.bounds = make([]typeInfo, r.len()) 440 for i := range dict.bounds { 441 dict.bounds[i] = r.typInfo() 442 } 443 444 dict.derived = make([]derivedInfo, r.len()) 445 dict.derivedTypes = make([]types2.Type, len(dict.derived)) 446 for i := range dict.derived { 447 dict.derived[i] = derivedInfo{r.reloc(relocType), r.bool()} 448 } 449 450 // function references follow, but reader2 doesn't need those 451 452 return &dict 453} 454 455func (r *reader2) typeParamNames() []*types2.TypeParam { 456 r.sync(syncTypeParamNames) 457 458 // Note: This code assumes it only processes objects without 459 // implement type parameters. This is currently fine, because 460 // reader2 is only used to read in exported declarations, which are 461 // always package scoped. 462 463 if len(r.dict.bounds) == 0 { 464 return nil 465 } 466 467 // Careful: Type parameter lists may have cycles. To allow for this, 468 // we construct the type parameter list in two passes: first we 469 // create all the TypeNames and TypeParams, then we construct and 470 // set the bound type. 471 472 r.dict.tparams = make([]*types2.TypeParam, len(r.dict.bounds)) 473 for i := range r.dict.bounds { 474 pos := r.pos() 475 pkg, name := r.localIdent() 476 477 tname := types2.NewTypeName(pos, pkg, name, nil) 478 r.dict.tparams[i] = types2.NewTypeParam(tname, nil) 479 } 480 481 for i, bound := range r.dict.bounds { 482 r.dict.tparams[i].SetConstraint(r.p.typIdx(bound, r.dict)) 483 } 484 485 return r.dict.tparams 486} 487 488func (r *reader2) method() *types2.Func { 489 r.sync(syncMethod) 490 pos := r.pos() 491 pkg, name := r.selector() 492 493 rparams := r.typeParamNames() 494 sig := r.signature(r.param()) 495 sig.SetRecvTypeParams(rparams) 496 497 _ = r.pos() // TODO(mdempsky): Remove; this is a hacker for linker.go. 498 return types2.NewFunc(pos, pkg, name, sig) 499} 500 501func (r *reader2) qualifiedIdent() (*types2.Package, string) { return r.ident(syncSym) } 502func (r *reader2) localIdent() (*types2.Package, string) { return r.ident(syncLocalIdent) } 503func (r *reader2) selector() (*types2.Package, string) { return r.ident(syncSelector) } 504 505func (r *reader2) ident(marker syncMarker) (*types2.Package, string) { 506 r.sync(marker) 507 return r.pkg(), r.string() 508} 509