github.com/bir3/gocompiler@v0.9.2202/src/cmd/compile/internal/noder/reader.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 "encoding/hex" 9 "fmt" 10 "github.com/bir3/gocompiler/src/go/constant" 11 "github.com/bir3/gocompiler/src/internal/buildcfg" 12 "github.com/bir3/gocompiler/src/internal/pkgbits" 13 "path/filepath" 14 "strings" 15 16 "github.com/bir3/gocompiler/src/cmd/compile/internal/base" 17 "github.com/bir3/gocompiler/src/cmd/compile/internal/dwarfgen" 18 "github.com/bir3/gocompiler/src/cmd/compile/internal/inline" 19 "github.com/bir3/gocompiler/src/cmd/compile/internal/inline/interleaved" 20 "github.com/bir3/gocompiler/src/cmd/compile/internal/ir" 21 "github.com/bir3/gocompiler/src/cmd/compile/internal/objw" 22 "github.com/bir3/gocompiler/src/cmd/compile/internal/reflectdata" 23 "github.com/bir3/gocompiler/src/cmd/compile/internal/staticinit" 24 "github.com/bir3/gocompiler/src/cmd/compile/internal/typecheck" 25 "github.com/bir3/gocompiler/src/cmd/compile/internal/types" 26 "github.com/bir3/gocompiler/src/cmd/internal/notsha256" 27 "github.com/bir3/gocompiler/src/cmd/internal/obj" 28 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 29 "github.com/bir3/gocompiler/src/cmd/internal/src" 30 ) 31 32 // This file implements cmd/compile backend's reader for the Unified 33 // IR export data. 34 35 // A pkgReader reads Unified IR export data. 36 type pkgReader struct { 37 pkgbits.PkgDecoder 38 39 // Indices for encoded things; lazily populated as needed. 40 // 41 // Note: Objects (i.e., ir.Names) are lazily instantiated by 42 // populating their types.Sym.Def; see objReader below. 43 44 posBases []*src.PosBase 45 pkgs []*types.Pkg 46 typs []*types.Type 47 48 // offset for rewriting the given (absolute!) index into the output, 49 // but bitwise inverted so we can detect if we're missing the entry 50 // or not. 51 newindex []pkgbits.Index 52 } 53 54 func newPkgReader(pr pkgbits.PkgDecoder) *pkgReader { 55 return &pkgReader{ 56 PkgDecoder: pr, 57 58 posBases: make([]*src.PosBase, pr.NumElems(pkgbits.RelocPosBase)), 59 pkgs: make([]*types.Pkg, pr.NumElems(pkgbits.RelocPkg)), 60 typs: make([]*types.Type, pr.NumElems(pkgbits.RelocType)), 61 62 newindex: make([]pkgbits.Index, pr.TotalElems()), 63 } 64 } 65 66 // A pkgReaderIndex compactly identifies an index (and its 67 // corresponding dictionary) within a package's export data. 68 type pkgReaderIndex struct { 69 pr *pkgReader 70 idx pkgbits.Index 71 dict *readerDict 72 methodSym *types.Sym 73 74 synthetic func(pos src.XPos, r *reader) 75 } 76 77 func (pri pkgReaderIndex) asReader(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *reader { 78 if pri.synthetic != nil { 79 return &reader{synthetic: pri.synthetic} 80 } 81 82 r := pri.pr.newReader(k, pri.idx, marker) 83 r.dict = pri.dict 84 r.methodSym = pri.methodSym 85 return r 86 } 87 88 func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader { 89 return &reader{ 90 Decoder: pr.NewDecoder(k, idx, marker), 91 p: pr, 92 } 93 } 94 95 // A reader provides APIs for reading an individual element. 96 type reader struct { 97 pkgbits.Decoder 98 99 p *pkgReader 100 101 dict *readerDict 102 103 // TODO(mdempsky): The state below is all specific to reading 104 // function bodies. It probably makes sense to split it out 105 // separately so that it doesn't take up space in every reader 106 // instance. 107 108 curfn *ir.Func 109 locals []*ir.Name 110 closureVars []*ir.Name 111 112 // funarghack is used during inlining to suppress setting 113 // Field.Nname to the inlined copies of the parameters. This is 114 // necessary because we reuse the same types.Type as the original 115 // function, and most of the compiler still relies on field.Nname to 116 // find parameters/results. 117 funarghack bool 118 119 // methodSym is the name of method's name, if reading a method. 120 // It's nil if reading a normal function or closure body. 121 methodSym *types.Sym 122 123 // dictParam is the .dict param, if any. 124 dictParam *ir.Name 125 126 // synthetic is a callback function to construct a synthetic 127 // function body. It's used for creating the bodies of function 128 // literals used to curry arguments to shaped functions. 129 synthetic func(pos src.XPos, r *reader) 130 131 // scopeVars is a stack tracking the number of variables declared in 132 // the current function at the moment each open scope was opened. 133 scopeVars []int 134 marker dwarfgen.ScopeMarker 135 lastCloseScopePos src.XPos 136 137 // === details for handling inline body expansion === 138 139 // If we're reading in a function body because of inlining, this is 140 // the call that we're inlining for. 141 inlCaller *ir.Func 142 inlCall *ir.CallExpr 143 inlFunc *ir.Func 144 inlTreeIndex int 145 inlPosBases map[*src.PosBase]*src.PosBase 146 147 // suppressInlPos tracks whether position base rewriting for 148 // inlining should be suppressed. See funcLit. 149 suppressInlPos int 150 151 delayResults bool 152 153 // Label to return to. 154 retlabel *types.Sym 155 } 156 157 // A readerDict represents an instantiated "compile-time dictionary," 158 // used for resolving any derived types needed for instantiating a 159 // generic object. 160 // 161 // A compile-time dictionary can either be "shaped" or "non-shaped." 162 // Shaped compile-time dictionaries are only used for instantiating 163 // shaped type definitions and function bodies, while non-shaped 164 // compile-time dictionaries are used for instantiating runtime 165 // dictionaries. 166 type readerDict struct { 167 shaped bool // whether this is a shaped dictionary 168 169 // baseSym is the symbol for the object this dictionary belongs to. 170 // If the object is an instantiated function or defined type, then 171 // baseSym is the mangled symbol, including any type arguments. 172 baseSym *types.Sym 173 174 // For non-shaped dictionaries, shapedObj is a reference to the 175 // corresponding shaped object (always a function or defined type). 176 shapedObj *ir.Name 177 178 // targs holds the implicit and explicit type arguments in use for 179 // reading the current object. For example: 180 // 181 // func F[T any]() { 182 // type X[U any] struct { t T; u U } 183 // var _ X[string] 184 // } 185 // 186 // var _ = F[int] 187 // 188 // While instantiating F[int], we need to in turn instantiate 189 // X[string]. [int] and [string] are explicit type arguments for F 190 // and X, respectively; but [int] is also the implicit type 191 // arguments for X. 192 // 193 // (As an analogy to function literals, explicits are the function 194 // literal's formal parameters, while implicits are variables 195 // captured by the function literal.) 196 targs []*types.Type 197 198 // implicits counts how many of types within targs are implicit type 199 // arguments; the rest are explicit. 200 implicits int 201 202 derived []derivedInfo // reloc index of the derived type's descriptor 203 derivedTypes []*types.Type // slice of previously computed derived types 204 205 // These slices correspond to entries in the runtime dictionary. 206 typeParamMethodExprs []readerMethodExprInfo 207 subdicts []objInfo 208 rtypes []typeInfo 209 itabs []itabInfo 210 } 211 212 type readerMethodExprInfo struct { 213 typeParamIdx int 214 method *types.Sym 215 } 216 217 func setType(n ir.Node, typ *types.Type) { 218 n.SetType(typ) 219 n.SetTypecheck(1) 220 } 221 222 func setValue(name *ir.Name, val constant.Value) { 223 name.SetVal(val) 224 name.Defn = nil 225 } 226 227 // @@@ Positions 228 229 // pos reads a position from the bitstream. 230 func (r *reader) pos() src.XPos { 231 return base.Ctxt.PosTable.XPos(r.pos0()) 232 } 233 234 // origPos reads a position from the bitstream, and returns both the 235 // original raw position and an inlining-adjusted position. 236 func (r *reader) origPos() (origPos, inlPos src.XPos) { 237 r.suppressInlPos++ 238 origPos = r.pos() 239 r.suppressInlPos-- 240 inlPos = r.inlPos(origPos) 241 return 242 } 243 244 func (r *reader) pos0() src.Pos { 245 r.Sync(pkgbits.SyncPos) 246 if !r.Bool() { 247 return src.NoPos 248 } 249 250 posBase := r.posBase() 251 line := r.Uint() 252 col := r.Uint() 253 return src.MakePos(posBase, line, col) 254 } 255 256 // posBase reads a position base from the bitstream. 257 func (r *reader) posBase() *src.PosBase { 258 return r.inlPosBase(r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase))) 259 } 260 261 // posBaseIdx returns the specified position base, reading it first if 262 // needed. 263 func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *src.PosBase { 264 if b := pr.posBases[idx]; b != nil { 265 return b 266 } 267 268 r := pr.newReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase) 269 var b *src.PosBase 270 271 absFilename := r.String() 272 filename := absFilename 273 274 // For build artifact stability, the export data format only 275 // contains the "absolute" filename as returned by objabi.AbsFile. 276 // However, some tests (e.g., test/run.go's asmcheck tests) expect 277 // to see the full, original filename printed out. Re-expanding 278 // "$GOROOT" to buildcfg.GOROOT is a close-enough approximation to 279 // satisfy this. 280 // 281 // The export data format only ever uses slash paths 282 // (for cross-operating-system reproducible builds), 283 // but error messages need to use native paths (backslash on Windows) 284 // as if they had been specified on the command line. 285 // (The go command always passes native paths to the compiler.) 286 const dollarGOROOT = "$GOROOT" 287 if buildcfg.GOROOT != "" && strings.HasPrefix(filename, dollarGOROOT) { 288 filename = filepath.FromSlash(buildcfg.GOROOT + filename[len(dollarGOROOT):]) 289 } 290 291 if r.Bool() { 292 b = src.NewFileBase(filename, absFilename) 293 } else { 294 pos := r.pos0() 295 line := r.Uint() 296 col := r.Uint() 297 b = src.NewLinePragmaBase(pos, filename, absFilename, line, col) 298 } 299 300 pr.posBases[idx] = b 301 return b 302 } 303 304 // inlPosBase returns the inlining-adjusted src.PosBase corresponding 305 // to oldBase, which must be a non-inlined position. When not 306 // inlining, this is just oldBase. 307 func (r *reader) inlPosBase(oldBase *src.PosBase) *src.PosBase { 308 if index := oldBase.InliningIndex(); index >= 0 { 309 base.Fatalf("oldBase %v already has inlining index %v", oldBase, index) 310 } 311 312 if r.inlCall == nil || r.suppressInlPos != 0 { 313 return oldBase 314 } 315 316 if newBase, ok := r.inlPosBases[oldBase]; ok { 317 return newBase 318 } 319 320 newBase := src.NewInliningBase(oldBase, r.inlTreeIndex) 321 r.inlPosBases[oldBase] = newBase 322 return newBase 323 } 324 325 // inlPos returns the inlining-adjusted src.XPos corresponding to 326 // xpos, which must be a non-inlined position. When not inlining, this 327 // is just xpos. 328 func (r *reader) inlPos(xpos src.XPos) src.XPos { 329 pos := base.Ctxt.PosTable.Pos(xpos) 330 pos.SetBase(r.inlPosBase(pos.Base())) 331 return base.Ctxt.PosTable.XPos(pos) 332 } 333 334 // @@@ Packages 335 336 // pkg reads a package reference from the bitstream. 337 func (r *reader) pkg() *types.Pkg { 338 r.Sync(pkgbits.SyncPkg) 339 return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg)) 340 } 341 342 // pkgIdx returns the specified package from the export data, reading 343 // it first if needed. 344 func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Pkg { 345 if pkg := pr.pkgs[idx]; pkg != nil { 346 return pkg 347 } 348 349 pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg() 350 pr.pkgs[idx] = pkg 351 return pkg 352 } 353 354 // doPkg reads a package definition from the bitstream. 355 func (r *reader) doPkg() *types.Pkg { 356 path := r.String() 357 switch path { 358 case "": 359 path = r.p.PkgPath() 360 case "builtin": 361 return types.BuiltinPkg 362 case "unsafe": 363 return types.UnsafePkg 364 } 365 366 name := r.String() 367 368 pkg := types.NewPkg(path, "") 369 370 if pkg.Name == "" { 371 pkg.Name = name 372 } else { 373 base.Assertf(pkg.Name == name, "package %q has name %q, but want %q", pkg.Path, pkg.Name, name) 374 } 375 376 return pkg 377 } 378 379 // @@@ Types 380 381 func (r *reader) typ() *types.Type { 382 return r.typWrapped(true) 383 } 384 385 // typWrapped is like typ, but allows suppressing generation of 386 // unnecessary wrappers as a compile-time optimization. 387 func (r *reader) typWrapped(wrapped bool) *types.Type { 388 return r.p.typIdx(r.typInfo(), r.dict, wrapped) 389 } 390 391 func (r *reader) typInfo() typeInfo { 392 r.Sync(pkgbits.SyncType) 393 if r.Bool() { 394 return typeInfo{idx: pkgbits.Index(r.Len()), derived: true} 395 } 396 return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false} 397 } 398 399 // typListIdx returns a list of the specified types, resolving derived 400 // types within the given dictionary. 401 func (pr *pkgReader) typListIdx(infos []typeInfo, dict *readerDict) []*types.Type { 402 typs := make([]*types.Type, len(infos)) 403 for i, info := range infos { 404 typs[i] = pr.typIdx(info, dict, true) 405 } 406 return typs 407 } 408 409 // typIdx returns the specified type. If info specifies a derived 410 // type, it's resolved within the given dictionary. If wrapped is 411 // true, then method wrappers will be generated, if appropriate. 412 func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *types.Type { 413 idx := info.idx 414 var where **types.Type 415 if info.derived { 416 where = &dict.derivedTypes[idx] 417 idx = dict.derived[idx].idx 418 } else { 419 where = &pr.typs[idx] 420 } 421 422 if typ := *where; typ != nil { 423 return typ 424 } 425 426 r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx) 427 r.dict = dict 428 429 typ := r.doTyp() 430 assert(typ != nil) 431 432 // For recursive type declarations involving interfaces and aliases, 433 // above r.doTyp() call may have already set pr.typs[idx], so just 434 // double check and return the type. 435 // 436 // Example: 437 // 438 // type F = func(I) 439 // 440 // type I interface { 441 // m(F) 442 // } 443 // 444 // The writer writes data types in following index order: 445 // 446 // 0: func(I) 447 // 1: I 448 // 2: interface{m(func(I))} 449 // 450 // The reader resolves it in following index order: 451 // 452 // 0 -> 1 -> 2 -> 0 -> 1 453 // 454 // and can divide in logically 2 steps: 455 // 456 // - 0 -> 1 : first time the reader reach type I, 457 // it creates new named type with symbol I. 458 // 459 // - 2 -> 0 -> 1: the reader ends up reaching symbol I again, 460 // now the symbol I was setup in above step, so 461 // the reader just return the named type. 462 // 463 // Now, the functions called return, the pr.typs looks like below: 464 // 465 // - 0 -> 1 -> 2 -> 0 : [<T> I <T>] 466 // - 0 -> 1 -> 2 : [func(I) I <T>] 467 // - 0 -> 1 : [func(I) I interface { "".m(func("".I)) }] 468 // 469 // The idx 1, corresponding with type I was resolved successfully 470 // after r.doTyp() call. 471 472 if prev := *where; prev != nil { 473 return prev 474 } 475 476 if wrapped { 477 // Only cache if we're adding wrappers, so that other callers that 478 // find a cached type know it was wrapped. 479 *where = typ 480 481 r.needWrapper(typ) 482 } 483 484 if !typ.IsUntyped() { 485 types.CheckSize(typ) 486 } 487 488 return typ 489 } 490 491 func (r *reader) doTyp() *types.Type { 492 switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag { 493 default: 494 panic(fmt.Sprintf("unexpected type: %v", tag)) 495 496 case pkgbits.TypeBasic: 497 return *basics[r.Len()] 498 499 case pkgbits.TypeNamed: 500 obj := r.obj() 501 assert(obj.Op() == ir.OTYPE) 502 return obj.Type() 503 504 case pkgbits.TypeTypeParam: 505 return r.dict.targs[r.Len()] 506 507 case pkgbits.TypeArray: 508 len := int64(r.Uint64()) 509 return types.NewArray(r.typ(), len) 510 case pkgbits.TypeChan: 511 dir := dirs[r.Len()] 512 return types.NewChan(r.typ(), dir) 513 case pkgbits.TypeMap: 514 return types.NewMap(r.typ(), r.typ()) 515 case pkgbits.TypePointer: 516 return types.NewPtr(r.typ()) 517 case pkgbits.TypeSignature: 518 return r.signature(nil) 519 case pkgbits.TypeSlice: 520 return types.NewSlice(r.typ()) 521 case pkgbits.TypeStruct: 522 return r.structType() 523 case pkgbits.TypeInterface: 524 return r.interfaceType() 525 case pkgbits.TypeUnion: 526 return r.unionType() 527 } 528 } 529 530 func (r *reader) unionType() *types.Type { 531 // In the types1 universe, we only need to handle value types. 532 // Impure interfaces (i.e., interfaces with non-trivial type sets 533 // like "int | string") can only appear as type parameter bounds, 534 // and this is enforced by the types2 type checker. 535 // 536 // However, type unions can still appear in pure interfaces if the 537 // type union is equivalent to "any". E.g., typeparam/issue52124.go 538 // declares variables with the type "interface { any | int }". 539 // 540 // To avoid needing to represent type unions in types1 (since we 541 // don't have any uses for that today anyway), we simply fold them 542 // to "any". 543 544 // TODO(mdempsky): Restore consistency check to make sure folding to 545 // "any" is safe. This is unfortunately tricky, because a pure 546 // interface can reference impure interfaces too, including 547 // cyclically (#60117). 548 if false { 549 pure := false 550 for i, n := 0, r.Len(); i < n; i++ { 551 _ = r.Bool() // tilde 552 term := r.typ() 553 if term.IsEmptyInterface() { 554 pure = true 555 } 556 } 557 if !pure { 558 base.Fatalf("impure type set used in value type") 559 } 560 } 561 562 return types.Types[types.TINTER] 563 } 564 565 func (r *reader) interfaceType() *types.Type { 566 nmethods, nembeddeds := r.Len(), r.Len() 567 implicit := nmethods == 0 && nembeddeds == 1 && r.Bool() 568 assert(!implicit) // implicit interfaces only appear in constraints 569 570 fields := make([]*types.Field, nmethods+nembeddeds) 571 methods, embeddeds := fields[:nmethods], fields[nmethods:] 572 573 for i := range methods { 574 methods[i] = types.NewField(r.pos(), r.selector(), r.signature(types.FakeRecv())) 575 } 576 for i := range embeddeds { 577 embeddeds[i] = types.NewField(src.NoXPos, nil, r.typ()) 578 } 579 580 if len(fields) == 0 { 581 return types.Types[types.TINTER] // empty interface 582 } 583 return types.NewInterface(fields) 584 } 585 586 func (r *reader) structType() *types.Type { 587 fields := make([]*types.Field, r.Len()) 588 for i := range fields { 589 field := types.NewField(r.pos(), r.selector(), r.typ()) 590 field.Note = r.String() 591 if r.Bool() { 592 field.Embedded = 1 593 } 594 fields[i] = field 595 } 596 return types.NewStruct(fields) 597 } 598 599 func (r *reader) signature(recv *types.Field) *types.Type { 600 r.Sync(pkgbits.SyncSignature) 601 602 params := r.params() 603 results := r.params() 604 if r.Bool() { // variadic 605 params[len(params)-1].SetIsDDD(true) 606 } 607 608 return types.NewSignature(recv, params, results) 609 } 610 611 func (r *reader) params() []*types.Field { 612 r.Sync(pkgbits.SyncParams) 613 params := make([]*types.Field, r.Len()) 614 for i := range params { 615 params[i] = r.param() 616 } 617 return params 618 } 619 620 func (r *reader) param() *types.Field { 621 r.Sync(pkgbits.SyncParam) 622 return types.NewField(r.pos(), r.localIdent(), r.typ()) 623 } 624 625 // @@@ Objects 626 627 // objReader maps qualified identifiers (represented as *types.Sym) to 628 // a pkgReader and corresponding index that can be used for reading 629 // that object's definition. 630 var objReader = map[*types.Sym]pkgReaderIndex{} 631 632 // obj reads an instantiated object reference from the bitstream. 633 func (r *reader) obj() ir.Node { 634 return r.p.objInstIdx(r.objInfo(), r.dict, false) 635 } 636 637 // objInfo reads an instantiated object reference from the bitstream 638 // and returns the encoded reference to it, without instantiating it. 639 func (r *reader) objInfo() objInfo { 640 r.Sync(pkgbits.SyncObject) 641 assert(!r.Bool()) // TODO(mdempsky): Remove; was derived func inst. 642 idx := r.Reloc(pkgbits.RelocObj) 643 644 explicits := make([]typeInfo, r.Len()) 645 for i := range explicits { 646 explicits[i] = r.typInfo() 647 } 648 649 return objInfo{idx, explicits} 650 } 651 652 // objInstIdx returns the encoded, instantiated object. If shaped is 653 // true, then the shaped variant of the object is returned instead. 654 func (pr *pkgReader) objInstIdx(info objInfo, dict *readerDict, shaped bool) ir.Node { 655 explicits := pr.typListIdx(info.explicits, dict) 656 657 var implicits []*types.Type 658 if dict != nil { 659 implicits = dict.targs 660 } 661 662 return pr.objIdx(info.idx, implicits, explicits, shaped) 663 } 664 665 // objIdx returns the specified object, instantiated with the given 666 // type arguments, if any. If shaped is true, then the shaped variant 667 // of the object is returned instead. 668 func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Type, shaped bool) ir.Node { 669 rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) 670 _, sym := rname.qualifiedIdent() 671 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) 672 673 if tag == pkgbits.ObjStub { 674 assert(!sym.IsBlank()) 675 switch sym.Pkg { 676 case types.BuiltinPkg, types.UnsafePkg: 677 return sym.Def.(ir.Node) 678 } 679 if pri, ok := objReader[sym]; ok { 680 return pri.pr.objIdx(pri.idx, nil, explicits, shaped) 681 } 682 if sym.Pkg.Path == "runtime" { 683 return typecheck.LookupRuntime(sym.Name) 684 } 685 base.Fatalf("unresolved stub: %v", sym) 686 } 687 688 dict := pr.objDictIdx(sym, idx, implicits, explicits, shaped) 689 690 sym = dict.baseSym 691 if !sym.IsBlank() && sym.Def != nil { 692 return sym.Def.(*ir.Name) 693 } 694 695 r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1) 696 rext := pr.newReader(pkgbits.RelocObjExt, idx, pkgbits.SyncObject1) 697 698 r.dict = dict 699 rext.dict = dict 700 701 do := func(op ir.Op, hasTParams bool) *ir.Name { 702 pos := r.pos() 703 setBasePos(pos) 704 if hasTParams { 705 r.typeParamNames() 706 } 707 708 name := ir.NewDeclNameAt(pos, op, sym) 709 name.Class = ir.PEXTERN // may be overridden later 710 if !sym.IsBlank() { 711 if sym.Def != nil { 712 base.FatalfAt(name.Pos(), "already have a definition for %v", name) 713 } 714 assert(sym.Def == nil) 715 sym.Def = name 716 } 717 return name 718 } 719 720 switch tag { 721 default: 722 panic("unexpected object") 723 724 case pkgbits.ObjAlias: 725 name := do(ir.OTYPE, false) 726 setType(name, r.typ()) 727 name.SetAlias(true) 728 return name 729 730 case pkgbits.ObjConst: 731 name := do(ir.OLITERAL, false) 732 typ := r.typ() 733 val := FixValue(typ, r.Value()) 734 setType(name, typ) 735 setValue(name, val) 736 return name 737 738 case pkgbits.ObjFunc: 739 if sym.Name == "init" { 740 sym = Renameinit() 741 } 742 743 npos := r.pos() 744 setBasePos(npos) 745 r.typeParamNames() 746 typ := r.signature(nil) 747 fpos := r.pos() 748 749 fn := ir.NewFunc(fpos, npos, sym, typ) 750 name := fn.Nname 751 if !sym.IsBlank() { 752 if sym.Def != nil { 753 base.FatalfAt(name.Pos(), "already have a definition for %v", name) 754 } 755 assert(sym.Def == nil) 756 sym.Def = name 757 } 758 759 if r.hasTypeParams() { 760 name.Func.SetDupok(true) 761 if r.dict.shaped { 762 setType(name, shapeSig(name.Func, r.dict)) 763 } else { 764 todoDicts = append(todoDicts, func() { 765 r.dict.shapedObj = pr.objIdx(idx, implicits, explicits, true).(*ir.Name) 766 }) 767 } 768 } 769 770 rext.funcExt(name, nil) 771 return name 772 773 case pkgbits.ObjType: 774 name := do(ir.OTYPE, true) 775 typ := types.NewNamed(name) 776 setType(name, typ) 777 if r.hasTypeParams() && r.dict.shaped { 778 typ.SetHasShape(true) 779 } 780 781 // Important: We need to do this before SetUnderlying. 782 rext.typeExt(name) 783 784 // We need to defer CheckSize until we've called SetUnderlying to 785 // handle recursive types. 786 types.DeferCheckSize() 787 typ.SetUnderlying(r.typWrapped(false)) 788 types.ResumeCheckSize() 789 790 if r.hasTypeParams() && !r.dict.shaped { 791 todoDicts = append(todoDicts, func() { 792 r.dict.shapedObj = pr.objIdx(idx, implicits, explicits, true).(*ir.Name) 793 }) 794 } 795 796 methods := make([]*types.Field, r.Len()) 797 for i := range methods { 798 methods[i] = r.method(rext) 799 } 800 if len(methods) != 0 { 801 typ.SetMethods(methods) 802 } 803 804 if !r.dict.shaped { 805 r.needWrapper(typ) 806 } 807 808 return name 809 810 case pkgbits.ObjVar: 811 name := do(ir.ONAME, false) 812 setType(name, r.typ()) 813 rext.varExt(name) 814 return name 815 } 816 } 817 818 func (dict *readerDict) mangle(sym *types.Sym) *types.Sym { 819 if !dict.hasTypeParams() { 820 return sym 821 } 822 823 // If sym is a locally defined generic type, we need the suffix to 824 // stay at the end after mangling so that types/fmt.go can strip it 825 // out again when writing the type's runtime descriptor (#54456). 826 base, suffix := types.SplitVargenSuffix(sym.Name) 827 828 var buf strings.Builder 829 buf.WriteString(base) 830 buf.WriteByte('[') 831 for i, targ := range dict.targs { 832 if i > 0 { 833 if i == dict.implicits { 834 buf.WriteByte(';') 835 } else { 836 buf.WriteByte(',') 837 } 838 } 839 buf.WriteString(targ.LinkString()) 840 } 841 buf.WriteByte(']') 842 buf.WriteString(suffix) 843 return sym.Pkg.Lookup(buf.String()) 844 } 845 846 // shapify returns the shape type for targ. 847 // 848 // If basic is true, then the type argument is used to instantiate a 849 // type parameter whose constraint is a basic interface. 850 func shapify(targ *types.Type, basic bool) *types.Type { 851 if targ.Kind() == types.TFORW { 852 if targ.IsFullyInstantiated() { 853 // For recursive instantiated type argument, it may still be a TFORW 854 // when shapifying happens. If we don't have targ's underlying type, 855 // shapify won't work. The worst case is we end up not reusing code 856 // optimally in some tricky cases. 857 if base.Debug.Shapify != 0 { 858 base.Warn("skipping shaping of recursive type %v", targ) 859 } 860 if targ.HasShape() { 861 return targ 862 } 863 } else { 864 base.Fatalf("%v is missing its underlying type", targ) 865 } 866 } 867 868 // When a pointer type is used to instantiate a type parameter 869 // constrained by a basic interface, we know the pointer's element 870 // type can't matter to the generated code. In this case, we can use 871 // an arbitrary pointer type as the shape type. (To match the 872 // non-unified frontend, we use `*byte`.) 873 // 874 // Otherwise, we simply use the type's underlying type as its shape. 875 // 876 // TODO(mdempsky): It should be possible to do much more aggressive 877 // shaping still; e.g., collapsing all pointer-shaped types into a 878 // common type, collapsing scalars of the same size/alignment into a 879 // common type, recursively shaping the element types of composite 880 // types, and discarding struct field names and tags. However, we'll 881 // need to start tracking how type parameters are actually used to 882 // implement some of these optimizations. 883 under := targ.Underlying() 884 if basic && targ.IsPtr() && !targ.Elem().NotInHeap() { 885 under = types.NewPtr(types.Types[types.TUINT8]) 886 } 887 888 // Hash long type names to bound symbol name length seen by users, 889 // particularly for large protobuf structs (#65030). 890 uls := under.LinkString() 891 if base.Debug.MaxShapeLen != 0 && 892 len(uls) > base.Debug.MaxShapeLen { 893 h := notsha256.Sum256([]byte(uls)) 894 uls = hex.EncodeToString(h[:]) 895 } 896 897 sym := types.ShapePkg.Lookup(uls) 898 if sym.Def == nil { 899 name := ir.NewDeclNameAt(under.Pos(), ir.OTYPE, sym) 900 typ := types.NewNamed(name) 901 typ.SetUnderlying(under) 902 sym.Def = typed(typ, name) 903 } 904 res := sym.Def.Type() 905 assert(res.IsShape()) 906 assert(res.HasShape()) 907 return res 908 } 909 910 // objDictIdx reads and returns the specified object dictionary. 911 func (pr *pkgReader) objDictIdx(sym *types.Sym, idx pkgbits.Index, implicits, explicits []*types.Type, shaped bool) *readerDict { 912 r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1) 913 914 dict := readerDict{ 915 shaped: shaped, 916 } 917 918 nimplicits := r.Len() 919 nexplicits := r.Len() 920 921 if nimplicits > len(implicits) || nexplicits != len(explicits) { 922 base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits)) 923 } 924 925 dict.targs = append(implicits[:nimplicits:nimplicits], explicits...) 926 dict.implicits = nimplicits 927 928 // Within the compiler, we can just skip over the type parameters. 929 for range dict.targs[dict.implicits:] { 930 // Skip past bounds without actually evaluating them. 931 r.typInfo() 932 } 933 934 dict.derived = make([]derivedInfo, r.Len()) 935 dict.derivedTypes = make([]*types.Type, len(dict.derived)) 936 for i := range dict.derived { 937 dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()} 938 } 939 940 // Runtime dictionary information; private to the compiler. 941 942 // If any type argument is already shaped, then we're constructing a 943 // shaped object, even if not explicitly requested (i.e., calling 944 // objIdx with shaped==true). This can happen with instantiating 945 // types that are referenced within a function body. 946 for _, targ := range dict.targs { 947 if targ.HasShape() { 948 dict.shaped = true 949 break 950 } 951 } 952 953 // And if we're constructing a shaped object, then shapify all type 954 // arguments. 955 for i, targ := range dict.targs { 956 basic := r.Bool() 957 if dict.shaped { 958 dict.targs[i] = shapify(targ, basic) 959 } 960 } 961 962 dict.baseSym = dict.mangle(sym) 963 964 dict.typeParamMethodExprs = make([]readerMethodExprInfo, r.Len()) 965 for i := range dict.typeParamMethodExprs { 966 typeParamIdx := r.Len() 967 method := r.selector() 968 969 dict.typeParamMethodExprs[i] = readerMethodExprInfo{typeParamIdx, method} 970 } 971 972 dict.subdicts = make([]objInfo, r.Len()) 973 for i := range dict.subdicts { 974 dict.subdicts[i] = r.objInfo() 975 } 976 977 dict.rtypes = make([]typeInfo, r.Len()) 978 for i := range dict.rtypes { 979 dict.rtypes[i] = r.typInfo() 980 } 981 982 dict.itabs = make([]itabInfo, r.Len()) 983 for i := range dict.itabs { 984 dict.itabs[i] = itabInfo{typ: r.typInfo(), iface: r.typInfo()} 985 } 986 987 return &dict 988 } 989 990 func (r *reader) typeParamNames() { 991 r.Sync(pkgbits.SyncTypeParamNames) 992 993 for range r.dict.targs[r.dict.implicits:] { 994 r.pos() 995 r.localIdent() 996 } 997 } 998 999 func (r *reader) method(rext *reader) *types.Field { 1000 r.Sync(pkgbits.SyncMethod) 1001 npos := r.pos() 1002 sym := r.selector() 1003 r.typeParamNames() 1004 recv := r.param() 1005 typ := r.signature(recv) 1006 1007 fpos := r.pos() 1008 fn := ir.NewFunc(fpos, npos, ir.MethodSym(recv.Type, sym), typ) 1009 name := fn.Nname 1010 1011 if r.hasTypeParams() { 1012 name.Func.SetDupok(true) 1013 if r.dict.shaped { 1014 typ = shapeSig(name.Func, r.dict) 1015 setType(name, typ) 1016 } 1017 } 1018 1019 rext.funcExt(name, sym) 1020 1021 meth := types.NewField(name.Func.Pos(), sym, typ) 1022 meth.Nname = name 1023 meth.SetNointerface(name.Func.Pragma&ir.Nointerface != 0) 1024 1025 return meth 1026 } 1027 1028 func (r *reader) qualifiedIdent() (pkg *types.Pkg, sym *types.Sym) { 1029 r.Sync(pkgbits.SyncSym) 1030 pkg = r.pkg() 1031 if name := r.String(); name != "" { 1032 sym = pkg.Lookup(name) 1033 } 1034 return 1035 } 1036 1037 func (r *reader) localIdent() *types.Sym { 1038 r.Sync(pkgbits.SyncLocalIdent) 1039 pkg := r.pkg() 1040 if name := r.String(); name != "" { 1041 return pkg.Lookup(name) 1042 } 1043 return nil 1044 } 1045 1046 func (r *reader) selector() *types.Sym { 1047 r.Sync(pkgbits.SyncSelector) 1048 pkg := r.pkg() 1049 name := r.String() 1050 if types.IsExported(name) { 1051 pkg = types.LocalPkg 1052 } 1053 return pkg.Lookup(name) 1054 } 1055 1056 func (r *reader) hasTypeParams() bool { 1057 return r.dict.hasTypeParams() 1058 } 1059 1060 func (dict *readerDict) hasTypeParams() bool { 1061 return dict != nil && len(dict.targs) != 0 1062 } 1063 1064 // @@@ Compiler extensions 1065 1066 func (r *reader) funcExt(name *ir.Name, method *types.Sym) { 1067 r.Sync(pkgbits.SyncFuncExt) 1068 1069 fn := name.Func 1070 1071 // XXX: Workaround because linker doesn't know how to copy Pos. 1072 if !fn.Pos().IsKnown() { 1073 fn.SetPos(name.Pos()) 1074 } 1075 1076 // Normally, we only compile local functions, which saves redundant compilation work. 1077 // n.Defn is not nil for local functions, and is nil for imported function. But for 1078 // generic functions, we might have an instantiation that no other package has seen before. 1079 // So we need to be conservative and compile it again. 1080 // 1081 // That's why name.Defn is set here, so ir.VisitFuncsBottomUp can analyze function. 1082 // TODO(mdempsky,cuonglm): find a cleaner way to handle this. 1083 if name.Sym().Pkg == types.LocalPkg || r.hasTypeParams() { 1084 name.Defn = fn 1085 } 1086 1087 fn.Pragma = r.pragmaFlag() 1088 r.linkname(name) 1089 1090 if buildcfg.GOARCH == "wasm" { 1091 xmod := r.String() 1092 xname := r.String() 1093 1094 if xmod != "" && xname != "" { 1095 fn.WasmImport = &ir.WasmImport{ 1096 Module: xmod, 1097 Name: xname, 1098 } 1099 } 1100 } 1101 1102 if r.Bool() { 1103 assert(name.Defn == nil) 1104 1105 fn.ABI = obj.ABI(r.Uint64()) 1106 1107 // Escape analysis. 1108 for _, f := range name.Type().RecvParams() { 1109 f.Note = r.String() 1110 } 1111 1112 if r.Bool() { 1113 fn.Inl = &ir.Inline{ 1114 Cost: int32(r.Len()), 1115 CanDelayResults: r.Bool(), 1116 } 1117 if buildcfg.Experiment.NewInliner { 1118 fn.Inl.Properties = r.String() 1119 } 1120 } 1121 } else { 1122 r.addBody(name.Func, method) 1123 } 1124 r.Sync(pkgbits.SyncEOF) 1125 } 1126 1127 func (r *reader) typeExt(name *ir.Name) { 1128 r.Sync(pkgbits.SyncTypeExt) 1129 1130 typ := name.Type() 1131 1132 if r.hasTypeParams() { 1133 // Set "RParams" (really type arguments here, not parameters) so 1134 // this type is treated as "fully instantiated". This ensures the 1135 // type descriptor is written out as DUPOK and method wrappers are 1136 // generated even for imported types. 1137 var targs []*types.Type 1138 targs = append(targs, r.dict.targs...) 1139 typ.SetRParams(targs) 1140 } 1141 1142 name.SetPragma(r.pragmaFlag()) 1143 1144 typecheck.SetBaseTypeIndex(typ, r.Int64(), r.Int64()) 1145 } 1146 1147 func (r *reader) varExt(name *ir.Name) { 1148 r.Sync(pkgbits.SyncVarExt) 1149 r.linkname(name) 1150 } 1151 1152 func (r *reader) linkname(name *ir.Name) { 1153 assert(name.Op() == ir.ONAME) 1154 r.Sync(pkgbits.SyncLinkname) 1155 1156 if idx := r.Int64(); idx >= 0 { 1157 lsym := name.Linksym() 1158 lsym.SymIdx = int32(idx) 1159 lsym.Set(obj.AttrIndexed, true) 1160 } else { 1161 name.Sym().Linkname = r.String() 1162 } 1163 } 1164 1165 func (r *reader) pragmaFlag() ir.PragmaFlag { 1166 r.Sync(pkgbits.SyncPragma) 1167 return ir.PragmaFlag(r.Int()) 1168 } 1169 1170 // @@@ Function bodies 1171 1172 // bodyReader tracks where the serialized IR for a local or imported, 1173 // generic function's body can be found. 1174 var bodyReader = map[*ir.Func]pkgReaderIndex{} 1175 1176 // importBodyReader tracks where the serialized IR for an imported, 1177 // static (i.e., non-generic) function body can be read. 1178 var importBodyReader = map[*types.Sym]pkgReaderIndex{} 1179 1180 // bodyReaderFor returns the pkgReaderIndex for reading fn's 1181 // serialized IR, and whether one was found. 1182 func bodyReaderFor(fn *ir.Func) (pri pkgReaderIndex, ok bool) { 1183 if fn.Nname.Defn != nil { 1184 pri, ok = bodyReader[fn] 1185 base.AssertfAt(ok, base.Pos, "must have bodyReader for %v", fn) // must always be available 1186 } else { 1187 pri, ok = importBodyReader[fn.Sym()] 1188 } 1189 return 1190 } 1191 1192 // todoDicts holds the list of dictionaries that still need their 1193 // runtime dictionary objects constructed. 1194 var todoDicts []func() 1195 1196 // todoBodies holds the list of function bodies that still need to be 1197 // constructed. 1198 var todoBodies []*ir.Func 1199 1200 // addBody reads a function body reference from the element bitstream, 1201 // and associates it with fn. 1202 func (r *reader) addBody(fn *ir.Func, method *types.Sym) { 1203 // addBody should only be called for local functions or imported 1204 // generic functions; see comment in funcExt. 1205 assert(fn.Nname.Defn != nil) 1206 1207 idx := r.Reloc(pkgbits.RelocBody) 1208 1209 pri := pkgReaderIndex{r.p, idx, r.dict, method, nil} 1210 bodyReader[fn] = pri 1211 1212 if r.curfn == nil { 1213 todoBodies = append(todoBodies, fn) 1214 return 1215 } 1216 1217 pri.funcBody(fn) 1218 } 1219 1220 func (pri pkgReaderIndex) funcBody(fn *ir.Func) { 1221 r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody) 1222 r.funcBody(fn) 1223 } 1224 1225 // funcBody reads a function body definition from the element 1226 // bitstream, and populates fn with it. 1227 func (r *reader) funcBody(fn *ir.Func) { 1228 r.curfn = fn 1229 r.closureVars = fn.ClosureVars 1230 if len(r.closureVars) != 0 && r.hasTypeParams() { 1231 r.dictParam = r.closureVars[len(r.closureVars)-1] // dictParam is last; see reader.funcLit 1232 } 1233 1234 ir.WithFunc(fn, func() { 1235 r.declareParams() 1236 1237 if r.syntheticBody(fn.Pos()) { 1238 return 1239 } 1240 1241 if !r.Bool() { 1242 return 1243 } 1244 1245 body := r.stmts() 1246 if body == nil { 1247 body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(src.NoXPos, nil))} 1248 } 1249 fn.Body = body 1250 fn.Endlineno = r.pos() 1251 }) 1252 1253 r.marker.WriteTo(fn) 1254 } 1255 1256 // syntheticBody adds a synthetic body to r.curfn if appropriate, and 1257 // reports whether it did. 1258 func (r *reader) syntheticBody(pos src.XPos) bool { 1259 if r.synthetic != nil { 1260 r.synthetic(pos, r) 1261 return true 1262 } 1263 1264 // If this function has type parameters and isn't shaped, then we 1265 // just tail call its corresponding shaped variant. 1266 if r.hasTypeParams() && !r.dict.shaped { 1267 r.callShaped(pos) 1268 return true 1269 } 1270 1271 return false 1272 } 1273 1274 // callShaped emits a tail call to r.shapedFn, passing along the 1275 // arguments to the current function. 1276 func (r *reader) callShaped(pos src.XPos) { 1277 shapedObj := r.dict.shapedObj 1278 assert(shapedObj != nil) 1279 1280 var shapedFn ir.Node 1281 if r.methodSym == nil { 1282 // Instantiating a generic function; shapedObj is the shaped 1283 // function itself. 1284 assert(shapedObj.Op() == ir.ONAME && shapedObj.Class == ir.PFUNC) 1285 shapedFn = shapedObj 1286 } else { 1287 // Instantiating a generic type's method; shapedObj is the shaped 1288 // type, so we need to select it's corresponding method. 1289 shapedFn = shapedMethodExpr(pos, shapedObj, r.methodSym) 1290 } 1291 1292 params := r.syntheticArgs() 1293 1294 // Construct the arguments list: receiver (if any), then runtime 1295 // dictionary, and finally normal parameters. 1296 // 1297 // Note: For simplicity, shaped methods are added as normal methods 1298 // on their shaped types. So existing code (e.g., packages ir and 1299 // typecheck) expects the shaped type to appear as the receiver 1300 // parameter (or first parameter, as a method expression). Hence 1301 // putting the dictionary parameter after that is the least invasive 1302 // solution at the moment. 1303 var args ir.Nodes 1304 if r.methodSym != nil { 1305 args.Append(params[0]) 1306 params = params[1:] 1307 } 1308 args.Append(typecheck.Expr(ir.NewAddrExpr(pos, r.p.dictNameOf(r.dict)))) 1309 args.Append(params...) 1310 1311 r.syntheticTailCall(pos, shapedFn, args) 1312 } 1313 1314 // syntheticArgs returns the recvs and params arguments passed to the 1315 // current function. 1316 func (r *reader) syntheticArgs() ir.Nodes { 1317 sig := r.curfn.Nname.Type() 1318 return ir.ToNodes(r.curfn.Dcl[:sig.NumRecvs()+sig.NumParams()]) 1319 } 1320 1321 // syntheticTailCall emits a tail call to fn, passing the given 1322 // arguments list. 1323 func (r *reader) syntheticTailCall(pos src.XPos, fn ir.Node, args ir.Nodes) { 1324 // Mark the function as a wrapper so it doesn't show up in stack 1325 // traces. 1326 r.curfn.SetWrapper(true) 1327 1328 call := typecheck.Call(pos, fn, args, fn.Type().IsVariadic()).(*ir.CallExpr) 1329 1330 var stmt ir.Node 1331 if fn.Type().NumResults() != 0 { 1332 stmt = typecheck.Stmt(ir.NewReturnStmt(pos, []ir.Node{call})) 1333 } else { 1334 stmt = call 1335 } 1336 r.curfn.Body.Append(stmt) 1337 } 1338 1339 // dictNameOf returns the runtime dictionary corresponding to dict. 1340 func (pr *pkgReader) dictNameOf(dict *readerDict) *ir.Name { 1341 pos := base.AutogeneratedPos 1342 1343 // Check that we only instantiate runtime dictionaries with real types. 1344 base.AssertfAt(!dict.shaped, pos, "runtime dictionary of shaped object %v", dict.baseSym) 1345 1346 sym := dict.baseSym.Pkg.Lookup(objabi.GlobalDictPrefix + "." + dict.baseSym.Name) 1347 if sym.Def != nil { 1348 return sym.Def.(*ir.Name) 1349 } 1350 1351 name := ir.NewNameAt(pos, sym, dict.varType()) 1352 name.Class = ir.PEXTERN 1353 sym.Def = name // break cycles with mutual subdictionaries 1354 1355 lsym := name.Linksym() 1356 ot := 0 1357 1358 assertOffset := func(section string, offset int) { 1359 base.AssertfAt(ot == offset*types.PtrSize, pos, "writing section %v at offset %v, but it should be at %v*%v", section, ot, offset, types.PtrSize) 1360 } 1361 1362 assertOffset("type param method exprs", dict.typeParamMethodExprsOffset()) 1363 for _, info := range dict.typeParamMethodExprs { 1364 typeParam := dict.targs[info.typeParamIdx] 1365 method := typecheck.NewMethodExpr(pos, typeParam, info.method) 1366 1367 rsym := method.FuncName().Linksym() 1368 assert(rsym.ABI() == obj.ABIInternal) // must be ABIInternal; see ir.OCFUNC in ssagen/ssa.go 1369 1370 ot = objw.SymPtr(lsym, ot, rsym, 0) 1371 } 1372 1373 assertOffset("subdictionaries", dict.subdictsOffset()) 1374 for _, info := range dict.subdicts { 1375 explicits := pr.typListIdx(info.explicits, dict) 1376 1377 // Careful: Due to subdictionary cycles, name may not be fully 1378 // initialized yet. 1379 name := pr.objDictName(info.idx, dict.targs, explicits) 1380 1381 ot = objw.SymPtr(lsym, ot, name.Linksym(), 0) 1382 } 1383 1384 assertOffset("rtypes", dict.rtypesOffset()) 1385 for _, info := range dict.rtypes { 1386 typ := pr.typIdx(info, dict, true) 1387 ot = objw.SymPtr(lsym, ot, reflectdata.TypeLinksym(typ), 0) 1388 1389 // TODO(mdempsky): Double check this. 1390 reflectdata.MarkTypeUsedInInterface(typ, lsym) 1391 } 1392 1393 // For each (typ, iface) pair, we write the *runtime.itab pointer 1394 // for the pair. For pairs that don't actually require an itab 1395 // (i.e., typ is an interface, or iface is an empty interface), we 1396 // write a nil pointer instead. This is wasteful, but rare in 1397 // practice (e.g., instantiating a type parameter with an interface 1398 // type). 1399 assertOffset("itabs", dict.itabsOffset()) 1400 for _, info := range dict.itabs { 1401 typ := pr.typIdx(info.typ, dict, true) 1402 iface := pr.typIdx(info.iface, dict, true) 1403 1404 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() { 1405 ot = objw.SymPtr(lsym, ot, reflectdata.ITabLsym(typ, iface), 0) 1406 } else { 1407 ot += types.PtrSize 1408 } 1409 1410 // TODO(mdempsky): Double check this. 1411 reflectdata.MarkTypeUsedInInterface(typ, lsym) 1412 reflectdata.MarkTypeUsedInInterface(iface, lsym) 1413 } 1414 1415 objw.Global(lsym, int32(ot), obj.DUPOK|obj.RODATA) 1416 1417 return name 1418 } 1419 1420 // typeParamMethodExprsOffset returns the offset of the runtime 1421 // dictionary's type parameter method expressions section, in words. 1422 func (dict *readerDict) typeParamMethodExprsOffset() int { 1423 return 0 1424 } 1425 1426 // subdictsOffset returns the offset of the runtime dictionary's 1427 // subdictionary section, in words. 1428 func (dict *readerDict) subdictsOffset() int { 1429 return dict.typeParamMethodExprsOffset() + len(dict.typeParamMethodExprs) 1430 } 1431 1432 // rtypesOffset returns the offset of the runtime dictionary's rtypes 1433 // section, in words. 1434 func (dict *readerDict) rtypesOffset() int { 1435 return dict.subdictsOffset() + len(dict.subdicts) 1436 } 1437 1438 // itabsOffset returns the offset of the runtime dictionary's itabs 1439 // section, in words. 1440 func (dict *readerDict) itabsOffset() int { 1441 return dict.rtypesOffset() + len(dict.rtypes) 1442 } 1443 1444 // numWords returns the total number of words that comprise dict's 1445 // runtime dictionary variable. 1446 func (dict *readerDict) numWords() int64 { 1447 return int64(dict.itabsOffset() + len(dict.itabs)) 1448 } 1449 1450 // varType returns the type of dict's runtime dictionary variable. 1451 func (dict *readerDict) varType() *types.Type { 1452 return types.NewArray(types.Types[types.TUINTPTR], dict.numWords()) 1453 } 1454 1455 func (r *reader) declareParams() { 1456 r.curfn.DeclareParams(!r.funarghack) 1457 1458 for _, name := range r.curfn.Dcl { 1459 if name.Sym().Name == dictParamName { 1460 r.dictParam = name 1461 continue 1462 } 1463 1464 r.addLocal(name) 1465 } 1466 } 1467 1468 func (r *reader) addLocal(name *ir.Name) { 1469 if r.synthetic == nil { 1470 r.Sync(pkgbits.SyncAddLocal) 1471 if r.p.SyncMarkers() { 1472 want := r.Int() 1473 if have := len(r.locals); have != want { 1474 base.FatalfAt(name.Pos(), "locals table has desynced") 1475 } 1476 } 1477 r.varDictIndex(name) 1478 } 1479 1480 r.locals = append(r.locals, name) 1481 } 1482 1483 func (r *reader) useLocal() *ir.Name { 1484 r.Sync(pkgbits.SyncUseObjLocal) 1485 if r.Bool() { 1486 return r.locals[r.Len()] 1487 } 1488 return r.closureVars[r.Len()] 1489 } 1490 1491 func (r *reader) openScope() { 1492 r.Sync(pkgbits.SyncOpenScope) 1493 pos := r.pos() 1494 1495 if base.Flag.Dwarf { 1496 r.scopeVars = append(r.scopeVars, len(r.curfn.Dcl)) 1497 r.marker.Push(pos) 1498 } 1499 } 1500 1501 func (r *reader) closeScope() { 1502 r.Sync(pkgbits.SyncCloseScope) 1503 r.lastCloseScopePos = r.pos() 1504 1505 r.closeAnotherScope() 1506 } 1507 1508 // closeAnotherScope is like closeScope, but it reuses the same mark 1509 // position as the last closeScope call. This is useful for "for" and 1510 // "if" statements, as their implicit blocks always end at the same 1511 // position as an explicit block. 1512 func (r *reader) closeAnotherScope() { 1513 r.Sync(pkgbits.SyncCloseAnotherScope) 1514 1515 if base.Flag.Dwarf { 1516 scopeVars := r.scopeVars[len(r.scopeVars)-1] 1517 r.scopeVars = r.scopeVars[:len(r.scopeVars)-1] 1518 1519 // Quirkish: noder decides which scopes to keep before 1520 // typechecking, whereas incremental typechecking during IR 1521 // construction can result in new autotemps being allocated. To 1522 // produce identical output, we ignore autotemps here for the 1523 // purpose of deciding whether to retract the scope. 1524 // 1525 // This is important for net/http/fcgi, because it contains: 1526 // 1527 // var body io.ReadCloser 1528 // if len(content) > 0 { 1529 // body, req.pw = io.Pipe() 1530 // } else { … } 1531 // 1532 // Notably, io.Pipe is inlinable, and inlining it introduces a ~R0 1533 // variable at the call site. 1534 // 1535 // Noder does not preserve the scope where the io.Pipe() call 1536 // resides, because it doesn't contain any declared variables in 1537 // source. So the ~R0 variable ends up being assigned to the 1538 // enclosing scope instead. 1539 // 1540 // However, typechecking this assignment also introduces 1541 // autotemps, because io.Pipe's results need conversion before 1542 // they can be assigned to their respective destination variables. 1543 // 1544 // TODO(mdempsky): We should probably just keep all scopes, and 1545 // let dwarfgen take care of pruning them instead. 1546 retract := true 1547 for _, n := range r.curfn.Dcl[scopeVars:] { 1548 if !n.AutoTemp() { 1549 retract = false 1550 break 1551 } 1552 } 1553 1554 if retract { 1555 // no variables were declared in this scope, so we can retract it. 1556 r.marker.Unpush() 1557 } else { 1558 r.marker.Pop(r.lastCloseScopePos) 1559 } 1560 } 1561 } 1562 1563 // @@@ Statements 1564 1565 func (r *reader) stmt() ir.Node { 1566 return block(r.stmts()) 1567 } 1568 1569 func block(stmts []ir.Node) ir.Node { 1570 switch len(stmts) { 1571 case 0: 1572 return nil 1573 case 1: 1574 return stmts[0] 1575 default: 1576 return ir.NewBlockStmt(stmts[0].Pos(), stmts) 1577 } 1578 } 1579 1580 func (r *reader) stmts() ir.Nodes { 1581 assert(ir.CurFunc == r.curfn) 1582 var res ir.Nodes 1583 1584 r.Sync(pkgbits.SyncStmts) 1585 for { 1586 tag := codeStmt(r.Code(pkgbits.SyncStmt1)) 1587 if tag == stmtEnd { 1588 r.Sync(pkgbits.SyncStmtsEnd) 1589 return res 1590 } 1591 1592 if n := r.stmt1(tag, &res); n != nil { 1593 res.Append(typecheck.Stmt(n)) 1594 } 1595 } 1596 } 1597 1598 func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node { 1599 var label *types.Sym 1600 if n := len(*out); n > 0 { 1601 if ls, ok := (*out)[n-1].(*ir.LabelStmt); ok { 1602 label = ls.Label 1603 } 1604 } 1605 1606 switch tag { 1607 default: 1608 panic("unexpected statement") 1609 1610 case stmtAssign: 1611 pos := r.pos() 1612 names, lhs := r.assignList() 1613 rhs := r.multiExpr() 1614 1615 if len(rhs) == 0 { 1616 for _, name := range names { 1617 as := ir.NewAssignStmt(pos, name, nil) 1618 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name)) 1619 out.Append(typecheck.Stmt(as)) 1620 } 1621 return nil 1622 } 1623 1624 if len(lhs) == 1 && len(rhs) == 1 { 1625 n := ir.NewAssignStmt(pos, lhs[0], rhs[0]) 1626 n.Def = r.initDefn(n, names) 1627 return n 1628 } 1629 1630 n := ir.NewAssignListStmt(pos, ir.OAS2, lhs, rhs) 1631 n.Def = r.initDefn(n, names) 1632 return n 1633 1634 case stmtAssignOp: 1635 op := r.op() 1636 lhs := r.expr() 1637 pos := r.pos() 1638 rhs := r.expr() 1639 return ir.NewAssignOpStmt(pos, op, lhs, rhs) 1640 1641 case stmtIncDec: 1642 op := r.op() 1643 lhs := r.expr() 1644 pos := r.pos() 1645 n := ir.NewAssignOpStmt(pos, op, lhs, ir.NewOne(pos, lhs.Type())) 1646 n.IncDec = true 1647 return n 1648 1649 case stmtBlock: 1650 out.Append(r.blockStmt()...) 1651 return nil 1652 1653 case stmtBranch: 1654 pos := r.pos() 1655 op := r.op() 1656 sym := r.optLabel() 1657 return ir.NewBranchStmt(pos, op, sym) 1658 1659 case stmtCall: 1660 pos := r.pos() 1661 op := r.op() 1662 call := r.expr() 1663 stmt := ir.NewGoDeferStmt(pos, op, call) 1664 if op == ir.ODEFER { 1665 x := r.optExpr() 1666 if x != nil { 1667 stmt.DeferAt = x.(ir.Expr) 1668 } 1669 } 1670 return stmt 1671 1672 case stmtExpr: 1673 return r.expr() 1674 1675 case stmtFor: 1676 return r.forStmt(label) 1677 1678 case stmtIf: 1679 return r.ifStmt() 1680 1681 case stmtLabel: 1682 pos := r.pos() 1683 sym := r.label() 1684 return ir.NewLabelStmt(pos, sym) 1685 1686 case stmtReturn: 1687 pos := r.pos() 1688 results := r.multiExpr() 1689 return ir.NewReturnStmt(pos, results) 1690 1691 case stmtSelect: 1692 return r.selectStmt(label) 1693 1694 case stmtSend: 1695 pos := r.pos() 1696 ch := r.expr() 1697 value := r.expr() 1698 return ir.NewSendStmt(pos, ch, value) 1699 1700 case stmtSwitch: 1701 return r.switchStmt(label) 1702 } 1703 } 1704 1705 func (r *reader) assignList() ([]*ir.Name, []ir.Node) { 1706 lhs := make([]ir.Node, r.Len()) 1707 var names []*ir.Name 1708 1709 for i := range lhs { 1710 expr, def := r.assign() 1711 lhs[i] = expr 1712 if def { 1713 names = append(names, expr.(*ir.Name)) 1714 } 1715 } 1716 1717 return names, lhs 1718 } 1719 1720 // assign returns an assignee expression. It also reports whether the 1721 // returned expression is a newly declared variable. 1722 func (r *reader) assign() (ir.Node, bool) { 1723 switch tag := codeAssign(r.Code(pkgbits.SyncAssign)); tag { 1724 default: 1725 panic("unhandled assignee expression") 1726 1727 case assignBlank: 1728 return typecheck.AssignExpr(ir.BlankNode), false 1729 1730 case assignDef: 1731 pos := r.pos() 1732 setBasePos(pos) // test/fixedbugs/issue49767.go depends on base.Pos being set for the r.typ() call here, ugh 1733 name := r.curfn.NewLocal(pos, r.localIdent(), r.typ()) 1734 r.addLocal(name) 1735 return name, true 1736 1737 case assignExpr: 1738 return r.expr(), false 1739 } 1740 } 1741 1742 func (r *reader) blockStmt() []ir.Node { 1743 r.Sync(pkgbits.SyncBlockStmt) 1744 r.openScope() 1745 stmts := r.stmts() 1746 r.closeScope() 1747 return stmts 1748 } 1749 1750 func (r *reader) forStmt(label *types.Sym) ir.Node { 1751 r.Sync(pkgbits.SyncForStmt) 1752 1753 r.openScope() 1754 1755 if r.Bool() { 1756 pos := r.pos() 1757 rang := ir.NewRangeStmt(pos, nil, nil, nil, nil, false) 1758 rang.Label = label 1759 1760 names, lhs := r.assignList() 1761 if len(lhs) >= 1 { 1762 rang.Key = lhs[0] 1763 if len(lhs) >= 2 { 1764 rang.Value = lhs[1] 1765 } 1766 } 1767 rang.Def = r.initDefn(rang, names) 1768 1769 rang.X = r.expr() 1770 if rang.X.Type().IsMap() { 1771 rang.RType = r.rtype(pos) 1772 } 1773 if rang.Key != nil && !ir.IsBlank(rang.Key) { 1774 rang.KeyTypeWord, rang.KeySrcRType = r.convRTTI(pos) 1775 } 1776 if rang.Value != nil && !ir.IsBlank(rang.Value) { 1777 rang.ValueTypeWord, rang.ValueSrcRType = r.convRTTI(pos) 1778 } 1779 1780 rang.Body = r.blockStmt() 1781 rang.DistinctVars = r.Bool() 1782 r.closeAnotherScope() 1783 1784 return rang 1785 } 1786 1787 pos := r.pos() 1788 init := r.stmt() 1789 cond := r.optExpr() 1790 post := r.stmt() 1791 body := r.blockStmt() 1792 perLoopVars := r.Bool() 1793 r.closeAnotherScope() 1794 1795 if ir.IsConst(cond, constant.Bool) && !ir.BoolVal(cond) { 1796 return init // simplify "for init; false; post { ... }" into "init" 1797 } 1798 1799 stmt := ir.NewForStmt(pos, init, cond, post, body, perLoopVars) 1800 stmt.Label = label 1801 return stmt 1802 } 1803 1804 func (r *reader) ifStmt() ir.Node { 1805 r.Sync(pkgbits.SyncIfStmt) 1806 r.openScope() 1807 pos := r.pos() 1808 init := r.stmts() 1809 cond := r.expr() 1810 staticCond := r.Int() 1811 var then, els []ir.Node 1812 if staticCond >= 0 { 1813 then = r.blockStmt() 1814 } else { 1815 r.lastCloseScopePos = r.pos() 1816 } 1817 if staticCond <= 0 { 1818 els = r.stmts() 1819 } 1820 r.closeAnotherScope() 1821 1822 if staticCond != 0 { 1823 // We may have removed a dead return statement, which can trip up 1824 // later passes (#62211). To avoid confusion, we instead flatten 1825 // the if statement into a block. 1826 1827 if cond.Op() != ir.OLITERAL { 1828 init.Append(typecheck.Stmt(ir.NewAssignStmt(pos, ir.BlankNode, cond))) // for side effects 1829 } 1830 init.Append(then...) 1831 init.Append(els...) 1832 return block(init) 1833 } 1834 1835 n := ir.NewIfStmt(pos, cond, then, els) 1836 n.SetInit(init) 1837 return n 1838 } 1839 1840 func (r *reader) selectStmt(label *types.Sym) ir.Node { 1841 r.Sync(pkgbits.SyncSelectStmt) 1842 1843 pos := r.pos() 1844 clauses := make([]*ir.CommClause, r.Len()) 1845 for i := range clauses { 1846 if i > 0 { 1847 r.closeScope() 1848 } 1849 r.openScope() 1850 1851 pos := r.pos() 1852 comm := r.stmt() 1853 body := r.stmts() 1854 1855 // "case i = <-c: ..." may require an implicit conversion (e.g., 1856 // see fixedbugs/bug312.go). Currently, typecheck throws away the 1857 // implicit conversion and relies on it being reinserted later, 1858 // but that would lose any explicit RTTI operands too. To preserve 1859 // RTTI, we rewrite this as "case tmp := <-c: i = tmp; ...". 1860 if as, ok := comm.(*ir.AssignStmt); ok && as.Op() == ir.OAS && !as.Def { 1861 if conv, ok := as.Y.(*ir.ConvExpr); ok && conv.Op() == ir.OCONVIFACE { 1862 base.AssertfAt(conv.Implicit(), conv.Pos(), "expected implicit conversion: %v", conv) 1863 1864 recv := conv.X 1865 base.AssertfAt(recv.Op() == ir.ORECV, recv.Pos(), "expected receive expression: %v", recv) 1866 1867 tmp := r.temp(pos, recv.Type()) 1868 1869 // Replace comm with `tmp := <-c`. 1870 tmpAs := ir.NewAssignStmt(pos, tmp, recv) 1871 tmpAs.Def = true 1872 tmpAs.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp)) 1873 comm = tmpAs 1874 1875 // Change original assignment to `i = tmp`, and prepend to body. 1876 conv.X = tmp 1877 body = append([]ir.Node{as}, body...) 1878 } 1879 } 1880 1881 // multiExpr will have desugared a comma-ok receive expression 1882 // into a separate statement. However, the rest of the compiler 1883 // expects comm to be the OAS2RECV statement itself, so we need to 1884 // shuffle things around to fit that pattern. 1885 if as2, ok := comm.(*ir.AssignListStmt); ok && as2.Op() == ir.OAS2 { 1886 init := ir.TakeInit(as2.Rhs[0]) 1887 base.AssertfAt(len(init) == 1 && init[0].Op() == ir.OAS2RECV, as2.Pos(), "unexpected assignment: %+v", as2) 1888 1889 comm = init[0] 1890 body = append([]ir.Node{as2}, body...) 1891 } 1892 1893 clauses[i] = ir.NewCommStmt(pos, comm, body) 1894 } 1895 if len(clauses) > 0 { 1896 r.closeScope() 1897 } 1898 n := ir.NewSelectStmt(pos, clauses) 1899 n.Label = label 1900 return n 1901 } 1902 1903 func (r *reader) switchStmt(label *types.Sym) ir.Node { 1904 r.Sync(pkgbits.SyncSwitchStmt) 1905 1906 r.openScope() 1907 pos := r.pos() 1908 init := r.stmt() 1909 1910 var tag ir.Node 1911 var ident *ir.Ident 1912 var iface *types.Type 1913 if r.Bool() { 1914 pos := r.pos() 1915 if r.Bool() { 1916 ident = ir.NewIdent(r.pos(), r.localIdent()) 1917 } 1918 x := r.expr() 1919 iface = x.Type() 1920 tag = ir.NewTypeSwitchGuard(pos, ident, x) 1921 } else { 1922 tag = r.optExpr() 1923 } 1924 1925 clauses := make([]*ir.CaseClause, r.Len()) 1926 for i := range clauses { 1927 if i > 0 { 1928 r.closeScope() 1929 } 1930 r.openScope() 1931 1932 pos := r.pos() 1933 var cases, rtypes []ir.Node 1934 if iface != nil { 1935 cases = make([]ir.Node, r.Len()) 1936 if len(cases) == 0 { 1937 cases = nil // TODO(mdempsky): Unclear if this matters. 1938 } 1939 for i := range cases { 1940 if r.Bool() { // case nil 1941 cases[i] = typecheck.Expr(types.BuiltinPkg.Lookup("nil").Def.(*ir.NilExpr)) 1942 } else { 1943 cases[i] = r.exprType() 1944 } 1945 } 1946 } else { 1947 cases = r.exprList() 1948 1949 // For `switch { case any(true): }` (e.g., issue 3980 in 1950 // test/switch.go), the backend still creates a mixed bool/any 1951 // comparison, and we need to explicitly supply the RTTI for the 1952 // comparison. 1953 // 1954 // TODO(mdempsky): Change writer.go to desugar "switch {" into 1955 // "switch true {", which we already handle correctly. 1956 if tag == nil { 1957 for i, cas := range cases { 1958 if cas.Type().IsEmptyInterface() { 1959 for len(rtypes) < i { 1960 rtypes = append(rtypes, nil) 1961 } 1962 rtypes = append(rtypes, reflectdata.TypePtrAt(cas.Pos(), types.Types[types.TBOOL])) 1963 } 1964 } 1965 } 1966 } 1967 1968 clause := ir.NewCaseStmt(pos, cases, nil) 1969 clause.RTypes = rtypes 1970 1971 if ident != nil { 1972 name := r.curfn.NewLocal(r.pos(), ident.Sym(), r.typ()) 1973 r.addLocal(name) 1974 clause.Var = name 1975 name.Defn = tag 1976 } 1977 1978 clause.Body = r.stmts() 1979 clauses[i] = clause 1980 } 1981 if len(clauses) > 0 { 1982 r.closeScope() 1983 } 1984 r.closeScope() 1985 1986 n := ir.NewSwitchStmt(pos, tag, clauses) 1987 n.Label = label 1988 if init != nil { 1989 n.SetInit([]ir.Node{init}) 1990 } 1991 return n 1992 } 1993 1994 func (r *reader) label() *types.Sym { 1995 r.Sync(pkgbits.SyncLabel) 1996 name := r.String() 1997 if r.inlCall != nil { 1998 name = fmt.Sprintf("~%s·%d", name, inlgen) 1999 } 2000 return typecheck.Lookup(name) 2001 } 2002 2003 func (r *reader) optLabel() *types.Sym { 2004 r.Sync(pkgbits.SyncOptLabel) 2005 if r.Bool() { 2006 return r.label() 2007 } 2008 return nil 2009 } 2010 2011 // initDefn marks the given names as declared by defn and populates 2012 // its Init field with ODCL nodes. It then reports whether any names 2013 // were so declared, which can be used to initialize defn.Def. 2014 func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool { 2015 if len(names) == 0 { 2016 return false 2017 } 2018 2019 init := make([]ir.Node, len(names)) 2020 for i, name := range names { 2021 name.Defn = defn 2022 init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name) 2023 } 2024 defn.SetInit(init) 2025 return true 2026 } 2027 2028 // @@@ Expressions 2029 2030 // expr reads and returns a typechecked expression. 2031 func (r *reader) expr() (res ir.Node) { 2032 defer func() { 2033 if res != nil && res.Typecheck() == 0 { 2034 base.FatalfAt(res.Pos(), "%v missed typecheck", res) 2035 } 2036 }() 2037 2038 switch tag := codeExpr(r.Code(pkgbits.SyncExpr)); tag { 2039 default: 2040 panic("unhandled expression") 2041 2042 case exprLocal: 2043 return typecheck.Expr(r.useLocal()) 2044 2045 case exprGlobal: 2046 // Callee instead of Expr allows builtins 2047 // TODO(mdempsky): Handle builtins directly in exprCall, like method calls? 2048 return typecheck.Callee(r.obj()) 2049 2050 case exprFuncInst: 2051 origPos, pos := r.origPos() 2052 wrapperFn, baseFn, dictPtr := r.funcInst(pos) 2053 if wrapperFn != nil { 2054 return wrapperFn 2055 } 2056 return r.curry(origPos, false, baseFn, dictPtr, nil) 2057 2058 case exprConst: 2059 pos := r.pos() 2060 typ := r.typ() 2061 val := FixValue(typ, r.Value()) 2062 return ir.NewBasicLit(pos, typ, val) 2063 2064 case exprZero: 2065 pos := r.pos() 2066 typ := r.typ() 2067 return ir.NewZero(pos, typ) 2068 2069 case exprCompLit: 2070 return r.compLit() 2071 2072 case exprFuncLit: 2073 return r.funcLit() 2074 2075 case exprFieldVal: 2076 x := r.expr() 2077 pos := r.pos() 2078 sym := r.selector() 2079 2080 return typecheck.XDotField(pos, x, sym) 2081 2082 case exprMethodVal: 2083 recv := r.expr() 2084 origPos, pos := r.origPos() 2085 wrapperFn, baseFn, dictPtr := r.methodExpr() 2086 2087 // For simple wrapperFn values, the existing machinery for creating 2088 // and deduplicating wrapperFn value wrappers still works fine. 2089 if wrapperFn, ok := wrapperFn.(*ir.SelectorExpr); ok && wrapperFn.Op() == ir.OMETHEXPR { 2090 // The receiver expression we constructed may have a shape type. 2091 // For example, in fixedbugs/issue54343.go, `New[int]()` is 2092 // constructed as `New[go.shape.int](&.dict.New[int])`, which 2093 // has type `*T[go.shape.int]`, not `*T[int]`. 2094 // 2095 // However, the method we want to select here is `(*T[int]).M`, 2096 // not `(*T[go.shape.int]).M`, so we need to manually convert 2097 // the type back so that the OXDOT resolves correctly. 2098 // 2099 // TODO(mdempsky): Logically it might make more sense for 2100 // exprCall to take responsibility for setting a non-shaped 2101 // result type, but this is the only place where we care 2102 // currently. And only because existing ir.OMETHVALUE backend 2103 // code relies on n.X.Type() instead of n.Selection.Recv().Type 2104 // (because the latter is types.FakeRecvType() in the case of 2105 // interface method values). 2106 // 2107 if recv.Type().HasShape() { 2108 typ := wrapperFn.Type().Param(0).Type 2109 if !types.Identical(typ, recv.Type()) { 2110 base.FatalfAt(wrapperFn.Pos(), "receiver %L does not match %L", recv, wrapperFn) 2111 } 2112 recv = typecheck.Expr(ir.NewConvExpr(recv.Pos(), ir.OCONVNOP, typ, recv)) 2113 } 2114 2115 n := typecheck.XDotMethod(pos, recv, wrapperFn.Sel, false) 2116 2117 // As a consistency check here, we make sure "n" selected the 2118 // same method (represented by a types.Field) that wrapperFn 2119 // selected. However, for anonymous receiver types, there can be 2120 // multiple such types.Field instances (#58563). So we may need 2121 // to fallback to making sure Sym and Type (including the 2122 // receiver parameter's type) match. 2123 if n.Selection != wrapperFn.Selection { 2124 assert(n.Selection.Sym == wrapperFn.Selection.Sym) 2125 assert(types.Identical(n.Selection.Type, wrapperFn.Selection.Type)) 2126 assert(types.Identical(n.Selection.Type.Recv().Type, wrapperFn.Selection.Type.Recv().Type)) 2127 } 2128 2129 wrapper := methodValueWrapper{ 2130 rcvr: n.X.Type(), 2131 method: n.Selection, 2132 } 2133 2134 if r.importedDef() { 2135 haveMethodValueWrappers = append(haveMethodValueWrappers, wrapper) 2136 } else { 2137 needMethodValueWrappers = append(needMethodValueWrappers, wrapper) 2138 } 2139 return n 2140 } 2141 2142 // For more complicated method expressions, we construct a 2143 // function literal wrapper. 2144 return r.curry(origPos, true, baseFn, recv, dictPtr) 2145 2146 case exprMethodExpr: 2147 recv := r.typ() 2148 2149 implicits := make([]int, r.Len()) 2150 for i := range implicits { 2151 implicits[i] = r.Len() 2152 } 2153 var deref, addr bool 2154 if r.Bool() { 2155 deref = true 2156 } else if r.Bool() { 2157 addr = true 2158 } 2159 2160 origPos, pos := r.origPos() 2161 wrapperFn, baseFn, dictPtr := r.methodExpr() 2162 2163 // If we already have a wrapper and don't need to do anything with 2164 // it, we can just return the wrapper directly. 2165 // 2166 // N.B., we use implicits/deref/addr here as the source of truth 2167 // rather than types.Identical, because the latter can be confused 2168 // by tricky promoted methods (e.g., typeparam/mdempsky/21.go). 2169 if wrapperFn != nil && len(implicits) == 0 && !deref && !addr { 2170 if !types.Identical(recv, wrapperFn.Type().Param(0).Type) { 2171 base.FatalfAt(pos, "want receiver type %v, but have method %L", recv, wrapperFn) 2172 } 2173 return wrapperFn 2174 } 2175 2176 // Otherwise, if the wrapper function is a static method 2177 // expression (OMETHEXPR) and the receiver type is unshaped, then 2178 // we can rely on a statically generated wrapper being available. 2179 if method, ok := wrapperFn.(*ir.SelectorExpr); ok && method.Op() == ir.OMETHEXPR && !recv.HasShape() { 2180 return typecheck.NewMethodExpr(pos, recv, method.Sel) 2181 } 2182 2183 return r.methodExprWrap(origPos, recv, implicits, deref, addr, baseFn, dictPtr) 2184 2185 case exprIndex: 2186 x := r.expr() 2187 pos := r.pos() 2188 index := r.expr() 2189 n := typecheck.Expr(ir.NewIndexExpr(pos, x, index)) 2190 switch n.Op() { 2191 case ir.OINDEXMAP: 2192 n := n.(*ir.IndexExpr) 2193 n.RType = r.rtype(pos) 2194 } 2195 return n 2196 2197 case exprSlice: 2198 x := r.expr() 2199 pos := r.pos() 2200 var index [3]ir.Node 2201 for i := range index { 2202 index[i] = r.optExpr() 2203 } 2204 op := ir.OSLICE 2205 if index[2] != nil { 2206 op = ir.OSLICE3 2207 } 2208 return typecheck.Expr(ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2])) 2209 2210 case exprAssert: 2211 x := r.expr() 2212 pos := r.pos() 2213 typ := r.exprType() 2214 srcRType := r.rtype(pos) 2215 2216 // TODO(mdempsky): Always emit ODYNAMICDOTTYPE for uniformity? 2217 if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE { 2218 assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType) 2219 assert.SrcRType = srcRType 2220 assert.ITab = typ.ITab 2221 return typed(typ.Type(), assert) 2222 } 2223 return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ.Type())) 2224 2225 case exprUnaryOp: 2226 op := r.op() 2227 pos := r.pos() 2228 x := r.expr() 2229 2230 switch op { 2231 case ir.OADDR: 2232 return typecheck.Expr(typecheck.NodAddrAt(pos, x)) 2233 case ir.ODEREF: 2234 return typecheck.Expr(ir.NewStarExpr(pos, x)) 2235 } 2236 return typecheck.Expr(ir.NewUnaryExpr(pos, op, x)) 2237 2238 case exprBinaryOp: 2239 op := r.op() 2240 x := r.expr() 2241 pos := r.pos() 2242 y := r.expr() 2243 2244 switch op { 2245 case ir.OANDAND, ir.OOROR: 2246 return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y)) 2247 case ir.OLSH, ir.ORSH: 2248 // Untyped rhs of non-constant shift, e.g. x << 1.0. 2249 // If we have a constant value, it must be an int >= 0. 2250 if ir.IsConstNode(y) { 2251 val := constant.ToInt(y.Val()) 2252 assert(val.Kind() == constant.Int && constant.Sign(val) >= 0) 2253 } 2254 } 2255 return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y)) 2256 2257 case exprRecv: 2258 x := r.expr() 2259 pos := r.pos() 2260 for i, n := 0, r.Len(); i < n; i++ { 2261 x = Implicit(typecheck.DotField(pos, x, r.Len())) 2262 } 2263 if r.Bool() { // needs deref 2264 x = Implicit(Deref(pos, x.Type().Elem(), x)) 2265 } else if r.Bool() { // needs addr 2266 x = Implicit(Addr(pos, x)) 2267 } 2268 return x 2269 2270 case exprCall: 2271 var fun ir.Node 2272 var args ir.Nodes 2273 if r.Bool() { // method call 2274 recv := r.expr() 2275 _, method, dictPtr := r.methodExpr() 2276 2277 if recv.Type().IsInterface() && method.Op() == ir.OMETHEXPR { 2278 method := method.(*ir.SelectorExpr) 2279 2280 // The compiler backend (e.g., devirtualization) handle 2281 // OCALLINTER/ODOTINTER better than OCALLFUNC/OMETHEXPR for 2282 // interface calls, so we prefer to continue constructing 2283 // calls that way where possible. 2284 // 2285 // There are also corner cases where semantically it's perhaps 2286 // significant; e.g., fixedbugs/issue15975.go, #38634, #52025. 2287 2288 fun = typecheck.XDotMethod(method.Pos(), recv, method.Sel, true) 2289 } else { 2290 if recv.Type().IsInterface() { 2291 // N.B., this happens currently for typeparam/issue51521.go 2292 // and typeparam/typeswitch3.go. 2293 if base.Flag.LowerM != 0 { 2294 base.WarnfAt(method.Pos(), "imprecise interface call") 2295 } 2296 } 2297 2298 fun = method 2299 args.Append(recv) 2300 } 2301 if dictPtr != nil { 2302 args.Append(dictPtr) 2303 } 2304 } else if r.Bool() { // call to instanced function 2305 pos := r.pos() 2306 _, shapedFn, dictPtr := r.funcInst(pos) 2307 fun = shapedFn 2308 args.Append(dictPtr) 2309 } else { 2310 fun = r.expr() 2311 } 2312 pos := r.pos() 2313 args.Append(r.multiExpr()...) 2314 dots := r.Bool() 2315 n := typecheck.Call(pos, fun, args, dots) 2316 switch n.Op() { 2317 case ir.OAPPEND: 2318 n := n.(*ir.CallExpr) 2319 n.RType = r.rtype(pos) 2320 // For append(a, b...), we don't need the implicit conversion. The typechecker already 2321 // ensured that a and b are both slices with the same base type, or []byte and string. 2322 if n.IsDDD { 2323 if conv, ok := n.Args[1].(*ir.ConvExpr); ok && conv.Op() == ir.OCONVNOP && conv.Implicit() { 2324 n.Args[1] = conv.X 2325 } 2326 } 2327 case ir.OCOPY: 2328 n := n.(*ir.BinaryExpr) 2329 n.RType = r.rtype(pos) 2330 case ir.ODELETE: 2331 n := n.(*ir.CallExpr) 2332 n.RType = r.rtype(pos) 2333 case ir.OUNSAFESLICE: 2334 n := n.(*ir.BinaryExpr) 2335 n.RType = r.rtype(pos) 2336 } 2337 return n 2338 2339 case exprMake: 2340 pos := r.pos() 2341 typ := r.exprType() 2342 extra := r.exprs() 2343 n := typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr) 2344 n.RType = r.rtype(pos) 2345 return n 2346 2347 case exprNew: 2348 pos := r.pos() 2349 typ := r.exprType() 2350 return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, typ)) 2351 2352 case exprSizeof: 2353 return ir.NewUintptr(r.pos(), r.typ().Size()) 2354 2355 case exprAlignof: 2356 return ir.NewUintptr(r.pos(), r.typ().Alignment()) 2357 2358 case exprOffsetof: 2359 pos := r.pos() 2360 typ := r.typ() 2361 types.CalcSize(typ) 2362 2363 var offset int64 2364 for i := r.Len(); i >= 0; i-- { 2365 field := typ.Field(r.Len()) 2366 offset += field.Offset 2367 typ = field.Type 2368 } 2369 2370 return ir.NewUintptr(pos, offset) 2371 2372 case exprReshape: 2373 typ := r.typ() 2374 x := r.expr() 2375 2376 if types.IdenticalStrict(x.Type(), typ) { 2377 return x 2378 } 2379 2380 // Comparison expressions are constructed as "untyped bool" still. 2381 // 2382 // TODO(mdempsky): It should be safe to reshape them here too, but 2383 // maybe it's better to construct them with the proper type 2384 // instead. 2385 if x.Type() == types.UntypedBool && typ.IsBoolean() { 2386 return x 2387 } 2388 2389 base.AssertfAt(x.Type().HasShape() || typ.HasShape(), x.Pos(), "%L and %v are not shape types", x, typ) 2390 base.AssertfAt(types.Identical(x.Type(), typ), x.Pos(), "%L is not shape-identical to %v", x, typ) 2391 2392 // We use ir.HasUniquePos here as a check that x only appears once 2393 // in the AST, so it's okay for us to call SetType without 2394 // breaking any other uses of it. 2395 // 2396 // Notably, any ONAMEs should already have the exactly right shape 2397 // type and been caught by types.IdenticalStrict above. 2398 base.AssertfAt(ir.HasUniquePos(x), x.Pos(), "cannot call SetType(%v) on %L", typ, x) 2399 2400 if base.Debug.Reshape != 0 { 2401 base.WarnfAt(x.Pos(), "reshaping %L to %v", x, typ) 2402 } 2403 2404 x.SetType(typ) 2405 return x 2406 2407 case exprConvert: 2408 implicit := r.Bool() 2409 typ := r.typ() 2410 pos := r.pos() 2411 typeWord, srcRType := r.convRTTI(pos) 2412 dstTypeParam := r.Bool() 2413 identical := r.Bool() 2414 x := r.expr() 2415 2416 // TODO(mdempsky): Stop constructing expressions of untyped type. 2417 x = typecheck.DefaultLit(x, typ) 2418 2419 ce := ir.NewConvExpr(pos, ir.OCONV, typ, x) 2420 ce.TypeWord, ce.SrcRType = typeWord, srcRType 2421 if implicit { 2422 ce.SetImplicit(true) 2423 } 2424 n := typecheck.Expr(ce) 2425 2426 // Conversions between non-identical, non-empty interfaces always 2427 // requires a runtime call, even if they have identical underlying 2428 // interfaces. This is because we create separate itab instances 2429 // for each unique interface type, not merely each unique 2430 // interface shape. 2431 // 2432 // However, due to shape types, typecheck.Expr might mistakenly 2433 // think a conversion between two non-empty interfaces are 2434 // identical and set ir.OCONVNOP, instead of ir.OCONVIFACE. To 2435 // ensure we update the itab field appropriately, we force it to 2436 // ir.OCONVIFACE instead when shape types are involved. 2437 // 2438 // TODO(mdempsky): Are there other places we might get this wrong? 2439 // Should this be moved down into typecheck.{Assign,Convert}op? 2440 // This would be a non-issue if itabs were unique for each 2441 // *underlying* interface type instead. 2442 if !identical { 2443 if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) { 2444 n.SetOp(ir.OCONVIFACE) 2445 } 2446 } 2447 2448 // spec: "If the type is a type parameter, the constant is converted 2449 // into a non-constant value of the type parameter." 2450 if dstTypeParam && ir.IsConstNode(n) { 2451 // Wrap in an OCONVNOP node to ensure result is non-constant. 2452 n = Implicit(ir.NewConvExpr(pos, ir.OCONVNOP, n.Type(), n)) 2453 n.SetTypecheck(1) 2454 } 2455 return n 2456 2457 case exprRuntimeBuiltin: 2458 builtin := typecheck.LookupRuntime(r.String()) 2459 return builtin 2460 } 2461 } 2462 2463 // funcInst reads an instantiated function reference, and returns 2464 // three (possibly nil) expressions related to it: 2465 // 2466 // baseFn is always non-nil: it's either a function of the appropriate 2467 // type already, or it has an extra dictionary parameter as the first 2468 // parameter. 2469 // 2470 // If dictPtr is non-nil, then it's a dictionary argument that must be 2471 // passed as the first argument to baseFn. 2472 // 2473 // If wrapperFn is non-nil, then it's either the same as baseFn (if 2474 // dictPtr is nil), or it's semantically equivalent to currying baseFn 2475 // to pass dictPtr. (wrapperFn is nil when dictPtr is an expression 2476 // that needs to be computed dynamically.) 2477 // 2478 // For callers that are creating a call to the returned function, it's 2479 // best to emit a call to baseFn, and include dictPtr in the arguments 2480 // list as appropriate. 2481 // 2482 // For callers that want to return the function without invoking it, 2483 // they may return wrapperFn if it's non-nil; but otherwise, they need 2484 // to create their own wrapper. 2485 func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) { 2486 // Like in methodExpr, I'm pretty sure this isn't needed. 2487 var implicits []*types.Type 2488 if r.dict != nil { 2489 implicits = r.dict.targs 2490 } 2491 2492 if r.Bool() { // dynamic subdictionary 2493 idx := r.Len() 2494 info := r.dict.subdicts[idx] 2495 explicits := r.p.typListIdx(info.explicits, r.dict) 2496 2497 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name) 2498 2499 // TODO(mdempsky): Is there a more robust way to get the 2500 // dictionary pointer type here? 2501 dictPtrType := baseFn.Type().Param(0).Type 2502 dictPtr = typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx))) 2503 2504 return 2505 } 2506 2507 info := r.objInfo() 2508 explicits := r.p.typListIdx(info.explicits, r.dict) 2509 2510 wrapperFn = r.p.objIdx(info.idx, implicits, explicits, false).(*ir.Name) 2511 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name) 2512 2513 dictName := r.p.objDictName(info.idx, implicits, explicits) 2514 dictPtr = typecheck.Expr(ir.NewAddrExpr(pos, dictName)) 2515 2516 return 2517 } 2518 2519 func (pr *pkgReader) objDictName(idx pkgbits.Index, implicits, explicits []*types.Type) *ir.Name { 2520 rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1) 2521 _, sym := rname.qualifiedIdent() 2522 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj)) 2523 2524 if tag == pkgbits.ObjStub { 2525 assert(!sym.IsBlank()) 2526 if pri, ok := objReader[sym]; ok { 2527 return pri.pr.objDictName(pri.idx, nil, explicits) 2528 } 2529 base.Fatalf("unresolved stub: %v", sym) 2530 } 2531 2532 dict := pr.objDictIdx(sym, idx, implicits, explicits, false) 2533 2534 return pr.dictNameOf(dict) 2535 } 2536 2537 // curry returns a function literal that calls fun with arg0 and 2538 // (optionally) arg1, accepting additional arguments to the function 2539 // literal as necessary to satisfy fun's signature. 2540 // 2541 // If nilCheck is true and arg0 is an interface value, then it's 2542 // checked to be non-nil as an initial step at the point of evaluating 2543 // the function literal itself. 2544 func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node { 2545 var captured ir.Nodes 2546 captured.Append(fun, arg0) 2547 if arg1 != nil { 2548 captured.Append(arg1) 2549 } 2550 2551 params, results := syntheticSig(fun.Type()) 2552 params = params[len(captured)-1:] // skip curried parameters 2553 typ := types.NewSignature(nil, params, results) 2554 2555 addBody := func(pos src.XPos, r *reader, captured []ir.Node) { 2556 fun := captured[0] 2557 2558 var args ir.Nodes 2559 args.Append(captured[1:]...) 2560 args.Append(r.syntheticArgs()...) 2561 2562 r.syntheticTailCall(pos, fun, args) 2563 } 2564 2565 return r.syntheticClosure(origPos, typ, ifaceHack, captured, addBody) 2566 } 2567 2568 // methodExprWrap returns a function literal that changes method's 2569 // first parameter's type to recv, and uses implicits/deref/addr to 2570 // select the appropriate receiver parameter to pass to method. 2571 func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node { 2572 var captured ir.Nodes 2573 captured.Append(method) 2574 2575 params, results := syntheticSig(method.Type()) 2576 2577 // Change first parameter to recv. 2578 params[0].Type = recv 2579 2580 // If we have a dictionary pointer argument to pass, then omit the 2581 // underlying method expression's dictionary parameter from the 2582 // returned signature too. 2583 if dictPtr != nil { 2584 captured.Append(dictPtr) 2585 params = append(params[:1], params[2:]...) 2586 } 2587 2588 typ := types.NewSignature(nil, params, results) 2589 2590 addBody := func(pos src.XPos, r *reader, captured []ir.Node) { 2591 fn := captured[0] 2592 args := r.syntheticArgs() 2593 2594 // Rewrite first argument based on implicits/deref/addr. 2595 { 2596 arg := args[0] 2597 for _, ix := range implicits { 2598 arg = Implicit(typecheck.DotField(pos, arg, ix)) 2599 } 2600 if deref { 2601 arg = Implicit(Deref(pos, arg.Type().Elem(), arg)) 2602 } else if addr { 2603 arg = Implicit(Addr(pos, arg)) 2604 } 2605 args[0] = arg 2606 } 2607 2608 // Insert dictionary argument, if provided. 2609 if dictPtr != nil { 2610 newArgs := make([]ir.Node, len(args)+1) 2611 newArgs[0] = args[0] 2612 newArgs[1] = captured[1] 2613 copy(newArgs[2:], args[1:]) 2614 args = newArgs 2615 } 2616 2617 r.syntheticTailCall(pos, fn, args) 2618 } 2619 2620 return r.syntheticClosure(origPos, typ, false, captured, addBody) 2621 } 2622 2623 // syntheticClosure constructs a synthetic function literal for 2624 // currying dictionary arguments. origPos is the position used for the 2625 // closure, which must be a non-inlined position. typ is the function 2626 // literal's signature type. 2627 // 2628 // captures is a list of expressions that need to be evaluated at the 2629 // point of function literal evaluation and captured by the function 2630 // literal. If ifaceHack is true and captures[1] is an interface type, 2631 // it's checked to be non-nil after evaluation. 2632 // 2633 // addBody is a callback function to populate the function body. The 2634 // list of captured values passed back has the captured variables for 2635 // use within the function literal, corresponding to the expressions 2636 // in captures. 2637 func (r *reader) syntheticClosure(origPos src.XPos, typ *types.Type, ifaceHack bool, captures ir.Nodes, addBody func(pos src.XPos, r *reader, captured []ir.Node)) ir.Node { 2638 // isSafe reports whether n is an expression that we can safely 2639 // defer to evaluating inside the closure instead, to avoid storing 2640 // them into the closure. 2641 // 2642 // In practice this is always (and only) the wrappee function. 2643 isSafe := func(n ir.Node) bool { 2644 if n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PFUNC { 2645 return true 2646 } 2647 if n.Op() == ir.OMETHEXPR { 2648 return true 2649 } 2650 2651 return false 2652 } 2653 2654 fn := r.inlClosureFunc(origPos, typ) 2655 fn.SetWrapper(true) 2656 2657 clo := fn.OClosure 2658 inlPos := clo.Pos() 2659 2660 var init ir.Nodes 2661 for i, n := range captures { 2662 if isSafe(n) { 2663 continue // skip capture; can reference directly 2664 } 2665 2666 tmp := r.tempCopy(inlPos, n, &init) 2667 ir.NewClosureVar(origPos, fn, tmp) 2668 2669 // We need to nil check interface receivers at the point of method 2670 // value evaluation, ugh. 2671 if ifaceHack && i == 1 && n.Type().IsInterface() { 2672 check := ir.NewUnaryExpr(inlPos, ir.OCHECKNIL, ir.NewUnaryExpr(inlPos, ir.OITAB, tmp)) 2673 init.Append(typecheck.Stmt(check)) 2674 } 2675 } 2676 2677 pri := pkgReaderIndex{synthetic: func(pos src.XPos, r *reader) { 2678 captured := make([]ir.Node, len(captures)) 2679 next := 0 2680 for i, n := range captures { 2681 if isSafe(n) { 2682 captured[i] = n 2683 } else { 2684 captured[i] = r.closureVars[next] 2685 next++ 2686 } 2687 } 2688 assert(next == len(r.closureVars)) 2689 2690 addBody(origPos, r, captured) 2691 }} 2692 bodyReader[fn] = pri 2693 pri.funcBody(fn) 2694 2695 return ir.InitExpr(init, clo) 2696 } 2697 2698 // syntheticSig duplicates and returns the params and results lists 2699 // for sig, but renaming anonymous parameters so they can be assigned 2700 // ir.Names. 2701 func syntheticSig(sig *types.Type) (params, results []*types.Field) { 2702 clone := func(params []*types.Field) []*types.Field { 2703 res := make([]*types.Field, len(params)) 2704 for i, param := range params { 2705 // TODO(mdempsky): It would be nice to preserve the original 2706 // parameter positions here instead, but at least 2707 // typecheck.NewMethodType replaces them with base.Pos, making 2708 // them useless. Worse, the positions copied from base.Pos may 2709 // have inlining contexts, which we definitely don't want here 2710 // (e.g., #54625). 2711 res[i] = types.NewField(base.AutogeneratedPos, param.Sym, param.Type) 2712 res[i].SetIsDDD(param.IsDDD()) 2713 } 2714 return res 2715 } 2716 2717 return clone(sig.Params()), clone(sig.Results()) 2718 } 2719 2720 func (r *reader) optExpr() ir.Node { 2721 if r.Bool() { 2722 return r.expr() 2723 } 2724 return nil 2725 } 2726 2727 // methodExpr reads a method expression reference, and returns three 2728 // (possibly nil) expressions related to it: 2729 // 2730 // baseFn is always non-nil: it's either a function of the appropriate 2731 // type already, or it has an extra dictionary parameter as the second 2732 // parameter (i.e., immediately after the promoted receiver 2733 // parameter). 2734 // 2735 // If dictPtr is non-nil, then it's a dictionary argument that must be 2736 // passed as the second argument to baseFn. 2737 // 2738 // If wrapperFn is non-nil, then it's either the same as baseFn (if 2739 // dictPtr is nil), or it's semantically equivalent to currying baseFn 2740 // to pass dictPtr. (wrapperFn is nil when dictPtr is an expression 2741 // that needs to be computed dynamically.) 2742 // 2743 // For callers that are creating a call to the returned method, it's 2744 // best to emit a call to baseFn, and include dictPtr in the arguments 2745 // list as appropriate. 2746 // 2747 // For callers that want to return a method expression without 2748 // invoking it, they may return wrapperFn if it's non-nil; but 2749 // otherwise, they need to create their own wrapper. 2750 func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) { 2751 recv := r.typ() 2752 sig0 := r.typ() 2753 pos := r.pos() 2754 sym := r.selector() 2755 2756 // Signature type to return (i.e., recv prepended to the method's 2757 // normal parameters list). 2758 sig := typecheck.NewMethodType(sig0, recv) 2759 2760 if r.Bool() { // type parameter method expression 2761 idx := r.Len() 2762 word := r.dictWord(pos, r.dict.typeParamMethodExprsOffset()+idx) 2763 2764 // TODO(mdempsky): If the type parameter was instantiated with an 2765 // interface type (i.e., embed.IsInterface()), then we could 2766 // return the OMETHEXPR instead and save an indirection. 2767 2768 // We wrote the method expression's entry point PC into the 2769 // dictionary, but for Go `func` values we need to return a 2770 // closure (i.e., pointer to a structure with the PC as the first 2771 // field). Because method expressions don't have any closure 2772 // variables, we pun the dictionary entry as the closure struct. 2773 fn := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, sig, ir.NewAddrExpr(pos, word))) 2774 return fn, fn, nil 2775 } 2776 2777 // TODO(mdempsky): I'm pretty sure this isn't needed: implicits is 2778 // only relevant to locally defined types, but they can't have 2779 // (non-promoted) methods. 2780 var implicits []*types.Type 2781 if r.dict != nil { 2782 implicits = r.dict.targs 2783 } 2784 2785 if r.Bool() { // dynamic subdictionary 2786 idx := r.Len() 2787 info := r.dict.subdicts[idx] 2788 explicits := r.p.typListIdx(info.explicits, r.dict) 2789 2790 shapedObj := r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name) 2791 shapedFn := shapedMethodExpr(pos, shapedObj, sym) 2792 2793 // TODO(mdempsky): Is there a more robust way to get the 2794 // dictionary pointer type here? 2795 dictPtrType := shapedFn.Type().Param(1).Type 2796 dictPtr := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx))) 2797 2798 return nil, shapedFn, dictPtr 2799 } 2800 2801 if r.Bool() { // static dictionary 2802 info := r.objInfo() 2803 explicits := r.p.typListIdx(info.explicits, r.dict) 2804 2805 shapedObj := r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name) 2806 shapedFn := shapedMethodExpr(pos, shapedObj, sym) 2807 2808 dict := r.p.objDictName(info.idx, implicits, explicits) 2809 dictPtr := typecheck.Expr(ir.NewAddrExpr(pos, dict)) 2810 2811 // Check that dictPtr matches shapedFn's dictionary parameter. 2812 if !types.Identical(dictPtr.Type(), shapedFn.Type().Param(1).Type) { 2813 base.FatalfAt(pos, "dict %L, but shaped method %L", dict, shapedFn) 2814 } 2815 2816 // For statically known instantiations, we can take advantage of 2817 // the stenciled wrapper. 2818 base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv) 2819 wrapperFn := typecheck.NewMethodExpr(pos, recv, sym) 2820 base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig) 2821 2822 return wrapperFn, shapedFn, dictPtr 2823 } 2824 2825 // Simple method expression; no dictionary needed. 2826 base.AssertfAt(!recv.HasShape() || recv.IsInterface(), pos, "shaped receiver %v", recv) 2827 fn := typecheck.NewMethodExpr(pos, recv, sym) 2828 return fn, fn, nil 2829 } 2830 2831 // shapedMethodExpr returns the specified method on the given shaped 2832 // type. 2833 func shapedMethodExpr(pos src.XPos, obj *ir.Name, sym *types.Sym) *ir.SelectorExpr { 2834 assert(obj.Op() == ir.OTYPE) 2835 2836 typ := obj.Type() 2837 assert(typ.HasShape()) 2838 2839 method := func() *types.Field { 2840 for _, method := range typ.Methods() { 2841 if method.Sym == sym { 2842 return method 2843 } 2844 } 2845 2846 base.FatalfAt(pos, "failed to find method %v in shaped type %v", sym, typ) 2847 panic("unreachable") 2848 }() 2849 2850 // Construct an OMETHEXPR node. 2851 recv := method.Type.Recv().Type 2852 return typecheck.NewMethodExpr(pos, recv, sym) 2853 } 2854 2855 func (r *reader) multiExpr() []ir.Node { 2856 r.Sync(pkgbits.SyncMultiExpr) 2857 2858 if r.Bool() { // N:1 2859 pos := r.pos() 2860 expr := r.expr() 2861 2862 results := make([]ir.Node, r.Len()) 2863 as := ir.NewAssignListStmt(pos, ir.OAS2, nil, []ir.Node{expr}) 2864 as.Def = true 2865 for i := range results { 2866 tmp := r.temp(pos, r.typ()) 2867 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp)) 2868 as.Lhs.Append(tmp) 2869 2870 res := ir.Node(tmp) 2871 if r.Bool() { 2872 n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res) 2873 n.TypeWord, n.SrcRType = r.convRTTI(pos) 2874 n.SetImplicit(true) 2875 res = typecheck.Expr(n) 2876 } 2877 results[i] = res 2878 } 2879 2880 // TODO(mdempsky): Could use ir.InlinedCallExpr instead? 2881 results[0] = ir.InitExpr([]ir.Node{typecheck.Stmt(as)}, results[0]) 2882 return results 2883 } 2884 2885 // N:N 2886 exprs := make([]ir.Node, r.Len()) 2887 if len(exprs) == 0 { 2888 return nil 2889 } 2890 for i := range exprs { 2891 exprs[i] = r.expr() 2892 } 2893 return exprs 2894 } 2895 2896 // temp returns a new autotemp of the specified type. 2897 func (r *reader) temp(pos src.XPos, typ *types.Type) *ir.Name { 2898 return typecheck.TempAt(pos, r.curfn, typ) 2899 } 2900 2901 // tempCopy declares and returns a new autotemp initialized to the 2902 // value of expr. 2903 func (r *reader) tempCopy(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name { 2904 tmp := r.temp(pos, expr.Type()) 2905 2906 init.Append(typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp))) 2907 2908 assign := ir.NewAssignStmt(pos, tmp, expr) 2909 assign.Def = true 2910 init.Append(typecheck.Stmt(ir.NewAssignStmt(pos, tmp, expr))) 2911 2912 tmp.Defn = assign 2913 2914 return tmp 2915 } 2916 2917 func (r *reader) compLit() ir.Node { 2918 r.Sync(pkgbits.SyncCompLit) 2919 pos := r.pos() 2920 typ0 := r.typ() 2921 2922 typ := typ0 2923 if typ.IsPtr() { 2924 typ = typ.Elem() 2925 } 2926 if typ.Kind() == types.TFORW { 2927 base.FatalfAt(pos, "unresolved composite literal type: %v", typ) 2928 } 2929 var rtype ir.Node 2930 if typ.IsMap() { 2931 rtype = r.rtype(pos) 2932 } 2933 isStruct := typ.Kind() == types.TSTRUCT 2934 2935 elems := make([]ir.Node, r.Len()) 2936 for i := range elems { 2937 elemp := &elems[i] 2938 2939 if isStruct { 2940 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.Len()), nil) 2941 *elemp, elemp = sk, &sk.Value 2942 } else if r.Bool() { 2943 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil) 2944 *elemp, elemp = kv, &kv.Value 2945 } 2946 2947 *elemp = wrapName(r.pos(), r.expr()) 2948 } 2949 2950 lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems)) 2951 if rtype != nil { 2952 lit := lit.(*ir.CompLitExpr) 2953 lit.RType = rtype 2954 } 2955 if typ0.IsPtr() { 2956 lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit)) 2957 lit.SetType(typ0) 2958 } 2959 return lit 2960 } 2961 2962 func wrapName(pos src.XPos, x ir.Node) ir.Node { 2963 // These nodes do not carry line numbers. 2964 // Introduce a wrapper node to give them the correct line. 2965 switch x.Op() { 2966 case ir.OTYPE, ir.OLITERAL: 2967 if x.Sym() == nil { 2968 break 2969 } 2970 fallthrough 2971 case ir.ONAME, ir.ONONAME, ir.ONIL: 2972 p := ir.NewParenExpr(pos, x) 2973 p.SetImplicit(true) 2974 return p 2975 } 2976 return x 2977 } 2978 2979 func (r *reader) funcLit() ir.Node { 2980 r.Sync(pkgbits.SyncFuncLit) 2981 2982 // The underlying function declaration (including its parameters' 2983 // positions, if any) need to remain the original, uninlined 2984 // positions. This is because we track inlining-context on nodes so 2985 // we can synthesize the extra implied stack frames dynamically when 2986 // generating tracebacks, whereas those stack frames don't make 2987 // sense *within* the function literal. (Any necessary inlining 2988 // adjustments will have been applied to the call expression 2989 // instead.) 2990 // 2991 // This is subtle, and getting it wrong leads to cycles in the 2992 // inlining tree, which lead to infinite loops during stack 2993 // unwinding (#46234, #54625). 2994 // 2995 // Note that we *do* want the inline-adjusted position for the 2996 // OCLOSURE node, because that position represents where any heap 2997 // allocation of the closure is credited (#49171). 2998 r.suppressInlPos++ 2999 origPos := r.pos() 3000 sig := r.signature(nil) 3001 r.suppressInlPos-- 3002 3003 fn := r.inlClosureFunc(origPos, sig) 3004 3005 fn.ClosureVars = make([]*ir.Name, 0, r.Len()) 3006 for len(fn.ClosureVars) < cap(fn.ClosureVars) { 3007 // TODO(mdempsky): I think these should be original positions too 3008 // (i.e., not inline-adjusted). 3009 ir.NewClosureVar(r.pos(), fn, r.useLocal()) 3010 } 3011 if param := r.dictParam; param != nil { 3012 // If we have a dictionary parameter, capture it too. For 3013 // simplicity, we capture it last and unconditionally. 3014 ir.NewClosureVar(param.Pos(), fn, param) 3015 } 3016 3017 r.addBody(fn, nil) 3018 3019 // un-hide closures belong to init function. 3020 if (r.curfn.IsPackageInit() || strings.HasPrefix(r.curfn.Sym().Name, "init.")) && ir.IsTrivialClosure(fn.OClosure) { 3021 fn.SetIsHiddenClosure(false) 3022 } 3023 3024 return fn.OClosure 3025 } 3026 3027 // inlClosureFunc constructs a new closure function, but correctly 3028 // handles inlining. 3029 func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type) *ir.Func { 3030 curfn := r.inlCaller 3031 if curfn == nil { 3032 curfn = r.curfn 3033 } 3034 3035 // TODO(mdempsky): Remove hard-coding of typecheck.Target. 3036 return ir.NewClosureFunc(origPos, r.inlPos(origPos), ir.OCLOSURE, sig, curfn, typecheck.Target) 3037 } 3038 3039 func (r *reader) exprList() []ir.Node { 3040 r.Sync(pkgbits.SyncExprList) 3041 return r.exprs() 3042 } 3043 3044 func (r *reader) exprs() []ir.Node { 3045 r.Sync(pkgbits.SyncExprs) 3046 nodes := make([]ir.Node, r.Len()) 3047 if len(nodes) == 0 { 3048 return nil // TODO(mdempsky): Unclear if this matters. 3049 } 3050 for i := range nodes { 3051 nodes[i] = r.expr() 3052 } 3053 return nodes 3054 } 3055 3056 // dictWord returns an expression to return the specified 3057 // uintptr-typed word from the dictionary parameter. 3058 func (r *reader) dictWord(pos src.XPos, idx int) ir.Node { 3059 base.AssertfAt(r.dictParam != nil, pos, "expected dictParam in %v", r.curfn) 3060 return typecheck.Expr(ir.NewIndexExpr(pos, r.dictParam, ir.NewInt(pos, int64(idx)))) 3061 } 3062 3063 // rttiWord is like dictWord, but converts it to *byte (the type used 3064 // internally to represent *runtime._type and *runtime.itab). 3065 func (r *reader) rttiWord(pos src.XPos, idx int) ir.Node { 3066 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TUINT8]), r.dictWord(pos, idx))) 3067 } 3068 3069 // rtype reads a type reference from the element bitstream, and 3070 // returns an expression of type *runtime._type representing that 3071 // type. 3072 func (r *reader) rtype(pos src.XPos) ir.Node { 3073 _, rtype := r.rtype0(pos) 3074 return rtype 3075 } 3076 3077 func (r *reader) rtype0(pos src.XPos) (typ *types.Type, rtype ir.Node) { 3078 r.Sync(pkgbits.SyncRType) 3079 if r.Bool() { // derived type 3080 idx := r.Len() 3081 info := r.dict.rtypes[idx] 3082 typ = r.p.typIdx(info, r.dict, true) 3083 rtype = r.rttiWord(pos, r.dict.rtypesOffset()+idx) 3084 return 3085 } 3086 3087 typ = r.typ() 3088 rtype = reflectdata.TypePtrAt(pos, typ) 3089 return 3090 } 3091 3092 // varDictIndex populates name.DictIndex if name is a derived type. 3093 func (r *reader) varDictIndex(name *ir.Name) { 3094 if r.Bool() { 3095 idx := 1 + r.dict.rtypesOffset() + r.Len() 3096 if int(uint16(idx)) != idx { 3097 base.FatalfAt(name.Pos(), "DictIndex overflow for %v: %v", name, idx) 3098 } 3099 name.DictIndex = uint16(idx) 3100 } 3101 } 3102 3103 // itab returns a (typ, iface) pair of types. 3104 // 3105 // typRType and ifaceRType are expressions that evaluate to the 3106 // *runtime._type for typ and iface, respectively. 3107 // 3108 // If typ is a concrete type and iface is a non-empty interface type, 3109 // then itab is an expression that evaluates to the *runtime.itab for 3110 // the pair. Otherwise, itab is nil. 3111 func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) { 3112 typ, typRType = r.rtype0(pos) 3113 iface, ifaceRType = r.rtype0(pos) 3114 3115 idx := -1 3116 if r.Bool() { 3117 idx = r.Len() 3118 } 3119 3120 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() { 3121 if idx >= 0 { 3122 itab = r.rttiWord(pos, r.dict.itabsOffset()+idx) 3123 } else { 3124 base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ) 3125 base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface) 3126 3127 lsym := reflectdata.ITabLsym(typ, iface) 3128 itab = typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8]) 3129 } 3130 } 3131 3132 return 3133 } 3134 3135 // convRTTI returns expressions appropriate for populating an 3136 // ir.ConvExpr's TypeWord and SrcRType fields, respectively. 3137 func (r *reader) convRTTI(pos src.XPos) (typeWord, srcRType ir.Node) { 3138 r.Sync(pkgbits.SyncConvRTTI) 3139 src, srcRType0, dst, dstRType, itab := r.itab(pos) 3140 if !dst.IsInterface() { 3141 return 3142 } 3143 3144 // See reflectdata.ConvIfaceTypeWord. 3145 switch { 3146 case dst.IsEmptyInterface(): 3147 if !src.IsInterface() { 3148 typeWord = srcRType0 // direct eface construction 3149 } 3150 case !src.IsInterface(): 3151 typeWord = itab // direct iface construction 3152 default: 3153 typeWord = dstRType // convI2I 3154 } 3155 3156 // See reflectdata.ConvIfaceSrcRType. 3157 if !src.IsInterface() { 3158 srcRType = srcRType0 3159 } 3160 3161 return 3162 } 3163 3164 func (r *reader) exprType() ir.Node { 3165 r.Sync(pkgbits.SyncExprType) 3166 pos := r.pos() 3167 3168 var typ *types.Type 3169 var rtype, itab ir.Node 3170 3171 if r.Bool() { 3172 typ, rtype, _, _, itab = r.itab(pos) 3173 if !typ.IsInterface() { 3174 rtype = nil // TODO(mdempsky): Leave set? 3175 } 3176 } else { 3177 typ, rtype = r.rtype0(pos) 3178 3179 if !r.Bool() { // not derived 3180 return ir.TypeNode(typ) 3181 } 3182 } 3183 3184 dt := ir.NewDynamicType(pos, rtype) 3185 dt.ITab = itab 3186 return typed(typ, dt) 3187 } 3188 3189 func (r *reader) op() ir.Op { 3190 r.Sync(pkgbits.SyncOp) 3191 return ir.Op(r.Len()) 3192 } 3193 3194 // @@@ Package initialization 3195 3196 func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) { 3197 cgoPragmas := make([][]string, r.Len()) 3198 for i := range cgoPragmas { 3199 cgoPragmas[i] = r.Strings() 3200 } 3201 target.CgoPragmas = cgoPragmas 3202 3203 r.pkgInitOrder(target) 3204 3205 r.pkgDecls(target) 3206 3207 r.Sync(pkgbits.SyncEOF) 3208 } 3209 3210 // pkgInitOrder creates a synthetic init function to handle any 3211 // package-scope initialization statements. 3212 func (r *reader) pkgInitOrder(target *ir.Package) { 3213 initOrder := make([]ir.Node, r.Len()) 3214 if len(initOrder) == 0 { 3215 return 3216 } 3217 3218 // Make a function that contains all the initialization statements. 3219 pos := base.AutogeneratedPos 3220 base.Pos = pos 3221 3222 fn := ir.NewFunc(pos, pos, typecheck.Lookup("init"), types.NewSignature(nil, nil, nil)) 3223 fn.SetIsPackageInit(true) 3224 fn.SetInlinabilityChecked(true) // suppress useless "can inline" diagnostics 3225 3226 typecheck.DeclFunc(fn) 3227 r.curfn = fn 3228 3229 for i := range initOrder { 3230 lhs := make([]ir.Node, r.Len()) 3231 for j := range lhs { 3232 lhs[j] = r.obj() 3233 } 3234 rhs := r.expr() 3235 pos := lhs[0].Pos() 3236 3237 var as ir.Node 3238 if len(lhs) == 1 { 3239 as = typecheck.Stmt(ir.NewAssignStmt(pos, lhs[0], rhs)) 3240 } else { 3241 as = typecheck.Stmt(ir.NewAssignListStmt(pos, ir.OAS2, lhs, []ir.Node{rhs})) 3242 } 3243 3244 for _, v := range lhs { 3245 v.(*ir.Name).Defn = as 3246 } 3247 3248 initOrder[i] = as 3249 } 3250 3251 fn.Body = initOrder 3252 3253 typecheck.FinishFuncBody() 3254 r.curfn = nil 3255 r.locals = nil 3256 3257 // Outline (if legal/profitable) global map inits. 3258 staticinit.OutlineMapInits(fn) 3259 3260 target.Inits = append(target.Inits, fn) 3261 } 3262 3263 func (r *reader) pkgDecls(target *ir.Package) { 3264 r.Sync(pkgbits.SyncDecls) 3265 for { 3266 switch code := codeDecl(r.Code(pkgbits.SyncDecl)); code { 3267 default: 3268 panic(fmt.Sprintf("unhandled decl: %v", code)) 3269 3270 case declEnd: 3271 return 3272 3273 case declFunc: 3274 names := r.pkgObjs(target) 3275 assert(len(names) == 1) 3276 target.Funcs = append(target.Funcs, names[0].Func) 3277 3278 case declMethod: 3279 typ := r.typ() 3280 sym := r.selector() 3281 3282 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0) 3283 target.Funcs = append(target.Funcs, method.Nname.(*ir.Name).Func) 3284 3285 case declVar: 3286 names := r.pkgObjs(target) 3287 3288 if n := r.Len(); n > 0 { 3289 assert(len(names) == 1) 3290 embeds := make([]ir.Embed, n) 3291 for i := range embeds { 3292 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.Strings()} 3293 } 3294 names[0].Embed = &embeds 3295 target.Embeds = append(target.Embeds, names[0]) 3296 } 3297 3298 case declOther: 3299 r.pkgObjs(target) 3300 } 3301 } 3302 } 3303 3304 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name { 3305 r.Sync(pkgbits.SyncDeclNames) 3306 nodes := make([]*ir.Name, r.Len()) 3307 for i := range nodes { 3308 r.Sync(pkgbits.SyncDeclName) 3309 3310 name := r.obj().(*ir.Name) 3311 nodes[i] = name 3312 3313 sym := name.Sym() 3314 if sym.IsBlank() { 3315 continue 3316 } 3317 3318 switch name.Class { 3319 default: 3320 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class) 3321 3322 case ir.PEXTERN: 3323 target.Externs = append(target.Externs, name) 3324 3325 case ir.PFUNC: 3326 assert(name.Type().Recv() == nil) 3327 3328 // TODO(mdempsky): Cleaner way to recognize init? 3329 if strings.HasPrefix(sym.Name, "init.") { 3330 target.Inits = append(target.Inits, name.Func) 3331 } 3332 } 3333 3334 if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME { 3335 assert(!sym.OnExportList()) 3336 target.PluginExports = append(target.PluginExports, name) 3337 sym.SetOnExportList(true) 3338 } 3339 3340 if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) { 3341 assert(!sym.Asm()) 3342 target.AsmHdrDecls = append(target.AsmHdrDecls, name) 3343 sym.SetAsm(true) 3344 } 3345 } 3346 3347 return nodes 3348 } 3349 3350 // @@@ Inlining 3351 3352 // unifiedHaveInlineBody reports whether we have the function body for 3353 // fn, so we can inline it. 3354 func unifiedHaveInlineBody(fn *ir.Func) bool { 3355 if fn.Inl == nil { 3356 return false 3357 } 3358 3359 _, ok := bodyReaderFor(fn) 3360 return ok 3361 } 3362 3363 var inlgen = 0 3364 3365 // unifiedInlineCall implements inline.NewInline by re-reading the function 3366 // body from its Unified IR export data. 3367 func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr { 3368 pri, ok := bodyReaderFor(fn) 3369 if !ok { 3370 base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn) 3371 } 3372 3373 if !fn.Inl.HaveDcl { 3374 expandInline(fn, pri) 3375 } 3376 3377 r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody) 3378 3379 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type()) 3380 3381 r.curfn = tmpfn 3382 3383 r.inlCaller = callerfn 3384 r.inlCall = call 3385 r.inlFunc = fn 3386 r.inlTreeIndex = inlIndex 3387 r.inlPosBases = make(map[*src.PosBase]*src.PosBase) 3388 r.funarghack = true 3389 3390 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars)) 3391 for i, cv := range r.inlFunc.ClosureVars { 3392 // TODO(mdempsky): It should be possible to support this case, but 3393 // for now we rely on the inliner avoiding it. 3394 if cv.Outer.Curfn != callerfn { 3395 base.FatalfAt(call.Pos(), "inlining closure call across frames") 3396 } 3397 r.closureVars[i] = cv.Outer 3398 } 3399 if len(r.closureVars) != 0 && r.hasTypeParams() { 3400 r.dictParam = r.closureVars[len(r.closureVars)-1] // dictParam is last; see reader.funcLit 3401 } 3402 3403 r.declareParams() 3404 3405 var inlvars, retvars []*ir.Name 3406 { 3407 sig := r.curfn.Type() 3408 endParams := sig.NumRecvs() + sig.NumParams() 3409 endResults := endParams + sig.NumResults() 3410 3411 inlvars = r.curfn.Dcl[:endParams] 3412 retvars = r.curfn.Dcl[endParams:endResults] 3413 } 3414 3415 r.delayResults = fn.Inl.CanDelayResults 3416 3417 r.retlabel = typecheck.AutoLabel(".i") 3418 inlgen++ 3419 3420 init := ir.TakeInit(call) 3421 3422 // For normal function calls, the function callee expression 3423 // may contain side effects. Make sure to preserve these, 3424 // if necessary (#42703). 3425 if call.Op() == ir.OCALLFUNC { 3426 inline.CalleeEffects(&init, call.Fun) 3427 } 3428 3429 var args ir.Nodes 3430 if call.Op() == ir.OCALLMETH { 3431 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck") 3432 } 3433 args.Append(call.Args...) 3434 3435 // Create assignment to declare and initialize inlvars. 3436 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, ir.ToNodes(inlvars), args) 3437 as2.Def = true 3438 var as2init ir.Nodes 3439 for _, name := range inlvars { 3440 if ir.IsBlank(name) { 3441 continue 3442 } 3443 // TODO(mdempsky): Use inlined position of name.Pos() instead? 3444 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name)) 3445 name.Defn = as2 3446 } 3447 as2.SetInit(as2init) 3448 init.Append(typecheck.Stmt(as2)) 3449 3450 if !r.delayResults { 3451 // If not delaying retvars, declare and zero initialize the 3452 // result variables now. 3453 for _, name := range retvars { 3454 // TODO(mdempsky): Use inlined position of name.Pos() instead? 3455 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name)) 3456 ras := ir.NewAssignStmt(call.Pos(), name, nil) 3457 init.Append(typecheck.Stmt(ras)) 3458 } 3459 } 3460 3461 // Add an inline mark just before the inlined body. 3462 // This mark is inline in the code so that it's a reasonable spot 3463 // to put a breakpoint. Not sure if that's really necessary or not 3464 // (in which case it could go at the end of the function instead). 3465 // Note issue 28603. 3466 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex))) 3467 3468 ir.WithFunc(r.curfn, func() { 3469 if !r.syntheticBody(call.Pos()) { 3470 assert(r.Bool()) // have body 3471 3472 r.curfn.Body = r.stmts() 3473 r.curfn.Endlineno = r.pos() 3474 } 3475 3476 // TODO(mdempsky): This shouldn't be necessary. Inlining might 3477 // read in new function/method declarations, which could 3478 // potentially be recursively inlined themselves; but we shouldn't 3479 // need to read in the non-inlined bodies for the declarations 3480 // themselves. But currently it's an easy fix to #50552. 3481 readBodies(typecheck.Target, true) 3482 3483 // Replace any "return" statements within the function body. 3484 var edit func(ir.Node) ir.Node 3485 edit = func(n ir.Node) ir.Node { 3486 if ret, ok := n.(*ir.ReturnStmt); ok { 3487 n = typecheck.Stmt(r.inlReturn(ret, retvars)) 3488 } 3489 ir.EditChildren(n, edit) 3490 return n 3491 } 3492 edit(r.curfn) 3493 }) 3494 3495 body := ir.Nodes(r.curfn.Body) 3496 3497 // Reparent any declarations into the caller function. 3498 for _, name := range r.curfn.Dcl { 3499 name.Curfn = callerfn 3500 3501 if name.Class != ir.PAUTO { 3502 name.SetPos(r.inlPos(name.Pos())) 3503 name.SetInlFormal(true) 3504 name.Class = ir.PAUTO 3505 } else { 3506 name.SetInlLocal(true) 3507 } 3508 } 3509 callerfn.Dcl = append(callerfn.Dcl, r.curfn.Dcl...) 3510 3511 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel)) 3512 3513 res := ir.NewInlinedCallExpr(call.Pos(), body, ir.ToNodes(retvars)) 3514 res.SetInit(init) 3515 res.SetType(call.Type()) 3516 res.SetTypecheck(1) 3517 3518 // Inlining shouldn't add any functions to todoBodies. 3519 assert(len(todoBodies) == 0) 3520 3521 return res 3522 } 3523 3524 // inlReturn returns a statement that can substitute for the given 3525 // return statement when inlining. 3526 func (r *reader) inlReturn(ret *ir.ReturnStmt, retvars []*ir.Name) *ir.BlockStmt { 3527 pos := r.inlCall.Pos() 3528 3529 block := ir.TakeInit(ret) 3530 3531 if results := ret.Results; len(results) != 0 { 3532 assert(len(retvars) == len(results)) 3533 3534 as2 := ir.NewAssignListStmt(pos, ir.OAS2, ir.ToNodes(retvars), ret.Results) 3535 3536 if r.delayResults { 3537 for _, name := range retvars { 3538 // TODO(mdempsky): Use inlined position of name.Pos() instead? 3539 block.Append(ir.NewDecl(pos, ir.ODCL, name)) 3540 name.Defn = as2 3541 } 3542 } 3543 3544 block.Append(as2) 3545 } 3546 3547 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel)) 3548 return ir.NewBlockStmt(pos, block) 3549 } 3550 3551 // expandInline reads in an extra copy of IR to populate 3552 // fn.Inl.Dcl. 3553 func expandInline(fn *ir.Func, pri pkgReaderIndex) { 3554 // TODO(mdempsky): Remove this function. It's currently needed by 3555 // dwarfgen/dwarf.go:preInliningDcls, which requires fn.Inl.Dcl to 3556 // create abstract function DIEs. But we should be able to provide it 3557 // with the same information some other way. 3558 3559 fndcls := len(fn.Dcl) 3560 topdcls := len(typecheck.Target.Funcs) 3561 3562 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type()) 3563 tmpfn.ClosureVars = fn.ClosureVars 3564 3565 { 3566 r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody) 3567 3568 // Don't change parameter's Sym/Nname fields. 3569 r.funarghack = true 3570 3571 r.funcBody(tmpfn) 3572 } 3573 3574 // Move tmpfn's params to fn.Inl.Dcl, and reparent under fn. 3575 for _, name := range tmpfn.Dcl { 3576 name.Curfn = fn 3577 } 3578 fn.Inl.Dcl = tmpfn.Dcl 3579 fn.Inl.HaveDcl = true 3580 3581 // Double check that we didn't change fn.Dcl by accident. 3582 assert(fndcls == len(fn.Dcl)) 3583 3584 // typecheck.Stmts may have added function literals to 3585 // typecheck.Target.Decls. Remove them again so we don't risk trying 3586 // to compile them multiple times. 3587 typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls] 3588 } 3589 3590 // usedLocals returns a set of local variables that are used within body. 3591 func usedLocals(body []ir.Node) ir.NameSet { 3592 var used ir.NameSet 3593 ir.VisitList(body, func(n ir.Node) { 3594 if n, ok := n.(*ir.Name); ok && n.Op() == ir.ONAME && n.Class == ir.PAUTO { 3595 used.Add(n) 3596 } 3597 }) 3598 return used 3599 } 3600 3601 // @@@ Method wrappers 3602 3603 // needWrapperTypes lists types for which we may need to generate 3604 // method wrappers. 3605 var needWrapperTypes []*types.Type 3606 3607 // haveWrapperTypes lists types for which we know we already have 3608 // method wrappers, because we found the type in an imported package. 3609 var haveWrapperTypes []*types.Type 3610 3611 // needMethodValueWrappers lists methods for which we may need to 3612 // generate method value wrappers. 3613 var needMethodValueWrappers []methodValueWrapper 3614 3615 // haveMethodValueWrappers lists methods for which we know we already 3616 // have method value wrappers, because we found it in an imported 3617 // package. 3618 var haveMethodValueWrappers []methodValueWrapper 3619 3620 type methodValueWrapper struct { 3621 rcvr *types.Type 3622 method *types.Field 3623 } 3624 3625 func (r *reader) needWrapper(typ *types.Type) { 3626 if typ.IsPtr() { 3627 return 3628 } 3629 3630 // If a type was found in an imported package, then we can assume 3631 // that package (or one of its transitive dependencies) already 3632 // generated method wrappers for it. 3633 if r.importedDef() { 3634 haveWrapperTypes = append(haveWrapperTypes, typ) 3635 } else { 3636 needWrapperTypes = append(needWrapperTypes, typ) 3637 } 3638 } 3639 3640 // importedDef reports whether r is reading from an imported and 3641 // non-generic element. 3642 // 3643 // If a type was found in an imported package, then we can assume that 3644 // package (or one of its transitive dependencies) already generated 3645 // method wrappers for it. 3646 // 3647 // Exception: If we're instantiating an imported generic type or 3648 // function, we might be instantiating it with type arguments not 3649 // previously seen before. 3650 // 3651 // TODO(mdempsky): Distinguish when a generic function or type was 3652 // instantiated in an imported package so that we can add types to 3653 // haveWrapperTypes instead. 3654 func (r *reader) importedDef() bool { 3655 return r.p != localPkgReader && !r.hasTypeParams() 3656 } 3657 3658 func MakeWrappers(target *ir.Package) { 3659 // always generate a wrapper for error.Error (#29304) 3660 needWrapperTypes = append(needWrapperTypes, types.ErrorType) 3661 3662 seen := make(map[string]*types.Type) 3663 3664 for _, typ := range haveWrapperTypes { 3665 wrapType(typ, target, seen, false) 3666 } 3667 haveWrapperTypes = nil 3668 3669 for _, typ := range needWrapperTypes { 3670 wrapType(typ, target, seen, true) 3671 } 3672 needWrapperTypes = nil 3673 3674 for _, wrapper := range haveMethodValueWrappers { 3675 wrapMethodValue(wrapper.rcvr, wrapper.method, target, false) 3676 } 3677 haveMethodValueWrappers = nil 3678 3679 for _, wrapper := range needMethodValueWrappers { 3680 wrapMethodValue(wrapper.rcvr, wrapper.method, target, true) 3681 } 3682 needMethodValueWrappers = nil 3683 } 3684 3685 func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) { 3686 key := typ.LinkString() 3687 if prev := seen[key]; prev != nil { 3688 if !types.Identical(typ, prev) { 3689 base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key) 3690 } 3691 return 3692 } 3693 seen[key] = typ 3694 3695 if !needed { 3696 // Only called to add to 'seen'. 3697 return 3698 } 3699 3700 if !typ.IsInterface() { 3701 typecheck.CalcMethods(typ) 3702 } 3703 for _, meth := range typ.AllMethods() { 3704 if meth.Sym.IsBlank() || !meth.IsMethod() { 3705 base.FatalfAt(meth.Pos, "invalid method: %v", meth) 3706 } 3707 3708 methodWrapper(0, typ, meth, target) 3709 3710 // For non-interface types, we also want *T wrappers. 3711 if !typ.IsInterface() { 3712 methodWrapper(1, typ, meth, target) 3713 3714 // For not-in-heap types, *T is a scalar, not pointer shaped, 3715 // so the interface wrappers use **T. 3716 if typ.NotInHeap() { 3717 methodWrapper(2, typ, meth, target) 3718 } 3719 } 3720 } 3721 } 3722 3723 func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) { 3724 wrapper := tbase 3725 for i := 0; i < derefs; i++ { 3726 wrapper = types.NewPtr(wrapper) 3727 } 3728 3729 sym := ir.MethodSym(wrapper, method.Sym) 3730 base.Assertf(!sym.Siggen(), "already generated wrapper %v", sym) 3731 sym.SetSiggen(true) 3732 3733 wrappee := method.Type.Recv().Type 3734 if types.Identical(wrapper, wrappee) || 3735 !types.IsMethodApplicable(wrapper, method) || 3736 !reflectdata.NeedEmit(tbase) { 3737 return 3738 } 3739 3740 // TODO(mdempsky): Use method.Pos instead? 3741 pos := base.AutogeneratedPos 3742 3743 fn := newWrapperFunc(pos, sym, wrapper, method) 3744 3745 var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name) 3746 3747 // For simple *T wrappers around T methods, panicwrap produces a 3748 // nicer panic message. 3749 if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) { 3750 cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node)) 3751 then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)} 3752 fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil)) 3753 } 3754 3755 // typecheck will add one implicit deref, if necessary, 3756 // but not-in-heap types require more for their **T wrappers. 3757 for i := 1; i < derefs; i++ { 3758 recv = Implicit(ir.NewStarExpr(pos, recv)) 3759 } 3760 3761 addTailCall(pos, fn, recv, method) 3762 3763 finishWrapperFunc(fn, target) 3764 } 3765 3766 func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) { 3767 sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm") 3768 if sym.Uniq() { 3769 return 3770 } 3771 sym.SetUniq(true) 3772 3773 // TODO(mdempsky): Use method.Pos instead? 3774 pos := base.AutogeneratedPos 3775 3776 fn := newWrapperFunc(pos, sym, nil, method) 3777 sym.Def = fn.Nname 3778 3779 // Declare and initialize variable holding receiver. 3780 recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType) 3781 3782 if !needed { 3783 return 3784 } 3785 3786 addTailCall(pos, fn, recv, method) 3787 3788 finishWrapperFunc(fn, target) 3789 } 3790 3791 func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func { 3792 sig := newWrapperType(wrapper, method) 3793 3794 fn := ir.NewFunc(pos, pos, sym, sig) 3795 fn.DeclareParams(true) 3796 fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers? 3797 3798 return fn 3799 } 3800 3801 func finishWrapperFunc(fn *ir.Func, target *ir.Package) { 3802 ir.WithFunc(fn, func() { 3803 typecheck.Stmts(fn.Body) 3804 }) 3805 3806 // We generate wrappers after the global inlining pass, 3807 // so we're responsible for applying inlining ourselves here. 3808 // TODO(prattmic): plumb PGO. 3809 interleaved.DevirtualizeAndInlineFunc(fn, nil) 3810 3811 // The body of wrapper function after inlining may reveal new ir.OMETHVALUE node, 3812 // we don't know whether wrapper function has been generated for it or not, so 3813 // generate one immediately here. 3814 // 3815 // Further, after CL 492017, function that construct closures is allowed to be inlined, 3816 // even though the closure itself can't be inline. So we also need to visit body of any 3817 // closure that we see when visiting body of the wrapper function. 3818 ir.VisitFuncAndClosures(fn, func(n ir.Node) { 3819 if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE { 3820 wrapMethodValue(n.X.Type(), n.Selection, target, true) 3821 } 3822 }) 3823 3824 fn.Nname.Defn = fn 3825 target.Funcs = append(target.Funcs, fn) 3826 } 3827 3828 // newWrapperType returns a copy of the given signature type, but with 3829 // the receiver parameter type substituted with recvType. 3830 // If recvType is nil, newWrapperType returns a signature 3831 // without a receiver parameter. 3832 func newWrapperType(recvType *types.Type, method *types.Field) *types.Type { 3833 clone := func(params []*types.Field) []*types.Field { 3834 res := make([]*types.Field, len(params)) 3835 for i, param := range params { 3836 res[i] = types.NewField(param.Pos, param.Sym, param.Type) 3837 res[i].SetIsDDD(param.IsDDD()) 3838 } 3839 return res 3840 } 3841 3842 sig := method.Type 3843 3844 var recv *types.Field 3845 if recvType != nil { 3846 recv = types.NewField(sig.Recv().Pos, sig.Recv().Sym, recvType) 3847 } 3848 params := clone(sig.Params()) 3849 results := clone(sig.Results()) 3850 3851 return types.NewSignature(recv, params, results) 3852 } 3853 3854 func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) { 3855 sig := fn.Nname.Type() 3856 args := make([]ir.Node, sig.NumParams()) 3857 for i, param := range sig.Params() { 3858 args[i] = param.Nname.(*ir.Name) 3859 } 3860 3861 // TODO(mdempsky): Support creating OTAILCALL, when possible. See reflectdata.methodWrapper. 3862 // Not urgent though, because tail calls are currently incompatible with regabi anyway. 3863 3864 fn.SetWrapper(true) // TODO(mdempsky): Leave unset for tail calls? 3865 3866 dot := typecheck.XDotMethod(pos, recv, method.Sym, true) 3867 call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr) 3868 3869 if method.Type.NumResults() == 0 { 3870 fn.Body.Append(call) 3871 return 3872 } 3873 3874 ret := ir.NewReturnStmt(pos, nil) 3875 ret.Results = []ir.Node{call} 3876 fn.Body.Append(ret) 3877 } 3878 3879 func setBasePos(pos src.XPos) { 3880 // Set the position for any error messages we might print (e.g. too large types). 3881 base.Pos = pos 3882 } 3883 3884 // dictParamName is the name of the synthetic dictionary parameter 3885 // added to shaped functions. 3886 // 3887 // N.B., this variable name is known to Delve: 3888 // https://github.com/go-delve/delve/blob/cb91509630529e6055be845688fd21eb89ae8714/pkg/proc/eval.go#L28 3889 const dictParamName = typecheck.LocalDictName 3890 3891 // shapeSig returns a copy of fn's signature, except adding a 3892 // dictionary parameter and promoting the receiver parameter (if any) 3893 // to a normal parameter. 3894 // 3895 // The parameter types.Fields are all copied too, so their Nname 3896 // fields can be initialized for use by the shape function. 3897 func shapeSig(fn *ir.Func, dict *readerDict) *types.Type { 3898 sig := fn.Nname.Type() 3899 oldRecv := sig.Recv() 3900 3901 var recv *types.Field 3902 if oldRecv != nil { 3903 recv = types.NewField(oldRecv.Pos, oldRecv.Sym, oldRecv.Type) 3904 } 3905 3906 params := make([]*types.Field, 1+sig.NumParams()) 3907 params[0] = types.NewField(fn.Pos(), fn.Sym().Pkg.Lookup(dictParamName), types.NewPtr(dict.varType())) 3908 for i, param := range sig.Params() { 3909 d := types.NewField(param.Pos, param.Sym, param.Type) 3910 d.SetIsDDD(param.IsDDD()) 3911 params[1+i] = d 3912 } 3913 3914 results := make([]*types.Field, sig.NumResults()) 3915 for i, result := range sig.Results() { 3916 results[i] = types.NewField(result.Pos, result.Sym, result.Type) 3917 } 3918 3919 return types.NewSignature(recv, params, results) 3920 }