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