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