github.com/bir3/gocompiler@v0.9.2202/src/cmd/compile/internal/noder/writer.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 noder 6 7 import ( 8 "fmt" 9 "github.com/bir3/gocompiler/src/go/constant" 10 "github.com/bir3/gocompiler/src/go/token" 11 "github.com/bir3/gocompiler/src/go/version" 12 "github.com/bir3/gocompiler/src/internal/buildcfg" 13 "github.com/bir3/gocompiler/src/internal/pkgbits" 14 "os" 15 16 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 17 "github.com/bir3/gocompiler/src/cmd/compile/internal/ir" 18 "github.com/bir3/gocompiler/src/cmd/compile/internal/syntax" 19 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 20 "github.com/bir3/gocompiler/src/cmd/compile/internal/types2" 21 ) 22 23 // This file implements the Unified IR package writer and defines the 24 // Unified IR export data format. 25 // 26 // Low-level coding details (e.g., byte-encoding of individual 27 // primitive values, or handling element bitstreams and 28 // cross-references) are handled by internal/pkgbits, so here we only 29 // concern ourselves with higher-level worries like mapping Go 30 // language constructs into elements. 31 32 // There are two central types in the writing process: the "writer" 33 // type handles writing out individual elements, while the "pkgWriter" 34 // type keeps track of which elements have already been created. 35 // 36 // For each sort of "thing" (e.g., position, package, object, type) 37 // that can be written into the export data, there are generally 38 // several methods that work together: 39 // 40 // - writer.thing handles writing out a *use* of a thing, which often 41 // means writing a relocation to that thing's encoded index. 42 // 43 // - pkgWriter.thingIdx handles reserving an index for a thing, and 44 // writing out any elements needed for the thing. 45 // 46 // - writer.doThing handles writing out the *definition* of a thing, 47 // which in general is a mix of low-level coding primitives (e.g., 48 // ints and strings) or uses of other things. 49 // 50 // A design goal of Unified IR is to have a single, canonical writer 51 // implementation, but multiple reader implementations each tailored 52 // to their respective needs. For example, within cmd/compile's own 53 // backend, inlining is implemented largely by just re-running the 54 // function body reading code. 55 56 // TODO(mdempsky): Add an importer for Unified IR to the x/tools repo, 57 // and better document the file format boundary between public and 58 // private data. 59 60 // A pkgWriter constructs Unified IR export data from the results of 61 // running the types2 type checker on a Go compilation unit. 62 type pkgWriter struct { 63 pkgbits.PkgEncoder 64 65 m posMap 66 curpkg *types2.Package 67 info *types2.Info 68 69 // Indices for previously written syntax and types2 things. 70 71 posBasesIdx map[*syntax.PosBase]pkgbits.Index 72 pkgsIdx map[*types2.Package]pkgbits.Index 73 typsIdx map[types2.Type]pkgbits.Index 74 objsIdx map[types2.Object]pkgbits.Index 75 76 // Maps from types2.Objects back to their syntax.Decl. 77 78 funDecls map[*types2.Func]*syntax.FuncDecl 79 typDecls map[*types2.TypeName]typeDeclGen 80 81 // linknames maps package-scope objects to their linker symbol name, 82 // if specified by a //go:linkname directive. 83 linknames map[types2.Object]string 84 85 // cgoPragmas accumulates any //go:cgo_* pragmas that need to be 86 // passed through to cmd/link. 87 cgoPragmas [][]string 88 } 89 90 // newPkgWriter returns an initialized pkgWriter for the specified 91 // package. 92 func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter { 93 return &pkgWriter{ 94 PkgEncoder: pkgbits.NewPkgEncoder(base.Debug.SyncFrames), 95 96 m: m, 97 curpkg: pkg, 98 info: info, 99 100 pkgsIdx: make(map[*types2.Package]pkgbits.Index), 101 objsIdx: make(map[types2.Object]pkgbits.Index), 102 typsIdx: make(map[types2.Type]pkgbits.Index), 103 104 posBasesIdx: make(map[*syntax.PosBase]pkgbits.Index), 105 106 funDecls: make(map[*types2.Func]*syntax.FuncDecl), 107 typDecls: make(map[*types2.TypeName]typeDeclGen), 108 109 linknames: make(map[types2.Object]string), 110 } 111 } 112 113 // errorf reports a user error about thing p. 114 func (pw *pkgWriter) errorf(p poser, msg string, args ...interface{}) { 115 base.ErrorfAt(pw.m.pos(p), 0, msg, args...) 116 } 117 118 // fatalf reports an internal compiler error about thing p. 119 func (pw *pkgWriter) fatalf(p poser, msg string, args ...interface{}) { 120 base.FatalfAt(pw.m.pos(p), msg, args...) 121 } 122 123 // unexpected reports a fatal error about a thing of unexpected 124 // dynamic type. 125 func (pw *pkgWriter) unexpected(what string, p poser) { 126 pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p) 127 } 128 129 func (pw *pkgWriter) typeAndValue(x syntax.Expr) syntax.TypeAndValue { 130 tv, ok := pw.maybeTypeAndValue(x) 131 if !ok { 132 pw.fatalf(x, "missing Types entry: %v", syntax.String(x)) 133 } 134 return tv 135 } 136 137 func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (syntax.TypeAndValue, bool) { 138 tv := x.GetTypeInfo() 139 140 // If x is a generic function whose type arguments are inferred 141 // from assignment context, then we need to find its inferred type 142 // in Info.Instances instead. 143 if name, ok := x.(*syntax.Name); ok { 144 if inst, ok := pw.info.Instances[name]; ok { 145 tv.Type = inst.Type 146 } 147 } 148 149 return tv, tv.Type != nil 150 } 151 152 // typeOf returns the Type of the given value expression. 153 func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type { 154 tv := pw.typeAndValue(expr) 155 if !tv.IsValue() { 156 pw.fatalf(expr, "expected value: %v", syntax.String(expr)) 157 } 158 return tv.Type 159 } 160 161 // A writer provides APIs for writing out an individual element. 162 type writer struct { 163 p *pkgWriter 164 165 pkgbits.Encoder 166 167 // sig holds the signature for the current function body, if any. 168 sig *types2.Signature 169 170 // TODO(mdempsky): We should be able to prune localsIdx whenever a 171 // scope closes, and then maybe we can just use the same map for 172 // storing the TypeParams too (as their TypeName instead). 173 174 // localsIdx tracks any local variables declared within this 175 // function body. It's unused for writing out non-body things. 176 localsIdx map[*types2.Var]int 177 178 // closureVars tracks any free variables that are referenced by this 179 // function body. It's unused for writing out non-body things. 180 closureVars []posVar 181 closureVarsIdx map[*types2.Var]int // index of previously seen free variables 182 183 dict *writerDict 184 185 // derived tracks whether the type being written out references any 186 // type parameters. It's unused for writing non-type things. 187 derived bool 188 } 189 190 // A writerDict tracks types and objects that are used by a declaration. 191 type writerDict struct { 192 implicits []*types2.TypeName 193 194 // derived is a slice of type indices for computing derived types 195 // (i.e., types that depend on the declaration's type parameters). 196 derived []derivedInfo 197 198 // derivedIdx maps a Type to its corresponding index within the 199 // derived slice, if present. 200 derivedIdx map[types2.Type]pkgbits.Index 201 202 // These slices correspond to entries in the runtime dictionary. 203 typeParamMethodExprs []writerMethodExprInfo 204 subdicts []objInfo 205 rtypes []typeInfo 206 itabs []itabInfo 207 } 208 209 type itabInfo struct { 210 typ typeInfo 211 iface typeInfo 212 } 213 214 // typeParamIndex returns the index of the given type parameter within 215 // the dictionary. This may differ from typ.Index() when there are 216 // implicit type parameters due to defined types declared within a 217 // generic function or method. 218 func (dict *writerDict) typeParamIndex(typ *types2.TypeParam) int { 219 for idx, implicit := range dict.implicits { 220 if types2.Unalias(implicit.Type()).(*types2.TypeParam) == typ { 221 return idx 222 } 223 } 224 225 return len(dict.implicits) + typ.Index() 226 } 227 228 // A derivedInfo represents a reference to an encoded generic Go type. 229 type derivedInfo struct { 230 idx pkgbits.Index 231 needed bool // TODO(mdempsky): Remove. 232 } 233 234 // A typeInfo represents a reference to an encoded Go type. 235 // 236 // If derived is true, then the typeInfo represents a generic Go type 237 // that contains type parameters. In this case, idx is an index into 238 // the readerDict.derived{,Types} arrays. 239 // 240 // Otherwise, the typeInfo represents a non-generic Go type, and idx 241 // is an index into the reader.typs array instead. 242 type typeInfo struct { 243 idx pkgbits.Index 244 derived bool 245 } 246 247 // An objInfo represents a reference to an encoded, instantiated (if 248 // applicable) Go object. 249 type objInfo struct { 250 idx pkgbits.Index // index for the generic function declaration 251 explicits []typeInfo // info for the type arguments 252 } 253 254 // A selectorInfo represents a reference to an encoded field or method 255 // name (i.e., objects that can only be accessed using selector 256 // expressions). 257 type selectorInfo struct { 258 pkgIdx pkgbits.Index 259 nameIdx pkgbits.Index 260 } 261 262 // anyDerived reports whether any of info's explicit type arguments 263 // are derived types. 264 func (info objInfo) anyDerived() bool { 265 for _, explicit := range info.explicits { 266 if explicit.derived { 267 return true 268 } 269 } 270 return false 271 } 272 273 // equals reports whether info and other represent the same Go object 274 // (i.e., same base object and identical type arguments, if any). 275 func (info objInfo) equals(other objInfo) bool { 276 if info.idx != other.idx { 277 return false 278 } 279 assert(len(info.explicits) == len(other.explicits)) 280 for i, targ := range info.explicits { 281 if targ != other.explicits[i] { 282 return false 283 } 284 } 285 return true 286 } 287 288 type writerMethodExprInfo struct { 289 typeParamIdx int 290 methodInfo selectorInfo 291 } 292 293 // typeParamMethodExprIdx returns the index where the given encoded 294 // method expression function pointer appears within this dictionary's 295 // type parameters method expressions section, adding it if necessary. 296 func (dict *writerDict) typeParamMethodExprIdx(typeParamIdx int, methodInfo selectorInfo) int { 297 newInfo := writerMethodExprInfo{typeParamIdx, methodInfo} 298 299 for idx, oldInfo := range dict.typeParamMethodExprs { 300 if oldInfo == newInfo { 301 return idx 302 } 303 } 304 305 idx := len(dict.typeParamMethodExprs) 306 dict.typeParamMethodExprs = append(dict.typeParamMethodExprs, newInfo) 307 return idx 308 } 309 310 // subdictIdx returns the index where the given encoded object's 311 // runtime dictionary appears within this dictionary's subdictionary 312 // section, adding it if necessary. 313 func (dict *writerDict) subdictIdx(newInfo objInfo) int { 314 for idx, oldInfo := range dict.subdicts { 315 if oldInfo.equals(newInfo) { 316 return idx 317 } 318 } 319 320 idx := len(dict.subdicts) 321 dict.subdicts = append(dict.subdicts, newInfo) 322 return idx 323 } 324 325 // rtypeIdx returns the index where the given encoded type's 326 // *runtime._type value appears within this dictionary's rtypes 327 // section, adding it if necessary. 328 func (dict *writerDict) rtypeIdx(newInfo typeInfo) int { 329 for idx, oldInfo := range dict.rtypes { 330 if oldInfo == newInfo { 331 return idx 332 } 333 } 334 335 idx := len(dict.rtypes) 336 dict.rtypes = append(dict.rtypes, newInfo) 337 return idx 338 } 339 340 // itabIdx returns the index where the given encoded type pair's 341 // *runtime.itab value appears within this dictionary's itabs section, 342 // adding it if necessary. 343 func (dict *writerDict) itabIdx(typInfo, ifaceInfo typeInfo) int { 344 newInfo := itabInfo{typInfo, ifaceInfo} 345 346 for idx, oldInfo := range dict.itabs { 347 if oldInfo == newInfo { 348 return idx 349 } 350 } 351 352 idx := len(dict.itabs) 353 dict.itabs = append(dict.itabs, newInfo) 354 return idx 355 } 356 357 func (pw *pkgWriter) newWriter(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *writer { 358 return &writer{ 359 Encoder: pw.NewEncoder(k, marker), 360 p: pw, 361 } 362 } 363 364 // @@@ Positions 365 366 // pos writes the position of p into the element bitstream. 367 func (w *writer) pos(p poser) { 368 w.Sync(pkgbits.SyncPos) 369 pos := p.Pos() 370 371 // TODO(mdempsky): Track down the remaining cases here and fix them. 372 if !w.Bool(pos.IsKnown()) { 373 return 374 } 375 376 // TODO(mdempsky): Delta encoding. 377 w.posBase(pos.Base()) 378 w.Uint(pos.Line()) 379 w.Uint(pos.Col()) 380 } 381 382 // posBase writes a reference to the given PosBase into the element 383 // bitstream. 384 func (w *writer) posBase(b *syntax.PosBase) { 385 w.Reloc(pkgbits.RelocPosBase, w.p.posBaseIdx(b)) 386 } 387 388 // posBaseIdx returns the index for the given PosBase. 389 func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) pkgbits.Index { 390 if idx, ok := pw.posBasesIdx[b]; ok { 391 return idx 392 } 393 394 w := pw.newWriter(pkgbits.RelocPosBase, pkgbits.SyncPosBase) 395 w.p.posBasesIdx[b] = w.Idx 396 397 w.String(trimFilename(b)) 398 399 if !w.Bool(b.IsFileBase()) { 400 w.pos(b) 401 w.Uint(b.Line()) 402 w.Uint(b.Col()) 403 } 404 405 return w.Flush() 406 } 407 408 // @@@ Packages 409 410 // pkg writes a use of the given Package into the element bitstream. 411 func (w *writer) pkg(pkg *types2.Package) { 412 w.pkgRef(w.p.pkgIdx(pkg)) 413 } 414 415 func (w *writer) pkgRef(idx pkgbits.Index) { 416 w.Sync(pkgbits.SyncPkg) 417 w.Reloc(pkgbits.RelocPkg, idx) 418 } 419 420 // pkgIdx returns the index for the given package, adding it to the 421 // package export data if needed. 422 func (pw *pkgWriter) pkgIdx(pkg *types2.Package) pkgbits.Index { 423 if idx, ok := pw.pkgsIdx[pkg]; ok { 424 return idx 425 } 426 427 w := pw.newWriter(pkgbits.RelocPkg, pkgbits.SyncPkgDef) 428 pw.pkgsIdx[pkg] = w.Idx 429 430 // The universe and package unsafe need to be handled specially by 431 // importers anyway, so we serialize them using just their package 432 // path. This ensures that readers don't confuse them for 433 // user-defined packages. 434 switch pkg { 435 case nil: // universe 436 w.String("builtin") // same package path used by godoc 437 case types2.Unsafe: 438 w.String("unsafe") 439 default: 440 // TODO(mdempsky): Write out pkg.Path() for curpkg too. 441 var path string 442 if pkg != w.p.curpkg { 443 path = pkg.Path() 444 } 445 base.Assertf(path != "builtin" && path != "unsafe", "unexpected path for user-defined package: %q", path) 446 w.String(path) 447 w.String(pkg.Name()) 448 449 w.Len(len(pkg.Imports())) 450 for _, imp := range pkg.Imports() { 451 w.pkg(imp) 452 } 453 } 454 455 return w.Flush() 456 } 457 458 // @@@ Types 459 460 var ( 461 anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName) 462 comparableTypeName = types2.Universe.Lookup("comparable").(*types2.TypeName) 463 runeTypeName = types2.Universe.Lookup("rune").(*types2.TypeName) 464 ) 465 466 // typ writes a use of the given type into the bitstream. 467 func (w *writer) typ(typ types2.Type) { 468 w.typInfo(w.p.typIdx(typ, w.dict)) 469 } 470 471 // typInfo writes a use of the given type (specified as a typeInfo 472 // instead) into the bitstream. 473 func (w *writer) typInfo(info typeInfo) { 474 w.Sync(pkgbits.SyncType) 475 if w.Bool(info.derived) { 476 w.Len(int(info.idx)) 477 w.derived = true 478 } else { 479 w.Reloc(pkgbits.RelocType, info.idx) 480 } 481 } 482 483 // typIdx returns the index where the export data description of type 484 // can be read back in. If no such index exists yet, it's created. 485 // 486 // typIdx also reports whether typ is a derived type; that is, whether 487 // its identity depends on type parameters. 488 func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { 489 if idx, ok := pw.typsIdx[typ]; ok { 490 return typeInfo{idx: idx, derived: false} 491 } 492 if dict != nil { 493 if idx, ok := dict.derivedIdx[typ]; ok { 494 return typeInfo{idx: idx, derived: true} 495 } 496 } 497 498 w := pw.newWriter(pkgbits.RelocType, pkgbits.SyncTypeIdx) 499 w.dict = dict 500 501 switch typ := types2.Unalias(typ).(type) { 502 default: 503 base.Fatalf("unexpected type: %v (%T)", typ, typ) 504 505 case *types2.Basic: 506 switch kind := typ.Kind(); { 507 case kind == types2.Invalid: 508 base.Fatalf("unexpected types2.Invalid") 509 510 case types2.Typ[kind] == typ: 511 w.Code(pkgbits.TypeBasic) 512 w.Len(int(kind)) 513 514 default: 515 // Handle "byte" and "rune" as references to their TypeNames. 516 obj := types2.Universe.Lookup(typ.Name()) 517 assert(obj.Type() == typ) 518 519 w.Code(pkgbits.TypeNamed) 520 w.obj(obj, nil) 521 } 522 523 case *types2.Named: 524 obj, targs := splitNamed(typ) 525 526 // Defined types that are declared within a generic function (and 527 // thus have implicit type parameters) are always derived types. 528 if w.p.hasImplicitTypeParams(obj) { 529 w.derived = true 530 } 531 532 w.Code(pkgbits.TypeNamed) 533 w.obj(obj, targs) 534 535 case *types2.TypeParam: 536 w.derived = true 537 w.Code(pkgbits.TypeTypeParam) 538 w.Len(w.dict.typeParamIndex(typ)) 539 540 case *types2.Array: 541 w.Code(pkgbits.TypeArray) 542 w.Uint64(uint64(typ.Len())) 543 w.typ(typ.Elem()) 544 545 case *types2.Chan: 546 w.Code(pkgbits.TypeChan) 547 w.Len(int(typ.Dir())) 548 w.typ(typ.Elem()) 549 550 case *types2.Map: 551 w.Code(pkgbits.TypeMap) 552 w.typ(typ.Key()) 553 w.typ(typ.Elem()) 554 555 case *types2.Pointer: 556 w.Code(pkgbits.TypePointer) 557 w.typ(typ.Elem()) 558 559 case *types2.Signature: 560 base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ) 561 w.Code(pkgbits.TypeSignature) 562 w.signature(typ) 563 564 case *types2.Slice: 565 w.Code(pkgbits.TypeSlice) 566 w.typ(typ.Elem()) 567 568 case *types2.Struct: 569 w.Code(pkgbits.TypeStruct) 570 w.structType(typ) 571 572 case *types2.Interface: 573 // Handle "any" as reference to its TypeName. 574 if typ == anyTypeName.Type() { 575 w.Code(pkgbits.TypeNamed) 576 w.obj(anyTypeName, nil) 577 break 578 } 579 580 w.Code(pkgbits.TypeInterface) 581 w.interfaceType(typ) 582 583 case *types2.Union: 584 w.Code(pkgbits.TypeUnion) 585 w.unionType(typ) 586 } 587 588 if w.derived { 589 idx := pkgbits.Index(len(dict.derived)) 590 dict.derived = append(dict.derived, derivedInfo{idx: w.Flush()}) 591 dict.derivedIdx[typ] = idx 592 return typeInfo{idx: idx, derived: true} 593 } 594 595 pw.typsIdx[typ] = w.Idx 596 return typeInfo{idx: w.Flush(), derived: false} 597 } 598 599 func (w *writer) structType(typ *types2.Struct) { 600 w.Len(typ.NumFields()) 601 for i := 0; i < typ.NumFields(); i++ { 602 f := typ.Field(i) 603 w.pos(f) 604 w.selector(f) 605 w.typ(f.Type()) 606 w.String(typ.Tag(i)) 607 w.Bool(f.Embedded()) 608 } 609 } 610 611 func (w *writer) unionType(typ *types2.Union) { 612 w.Len(typ.Len()) 613 for i := 0; i < typ.Len(); i++ { 614 t := typ.Term(i) 615 w.Bool(t.Tilde()) 616 w.typ(t.Type()) 617 } 618 } 619 620 func (w *writer) interfaceType(typ *types2.Interface) { 621 // If typ has no embedded types but it's not a basic interface, then 622 // the natural description we write out below will fail to 623 // reconstruct it. 624 if typ.NumEmbeddeds() == 0 && !typ.IsMethodSet() { 625 // Currently, this can only happen for the underlying Interface of 626 // "comparable", which is needed to handle type declarations like 627 // "type C comparable". 628 assert(typ == comparableTypeName.Type().(*types2.Named).Underlying()) 629 630 // Export as "interface{ comparable }". 631 w.Len(0) // NumExplicitMethods 632 w.Len(1) // NumEmbeddeds 633 w.Bool(false) // IsImplicit 634 w.typ(comparableTypeName.Type()) // EmbeddedType(0) 635 return 636 } 637 638 w.Len(typ.NumExplicitMethods()) 639 w.Len(typ.NumEmbeddeds()) 640 641 if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 1 { 642 w.Bool(typ.IsImplicit()) 643 } else { 644 // Implicit interfaces always have 0 explicit methods and 1 645 // embedded type, so we skip writing out the implicit flag 646 // otherwise as a space optimization. 647 assert(!typ.IsImplicit()) 648 } 649 650 for i := 0; i < typ.NumExplicitMethods(); i++ { 651 m := typ.ExplicitMethod(i) 652 sig := m.Type().(*types2.Signature) 653 assert(sig.TypeParams() == nil) 654 655 w.pos(m) 656 w.selector(m) 657 w.signature(sig) 658 } 659 660 for i := 0; i < typ.NumEmbeddeds(); i++ { 661 w.typ(typ.EmbeddedType(i)) 662 } 663 } 664 665 func (w *writer) signature(sig *types2.Signature) { 666 w.Sync(pkgbits.SyncSignature) 667 w.params(sig.Params()) 668 w.params(sig.Results()) 669 w.Bool(sig.Variadic()) 670 } 671 672 func (w *writer) params(typ *types2.Tuple) { 673 w.Sync(pkgbits.SyncParams) 674 w.Len(typ.Len()) 675 for i := 0; i < typ.Len(); i++ { 676 w.param(typ.At(i)) 677 } 678 } 679 680 func (w *writer) param(param *types2.Var) { 681 w.Sync(pkgbits.SyncParam) 682 w.pos(param) 683 w.localIdent(param) 684 w.typ(param.Type()) 685 } 686 687 // @@@ Objects 688 689 // obj writes a use of the given object into the bitstream. 690 // 691 // If obj is a generic object, then explicits are the explicit type 692 // arguments used to instantiate it (i.e., used to substitute the 693 // object's own declared type parameters). 694 func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) { 695 w.objInfo(w.p.objInstIdx(obj, explicits, w.dict)) 696 } 697 698 // objInfo writes a use of the given encoded object into the 699 // bitstream. 700 func (w *writer) objInfo(info objInfo) { 701 w.Sync(pkgbits.SyncObject) 702 w.Bool(false) // TODO(mdempsky): Remove; was derived func inst. 703 w.Reloc(pkgbits.RelocObj, info.idx) 704 705 w.Len(len(info.explicits)) 706 for _, info := range info.explicits { 707 w.typInfo(info) 708 } 709 } 710 711 // objInstIdx returns the indices for an object and a corresponding 712 // list of type arguments used to instantiate it, adding them to the 713 // export data as needed. 714 func (pw *pkgWriter) objInstIdx(obj types2.Object, explicits *types2.TypeList, dict *writerDict) objInfo { 715 explicitInfos := make([]typeInfo, explicits.Len()) 716 for i := range explicitInfos { 717 explicitInfos[i] = pw.typIdx(explicits.At(i), dict) 718 } 719 return objInfo{idx: pw.objIdx(obj), explicits: explicitInfos} 720 } 721 722 // objIdx returns the index for the given Object, adding it to the 723 // export data as needed. 724 func (pw *pkgWriter) objIdx(obj types2.Object) pkgbits.Index { 725 // TODO(mdempsky): Validate that obj is a global object (or a local 726 // defined type, which we hoist to global scope anyway). 727 728 if idx, ok := pw.objsIdx[obj]; ok { 729 return idx 730 } 731 732 dict := &writerDict{ 733 derivedIdx: make(map[types2.Type]pkgbits.Index), 734 } 735 736 if isDefinedType(obj) && obj.Pkg() == pw.curpkg { 737 decl, ok := pw.typDecls[obj.(*types2.TypeName)] 738 assert(ok) 739 dict.implicits = decl.implicits 740 } 741 742 // We encode objects into 4 elements across different sections, all 743 // sharing the same index: 744 // 745 // - RelocName has just the object's qualified name (i.e., 746 // Object.Pkg and Object.Name) and the CodeObj indicating what 747 // specific type of Object it is (Var, Func, etc). 748 // 749 // - RelocObj has the remaining public details about the object, 750 // relevant to go/types importers. 751 // 752 // - RelocObjExt has additional private details about the object, 753 // which are only relevant to cmd/compile itself. This is 754 // separated from RelocObj so that go/types importers are 755 // unaffected by internal compiler changes. 756 // 757 // - RelocObjDict has public details about the object's type 758 // parameters and derived type's used by the object. This is 759 // separated to facilitate the eventual introduction of 760 // shape-based stenciling. 761 // 762 // TODO(mdempsky): Re-evaluate whether RelocName still makes sense 763 // to keep separate from RelocObj. 764 765 w := pw.newWriter(pkgbits.RelocObj, pkgbits.SyncObject1) 766 wext := pw.newWriter(pkgbits.RelocObjExt, pkgbits.SyncObject1) 767 wname := pw.newWriter(pkgbits.RelocName, pkgbits.SyncObject1) 768 wdict := pw.newWriter(pkgbits.RelocObjDict, pkgbits.SyncObject1) 769 770 pw.objsIdx[obj] = w.Idx // break cycles 771 assert(wext.Idx == w.Idx) 772 assert(wname.Idx == w.Idx) 773 assert(wdict.Idx == w.Idx) 774 775 w.dict = dict 776 wext.dict = dict 777 778 code := w.doObj(wext, obj) 779 w.Flush() 780 wext.Flush() 781 782 wname.qualifiedIdent(obj) 783 wname.Code(code) 784 wname.Flush() 785 786 wdict.objDict(obj, w.dict) 787 wdict.Flush() 788 789 return w.Idx 790 } 791 792 // doObj writes the RelocObj definition for obj to w, and the 793 // RelocObjExt definition to wext. 794 func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj { 795 if obj.Pkg() != w.p.curpkg { 796 return pkgbits.ObjStub 797 } 798 799 switch obj := obj.(type) { 800 default: 801 w.p.unexpected("object", obj) 802 panic("unreachable") 803 804 case *types2.Const: 805 w.pos(obj) 806 w.typ(obj.Type()) 807 w.Value(obj.Val()) 808 return pkgbits.ObjConst 809 810 case *types2.Func: 811 decl, ok := w.p.funDecls[obj] 812 assert(ok) 813 sig := obj.Type().(*types2.Signature) 814 815 w.pos(obj) 816 w.typeParamNames(sig.TypeParams()) 817 w.signature(sig) 818 w.pos(decl) 819 wext.funcExt(obj) 820 return pkgbits.ObjFunc 821 822 case *types2.TypeName: 823 if obj.IsAlias() { 824 w.pos(obj) 825 w.typ(obj.Type()) 826 return pkgbits.ObjAlias 827 } 828 829 named := obj.Type().(*types2.Named) 830 assert(named.TypeArgs() == nil) 831 832 w.pos(obj) 833 w.typeParamNames(named.TypeParams()) 834 wext.typeExt(obj) 835 w.typ(named.Underlying()) 836 837 w.Len(named.NumMethods()) 838 for i := 0; i < named.NumMethods(); i++ { 839 w.method(wext, named.Method(i)) 840 } 841 842 return pkgbits.ObjType 843 844 case *types2.Var: 845 w.pos(obj) 846 w.typ(obj.Type()) 847 wext.varExt(obj) 848 return pkgbits.ObjVar 849 } 850 } 851 852 // objDict writes the dictionary needed for reading the given object. 853 func (w *writer) objDict(obj types2.Object, dict *writerDict) { 854 // TODO(mdempsky): Split objDict into multiple entries? reader.go 855 // doesn't care about the type parameter bounds, and reader2.go 856 // doesn't care about referenced functions. 857 858 w.dict = dict // TODO(mdempsky): This is a bit sketchy. 859 860 w.Len(len(dict.implicits)) 861 862 tparams := objTypeParams(obj) 863 ntparams := tparams.Len() 864 w.Len(ntparams) 865 for i := 0; i < ntparams; i++ { 866 w.typ(tparams.At(i).Constraint()) 867 } 868 869 nderived := len(dict.derived) 870 w.Len(nderived) 871 for _, typ := range dict.derived { 872 w.Reloc(pkgbits.RelocType, typ.idx) 873 w.Bool(typ.needed) 874 } 875 876 // Write runtime dictionary information. 877 // 878 // N.B., the go/types importer reads up to the section, but doesn't 879 // read any further, so it's safe to change. (See TODO above.) 880 881 // For each type parameter, write out whether the constraint is a 882 // basic interface. This is used to determine how aggressively we 883 // can shape corresponding type arguments. 884 // 885 // This is somewhat redundant with writing out the full type 886 // parameter constraints above, but the compiler currently skips 887 // over those. Also, we don't care about the *declared* constraints, 888 // but how the type parameters are actually *used*. E.g., if a type 889 // parameter is constrained to `int | uint` but then never used in 890 // arithmetic/conversions/etc, we could shape those together. 891 for _, implicit := range dict.implicits { 892 tparam := types2.Unalias(implicit.Type()).(*types2.TypeParam) 893 w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet()) 894 } 895 for i := 0; i < ntparams; i++ { 896 tparam := tparams.At(i) 897 w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet()) 898 } 899 900 w.Len(len(dict.typeParamMethodExprs)) 901 for _, info := range dict.typeParamMethodExprs { 902 w.Len(info.typeParamIdx) 903 w.selectorInfo(info.methodInfo) 904 } 905 906 w.Len(len(dict.subdicts)) 907 for _, info := range dict.subdicts { 908 w.objInfo(info) 909 } 910 911 w.Len(len(dict.rtypes)) 912 for _, info := range dict.rtypes { 913 w.typInfo(info) 914 } 915 916 w.Len(len(dict.itabs)) 917 for _, info := range dict.itabs { 918 w.typInfo(info.typ) 919 w.typInfo(info.iface) 920 } 921 922 assert(len(dict.derived) == nderived) 923 } 924 925 func (w *writer) typeParamNames(tparams *types2.TypeParamList) { 926 w.Sync(pkgbits.SyncTypeParamNames) 927 928 ntparams := tparams.Len() 929 for i := 0; i < ntparams; i++ { 930 tparam := tparams.At(i).Obj() 931 w.pos(tparam) 932 w.localIdent(tparam) 933 } 934 } 935 936 func (w *writer) method(wext *writer, meth *types2.Func) { 937 decl, ok := w.p.funDecls[meth] 938 assert(ok) 939 sig := meth.Type().(*types2.Signature) 940 941 w.Sync(pkgbits.SyncMethod) 942 w.pos(meth) 943 w.selector(meth) 944 w.typeParamNames(sig.RecvTypeParams()) 945 w.param(sig.Recv()) 946 w.signature(sig) 947 948 w.pos(decl) // XXX: Hack to workaround linker limitations. 949 wext.funcExt(meth) 950 } 951 952 // qualifiedIdent writes out the name of an object declared at package 953 // scope. (For now, it's also used to refer to local defined types.) 954 func (w *writer) qualifiedIdent(obj types2.Object) { 955 w.Sync(pkgbits.SyncSym) 956 957 name := obj.Name() 958 if isDefinedType(obj) && obj.Pkg() == w.p.curpkg { 959 decl, ok := w.p.typDecls[obj.(*types2.TypeName)] 960 assert(ok) 961 if decl.gen != 0 { 962 // For local defined types, we embed a scope-disambiguation 963 // number directly into their name. types.SplitVargenSuffix then 964 // knows to look for this. 965 // 966 // TODO(mdempsky): Find a better solution; this is terrible. 967 name = fmt.Sprintf("%s·%v", name, decl.gen) 968 } 969 } 970 971 w.pkg(obj.Pkg()) 972 w.String(name) 973 } 974 975 // TODO(mdempsky): We should be able to omit pkg from both localIdent 976 // and selector, because they should always be known from context. 977 // However, past frustrations with this optimization in iexport make 978 // me a little nervous to try it again. 979 980 // localIdent writes the name of a locally declared object (i.e., 981 // objects that can only be accessed by non-qualified name, within the 982 // context of a particular function). 983 func (w *writer) localIdent(obj types2.Object) { 984 assert(!isGlobal(obj)) 985 w.Sync(pkgbits.SyncLocalIdent) 986 w.pkg(obj.Pkg()) 987 w.String(obj.Name()) 988 } 989 990 // selector writes the name of a field or method (i.e., objects that 991 // can only be accessed using selector expressions). 992 func (w *writer) selector(obj types2.Object) { 993 w.selectorInfo(w.p.selectorIdx(obj)) 994 } 995 996 func (w *writer) selectorInfo(info selectorInfo) { 997 w.Sync(pkgbits.SyncSelector) 998 w.pkgRef(info.pkgIdx) 999 w.StringRef(info.nameIdx) 1000 } 1001 1002 func (pw *pkgWriter) selectorIdx(obj types2.Object) selectorInfo { 1003 pkgIdx := pw.pkgIdx(obj.Pkg()) 1004 nameIdx := pw.StringIdx(obj.Name()) 1005 return selectorInfo{pkgIdx: pkgIdx, nameIdx: nameIdx} 1006 } 1007 1008 // @@@ Compiler extensions 1009 1010 func (w *writer) funcExt(obj *types2.Func) { 1011 decl, ok := w.p.funDecls[obj] 1012 assert(ok) 1013 1014 // TODO(mdempsky): Extend these pragma validation flags to account 1015 // for generics. E.g., linkname probably doesn't make sense at 1016 // least. 1017 1018 pragma := asPragmaFlag(decl.Pragma) 1019 if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 { 1020 w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined") 1021 } 1022 wi := asWasmImport(decl.Pragma) 1023 1024 if decl.Body != nil { 1025 if pragma&ir.Noescape != 0 { 1026 w.p.errorf(decl, "can only use //go:noescape with external func implementations") 1027 } 1028 if wi != nil { 1029 w.p.errorf(decl, "can only use //go:wasmimport with external func implementations") 1030 } 1031 if (pragma&ir.UintptrKeepAlive != 0 && pragma&ir.UintptrEscapes == 0) && pragma&ir.Nosplit == 0 { 1032 // Stack growth can't handle uintptr arguments that may 1033 // be pointers (as we don't know which are pointers 1034 // when creating the stack map). Thus uintptrkeepalive 1035 // functions (and all transitive callees) must be 1036 // nosplit. 1037 // 1038 // N.B. uintptrescapes implies uintptrkeepalive but it 1039 // is OK since the arguments must escape to the heap. 1040 // 1041 // TODO(prattmic): Add recursive nosplit check of callees. 1042 // TODO(prattmic): Functions with no body (i.e., 1043 // assembly) must also be nosplit, but we can't check 1044 // that here. 1045 w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit") 1046 } 1047 } else { 1048 if base.Flag.Complete || decl.Name.Value == "init" { 1049 // Linknamed functions are allowed to have no body. Hopefully 1050 // the linkname target has a body. See issue 23311. 1051 // Wasmimport functions are also allowed to have no body. 1052 if _, ok := w.p.linknames[obj]; !ok && wi == nil { 1053 w.p.errorf(decl, "missing function body") 1054 } 1055 } 1056 } 1057 1058 sig, block := obj.Type().(*types2.Signature), decl.Body 1059 body, closureVars := w.p.bodyIdx(sig, block, w.dict) 1060 if len(closureVars) > 0 { 1061 fmt.Fprintln(os.Stderr, "CLOSURE", closureVars) 1062 } 1063 assert(len(closureVars) == 0) 1064 1065 w.Sync(pkgbits.SyncFuncExt) 1066 w.pragmaFlag(pragma) 1067 w.linkname(obj) 1068 1069 if buildcfg.GOARCH == "wasm" { 1070 if wi != nil { 1071 w.String(wi.Module) 1072 w.String(wi.Name) 1073 } else { 1074 w.String("") 1075 w.String("") 1076 } 1077 } 1078 1079 w.Bool(false) // stub extension 1080 w.Reloc(pkgbits.RelocBody, body) 1081 w.Sync(pkgbits.SyncEOF) 1082 } 1083 1084 func (w *writer) typeExt(obj *types2.TypeName) { 1085 decl, ok := w.p.typDecls[obj] 1086 assert(ok) 1087 1088 w.Sync(pkgbits.SyncTypeExt) 1089 1090 w.pragmaFlag(asPragmaFlag(decl.Pragma)) 1091 1092 // No LSym.SymIdx info yet. 1093 w.Int64(-1) 1094 w.Int64(-1) 1095 } 1096 1097 func (w *writer) varExt(obj *types2.Var) { 1098 w.Sync(pkgbits.SyncVarExt) 1099 w.linkname(obj) 1100 } 1101 1102 func (w *writer) linkname(obj types2.Object) { 1103 w.Sync(pkgbits.SyncLinkname) 1104 w.Int64(-1) 1105 w.String(w.p.linknames[obj]) 1106 } 1107 1108 func (w *writer) pragmaFlag(p ir.PragmaFlag) { 1109 w.Sync(pkgbits.SyncPragma) 1110 w.Int(int(p)) 1111 } 1112 1113 // @@@ Function bodies 1114 1115 // bodyIdx returns the index for the given function body (specified by 1116 // block), adding it to the export data 1117 func (pw *pkgWriter) bodyIdx(sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx pkgbits.Index, closureVars []posVar) { 1118 w := pw.newWriter(pkgbits.RelocBody, pkgbits.SyncFuncBody) 1119 w.sig = sig 1120 w.dict = dict 1121 1122 w.declareParams(sig) 1123 if w.Bool(block != nil) { 1124 w.stmts(block.List) 1125 w.pos(block.Rbrace) 1126 } 1127 1128 return w.Flush(), w.closureVars 1129 } 1130 1131 func (w *writer) declareParams(sig *types2.Signature) { 1132 addLocals := func(params *types2.Tuple) { 1133 for i := 0; i < params.Len(); i++ { 1134 w.addLocal(params.At(i)) 1135 } 1136 } 1137 1138 if recv := sig.Recv(); recv != nil { 1139 w.addLocal(recv) 1140 } 1141 addLocals(sig.Params()) 1142 addLocals(sig.Results()) 1143 } 1144 1145 // addLocal records the declaration of a new local variable. 1146 func (w *writer) addLocal(obj *types2.Var) { 1147 idx := len(w.localsIdx) 1148 1149 w.Sync(pkgbits.SyncAddLocal) 1150 if w.p.SyncMarkers() { 1151 w.Int(idx) 1152 } 1153 w.varDictIndex(obj) 1154 1155 if w.localsIdx == nil { 1156 w.localsIdx = make(map[*types2.Var]int) 1157 } 1158 w.localsIdx[obj] = idx 1159 } 1160 1161 // useLocal writes a reference to the given local or free variable 1162 // into the bitstream. 1163 func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) { 1164 w.Sync(pkgbits.SyncUseObjLocal) 1165 1166 if idx, ok := w.localsIdx[obj]; w.Bool(ok) { 1167 w.Len(idx) 1168 return 1169 } 1170 1171 idx, ok := w.closureVarsIdx[obj] 1172 if !ok { 1173 if w.closureVarsIdx == nil { 1174 w.closureVarsIdx = make(map[*types2.Var]int) 1175 } 1176 idx = len(w.closureVars) 1177 w.closureVars = append(w.closureVars, posVar{pos, obj}) 1178 w.closureVarsIdx[obj] = idx 1179 } 1180 w.Len(idx) 1181 } 1182 1183 func (w *writer) openScope(pos syntax.Pos) { 1184 w.Sync(pkgbits.SyncOpenScope) 1185 w.pos(pos) 1186 } 1187 1188 func (w *writer) closeScope(pos syntax.Pos) { 1189 w.Sync(pkgbits.SyncCloseScope) 1190 w.pos(pos) 1191 w.closeAnotherScope() 1192 } 1193 1194 func (w *writer) closeAnotherScope() { 1195 w.Sync(pkgbits.SyncCloseAnotherScope) 1196 } 1197 1198 // @@@ Statements 1199 1200 // stmt writes the given statement into the function body bitstream. 1201 func (w *writer) stmt(stmt syntax.Stmt) { 1202 var stmts []syntax.Stmt 1203 if stmt != nil { 1204 stmts = []syntax.Stmt{stmt} 1205 } 1206 w.stmts(stmts) 1207 } 1208 1209 func (w *writer) stmts(stmts []syntax.Stmt) { 1210 dead := false 1211 w.Sync(pkgbits.SyncStmts) 1212 for _, stmt := range stmts { 1213 if dead { 1214 // Any statements after a terminating statement are safe to 1215 // omit, at least until the next labeled statement. 1216 if _, ok := stmt.(*syntax.LabeledStmt); !ok { 1217 continue 1218 } 1219 } 1220 w.stmt1(stmt) 1221 dead = w.p.terminates(stmt) 1222 } 1223 w.Code(stmtEnd) 1224 w.Sync(pkgbits.SyncStmtsEnd) 1225 } 1226 1227 func (w *writer) stmt1(stmt syntax.Stmt) { 1228 switch stmt := stmt.(type) { 1229 default: 1230 w.p.unexpected("statement", stmt) 1231 1232 case nil, *syntax.EmptyStmt: 1233 return 1234 1235 case *syntax.AssignStmt: 1236 switch { 1237 case stmt.Rhs == nil: 1238 w.Code(stmtIncDec) 1239 w.op(binOps[stmt.Op]) 1240 w.expr(stmt.Lhs) 1241 w.pos(stmt) 1242 1243 case stmt.Op != 0 && stmt.Op != syntax.Def: 1244 w.Code(stmtAssignOp) 1245 w.op(binOps[stmt.Op]) 1246 w.expr(stmt.Lhs) 1247 w.pos(stmt) 1248 1249 var typ types2.Type 1250 if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr { 1251 typ = w.p.typeOf(stmt.Lhs) 1252 } 1253 w.implicitConvExpr(typ, stmt.Rhs) 1254 1255 default: 1256 w.assignStmt(stmt, stmt.Lhs, stmt.Rhs) 1257 } 1258 1259 case *syntax.BlockStmt: 1260 w.Code(stmtBlock) 1261 w.blockStmt(stmt) 1262 1263 case *syntax.BranchStmt: 1264 w.Code(stmtBranch) 1265 w.pos(stmt) 1266 w.op(branchOps[stmt.Tok]) 1267 w.optLabel(stmt.Label) 1268 1269 case *syntax.CallStmt: 1270 w.Code(stmtCall) 1271 w.pos(stmt) 1272 w.op(callOps[stmt.Tok]) 1273 w.expr(stmt.Call) 1274 if stmt.Tok == syntax.Defer { 1275 w.optExpr(stmt.DeferAt) 1276 } 1277 1278 case *syntax.DeclStmt: 1279 for _, decl := range stmt.DeclList { 1280 w.declStmt(decl) 1281 } 1282 1283 case *syntax.ExprStmt: 1284 w.Code(stmtExpr) 1285 w.expr(stmt.X) 1286 1287 case *syntax.ForStmt: 1288 w.Code(stmtFor) 1289 w.forStmt(stmt) 1290 1291 case *syntax.IfStmt: 1292 w.Code(stmtIf) 1293 w.ifStmt(stmt) 1294 1295 case *syntax.LabeledStmt: 1296 w.Code(stmtLabel) 1297 w.pos(stmt) 1298 w.label(stmt.Label) 1299 w.stmt1(stmt.Stmt) 1300 1301 case *syntax.ReturnStmt: 1302 w.Code(stmtReturn) 1303 w.pos(stmt) 1304 1305 resultTypes := w.sig.Results() 1306 dstType := func(i int) types2.Type { 1307 return resultTypes.At(i).Type() 1308 } 1309 w.multiExpr(stmt, dstType, syntax.UnpackListExpr(stmt.Results)) 1310 1311 case *syntax.SelectStmt: 1312 w.Code(stmtSelect) 1313 w.selectStmt(stmt) 1314 1315 case *syntax.SendStmt: 1316 chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan) 1317 1318 w.Code(stmtSend) 1319 w.pos(stmt) 1320 w.expr(stmt.Chan) 1321 w.implicitConvExpr(chanType.Elem(), stmt.Value) 1322 1323 case *syntax.SwitchStmt: 1324 w.Code(stmtSwitch) 1325 w.switchStmt(stmt) 1326 } 1327 } 1328 1329 func (w *writer) assignList(expr syntax.Expr) { 1330 exprs := syntax.UnpackListExpr(expr) 1331 w.Len(len(exprs)) 1332 1333 for _, expr := range exprs { 1334 w.assign(expr) 1335 } 1336 } 1337 1338 func (w *writer) assign(expr syntax.Expr) { 1339 expr = syntax.Unparen(expr) 1340 1341 if name, ok := expr.(*syntax.Name); ok { 1342 if name.Value == "_" { 1343 w.Code(assignBlank) 1344 return 1345 } 1346 1347 if obj, ok := w.p.info.Defs[name]; ok { 1348 obj := obj.(*types2.Var) 1349 1350 w.Code(assignDef) 1351 w.pos(obj) 1352 w.localIdent(obj) 1353 w.typ(obj.Type()) 1354 1355 // TODO(mdempsky): Minimize locals index size by deferring 1356 // this until the variables actually come into scope. 1357 w.addLocal(obj) 1358 return 1359 } 1360 } 1361 1362 w.Code(assignExpr) 1363 w.expr(expr) 1364 } 1365 1366 func (w *writer) declStmt(decl syntax.Decl) { 1367 switch decl := decl.(type) { 1368 default: 1369 w.p.unexpected("declaration", decl) 1370 1371 case *syntax.ConstDecl, *syntax.TypeDecl: 1372 1373 case *syntax.VarDecl: 1374 w.assignStmt(decl, namesAsExpr(decl.NameList), decl.Values) 1375 } 1376 } 1377 1378 // assignStmt writes out an assignment for "lhs = rhs". 1379 func (w *writer) assignStmt(pos poser, lhs0, rhs0 syntax.Expr) { 1380 lhs := syntax.UnpackListExpr(lhs0) 1381 rhs := syntax.UnpackListExpr(rhs0) 1382 1383 w.Code(stmtAssign) 1384 w.pos(pos) 1385 1386 // As if w.assignList(lhs0). 1387 w.Len(len(lhs)) 1388 for _, expr := range lhs { 1389 w.assign(expr) 1390 } 1391 1392 dstType := func(i int) types2.Type { 1393 dst := lhs[i] 1394 1395 // Finding dstType is somewhat involved, because for VarDecl 1396 // statements, the Names are only added to the info.{Defs,Uses} 1397 // maps, not to info.Types. 1398 if name, ok := syntax.Unparen(dst).(*syntax.Name); ok { 1399 if name.Value == "_" { 1400 return nil // ok: no implicit conversion 1401 } else if def, ok := w.p.info.Defs[name].(*types2.Var); ok { 1402 return def.Type() 1403 } else if use, ok := w.p.info.Uses[name].(*types2.Var); ok { 1404 return use.Type() 1405 } else { 1406 w.p.fatalf(dst, "cannot find type of destination object: %v", dst) 1407 } 1408 } 1409 1410 return w.p.typeOf(dst) 1411 } 1412 1413 w.multiExpr(pos, dstType, rhs) 1414 } 1415 1416 func (w *writer) blockStmt(stmt *syntax.BlockStmt) { 1417 w.Sync(pkgbits.SyncBlockStmt) 1418 w.openScope(stmt.Pos()) 1419 w.stmts(stmt.List) 1420 w.closeScope(stmt.Rbrace) 1421 } 1422 1423 func (w *writer) forStmt(stmt *syntax.ForStmt) { 1424 w.Sync(pkgbits.SyncForStmt) 1425 w.openScope(stmt.Pos()) 1426 1427 if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) { 1428 w.pos(rang) 1429 w.assignList(rang.Lhs) 1430 w.expr(rang.X) 1431 1432 xtyp := w.p.typeOf(rang.X) 1433 if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap { 1434 w.rtype(xtyp) 1435 } 1436 { 1437 lhs := syntax.UnpackListExpr(rang.Lhs) 1438 assign := func(i int, src types2.Type) { 1439 if i >= len(lhs) { 1440 return 1441 } 1442 dst := syntax.Unparen(lhs[i]) 1443 if name, ok := dst.(*syntax.Name); ok && name.Value == "_" { 1444 return 1445 } 1446 1447 var dstType types2.Type 1448 if rang.Def { 1449 // For `:=` assignments, the LHS names only appear in Defs, 1450 // not Types (as used by typeOf). 1451 dstType = w.p.info.Defs[dst.(*syntax.Name)].(*types2.Var).Type() 1452 } else { 1453 dstType = w.p.typeOf(dst) 1454 } 1455 1456 w.convRTTI(src, dstType) 1457 } 1458 1459 keyType, valueType := types2.RangeKeyVal(w.p.typeOf(rang.X)) 1460 assign(0, keyType) 1461 assign(1, valueType) 1462 } 1463 1464 } else { 1465 if stmt.Cond != nil && w.p.staticBool(&stmt.Cond) < 0 { // always false 1466 stmt.Post = nil 1467 stmt.Body.List = nil 1468 } 1469 1470 w.pos(stmt) 1471 w.stmt(stmt.Init) 1472 w.optExpr(stmt.Cond) 1473 w.stmt(stmt.Post) 1474 } 1475 1476 w.blockStmt(stmt.Body) 1477 w.Bool(w.distinctVars(stmt)) 1478 w.closeAnotherScope() 1479 } 1480 1481 func (w *writer) distinctVars(stmt *syntax.ForStmt) bool { 1482 lv := base.Debug.LoopVar 1483 fileVersion := w.p.info.FileVersions[stmt.Pos().Base()] 1484 is122 := fileVersion == "" || version.Compare(fileVersion, "go1.22") >= 0 1485 1486 // Turning off loopvar for 1.22 is only possible with loopvarhash=qn 1487 // 1488 // Debug.LoopVar values to be preserved for 1.21 compatibility are 1 and 2, 1489 // which are also set (=1) by GOEXPERIMENT=loopvar. The knobs for turning on 1490 // the new, unshared, loopvar behavior apply to versions less than 1.21 because 1491 // (1) 1.21 also did that and (2) this is believed to be the likely use case; 1492 // anyone checking to see if it affects their code will just run the GOEXPERIMENT 1493 // but will not also update all their go.mod files to 1.21. 1494 // 1495 // -gcflags=-d=loopvar=3 enables logging for 1.22 but does not turn loopvar on for <= 1.21. 1496 1497 return is122 || lv > 0 && lv != 3 1498 } 1499 1500 func (w *writer) ifStmt(stmt *syntax.IfStmt) { 1501 cond := w.p.staticBool(&stmt.Cond) 1502 1503 w.Sync(pkgbits.SyncIfStmt) 1504 w.openScope(stmt.Pos()) 1505 w.pos(stmt) 1506 w.stmt(stmt.Init) 1507 w.expr(stmt.Cond) 1508 w.Int(cond) 1509 if cond >= 0 { 1510 w.blockStmt(stmt.Then) 1511 } else { 1512 w.pos(stmt.Then.Rbrace) 1513 } 1514 if cond <= 0 { 1515 w.stmt(stmt.Else) 1516 } 1517 w.closeAnotherScope() 1518 } 1519 1520 func (w *writer) selectStmt(stmt *syntax.SelectStmt) { 1521 w.Sync(pkgbits.SyncSelectStmt) 1522 1523 w.pos(stmt) 1524 w.Len(len(stmt.Body)) 1525 for i, clause := range stmt.Body { 1526 if i > 0 { 1527 w.closeScope(clause.Pos()) 1528 } 1529 w.openScope(clause.Pos()) 1530 1531 w.pos(clause) 1532 w.stmt(clause.Comm) 1533 w.stmts(clause.Body) 1534 } 1535 if len(stmt.Body) > 0 { 1536 w.closeScope(stmt.Rbrace) 1537 } 1538 } 1539 1540 func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { 1541 w.Sync(pkgbits.SyncSwitchStmt) 1542 1543 w.openScope(stmt.Pos()) 1544 w.pos(stmt) 1545 w.stmt(stmt.Init) 1546 1547 var iface, tagType types2.Type 1548 if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) { 1549 iface = w.p.typeOf(guard.X) 1550 1551 w.pos(guard) 1552 if tag := guard.Lhs; w.Bool(tag != nil) { 1553 w.pos(tag) 1554 1555 // Like w.localIdent, but we don't have a types2.Object. 1556 w.Sync(pkgbits.SyncLocalIdent) 1557 w.pkg(w.p.curpkg) 1558 w.String(tag.Value) 1559 } 1560 w.expr(guard.X) 1561 } else { 1562 tag := stmt.Tag 1563 1564 var tagValue constant.Value 1565 if tag != nil { 1566 tv := w.p.typeAndValue(tag) 1567 tagType = tv.Type 1568 tagValue = tv.Value 1569 } else { 1570 tagType = types2.Typ[types2.Bool] 1571 tagValue = constant.MakeBool(true) 1572 } 1573 1574 if tagValue != nil { 1575 // If the switch tag has a constant value, look for a case 1576 // clause that we always branch to. 1577 func() { 1578 var target *syntax.CaseClause 1579 Outer: 1580 for _, clause := range stmt.Body { 1581 if clause.Cases == nil { 1582 target = clause 1583 } 1584 for _, cas := range syntax.UnpackListExpr(clause.Cases) { 1585 tv := w.p.typeAndValue(cas) 1586 if tv.Value == nil { 1587 return // non-constant case; give up 1588 } 1589 if constant.Compare(tagValue, token.EQL, tv.Value) { 1590 target = clause 1591 break Outer 1592 } 1593 } 1594 } 1595 // We've found the target clause, if any. 1596 1597 if target != nil { 1598 if hasFallthrough(target.Body) { 1599 return // fallthrough is tricky; give up 1600 } 1601 1602 // Rewrite as single "default" case. 1603 target.Cases = nil 1604 stmt.Body = []*syntax.CaseClause{target} 1605 } else { 1606 stmt.Body = nil 1607 } 1608 1609 // Clear switch tag (i.e., replace with implicit "true"). 1610 tag = nil 1611 stmt.Tag = nil 1612 tagType = types2.Typ[types2.Bool] 1613 }() 1614 } 1615 1616 // Walk is going to emit comparisons between the tag value and 1617 // each case expression, and we want these comparisons to always 1618 // have the same type. If there are any case values that can't be 1619 // converted to the tag value's type, then convert everything to 1620 // `any` instead. 1621 Outer: 1622 for _, clause := range stmt.Body { 1623 for _, cas := range syntax.UnpackListExpr(clause.Cases) { 1624 if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) { 1625 tagType = types2.NewInterfaceType(nil, nil) 1626 break Outer 1627 } 1628 } 1629 } 1630 1631 if w.Bool(tag != nil) { 1632 w.implicitConvExpr(tagType, tag) 1633 } 1634 } 1635 1636 w.Len(len(stmt.Body)) 1637 for i, clause := range stmt.Body { 1638 if i > 0 { 1639 w.closeScope(clause.Pos()) 1640 } 1641 w.openScope(clause.Pos()) 1642 1643 w.pos(clause) 1644 1645 cases := syntax.UnpackListExpr(clause.Cases) 1646 if iface != nil { 1647 w.Len(len(cases)) 1648 for _, cas := range cases { 1649 if w.Bool(isNil(w.p, cas)) { 1650 continue 1651 } 1652 w.exprType(iface, cas) 1653 } 1654 } else { 1655 // As if w.exprList(clause.Cases), 1656 // but with implicit conversions to tagType. 1657 1658 w.Sync(pkgbits.SyncExprList) 1659 w.Sync(pkgbits.SyncExprs) 1660 w.Len(len(cases)) 1661 for _, cas := range cases { 1662 w.implicitConvExpr(tagType, cas) 1663 } 1664 } 1665 1666 if obj, ok := w.p.info.Implicits[clause]; ok { 1667 // TODO(mdempsky): These pos details are quirkish, but also 1668 // necessary so the variable's position is correct for DWARF 1669 // scope assignment later. It would probably be better for us to 1670 // instead just set the variable's DWARF scoping info earlier so 1671 // we can give it the correct position information. 1672 pos := clause.Pos() 1673 if typs := syntax.UnpackListExpr(clause.Cases); len(typs) != 0 { 1674 pos = typeExprEndPos(typs[len(typs)-1]) 1675 } 1676 w.pos(pos) 1677 1678 obj := obj.(*types2.Var) 1679 w.typ(obj.Type()) 1680 w.addLocal(obj) 1681 } 1682 1683 w.stmts(clause.Body) 1684 } 1685 if len(stmt.Body) > 0 { 1686 w.closeScope(stmt.Rbrace) 1687 } 1688 1689 w.closeScope(stmt.Rbrace) 1690 } 1691 1692 func (w *writer) label(label *syntax.Name) { 1693 w.Sync(pkgbits.SyncLabel) 1694 1695 // TODO(mdempsky): Replace label strings with dense indices. 1696 w.String(label.Value) 1697 } 1698 1699 func (w *writer) optLabel(label *syntax.Name) { 1700 w.Sync(pkgbits.SyncOptLabel) 1701 if w.Bool(label != nil) { 1702 w.label(label) 1703 } 1704 } 1705 1706 // @@@ Expressions 1707 1708 // expr writes the given expression into the function body bitstream. 1709 func (w *writer) expr(expr syntax.Expr) { 1710 base.Assertf(expr != nil, "missing expression") 1711 1712 expr = syntax.Unparen(expr) // skip parens; unneeded after typecheck 1713 1714 obj, inst := lookupObj(w.p, expr) 1715 targs := inst.TypeArgs 1716 1717 if tv, ok := w.p.maybeTypeAndValue(expr); ok { 1718 if tv.IsRuntimeHelper() { 1719 if pkg := obj.Pkg(); pkg != nil && pkg.Name() == "runtime" { 1720 objName := obj.Name() 1721 w.Code(exprRuntimeBuiltin) 1722 w.String(objName) 1723 return 1724 } 1725 } 1726 1727 if tv.IsType() { 1728 w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr)) 1729 } 1730 1731 if tv.Value != nil { 1732 w.Code(exprConst) 1733 w.pos(expr) 1734 typ := idealType(tv) 1735 assert(typ != nil) 1736 w.typ(typ) 1737 w.Value(tv.Value) 1738 return 1739 } 1740 1741 if _, isNil := obj.(*types2.Nil); isNil { 1742 w.Code(exprZero) 1743 w.pos(expr) 1744 w.typ(tv.Type) 1745 return 1746 } 1747 1748 // With shape types (and particular pointer shaping), we may have 1749 // an expression of type "go.shape.*uint8", but need to reshape it 1750 // to another shape-identical type to allow use in field 1751 // selection, indexing, etc. 1752 if typ := tv.Type; !tv.IsBuiltin() && !isTuple(typ) && !isUntyped(typ) { 1753 w.Code(exprReshape) 1754 w.typ(typ) 1755 // fallthrough 1756 } 1757 } 1758 1759 if obj != nil { 1760 if targs.Len() != 0 { 1761 obj := obj.(*types2.Func) 1762 1763 w.Code(exprFuncInst) 1764 w.pos(expr) 1765 w.funcInst(obj, targs) 1766 return 1767 } 1768 1769 if isGlobal(obj) { 1770 w.Code(exprGlobal) 1771 w.obj(obj, nil) 1772 return 1773 } 1774 1775 obj := obj.(*types2.Var) 1776 assert(!obj.IsField()) 1777 1778 w.Code(exprLocal) 1779 w.useLocal(expr.Pos(), obj) 1780 return 1781 } 1782 1783 switch expr := expr.(type) { 1784 default: 1785 w.p.unexpected("expression", expr) 1786 1787 case *syntax.CompositeLit: 1788 w.Code(exprCompLit) 1789 w.compLit(expr) 1790 1791 case *syntax.FuncLit: 1792 w.Code(exprFuncLit) 1793 w.funcLit(expr) 1794 1795 case *syntax.SelectorExpr: 1796 sel, ok := w.p.info.Selections[expr] 1797 assert(ok) 1798 1799 switch sel.Kind() { 1800 default: 1801 w.p.fatalf(expr, "unexpected selection kind: %v", sel.Kind()) 1802 1803 case types2.FieldVal: 1804 w.Code(exprFieldVal) 1805 w.expr(expr.X) 1806 w.pos(expr) 1807 w.selector(sel.Obj()) 1808 1809 case types2.MethodVal: 1810 w.Code(exprMethodVal) 1811 typ := w.recvExpr(expr, sel) 1812 w.pos(expr) 1813 w.methodExpr(expr, typ, sel) 1814 1815 case types2.MethodExpr: 1816 w.Code(exprMethodExpr) 1817 1818 tv := w.p.typeAndValue(expr.X) 1819 assert(tv.IsType()) 1820 1821 index := sel.Index() 1822 implicits := index[:len(index)-1] 1823 1824 typ := tv.Type 1825 w.typ(typ) 1826 1827 w.Len(len(implicits)) 1828 for _, ix := range implicits { 1829 w.Len(ix) 1830 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type() 1831 } 1832 1833 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type() 1834 if w.Bool(isPtrTo(typ, recv)) { // need deref 1835 typ = recv 1836 } else if w.Bool(isPtrTo(recv, typ)) { // need addr 1837 typ = recv 1838 } 1839 1840 w.pos(expr) 1841 w.methodExpr(expr, typ, sel) 1842 } 1843 1844 case *syntax.IndexExpr: 1845 _ = w.p.typeOf(expr.Index) // ensure this is an index expression, not an instantiation 1846 1847 xtyp := w.p.typeOf(expr.X) 1848 1849 var keyType types2.Type 1850 if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok { 1851 keyType = mapType.Key() 1852 } 1853 1854 w.Code(exprIndex) 1855 w.expr(expr.X) 1856 w.pos(expr) 1857 w.implicitConvExpr(keyType, expr.Index) 1858 if keyType != nil { 1859 w.rtype(xtyp) 1860 } 1861 1862 case *syntax.SliceExpr: 1863 w.Code(exprSlice) 1864 w.expr(expr.X) 1865 w.pos(expr) 1866 for _, n := range &expr.Index { 1867 w.optExpr(n) 1868 } 1869 1870 case *syntax.AssertExpr: 1871 iface := w.p.typeOf(expr.X) 1872 1873 w.Code(exprAssert) 1874 w.expr(expr.X) 1875 w.pos(expr) 1876 w.exprType(iface, expr.Type) 1877 w.rtype(iface) 1878 1879 case *syntax.Operation: 1880 if expr.Y == nil { 1881 w.Code(exprUnaryOp) 1882 w.op(unOps[expr.Op]) 1883 w.pos(expr) 1884 w.expr(expr.X) 1885 break 1886 } 1887 1888 var commonType types2.Type 1889 switch expr.Op { 1890 case syntax.Shl, syntax.Shr: 1891 // ok: operands are allowed to have different types 1892 default: 1893 xtyp := w.p.typeOf(expr.X) 1894 ytyp := w.p.typeOf(expr.Y) 1895 switch { 1896 case types2.AssignableTo(xtyp, ytyp): 1897 commonType = ytyp 1898 case types2.AssignableTo(ytyp, xtyp): 1899 commonType = xtyp 1900 default: 1901 w.p.fatalf(expr, "failed to find common type between %v and %v", xtyp, ytyp) 1902 } 1903 } 1904 1905 w.Code(exprBinaryOp) 1906 w.op(binOps[expr.Op]) 1907 w.implicitConvExpr(commonType, expr.X) 1908 w.pos(expr) 1909 w.implicitConvExpr(commonType, expr.Y) 1910 1911 case *syntax.CallExpr: 1912 tv := w.p.typeAndValue(expr.Fun) 1913 if tv.IsType() { 1914 assert(len(expr.ArgList) == 1) 1915 assert(!expr.HasDots) 1916 w.convertExpr(tv.Type, expr.ArgList[0], false) 1917 break 1918 } 1919 1920 var rtype types2.Type 1921 if tv.IsBuiltin() { 1922 switch obj, _ := lookupObj(w.p, syntax.Unparen(expr.Fun)); obj.Name() { 1923 case "make": 1924 assert(len(expr.ArgList) >= 1) 1925 assert(!expr.HasDots) 1926 1927 w.Code(exprMake) 1928 w.pos(expr) 1929 w.exprType(nil, expr.ArgList[0]) 1930 w.exprs(expr.ArgList[1:]) 1931 1932 typ := w.p.typeOf(expr) 1933 switch coreType := types2.CoreType(typ).(type) { 1934 default: 1935 w.p.fatalf(expr, "unexpected core type: %v", coreType) 1936 case *types2.Chan: 1937 w.rtype(typ) 1938 case *types2.Map: 1939 w.rtype(typ) 1940 case *types2.Slice: 1941 w.rtype(sliceElem(typ)) 1942 } 1943 1944 return 1945 1946 case "new": 1947 assert(len(expr.ArgList) == 1) 1948 assert(!expr.HasDots) 1949 1950 w.Code(exprNew) 1951 w.pos(expr) 1952 w.exprType(nil, expr.ArgList[0]) 1953 return 1954 1955 case "Sizeof": 1956 assert(len(expr.ArgList) == 1) 1957 assert(!expr.HasDots) 1958 1959 w.Code(exprSizeof) 1960 w.pos(expr) 1961 w.typ(w.p.typeOf(expr.ArgList[0])) 1962 return 1963 1964 case "Alignof": 1965 assert(len(expr.ArgList) == 1) 1966 assert(!expr.HasDots) 1967 1968 w.Code(exprAlignof) 1969 w.pos(expr) 1970 w.typ(w.p.typeOf(expr.ArgList[0])) 1971 return 1972 1973 case "Offsetof": 1974 assert(len(expr.ArgList) == 1) 1975 assert(!expr.HasDots) 1976 selector := syntax.Unparen(expr.ArgList[0]).(*syntax.SelectorExpr) 1977 index := w.p.info.Selections[selector].Index() 1978 1979 w.Code(exprOffsetof) 1980 w.pos(expr) 1981 w.typ(deref2(w.p.typeOf(selector.X))) 1982 w.Len(len(index) - 1) 1983 for _, idx := range index { 1984 w.Len(idx) 1985 } 1986 return 1987 1988 case "append": 1989 rtype = sliceElem(w.p.typeOf(expr)) 1990 case "copy": 1991 typ := w.p.typeOf(expr.ArgList[0]) 1992 if tuple, ok := typ.(*types2.Tuple); ok { // "copy(g())" 1993 typ = tuple.At(0).Type() 1994 } 1995 rtype = sliceElem(typ) 1996 case "delete": 1997 typ := w.p.typeOf(expr.ArgList[0]) 1998 if tuple, ok := typ.(*types2.Tuple); ok { // "delete(g())" 1999 typ = tuple.At(0).Type() 2000 } 2001 rtype = typ 2002 case "Slice": 2003 rtype = sliceElem(w.p.typeOf(expr)) 2004 } 2005 } 2006 2007 writeFunExpr := func() { 2008 fun := syntax.Unparen(expr.Fun) 2009 2010 if selector, ok := fun.(*syntax.SelectorExpr); ok { 2011 if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal { 2012 w.Bool(true) // method call 2013 typ := w.recvExpr(selector, sel) 2014 w.methodExpr(selector, typ, sel) 2015 return 2016 } 2017 } 2018 2019 w.Bool(false) // not a method call (i.e., normal function call) 2020 2021 if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) { 2022 obj := obj.(*types2.Func) 2023 2024 w.pos(fun) 2025 w.funcInst(obj, inst.TypeArgs) 2026 return 2027 } 2028 2029 w.expr(fun) 2030 } 2031 2032 sigType := types2.CoreType(tv.Type).(*types2.Signature) 2033 paramTypes := sigType.Params() 2034 2035 w.Code(exprCall) 2036 writeFunExpr() 2037 w.pos(expr) 2038 2039 paramType := func(i int) types2.Type { 2040 if sigType.Variadic() && !expr.HasDots && i >= paramTypes.Len()-1 { 2041 return paramTypes.At(paramTypes.Len() - 1).Type().(*types2.Slice).Elem() 2042 } 2043 return paramTypes.At(i).Type() 2044 } 2045 2046 w.multiExpr(expr, paramType, expr.ArgList) 2047 w.Bool(expr.HasDots) 2048 if rtype != nil { 2049 w.rtype(rtype) 2050 } 2051 } 2052 } 2053 2054 func sliceElem(typ types2.Type) types2.Type { 2055 return types2.CoreType(typ).(*types2.Slice).Elem() 2056 } 2057 2058 func (w *writer) optExpr(expr syntax.Expr) { 2059 if w.Bool(expr != nil) { 2060 w.expr(expr) 2061 } 2062 } 2063 2064 // recvExpr writes out expr.X, but handles any implicit addressing, 2065 // dereferencing, and field selections appropriate for the method 2066 // selection. 2067 func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type { 2068 index := sel.Index() 2069 implicits := index[:len(index)-1] 2070 2071 w.Code(exprRecv) 2072 w.expr(expr.X) 2073 w.pos(expr) 2074 w.Len(len(implicits)) 2075 2076 typ := w.p.typeOf(expr.X) 2077 for _, ix := range implicits { 2078 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type() 2079 w.Len(ix) 2080 } 2081 2082 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type() 2083 if w.Bool(isPtrTo(typ, recv)) { // needs deref 2084 typ = recv 2085 } else if w.Bool(isPtrTo(recv, typ)) { // needs addr 2086 typ = recv 2087 } 2088 2089 return typ 2090 } 2091 2092 // funcInst writes a reference to an instantiated function. 2093 func (w *writer) funcInst(obj *types2.Func, targs *types2.TypeList) { 2094 info := w.p.objInstIdx(obj, targs, w.dict) 2095 2096 // Type arguments list contains derived types; we can emit a static 2097 // call to the shaped function, but need to dynamically compute the 2098 // runtime dictionary pointer. 2099 if w.Bool(info.anyDerived()) { 2100 w.Len(w.dict.subdictIdx(info)) 2101 return 2102 } 2103 2104 // Type arguments list is statically known; we can emit a static 2105 // call with a statically reference to the respective runtime 2106 // dictionary. 2107 w.objInfo(info) 2108 } 2109 2110 // methodExpr writes out a reference to the method selected by 2111 // expr. sel should be the corresponding types2.Selection, and recv 2112 // the type produced after any implicit addressing, dereferencing, and 2113 // field selection. (Note: recv might differ from sel.Obj()'s receiver 2114 // parameter in the case of interface types, and is needed for 2115 // handling type parameter methods.) 2116 func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *types2.Selection) { 2117 fun := sel.Obj().(*types2.Func) 2118 sig := fun.Type().(*types2.Signature) 2119 2120 w.typ(recv) 2121 w.typ(sig) 2122 w.pos(expr) 2123 w.selector(fun) 2124 2125 // Method on a type parameter. These require an indirect call 2126 // through the current function's runtime dictionary. 2127 if typeParam, ok := types2.Unalias(recv).(*types2.TypeParam); w.Bool(ok) { 2128 typeParamIdx := w.dict.typeParamIndex(typeParam) 2129 methodInfo := w.p.selectorIdx(fun) 2130 2131 w.Len(w.dict.typeParamMethodExprIdx(typeParamIdx, methodInfo)) 2132 return 2133 } 2134 2135 if isInterface(recv) != isInterface(sig.Recv().Type()) { 2136 w.p.fatalf(expr, "isInterface inconsistency: %v and %v", recv, sig.Recv().Type()) 2137 } 2138 2139 if !isInterface(recv) { 2140 if named, ok := types2.Unalias(deref2(recv)).(*types2.Named); ok { 2141 obj, targs := splitNamed(named) 2142 info := w.p.objInstIdx(obj, targs, w.dict) 2143 2144 // Method on a derived receiver type. These can be handled by a 2145 // static call to the shaped method, but require dynamically 2146 // looking up the appropriate dictionary argument in the current 2147 // function's runtime dictionary. 2148 if w.p.hasImplicitTypeParams(obj) || info.anyDerived() { 2149 w.Bool(true) // dynamic subdictionary 2150 w.Len(w.dict.subdictIdx(info)) 2151 return 2152 } 2153 2154 // Method on a fully known receiver type. These can be handled 2155 // by a static call to the shaped method, and with a static 2156 // reference to the receiver type's dictionary. 2157 if targs.Len() != 0 { 2158 w.Bool(false) // no dynamic subdictionary 2159 w.Bool(true) // static dictionary 2160 w.objInfo(info) 2161 return 2162 } 2163 } 2164 } 2165 2166 w.Bool(false) // no dynamic subdictionary 2167 w.Bool(false) // no static dictionary 2168 } 2169 2170 // multiExpr writes a sequence of expressions, where the i'th value is 2171 // implicitly converted to dstType(i). It also handles when exprs is a 2172 // single, multi-valued expression (e.g., the multi-valued argument in 2173 // an f(g()) call, or the RHS operand in a comma-ok assignment). 2174 func (w *writer) multiExpr(pos poser, dstType func(int) types2.Type, exprs []syntax.Expr) { 2175 w.Sync(pkgbits.SyncMultiExpr) 2176 2177 if len(exprs) == 1 { 2178 expr := exprs[0] 2179 if tuple, ok := w.p.typeOf(expr).(*types2.Tuple); ok { 2180 assert(tuple.Len() > 1) 2181 w.Bool(true) // N:1 assignment 2182 w.pos(pos) 2183 w.expr(expr) 2184 2185 w.Len(tuple.Len()) 2186 for i := 0; i < tuple.Len(); i++ { 2187 src := tuple.At(i).Type() 2188 // TODO(mdempsky): Investigate not writing src here. I think 2189 // the reader should be able to infer it from expr anyway. 2190 w.typ(src) 2191 if dst := dstType(i); w.Bool(dst != nil && !types2.Identical(src, dst)) { 2192 if src == nil || dst == nil { 2193 w.p.fatalf(pos, "src is %v, dst is %v", src, dst) 2194 } 2195 if !types2.AssignableTo(src, dst) { 2196 w.p.fatalf(pos, "%v is not assignable to %v", src, dst) 2197 } 2198 w.typ(dst) 2199 w.convRTTI(src, dst) 2200 } 2201 } 2202 return 2203 } 2204 } 2205 2206 w.Bool(false) // N:N assignment 2207 w.Len(len(exprs)) 2208 for i, expr := range exprs { 2209 w.implicitConvExpr(dstType(i), expr) 2210 } 2211 } 2212 2213 // implicitConvExpr is like expr, but if dst is non-nil and different 2214 // from expr's type, then an implicit conversion operation is inserted 2215 // at expr's position. 2216 func (w *writer) implicitConvExpr(dst types2.Type, expr syntax.Expr) { 2217 w.convertExpr(dst, expr, true) 2218 } 2219 2220 func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) { 2221 src := w.p.typeOf(expr) 2222 2223 // Omit implicit no-op conversions. 2224 identical := dst == nil || types2.Identical(src, dst) 2225 if implicit && identical { 2226 w.expr(expr) 2227 return 2228 } 2229 2230 if implicit && !types2.AssignableTo(src, dst) { 2231 w.p.fatalf(expr, "%v is not assignable to %v", src, dst) 2232 } 2233 2234 w.Code(exprConvert) 2235 w.Bool(implicit) 2236 w.typ(dst) 2237 w.pos(expr) 2238 w.convRTTI(src, dst) 2239 w.Bool(isTypeParam(dst)) 2240 w.Bool(identical) 2241 w.expr(expr) 2242 } 2243 2244 func (w *writer) compLit(lit *syntax.CompositeLit) { 2245 typ := w.p.typeOf(lit) 2246 2247 w.Sync(pkgbits.SyncCompLit) 2248 w.pos(lit) 2249 w.typ(typ) 2250 2251 if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok { 2252 typ = ptr.Elem() 2253 } 2254 var keyType, elemType types2.Type 2255 var structType *types2.Struct 2256 switch typ0 := typ; typ := types2.CoreType(typ).(type) { 2257 default: 2258 w.p.fatalf(lit, "unexpected composite literal type: %v", typ) 2259 case *types2.Array: 2260 elemType = typ.Elem() 2261 case *types2.Map: 2262 w.rtype(typ0) 2263 keyType, elemType = typ.Key(), typ.Elem() 2264 case *types2.Slice: 2265 elemType = typ.Elem() 2266 case *types2.Struct: 2267 structType = typ 2268 } 2269 2270 w.Len(len(lit.ElemList)) 2271 for i, elem := range lit.ElemList { 2272 elemType := elemType 2273 if structType != nil { 2274 if kv, ok := elem.(*syntax.KeyValueExpr); ok { 2275 // use position of expr.Key rather than of elem (which has position of ':') 2276 w.pos(kv.Key) 2277 i = fieldIndex(w.p.info, structType, kv.Key.(*syntax.Name)) 2278 elem = kv.Value 2279 } else { 2280 w.pos(elem) 2281 } 2282 elemType = structType.Field(i).Type() 2283 w.Len(i) 2284 } else { 2285 if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) { 2286 // use position of expr.Key rather than of elem (which has position of ':') 2287 w.pos(kv.Key) 2288 w.implicitConvExpr(keyType, kv.Key) 2289 elem = kv.Value 2290 } 2291 } 2292 w.pos(elem) 2293 w.implicitConvExpr(elemType, elem) 2294 } 2295 } 2296 2297 func (w *writer) funcLit(expr *syntax.FuncLit) { 2298 sig := w.p.typeOf(expr).(*types2.Signature) 2299 2300 body, closureVars := w.p.bodyIdx(sig, expr.Body, w.dict) 2301 2302 w.Sync(pkgbits.SyncFuncLit) 2303 w.pos(expr) 2304 w.signature(sig) 2305 2306 w.Len(len(closureVars)) 2307 for _, cv := range closureVars { 2308 w.pos(cv.pos) 2309 w.useLocal(cv.pos, cv.var_) 2310 } 2311 2312 w.Reloc(pkgbits.RelocBody, body) 2313 } 2314 2315 type posVar struct { 2316 pos syntax.Pos 2317 var_ *types2.Var 2318 } 2319 2320 func (p posVar) String() string { 2321 return p.pos.String() + ":" + p.var_.String() 2322 } 2323 2324 func (w *writer) exprList(expr syntax.Expr) { 2325 w.Sync(pkgbits.SyncExprList) 2326 w.exprs(syntax.UnpackListExpr(expr)) 2327 } 2328 2329 func (w *writer) exprs(exprs []syntax.Expr) { 2330 w.Sync(pkgbits.SyncExprs) 2331 w.Len(len(exprs)) 2332 for _, expr := range exprs { 2333 w.expr(expr) 2334 } 2335 } 2336 2337 // rtype writes information so that the reader can construct an 2338 // expression of type *runtime._type representing typ. 2339 func (w *writer) rtype(typ types2.Type) { 2340 typ = types2.Default(typ) 2341 2342 info := w.p.typIdx(typ, w.dict) 2343 w.rtypeInfo(info) 2344 } 2345 2346 func (w *writer) rtypeInfo(info typeInfo) { 2347 w.Sync(pkgbits.SyncRType) 2348 2349 if w.Bool(info.derived) { 2350 w.Len(w.dict.rtypeIdx(info)) 2351 } else { 2352 w.typInfo(info) 2353 } 2354 } 2355 2356 // varDictIndex writes out information for populating DictIndex for 2357 // the ir.Name that will represent obj. 2358 func (w *writer) varDictIndex(obj *types2.Var) { 2359 info := w.p.typIdx(obj.Type(), w.dict) 2360 if w.Bool(info.derived) { 2361 w.Len(w.dict.rtypeIdx(info)) 2362 } 2363 } 2364 2365 func isUntyped(typ types2.Type) bool { 2366 basic, ok := types2.Unalias(typ).(*types2.Basic) 2367 return ok && basic.Info()&types2.IsUntyped != 0 2368 } 2369 2370 func isTuple(typ types2.Type) bool { 2371 _, ok := typ.(*types2.Tuple) 2372 return ok 2373 } 2374 2375 func (w *writer) itab(typ, iface types2.Type) { 2376 typ = types2.Default(typ) 2377 iface = types2.Default(iface) 2378 2379 typInfo := w.p.typIdx(typ, w.dict) 2380 ifaceInfo := w.p.typIdx(iface, w.dict) 2381 2382 w.rtypeInfo(typInfo) 2383 w.rtypeInfo(ifaceInfo) 2384 if w.Bool(typInfo.derived || ifaceInfo.derived) { 2385 w.Len(w.dict.itabIdx(typInfo, ifaceInfo)) 2386 } 2387 } 2388 2389 // convRTTI writes information so that the reader can construct 2390 // expressions for converting from src to dst. 2391 func (w *writer) convRTTI(src, dst types2.Type) { 2392 w.Sync(pkgbits.SyncConvRTTI) 2393 w.itab(src, dst) 2394 } 2395 2396 func (w *writer) exprType(iface types2.Type, typ syntax.Expr) { 2397 base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface) 2398 2399 tv := w.p.typeAndValue(typ) 2400 assert(tv.IsType()) 2401 2402 w.Sync(pkgbits.SyncExprType) 2403 w.pos(typ) 2404 2405 if w.Bool(iface != nil && !iface.Underlying().(*types2.Interface).Empty()) { 2406 w.itab(tv.Type, iface) 2407 } else { 2408 w.rtype(tv.Type) 2409 2410 info := w.p.typIdx(tv.Type, w.dict) 2411 w.Bool(info.derived) 2412 } 2413 } 2414 2415 // isInterface reports whether typ is known to be an interface type. 2416 // If typ is a type parameter, then isInterface reports an internal 2417 // compiler error instead. 2418 func isInterface(typ types2.Type) bool { 2419 if _, ok := types2.Unalias(typ).(*types2.TypeParam); ok { 2420 // typ is a type parameter and may be instantiated as either a 2421 // concrete or interface type, so the writer can't depend on 2422 // knowing this. 2423 base.Fatalf("%v is a type parameter", typ) 2424 } 2425 2426 _, ok := typ.Underlying().(*types2.Interface) 2427 return ok 2428 } 2429 2430 // op writes an Op into the bitstream. 2431 func (w *writer) op(op ir.Op) { 2432 // TODO(mdempsky): Remove in favor of explicit codes? Would make 2433 // export data more stable against internal refactorings, but low 2434 // priority at the moment. 2435 assert(op != 0) 2436 w.Sync(pkgbits.SyncOp) 2437 w.Len(int(op)) 2438 } 2439 2440 // @@@ Package initialization 2441 2442 // Caution: This code is still clumsy, because toolstash -cmp is 2443 // particularly sensitive to it. 2444 2445 type typeDeclGen struct { 2446 *syntax.TypeDecl 2447 gen int 2448 2449 // Implicit type parameters in scope at this type declaration. 2450 implicits []*types2.TypeName 2451 } 2452 2453 type fileImports struct { 2454 importedEmbed, importedUnsafe bool 2455 } 2456 2457 // declCollector is a visitor type that collects compiler-needed 2458 // information about declarations that types2 doesn't track. 2459 // 2460 // Notably, it maps declared types and functions back to their 2461 // declaration statement, keeps track of implicit type parameters, and 2462 // assigns unique type "generation" numbers to local defined types. 2463 type declCollector struct { 2464 pw *pkgWriter 2465 typegen *int 2466 file *fileImports 2467 withinFunc bool 2468 implicits []*types2.TypeName 2469 } 2470 2471 func (c *declCollector) withTParams(obj types2.Object) *declCollector { 2472 tparams := objTypeParams(obj) 2473 n := tparams.Len() 2474 if n == 0 { 2475 return c 2476 } 2477 2478 copy := *c 2479 copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)] 2480 for i := 0; i < n; i++ { 2481 copy.implicits = append(copy.implicits, tparams.At(i).Obj()) 2482 } 2483 return © 2484 } 2485 2486 func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { 2487 pw := c.pw 2488 2489 switch n := n.(type) { 2490 case *syntax.File: 2491 pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false) 2492 2493 case *syntax.ImportDecl: 2494 pw.checkPragmas(n.Pragma, 0, false) 2495 2496 switch pw.info.PkgNameOf(n).Imported().Path() { 2497 case "embed": 2498 c.file.importedEmbed = true 2499 case "unsafe": 2500 c.file.importedUnsafe = true 2501 } 2502 2503 case *syntax.ConstDecl: 2504 pw.checkPragmas(n.Pragma, 0, false) 2505 2506 case *syntax.FuncDecl: 2507 pw.checkPragmas(n.Pragma, funcPragmas, false) 2508 2509 obj := pw.info.Defs[n.Name].(*types2.Func) 2510 pw.funDecls[obj] = n 2511 2512 return c.withTParams(obj) 2513 2514 case *syntax.TypeDecl: 2515 obj := pw.info.Defs[n.Name].(*types2.TypeName) 2516 d := typeDeclGen{TypeDecl: n, implicits: c.implicits} 2517 2518 if n.Alias { 2519 pw.checkPragmas(n.Pragma, 0, false) 2520 } else { 2521 pw.checkPragmas(n.Pragma, 0, false) 2522 2523 // Assign a unique ID to function-scoped defined types. 2524 if c.withinFunc { 2525 *c.typegen++ 2526 d.gen = *c.typegen 2527 } 2528 } 2529 2530 pw.typDecls[obj] = d 2531 2532 // TODO(mdempsky): Omit? Not strictly necessary; only matters for 2533 // type declarations within function literals within parameterized 2534 // type declarations, but types2 the function literals will be 2535 // constant folded away. 2536 return c.withTParams(obj) 2537 2538 case *syntax.VarDecl: 2539 pw.checkPragmas(n.Pragma, 0, true) 2540 2541 if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 { 2542 if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil { 2543 pw.errorf(p.Embeds[0].Pos, "%s", err) 2544 } 2545 } 2546 2547 case *syntax.BlockStmt: 2548 if !c.withinFunc { 2549 copy := *c 2550 copy.withinFunc = true 2551 return © 2552 } 2553 } 2554 2555 return c 2556 } 2557 2558 func (pw *pkgWriter) collectDecls(noders []*noder) { 2559 var typegen int 2560 for _, p := range noders { 2561 var file fileImports 2562 2563 syntax.Walk(p.file, &declCollector{ 2564 pw: pw, 2565 typegen: &typegen, 2566 file: &file, 2567 }) 2568 2569 pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...) 2570 2571 for _, l := range p.linknames { 2572 if !file.importedUnsafe { 2573 pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"") 2574 continue 2575 } 2576 2577 switch obj := pw.curpkg.Scope().Lookup(l.local).(type) { 2578 case *types2.Func, *types2.Var: 2579 if _, ok := pw.linknames[obj]; !ok { 2580 pw.linknames[obj] = l.remote 2581 } else { 2582 pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local) 2583 } 2584 2585 default: 2586 if types.AllowsGoVersion(1, 18) { 2587 pw.errorf(l.pos, "//go:linkname must refer to declared function or variable") 2588 } 2589 } 2590 } 2591 } 2592 } 2593 2594 func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) { 2595 if p == nil { 2596 return 2597 } 2598 pragma := p.(*pragmas) 2599 2600 for _, pos := range pragma.Pos { 2601 if pos.Flag&^allowed != 0 { 2602 pw.errorf(pos.Pos, "misplaced compiler directive") 2603 } 2604 } 2605 2606 if !embedOK { 2607 for _, e := range pragma.Embeds { 2608 pw.errorf(e.Pos, "misplaced go:embed directive") 2609 } 2610 } 2611 } 2612 2613 func (w *writer) pkgInit(noders []*noder) { 2614 w.Len(len(w.p.cgoPragmas)) 2615 for _, cgoPragma := range w.p.cgoPragmas { 2616 w.Strings(cgoPragma) 2617 } 2618 2619 w.pkgInitOrder() 2620 2621 w.Sync(pkgbits.SyncDecls) 2622 for _, p := range noders { 2623 for _, decl := range p.file.DeclList { 2624 w.pkgDecl(decl) 2625 } 2626 } 2627 w.Code(declEnd) 2628 2629 w.Sync(pkgbits.SyncEOF) 2630 } 2631 2632 func (w *writer) pkgInitOrder() { 2633 // TODO(mdempsky): Write as a function body instead? 2634 w.Len(len(w.p.info.InitOrder)) 2635 for _, init := range w.p.info.InitOrder { 2636 w.Len(len(init.Lhs)) 2637 for _, v := range init.Lhs { 2638 w.obj(v, nil) 2639 } 2640 w.expr(init.Rhs) 2641 } 2642 } 2643 2644 func (w *writer) pkgDecl(decl syntax.Decl) { 2645 switch decl := decl.(type) { 2646 default: 2647 w.p.unexpected("declaration", decl) 2648 2649 case *syntax.ImportDecl: 2650 2651 case *syntax.ConstDecl: 2652 w.Code(declOther) 2653 w.pkgObjs(decl.NameList...) 2654 2655 case *syntax.FuncDecl: 2656 if decl.Name.Value == "_" { 2657 break // skip blank functions 2658 } 2659 2660 obj := w.p.info.Defs[decl.Name].(*types2.Func) 2661 sig := obj.Type().(*types2.Signature) 2662 2663 if sig.RecvTypeParams() != nil || sig.TypeParams() != nil { 2664 break // skip generic functions 2665 } 2666 2667 if recv := sig.Recv(); recv != nil { 2668 w.Code(declMethod) 2669 w.typ(recvBase(recv)) 2670 w.selector(obj) 2671 break 2672 } 2673 2674 w.Code(declFunc) 2675 w.pkgObjs(decl.Name) 2676 2677 case *syntax.TypeDecl: 2678 if len(decl.TParamList) != 0 { 2679 break // skip generic type decls 2680 } 2681 2682 if decl.Name.Value == "_" { 2683 break // skip blank type decls 2684 } 2685 2686 name := w.p.info.Defs[decl.Name].(*types2.TypeName) 2687 // Skip type declarations for interfaces that are only usable as 2688 // type parameter bounds. 2689 if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() { 2690 break 2691 } 2692 2693 w.Code(declOther) 2694 w.pkgObjs(decl.Name) 2695 2696 case *syntax.VarDecl: 2697 w.Code(declVar) 2698 w.pkgObjs(decl.NameList...) 2699 2700 var embeds []pragmaEmbed 2701 if p, ok := decl.Pragma.(*pragmas); ok { 2702 embeds = p.Embeds 2703 } 2704 w.Len(len(embeds)) 2705 for _, embed := range embeds { 2706 w.pos(embed.Pos) 2707 w.Strings(embed.Patterns) 2708 } 2709 } 2710 } 2711 2712 func (w *writer) pkgObjs(names ...*syntax.Name) { 2713 w.Sync(pkgbits.SyncDeclNames) 2714 w.Len(len(names)) 2715 2716 for _, name := range names { 2717 obj, ok := w.p.info.Defs[name] 2718 assert(ok) 2719 2720 w.Sync(pkgbits.SyncDeclName) 2721 w.obj(obj, nil) 2722 } 2723 } 2724 2725 // @@@ Helpers 2726 2727 // staticBool analyzes a boolean expression and reports whether it's 2728 // always true (positive result), always false (negative result), or 2729 // unknown (zero). 2730 // 2731 // It also simplifies the expression while preserving semantics, if 2732 // possible. 2733 func (pw *pkgWriter) staticBool(ep *syntax.Expr) int { 2734 if val := pw.typeAndValue(*ep).Value; val != nil { 2735 if constant.BoolVal(val) { 2736 return +1 2737 } else { 2738 return -1 2739 } 2740 } 2741 2742 if e, ok := (*ep).(*syntax.Operation); ok { 2743 switch e.Op { 2744 case syntax.Not: 2745 return pw.staticBool(&e.X) 2746 2747 case syntax.AndAnd: 2748 x := pw.staticBool(&e.X) 2749 if x < 0 { 2750 *ep = e.X 2751 return x 2752 } 2753 2754 y := pw.staticBool(&e.Y) 2755 if x > 0 || y < 0 { 2756 if pw.typeAndValue(e.X).Value != nil { 2757 *ep = e.Y 2758 } 2759 return y 2760 } 2761 2762 case syntax.OrOr: 2763 x := pw.staticBool(&e.X) 2764 if x > 0 { 2765 *ep = e.X 2766 return x 2767 } 2768 2769 y := pw.staticBool(&e.Y) 2770 if x < 0 || y > 0 { 2771 if pw.typeAndValue(e.X).Value != nil { 2772 *ep = e.Y 2773 } 2774 return y 2775 } 2776 } 2777 } 2778 2779 return 0 2780 } 2781 2782 // hasImplicitTypeParams reports whether obj is a defined type with 2783 // implicit type parameters (e.g., declared within a generic function 2784 // or method). 2785 func (pw *pkgWriter) hasImplicitTypeParams(obj *types2.TypeName) bool { 2786 if obj.Pkg() == pw.curpkg { 2787 decl, ok := pw.typDecls[obj] 2788 assert(ok) 2789 if len(decl.implicits) != 0 { 2790 return true 2791 } 2792 } 2793 return false 2794 } 2795 2796 // isDefinedType reports whether obj is a defined type. 2797 func isDefinedType(obj types2.Object) bool { 2798 if obj, ok := obj.(*types2.TypeName); ok { 2799 return !obj.IsAlias() 2800 } 2801 return false 2802 } 2803 2804 // isGlobal reports whether obj was declared at package scope. 2805 // 2806 // Caveat: blank objects are not declared. 2807 func isGlobal(obj types2.Object) bool { 2808 return obj.Parent() == obj.Pkg().Scope() 2809 } 2810 2811 // lookupObj returns the object that expr refers to, if any. If expr 2812 // is an explicit instantiation of a generic object, then the instance 2813 // object is returned as well. 2814 func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) { 2815 if index, ok := expr.(*syntax.IndexExpr); ok { 2816 args := syntax.UnpackListExpr(index.Index) 2817 if len(args) == 1 { 2818 tv := p.typeAndValue(args[0]) 2819 if tv.IsValue() { 2820 return // normal index expression 2821 } 2822 } 2823 2824 expr = index.X 2825 } 2826 2827 // Strip package qualifier, if present. 2828 if sel, ok := expr.(*syntax.SelectorExpr); ok { 2829 if !isPkgQual(p.info, sel) { 2830 return // normal selector expression 2831 } 2832 expr = sel.Sel 2833 } 2834 2835 if name, ok := expr.(*syntax.Name); ok { 2836 obj = p.info.Uses[name] 2837 inst = p.info.Instances[name] 2838 } 2839 return 2840 } 2841 2842 // isPkgQual reports whether the given selector expression is a 2843 // package-qualified identifier. 2844 func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool { 2845 if name, ok := sel.X.(*syntax.Name); ok { 2846 _, isPkgName := info.Uses[name].(*types2.PkgName) 2847 return isPkgName 2848 } 2849 return false 2850 } 2851 2852 // isNil reports whether expr is a (possibly parenthesized) reference 2853 // to the predeclared nil value. 2854 func isNil(p *pkgWriter, expr syntax.Expr) bool { 2855 tv := p.typeAndValue(expr) 2856 return tv.IsNil() 2857 } 2858 2859 // isBuiltin reports whether expr is a (possibly parenthesized) 2860 // referenced to the specified built-in function. 2861 func (pw *pkgWriter) isBuiltin(expr syntax.Expr, builtin string) bool { 2862 if name, ok := syntax.Unparen(expr).(*syntax.Name); ok && name.Value == builtin { 2863 return pw.typeAndValue(name).IsBuiltin() 2864 } 2865 return false 2866 } 2867 2868 // recvBase returns the base type for the given receiver parameter. 2869 func recvBase(recv *types2.Var) *types2.Named { 2870 typ := types2.Unalias(recv.Type()) 2871 if ptr, ok := typ.(*types2.Pointer); ok { 2872 typ = ptr.Elem() 2873 } 2874 return typ.(*types2.Named) 2875 } 2876 2877 // namesAsExpr returns a list of names as a syntax.Expr. 2878 func namesAsExpr(names []*syntax.Name) syntax.Expr { 2879 if len(names) == 1 { 2880 return names[0] 2881 } 2882 2883 exprs := make([]syntax.Expr, len(names)) 2884 for i, name := range names { 2885 exprs[i] = name 2886 } 2887 return &syntax.ListExpr{ElemList: exprs} 2888 } 2889 2890 // fieldIndex returns the index of the struct field named by key. 2891 func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int { 2892 field := info.Uses[key].(*types2.Var) 2893 2894 for i := 0; i < str.NumFields(); i++ { 2895 if str.Field(i) == field { 2896 return i 2897 } 2898 } 2899 2900 panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str)) 2901 } 2902 2903 // objTypeParams returns the type parameters on the given object. 2904 func objTypeParams(obj types2.Object) *types2.TypeParamList { 2905 switch obj := obj.(type) { 2906 case *types2.Func: 2907 sig := obj.Type().(*types2.Signature) 2908 if sig.Recv() != nil { 2909 return sig.RecvTypeParams() 2910 } 2911 return sig.TypeParams() 2912 case *types2.TypeName: 2913 if !obj.IsAlias() { 2914 return obj.Type().(*types2.Named).TypeParams() 2915 } 2916 } 2917 return nil 2918 } 2919 2920 // splitNamed decomposes a use of a defined type into its original 2921 // type definition and the type arguments used to instantiate it. 2922 func splitNamed(typ *types2.Named) (*types2.TypeName, *types2.TypeList) { 2923 base.Assertf(typ.TypeParams().Len() == typ.TypeArgs().Len(), "use of uninstantiated type: %v", typ) 2924 2925 orig := typ.Origin() 2926 base.Assertf(orig.TypeArgs() == nil, "origin %v of %v has type arguments", orig, typ) 2927 base.Assertf(typ.Obj() == orig.Obj(), "%v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj()) 2928 2929 return typ.Obj(), typ.TypeArgs() 2930 } 2931 2932 func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag { 2933 if p == nil { 2934 return 0 2935 } 2936 return p.(*pragmas).Flag 2937 } 2938 2939 func asWasmImport(p syntax.Pragma) *WasmImport { 2940 if p == nil { 2941 return nil 2942 } 2943 return p.(*pragmas).WasmImport 2944 } 2945 2946 // isPtrTo reports whether from is the type *to. 2947 func isPtrTo(from, to types2.Type) bool { 2948 ptr, ok := types2.Unalias(from).(*types2.Pointer) 2949 return ok && types2.Identical(ptr.Elem(), to) 2950 } 2951 2952 // hasFallthrough reports whether stmts ends in a fallthrough 2953 // statement. 2954 func hasFallthrough(stmts []syntax.Stmt) bool { 2955 last, ok := lastNonEmptyStmt(stmts).(*syntax.BranchStmt) 2956 return ok && last.Tok == syntax.Fallthrough 2957 } 2958 2959 // lastNonEmptyStmt returns the last non-empty statement in list, if 2960 // any. 2961 func lastNonEmptyStmt(stmts []syntax.Stmt) syntax.Stmt { 2962 for i := len(stmts) - 1; i >= 0; i-- { 2963 stmt := stmts[i] 2964 if _, ok := stmt.(*syntax.EmptyStmt); !ok { 2965 return stmt 2966 } 2967 } 2968 return nil 2969 } 2970 2971 // terminates reports whether stmt terminates normal control flow 2972 // (i.e., does not merely advance to the following statement). 2973 func (pw *pkgWriter) terminates(stmt syntax.Stmt) bool { 2974 switch stmt := stmt.(type) { 2975 case *syntax.BranchStmt: 2976 if stmt.Tok == syntax.Goto { 2977 return true 2978 } 2979 case *syntax.ReturnStmt: 2980 return true 2981 case *syntax.ExprStmt: 2982 if call, ok := syntax.Unparen(stmt.X).(*syntax.CallExpr); ok { 2983 if pw.isBuiltin(call.Fun, "panic") { 2984 return true 2985 } 2986 } 2987 2988 // The handling of BlockStmt here is approximate, but it serves to 2989 // allow dead-code elimination for: 2990 // 2991 // if true { 2992 // return x 2993 // } 2994 // unreachable 2995 case *syntax.IfStmt: 2996 cond := pw.staticBool(&stmt.Cond) 2997 return (cond < 0 || pw.terminates(stmt.Then)) && (cond > 0 || pw.terminates(stmt.Else)) 2998 case *syntax.BlockStmt: 2999 return pw.terminates(lastNonEmptyStmt(stmt.List)) 3000 } 3001 3002 return false 3003 }