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.
15 "cmd/compile/internal/base"
16 "cmd/compile/internal/dwarfgen"
17 "cmd/compile/internal/inline"
18 "cmd/compile/internal/ir"
19 "cmd/compile/internal/objw"
20 "cmd/compile/internal/reflectdata"
21 "cmd/compile/internal/staticinit"
22 "cmd/compile/internal/typecheck"
23 "cmd/compile/internal/types"
29 // This file implements cmd/compile backend's reader for the Unified
32 // A pkgReader reads Unified IR export data.
33 type pkgReader struct {
36 // Indices for encoded things; lazily populated as needed.
38 // Note: Objects (i.e., ir.Names) are lazily instantiated by
39 // populating their types.Sym.Def; see objReader below.
41 posBases []*src.PosBase
45 // offset for rewriting the given (absolute!) index into the output,
46 // but bitwise inverted so we can detect if we're missing the entry
48 newindex []pkgbits.Index
51 func newPkgReader(pr pkgbits.PkgDecoder) *pkgReader {
55 posBases: make([]*src.PosBase, pr.NumElems(pkgbits.RelocPosBase)),
56 pkgs: make([]*types.Pkg, pr.NumElems(pkgbits.RelocPkg)),
57 typs: make([]*types.Type, pr.NumElems(pkgbits.RelocType)),
59 newindex: make([]pkgbits.Index, pr.TotalElems()),
63 // A pkgReaderIndex compactly identifies an index (and its
64 // corresponding dictionary) within a package's export data.
65 type pkgReaderIndex struct {
71 synthetic func(pos src.XPos, r *reader)
74 func (pri pkgReaderIndex) asReader(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *reader {
75 if pri.synthetic != nil {
76 return &reader{synthetic: pri.synthetic}
79 r := pri.pr.newReader(k, pri.idx, marker)
81 r.methodSym = pri.methodSym
85 func (pr *pkgReader) newReader(k pkgbits.RelocKind, idx pkgbits.Index, marker pkgbits.SyncMarker) *reader {
87 Decoder: pr.NewDecoder(k, idx, marker),
92 // A reader provides APIs for reading an individual element.
100 // TODO(mdempsky): The state below is all specific to reading
101 // function bodies. It probably makes sense to split it out
102 // separately so that it doesn't take up space in every reader
107 closureVars []*ir.Name
111 // methodSym is the name of method's name, if reading a method.
112 // It's nil if reading a normal function or closure body.
115 // dictParam is the .dict param, if any.
118 // synthetic is a callback function to construct a synthetic
119 // function body. It's used for creating the bodies of function
120 // literals used to curry arguments to shaped functions.
121 synthetic func(pos src.XPos, r *reader)
123 // scopeVars is a stack tracking the number of variables declared in
124 // the current function at the moment each open scope was opened.
126 marker dwarfgen.ScopeMarker
127 lastCloseScopePos src.XPos
129 // === details for handling inline body expansion ===
131 // If we're reading in a function body because of inlining, this is
132 // the call that we're inlining for.
137 inlPosBases map[*src.PosBase]*src.PosBase
139 // suppressInlPos tracks whether position base rewriting for
140 // inlining should be suppressed. See funcLit.
145 // Label to return to.
148 // inlvars is the list of variables that the inlinee's arguments are
149 // assigned to, one for each receiver and normal parameter, in order.
152 // retvars is the list of variables that the inlinee's results are
153 // assigned to, one for each result parameter, in order.
157 // A readerDict represents an instantiated "compile-time dictionary,"
158 // used for resolving any derived types needed for instantiating a
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
166 type readerDict struct {
167 shaped bool // whether this is a shaped dictionary
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.
174 // For non-shaped dictionaries, shapedObj is a reference to the
175 // corresponding shaped object (always a function or defined type).
178 // targs holds the implicit and explicit type arguments in use for
179 // reading the current object. For example:
182 // type X[U any] struct { t T; u U }
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
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.)
198 // implicits counts how many of types within targs are implicit type
199 // arguments; the rest are explicit.
202 derived []derivedInfo // reloc index of the derived type's descriptor
203 derivedTypes []*types.Type // slice of previously computed derived types
205 // These slices correspond to entries in the runtime dictionary.
206 typeParamMethodExprs []readerMethodExprInfo
212 type readerMethodExprInfo struct {
217 func setType(n ir.Node, typ *types.Type) {
222 func setValue(name *ir.Name, val constant.Value) {
229 // pos reads a position from the bitstream.
230 func (r *reader) pos() src.XPos {
231 return base.Ctxt.PosTable.XPos(r.pos0())
234 // origPos reads a position from the bitstream, and returns both the
235 // original raw position and an inlining-adjusted position.
236 func (r *reader) origPos() (origPos, inlPos src.XPos) {
240 inlPos = r.inlPos(origPos)
244 func (r *reader) pos0() src.Pos {
245 r.Sync(pkgbits.SyncPos)
250 posBase := r.posBase()
253 return src.MakePos(posBase, line, col)
256 // posBase reads a position base from the bitstream.
257 func (r *reader) posBase() *src.PosBase {
258 return r.inlPosBase(r.p.posBaseIdx(r.Reloc(pkgbits.RelocPosBase)))
261 // posBaseIdx returns the specified position base, reading it first if
263 func (pr *pkgReader) posBaseIdx(idx pkgbits.Index) *src.PosBase {
264 if b := pr.posBases[idx]; b != nil {
268 r := pr.newReader(pkgbits.RelocPosBase, idx, pkgbits.SyncPosBase)
271 absFilename := r.String()
272 filename := absFilename
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
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):])
292 b = src.NewFileBase(filename, absFilename)
297 b = src.NewLinePragmaBase(pos, filename, absFilename, line, col)
304 // inlPosBase returns the inlining-adjusted src.PosBase corresponding
305 // to oldBase, which must be a non-inlined position. When not
306 // inlining, this is just oldBase.
307 func (r *reader) inlPosBase(oldBase *src.PosBase) *src.PosBase {
308 if index := oldBase.InliningIndex(); index >= 0 {
309 base.Fatalf("oldBase %v already has inlining index %v", oldBase, index)
312 if r.inlCall == nil || r.suppressInlPos != 0 {
316 if newBase, ok := r.inlPosBases[oldBase]; ok {
320 newBase := src.NewInliningBase(oldBase, r.inlTreeIndex)
321 r.inlPosBases[oldBase] = newBase
325 // inlPos returns the inlining-adjusted src.XPos corresponding to
326 // xpos, which must be a non-inlined position. When not inlining, this
328 func (r *reader) inlPos(xpos src.XPos) src.XPos {
329 pos := base.Ctxt.PosTable.Pos(xpos)
330 pos.SetBase(r.inlPosBase(pos.Base()))
331 return base.Ctxt.PosTable.XPos(pos)
336 // pkg reads a package reference from the bitstream.
337 func (r *reader) pkg() *types.Pkg {
338 r.Sync(pkgbits.SyncPkg)
339 return r.p.pkgIdx(r.Reloc(pkgbits.RelocPkg))
342 // pkgIdx returns the specified package from the export data, reading
343 // it first if needed.
344 func (pr *pkgReader) pkgIdx(idx pkgbits.Index) *types.Pkg {
345 if pkg := pr.pkgs[idx]; pkg != nil {
349 pkg := pr.newReader(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef).doPkg()
354 // doPkg reads a package definition from the bitstream.
355 func (r *reader) doPkg() *types.Pkg {
361 return types.BuiltinPkg
363 return types.UnsafePkg
368 pkg := types.NewPkg(path, "")
373 base.Assertf(pkg.Name == name, "package %q has name %q, but want %q", pkg.Path, pkg.Name, name)
381 func (r *reader) typ() *types.Type {
382 return r.typWrapped(true)
385 // typWrapped is like typ, but allows suppressing generation of
386 // unnecessary wrappers as a compile-time optimization.
387 func (r *reader) typWrapped(wrapped bool) *types.Type {
388 return r.p.typIdx(r.typInfo(), r.dict, wrapped)
391 func (r *reader) typInfo() typeInfo {
392 r.Sync(pkgbits.SyncType)
394 return typeInfo{idx: pkgbits.Index(r.Len()), derived: true}
396 return typeInfo{idx: r.Reloc(pkgbits.RelocType), derived: false}
399 // typListIdx returns a list of the specified types, resolving derived
400 // types within the given dictionary.
401 func (pr *pkgReader) typListIdx(infos []typeInfo, dict *readerDict) []*types.Type {
402 typs := make([]*types.Type, len(infos))
403 for i, info := range infos {
404 typs[i] = pr.typIdx(info, dict, true)
409 // typIdx returns the specified type. If info specifies a derived
410 // type, it's resolved within the given dictionary. If wrapped is
411 // true, then method wrappers will be generated, if appropriate.
412 func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *types.Type {
414 var where **types.Type
416 where = &dict.derivedTypes[idx]
417 idx = dict.derived[idx].idx
419 where = &pr.typs[idx]
422 if typ := *where; typ != nil {
426 r := pr.newReader(pkgbits.RelocType, idx, pkgbits.SyncTypeIdx)
432 // For recursive type declarations involving interfaces and aliases,
433 // above r.doTyp() call may have already set pr.typs[idx], so just
434 // double check and return the type.
440 // type I interface {
444 // The writer writes data types in following index order:
448 // 2: interface{m(func(I))}
450 // The reader resolves it in following index order:
452 // 0 -> 1 -> 2 -> 0 -> 1
454 // and can divide in logically 2 steps:
456 // - 0 -> 1 : first time the reader reach type I,
457 // it creates new named type with symbol I.
459 // - 2 -> 0 -> 1: the reader ends up reaching symbol I again,
460 // now the symbol I was setup in above step, so
461 // the reader just return the named type.
463 // Now, the functions called return, the pr.typs looks like below:
465 // - 0 -> 1 -> 2 -> 0 : [<T> I <T>]
466 // - 0 -> 1 -> 2 : [func(I) I <T>]
467 // - 0 -> 1 : [func(I) I interface { "".m(func("".I)) }]
469 // The idx 1, corresponding with type I was resolved successfully
470 // after r.doTyp() call.
472 if prev := *where; prev != nil {
477 // Only cache if we're adding wrappers, so that other callers that
478 // find a cached type know it was wrapped.
484 if !typ.IsUntyped() {
491 func (r *reader) doTyp() *types.Type {
492 switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {
494 panic(fmt.Sprintf("unexpected type: %v", tag))
496 case pkgbits.TypeBasic:
497 return *basics[r.Len()]
499 case pkgbits.TypeNamed:
501 assert(obj.Op() == ir.OTYPE)
504 case pkgbits.TypeTypeParam:
505 return r.dict.targs[r.Len()]
507 case pkgbits.TypeArray:
508 len := int64(r.Uint64())
509 return types.NewArray(r.typ(), len)
510 case pkgbits.TypeChan:
512 return types.NewChan(r.typ(), dir)
513 case pkgbits.TypeMap:
514 return types.NewMap(r.typ(), r.typ())
515 case pkgbits.TypePointer:
516 return types.NewPtr(r.typ())
517 case pkgbits.TypeSignature:
518 return r.signature(nil)
519 case pkgbits.TypeSlice:
520 return types.NewSlice(r.typ())
521 case pkgbits.TypeStruct:
522 return r.structType()
523 case pkgbits.TypeInterface:
524 return r.interfaceType()
525 case pkgbits.TypeUnion:
530 func (r *reader) unionType() *types.Type {
531 // In the types1 universe, we only need to handle value types.
532 // Impure interfaces (i.e., interfaces with non-trivial type sets
533 // like "int | string") can only appear as type parameter bounds,
534 // and this is enforced by the types2 type checker.
536 // However, type unions can still appear in pure interfaces if the
537 // type union is equivalent to "any". E.g., typeparam/issue52124.go
538 // declares variables with the type "interface { any | int }".
540 // To avoid needing to represent type unions in types1 (since we
541 // don't have any uses for that today anyway), we simply fold them
544 // TODO(mdempsky): Restore consistency check to make sure folding to
545 // "any" is safe. This is unfortunately tricky, because a pure
546 // interface can reference impure interfaces too, including
547 // cyclically (#60117).
550 for i, n := 0, r.Len(); i < n; i++ {
551 _ = r.Bool() // tilde
553 if term.IsEmptyInterface() {
558 base.Fatalf("impure type set used in value type")
562 return types.Types[types.TINTER]
565 func (r *reader) interfaceType() *types.Type {
566 nmethods, nembeddeds := r.Len(), r.Len()
567 implicit := nmethods == 0 && nembeddeds == 1 && r.Bool()
568 assert(!implicit) // implicit interfaces only appear in constraints
570 fields := make([]*types.Field, nmethods+nembeddeds)
571 methods, embeddeds := fields[:nmethods], fields[nmethods:]
573 for i := range methods {
575 _, sym := r.selector()
576 mtyp := r.signature(types.FakeRecv())
577 methods[i] = types.NewField(pos, sym, mtyp)
579 for i := range embeddeds {
580 embeddeds[i] = types.NewField(src.NoXPos, nil, r.typ())
583 if len(fields) == 0 {
584 return types.Types[types.TINTER] // empty interface
586 return types.NewInterface(fields)
589 func (r *reader) structType() *types.Type {
590 fields := make([]*types.Field, r.Len())
591 for i := range fields {
593 _, sym := r.selector()
598 f := types.NewField(pos, sym, ftyp)
605 return types.NewStruct(fields)
608 func (r *reader) signature(recv *types.Field) *types.Type {
609 r.Sync(pkgbits.SyncSignature)
612 results := r.params()
613 if r.Bool() { // variadic
614 params[len(params)-1].SetIsDDD(true)
617 return types.NewSignature(recv, params, results)
620 func (r *reader) params() []*types.Field {
621 r.Sync(pkgbits.SyncParams)
622 fields := make([]*types.Field, r.Len())
623 for i := range fields {
624 _, fields[i] = r.param()
629 func (r *reader) param() (*types.Pkg, *types.Field) {
630 r.Sync(pkgbits.SyncParam)
633 pkg, sym := r.localIdent()
636 return pkg, types.NewField(pos, sym, typ)
641 // objReader maps qualified identifiers (represented as *types.Sym) to
642 // a pkgReader and corresponding index that can be used for reading
643 // that object's definition.
644 var objReader = map[*types.Sym]pkgReaderIndex{}
646 // obj reads an instantiated object reference from the bitstream.
647 func (r *reader) obj() ir.Node {
648 return r.p.objInstIdx(r.objInfo(), r.dict, false)
651 // objInfo reads an instantiated object reference from the bitstream
652 // and returns the encoded reference to it, without instantiating it.
653 func (r *reader) objInfo() objInfo {
654 r.Sync(pkgbits.SyncObject)
655 assert(!r.Bool()) // TODO(mdempsky): Remove; was derived func inst.
656 idx := r.Reloc(pkgbits.RelocObj)
658 explicits := make([]typeInfo, r.Len())
659 for i := range explicits {
660 explicits[i] = r.typInfo()
663 return objInfo{idx, explicits}
666 // objInstIdx returns the encoded, instantiated object. If shaped is
667 // true, then the shaped variant of the object is returned instead.
668 func (pr *pkgReader) objInstIdx(info objInfo, dict *readerDict, shaped bool) ir.Node {
669 explicits := pr.typListIdx(info.explicits, dict)
671 var implicits []*types.Type
673 implicits = dict.targs
676 return pr.objIdx(info.idx, implicits, explicits, shaped)
679 // objIdx returns the specified object, instantiated with the given
680 // type arguments, if any. If shaped is true, then the shaped variant
681 // of the object is returned instead.
682 func (pr *pkgReader) objIdx(idx pkgbits.Index, implicits, explicits []*types.Type, shaped bool) ir.Node {
683 rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
684 _, sym := rname.qualifiedIdent()
685 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
687 if tag == pkgbits.ObjStub {
688 assert(!sym.IsBlank())
690 case types.BuiltinPkg, types.UnsafePkg:
691 return sym.Def.(ir.Node)
693 if pri, ok := objReader[sym]; ok {
694 return pri.pr.objIdx(pri.idx, nil, explicits, shaped)
696 base.Fatalf("unresolved stub: %v", sym)
699 dict := pr.objDictIdx(sym, idx, implicits, explicits, shaped)
702 if !sym.IsBlank() && sym.Def != nil {
703 return sym.Def.(*ir.Name)
706 r := pr.newReader(pkgbits.RelocObj, idx, pkgbits.SyncObject1)
707 rext := pr.newReader(pkgbits.RelocObjExt, idx, pkgbits.SyncObject1)
712 do := func(op ir.Op, hasTParams bool) *ir.Name {
719 name := ir.NewDeclNameAt(pos, op, sym)
720 name.Class = ir.PEXTERN // may be overridden later
723 base.FatalfAt(name.Pos(), "already have a definition for %v", name)
725 assert(sym.Def == nil)
733 panic("unexpected object")
735 case pkgbits.ObjAlias:
736 name := do(ir.OTYPE, false)
737 setType(name, r.typ())
741 case pkgbits.ObjConst:
742 name := do(ir.OLITERAL, false)
744 val := FixValue(typ, r.Value())
749 case pkgbits.ObjFunc:
750 if sym.Name == "init" {
757 typ := r.signature(nil)
760 fn := ir.NewFunc(fpos, npos, sym, typ)
764 base.FatalfAt(name.Pos(), "already have a definition for %v", name)
766 assert(sym.Def == nil)
770 if r.hasTypeParams() {
771 name.Func.SetDupok(true)
773 setType(name, shapeSig(name.Func, r.dict))
775 todoDicts = append(todoDicts, func() {
776 r.dict.shapedObj = pr.objIdx(idx, implicits, explicits, true).(*ir.Name)
781 rext.funcExt(name, nil)
784 case pkgbits.ObjType:
785 name := do(ir.OTYPE, true)
786 typ := types.NewNamed(name)
788 if r.hasTypeParams() && r.dict.shaped {
789 typ.SetHasShape(true)
792 // Important: We need to do this before SetUnderlying.
795 // We need to defer CheckSize until we've called SetUnderlying to
796 // handle recursive types.
797 types.DeferCheckSize()
798 typ.SetUnderlying(r.typWrapped(false))
799 types.ResumeCheckSize()
801 if r.hasTypeParams() && !r.dict.shaped {
802 todoDicts = append(todoDicts, func() {
803 r.dict.shapedObj = pr.objIdx(idx, implicits, explicits, true).(*ir.Name)
807 methods := make([]*types.Field, r.Len())
808 for i := range methods {
809 methods[i] = r.method(rext)
811 if len(methods) != 0 {
812 typ.Methods().Set(methods)
822 name := do(ir.ONAME, false)
823 setType(name, r.typ())
829 func (dict *readerDict) mangle(sym *types.Sym) *types.Sym {
830 if !dict.hasTypeParams() {
834 // If sym is a locally defined generic type, we need the suffix to
835 // stay at the end after mangling so that types/fmt.go can strip it
836 // out again when writing the type's runtime descriptor (#54456).
837 base, suffix := types.SplitVargenSuffix(sym.Name)
839 var buf strings.Builder
840 buf.WriteString(base)
842 for i, targ := range dict.targs {
844 if i == dict.implicits {
850 buf.WriteString(targ.LinkString())
853 buf.WriteString(suffix)
854 return sym.Pkg.Lookup(buf.String())
857 // shapify returns the shape type for targ.
859 // If basic is true, then the type argument is used to instantiate a
860 // type parameter whose constraint is a basic interface.
861 func shapify(targ *types.Type, basic bool) *types.Type {
862 if targ.Kind() == types.TFORW {
863 if targ.IsFullyInstantiated() {
864 // For recursive instantiated type argument, it may still be a TFORW
865 // when shapifying happens. If we don't have targ's underlying type,
866 // shapify won't work. The worst case is we end up not reusing code
867 // optimally in some tricky cases.
868 if base.Debug.Shapify != 0 {
869 base.Warn("skipping shaping of recursive type %v", targ)
875 base.Fatalf("%v is missing its underlying type", targ)
879 // When a pointer type is used to instantiate a type parameter
880 // constrained by a basic interface, we know the pointer's element
881 // type can't matter to the generated code. In this case, we can use
882 // an arbitrary pointer type as the shape type. (To match the
883 // non-unified frontend, we use `*byte`.)
885 // Otherwise, we simply use the type's underlying type as its shape.
887 // TODO(mdempsky): It should be possible to do much more aggressive
888 // shaping still; e.g., collapsing all pointer-shaped types into a
889 // common type, collapsing scalars of the same size/alignment into a
890 // common type, recursively shaping the element types of composite
891 // types, and discarding struct field names and tags. However, we'll
892 // need to start tracking how type parameters are actually used to
893 // implement some of these optimizations.
894 under := targ.Underlying()
895 if basic && targ.IsPtr() && !targ.Elem().NotInHeap() {
896 under = types.NewPtr(types.Types[types.TUINT8])
899 sym := types.ShapePkg.Lookup(under.LinkString())
901 name := ir.NewDeclNameAt(under.Pos(), ir.OTYPE, sym)
902 typ := types.NewNamed(name)
903 typ.SetUnderlying(under)
904 sym.Def = typed(typ, name)
906 res := sym.Def.Type()
907 assert(res.IsShape())
908 assert(res.HasShape())
912 // objDictIdx reads and returns the specified object dictionary.
913 func (pr *pkgReader) objDictIdx(sym *types.Sym, idx pkgbits.Index, implicits, explicits []*types.Type, shaped bool) *readerDict {
914 r := pr.newReader(pkgbits.RelocObjDict, idx, pkgbits.SyncObject1)
920 nimplicits := r.Len()
921 nexplicits := r.Len()
923 if nimplicits > len(implicits) || nexplicits != len(explicits) {
924 base.Fatalf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits))
927 dict.targs = append(implicits[:nimplicits:nimplicits], explicits...)
928 dict.implicits = nimplicits
930 // Within the compiler, we can just skip over the type parameters.
931 for range dict.targs[dict.implicits:] {
932 // Skip past bounds without actually evaluating them.
936 dict.derived = make([]derivedInfo, r.Len())
937 dict.derivedTypes = make([]*types.Type, len(dict.derived))
938 for i := range dict.derived {
939 dict.derived[i] = derivedInfo{r.Reloc(pkgbits.RelocType), r.Bool()}
942 // Runtime dictionary information; private to the compiler.
944 // If any type argument is already shaped, then we're constructing a
945 // shaped object, even if not explicitly requested (i.e., calling
946 // objIdx with shaped==true). This can happen with instantiating
947 // types that are referenced within a function body.
948 for _, targ := range dict.targs {
955 // And if we're constructing a shaped object, then shapify all type
957 for i, targ := range dict.targs {
960 dict.targs[i] = shapify(targ, basic)
964 dict.baseSym = dict.mangle(sym)
966 dict.typeParamMethodExprs = make([]readerMethodExprInfo, r.Len())
967 for i := range dict.typeParamMethodExprs {
968 typeParamIdx := r.Len()
969 _, method := r.selector()
971 dict.typeParamMethodExprs[i] = readerMethodExprInfo{typeParamIdx, method}
974 dict.subdicts = make([]objInfo, r.Len())
975 for i := range dict.subdicts {
976 dict.subdicts[i] = r.objInfo()
979 dict.rtypes = make([]typeInfo, r.Len())
980 for i := range dict.rtypes {
981 dict.rtypes[i] = r.typInfo()
984 dict.itabs = make([]itabInfo, r.Len())
985 for i := range dict.itabs {
986 dict.itabs[i] = itabInfo{typ: r.typInfo(), iface: r.typInfo()}
992 func (r *reader) typeParamNames() {
993 r.Sync(pkgbits.SyncTypeParamNames)
995 for range r.dict.targs[r.dict.implicits:] {
1001 func (r *reader) method(rext *reader) *types.Field {
1002 r.Sync(pkgbits.SyncMethod)
1004 _, sym := r.selector()
1006 _, recv := r.param()
1007 typ := r.signature(recv)
1010 fn := ir.NewFunc(fpos, npos, ir.MethodSym(recv.Type, sym), typ)
1013 if r.hasTypeParams() {
1014 name.Func.SetDupok(true)
1016 typ = shapeSig(name.Func, r.dict)
1021 rext.funcExt(name, sym)
1023 meth := types.NewField(name.Func.Pos(), sym, typ)
1025 meth.SetNointerface(name.Func.Pragma&ir.Nointerface != 0)
1030 func (r *reader) qualifiedIdent() (pkg *types.Pkg, sym *types.Sym) {
1031 r.Sync(pkgbits.SyncSym)
1033 if name := r.String(); name != "" {
1034 sym = pkg.Lookup(name)
1039 func (r *reader) localIdent() (pkg *types.Pkg, sym *types.Sym) {
1040 r.Sync(pkgbits.SyncLocalIdent)
1042 if name := r.String(); name != "" {
1043 sym = pkg.Lookup(name)
1048 func (r *reader) selector() (origPkg *types.Pkg, sym *types.Sym) {
1049 r.Sync(pkgbits.SyncSelector)
1053 if types.IsExported(name) {
1054 pkg = types.LocalPkg
1056 sym = pkg.Lookup(name)
1060 func (r *reader) hasTypeParams() bool {
1061 return r.dict.hasTypeParams()
1064 func (dict *readerDict) hasTypeParams() bool {
1065 return dict != nil && len(dict.targs) != 0
1068 // @@@ Compiler extensions
1070 func (r *reader) funcExt(name *ir.Name, method *types.Sym) {
1071 r.Sync(pkgbits.SyncFuncExt)
1075 // XXX: Workaround because linker doesn't know how to copy Pos.
1076 if !fn.Pos().IsKnown() {
1077 fn.SetPos(name.Pos())
1080 // Normally, we only compile local functions, which saves redundant compilation work.
1081 // n.Defn is not nil for local functions, and is nil for imported function. But for
1082 // generic functions, we might have an instantiation that no other package has seen before.
1083 // So we need to be conservative and compile it again.
1085 // That's why name.Defn is set here, so ir.VisitFuncsBottomUp can analyze function.
1086 // TODO(mdempsky,cuonglm): find a cleaner way to handle this.
1087 if name.Sym().Pkg == types.LocalPkg || r.hasTypeParams() {
1091 fn.Pragma = r.pragmaFlag()
1094 if buildcfg.GOARCH == "wasm" {
1098 if xmod != "" && xname != "" {
1099 fn.WasmImport = &ir.WasmImport{
1107 assert(name.Defn == nil)
1109 fn.ABI = obj.ABI(r.Uint64())
1112 for _, fs := range &types.RecvsParams {
1113 for _, f := range fs(name.Type()).FieldSlice() {
1119 fn.Inl = &ir.Inline{
1120 Cost: int32(r.Len()),
1121 CanDelayResults: r.Bool(),
1125 r.addBody(name.Func, method)
1127 r.Sync(pkgbits.SyncEOF)
1130 func (r *reader) typeExt(name *ir.Name) {
1131 r.Sync(pkgbits.SyncTypeExt)
1135 if r.hasTypeParams() {
1136 // Set "RParams" (really type arguments here, not parameters) so
1137 // this type is treated as "fully instantiated". This ensures the
1138 // type descriptor is written out as DUPOK and method wrappers are
1139 // generated even for imported types.
1140 var targs []*types.Type
1141 targs = append(targs, r.dict.targs...)
1142 typ.SetRParams(targs)
1145 name.SetPragma(r.pragmaFlag())
1147 typecheck.SetBaseTypeIndex(typ, r.Int64(), r.Int64())
1150 func (r *reader) varExt(name *ir.Name) {
1151 r.Sync(pkgbits.SyncVarExt)
1155 func (r *reader) linkname(name *ir.Name) {
1156 assert(name.Op() == ir.ONAME)
1157 r.Sync(pkgbits.SyncLinkname)
1159 if idx := r.Int64(); idx >= 0 {
1160 lsym := name.Linksym()
1161 lsym.SymIdx = int32(idx)
1162 lsym.Set(obj.AttrIndexed, true)
1164 name.Sym().Linkname = r.String()
1168 func (r *reader) pragmaFlag() ir.PragmaFlag {
1169 r.Sync(pkgbits.SyncPragma)
1170 return ir.PragmaFlag(r.Int())
1173 // @@@ Function bodies
1175 // bodyReader tracks where the serialized IR for a local or imported,
1176 // generic function's body can be found.
1177 var bodyReader = map[*ir.Func]pkgReaderIndex{}
1179 // importBodyReader tracks where the serialized IR for an imported,
1180 // static (i.e., non-generic) function body can be read.
1181 var importBodyReader = map[*types.Sym]pkgReaderIndex{}
1183 // bodyReaderFor returns the pkgReaderIndex for reading fn's
1184 // serialized IR, and whether one was found.
1185 func bodyReaderFor(fn *ir.Func) (pri pkgReaderIndex, ok bool) {
1186 if fn.Nname.Defn != nil {
1187 pri, ok = bodyReader[fn]
1188 base.AssertfAt(ok, base.Pos, "must have bodyReader for %v", fn) // must always be available
1190 pri, ok = importBodyReader[fn.Sym()]
1195 // todoDicts holds the list of dictionaries that still need their
1196 // runtime dictionary objects constructed.
1197 var todoDicts []func()
1199 // todoBodies holds the list of function bodies that still need to be
1201 var todoBodies []*ir.Func
1203 // addBody reads a function body reference from the element bitstream,
1204 // and associates it with fn.
1205 func (r *reader) addBody(fn *ir.Func, method *types.Sym) {
1206 // addBody should only be called for local functions or imported
1207 // generic functions; see comment in funcExt.
1208 assert(fn.Nname.Defn != nil)
1210 idx := r.Reloc(pkgbits.RelocBody)
1212 pri := pkgReaderIndex{r.p, idx, r.dict, method, nil}
1213 bodyReader[fn] = pri
1216 todoBodies = append(todoBodies, fn)
1223 func (pri pkgReaderIndex) funcBody(fn *ir.Func) {
1224 r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody)
1228 // funcBody reads a function body definition from the element
1229 // bitstream, and populates fn with it.
1230 func (r *reader) funcBody(fn *ir.Func) {
1232 r.closureVars = fn.ClosureVars
1233 if len(r.closureVars) != 0 && r.hasTypeParams() {
1234 r.dictParam = r.closureVars[len(r.closureVars)-1] // dictParam is last; see reader.funcLit
1237 ir.WithFunc(fn, func() {
1240 if r.syntheticBody(fn.Pos()) {
1250 body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(src.NoXPos, nil))}
1253 fn.Endlineno = r.pos()
1256 r.marker.WriteTo(fn)
1259 // syntheticBody adds a synthetic body to r.curfn if appropriate, and
1260 // reports whether it did.
1261 func (r *reader) syntheticBody(pos src.XPos) bool {
1262 if r.synthetic != nil {
1267 // If this function has type parameters and isn't shaped, then we
1268 // just tail call its corresponding shaped variant.
1269 if r.hasTypeParams() && !r.dict.shaped {
1277 // callShaped emits a tail call to r.shapedFn, passing along the
1278 // arguments to the current function.
1279 func (r *reader) callShaped(pos src.XPos) {
1280 shapedObj := r.dict.shapedObj
1281 assert(shapedObj != nil)
1283 var shapedFn ir.Node
1284 if r.methodSym == nil {
1285 // Instantiating a generic function; shapedObj is the shaped
1287 assert(shapedObj.Op() == ir.ONAME && shapedObj.Class == ir.PFUNC)
1288 shapedFn = shapedObj
1290 // Instantiating a generic type's method; shapedObj is the shaped
1291 // type, so we need to select it's corresponding method.
1292 shapedFn = shapedMethodExpr(pos, shapedObj, r.methodSym)
1295 recvs, params := r.syntheticArgs(pos)
1297 // Construct the arguments list: receiver (if any), then runtime
1298 // dictionary, and finally normal parameters.
1300 // Note: For simplicity, shaped methods are added as normal methods
1301 // on their shaped types. So existing code (e.g., packages ir and
1302 // typecheck) expects the shaped type to appear as the receiver
1303 // parameter (or first parameter, as a method expression). Hence
1304 // putting the dictionary parameter after that is the least invasive
1305 // solution at the moment.
1307 args.Append(recvs...)
1308 args.Append(typecheck.Expr(ir.NewAddrExpr(pos, r.p.dictNameOf(r.dict))))
1309 args.Append(params...)
1311 r.syntheticTailCall(pos, shapedFn, args)
1314 // syntheticArgs returns the recvs and params arguments passed to the
1315 // current function.
1316 func (r *reader) syntheticArgs(pos src.XPos) (recvs, params ir.Nodes) {
1317 sig := r.curfn.Nname.Type()
1320 addParams := func(out *ir.Nodes, params []*types.Field) {
1321 for _, param := range params {
1323 if param.Nname != nil {
1324 name := param.Nname.(*ir.Name)
1325 if !ir.IsBlank(name) {
1326 if r.inlCall != nil {
1327 // During inlining, we want the respective inlvar where we
1328 // assigned the callee's arguments.
1329 arg = r.inlvars[inlVarIdx]
1331 // Otherwise, we can use the parameter itself directly.
1332 base.AssertfAt(name.Curfn == r.curfn, name.Pos(), "%v has curfn %v, but want %v", name, name.Curfn, r.curfn)
1338 // For anonymous and blank parameters, we don't have an *ir.Name
1339 // to use as the argument. However, since we know the shaped
1340 // function won't use the value either, we can just pass the
1341 // zero value. (Also unfortunately, we don't have an easy
1342 // zero-value IR node; so we use a default-initialized temporary
1345 tmp := typecheck.TempAt(pos, r.curfn, param.Type)
1346 r.curfn.Body.Append(
1347 typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)),
1348 typecheck.Stmt(ir.NewAssignStmt(pos, tmp, nil)),
1358 addParams(&recvs, sig.Recvs().FieldSlice())
1359 addParams(¶ms, sig.Params().FieldSlice())
1363 // syntheticTailCall emits a tail call to fn, passing the given
1365 func (r *reader) syntheticTailCall(pos src.XPos, fn ir.Node, args ir.Nodes) {
1366 // Mark the function as a wrapper so it doesn't show up in stack
1368 r.curfn.SetWrapper(true)
1370 call := typecheck.Call(pos, fn, args, fn.Type().IsVariadic()).(*ir.CallExpr)
1373 if fn.Type().NumResults() != 0 {
1374 stmt = typecheck.Stmt(ir.NewReturnStmt(pos, []ir.Node{call}))
1378 r.curfn.Body.Append(stmt)
1381 // dictNameOf returns the runtime dictionary corresponding to dict.
1382 func (pr *pkgReader) dictNameOf(dict *readerDict) *ir.Name {
1383 pos := base.AutogeneratedPos
1385 // Check that we only instantiate runtime dictionaries with real types.
1386 base.AssertfAt(!dict.shaped, pos, "runtime dictionary of shaped object %v", dict.baseSym)
1388 sym := dict.baseSym.Pkg.Lookup(objabi.GlobalDictPrefix + "." + dict.baseSym.Name)
1390 return sym.Def.(*ir.Name)
1393 name := ir.NewNameAt(pos, sym, dict.varType())
1394 name.Class = ir.PEXTERN
1395 sym.Def = name // break cycles with mutual subdictionaries
1397 lsym := name.Linksym()
1400 assertOffset := func(section string, offset int) {
1401 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)
1404 assertOffset("type param method exprs", dict.typeParamMethodExprsOffset())
1405 for _, info := range dict.typeParamMethodExprs {
1406 typeParam := dict.targs[info.typeParamIdx]
1407 method := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, ir.TypeNode(typeParam), info.method)).(*ir.SelectorExpr)
1408 assert(method.Op() == ir.OMETHEXPR)
1410 rsym := method.FuncName().Linksym()
1411 assert(rsym.ABI() == obj.ABIInternal) // must be ABIInternal; see ir.OCFUNC in ssagen/ssa.go
1413 ot = objw.SymPtr(lsym, ot, rsym, 0)
1416 assertOffset("subdictionaries", dict.subdictsOffset())
1417 for _, info := range dict.subdicts {
1418 explicits := pr.typListIdx(info.explicits, dict)
1420 // Careful: Due to subdictionary cycles, name may not be fully
1422 name := pr.objDictName(info.idx, dict.targs, explicits)
1424 ot = objw.SymPtr(lsym, ot, name.Linksym(), 0)
1427 assertOffset("rtypes", dict.rtypesOffset())
1428 for _, info := range dict.rtypes {
1429 typ := pr.typIdx(info, dict, true)
1430 ot = objw.SymPtr(lsym, ot, reflectdata.TypeLinksym(typ), 0)
1432 // TODO(mdempsky): Double check this.
1433 reflectdata.MarkTypeUsedInInterface(typ, lsym)
1436 // For each (typ, iface) pair, we write the *runtime.itab pointer
1437 // for the pair. For pairs that don't actually require an itab
1438 // (i.e., typ is an interface, or iface is an empty interface), we
1439 // write a nil pointer instead. This is wasteful, but rare in
1440 // practice (e.g., instantiating a type parameter with an interface
1442 assertOffset("itabs", dict.itabsOffset())
1443 for _, info := range dict.itabs {
1444 typ := pr.typIdx(info.typ, dict, true)
1445 iface := pr.typIdx(info.iface, dict, true)
1447 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
1448 ot = objw.SymPtr(lsym, ot, reflectdata.ITabLsym(typ, iface), 0)
1453 // TODO(mdempsky): Double check this.
1454 reflectdata.MarkTypeUsedInInterface(typ, lsym)
1455 reflectdata.MarkTypeUsedInInterface(iface, lsym)
1458 objw.Global(lsym, int32(ot), obj.DUPOK|obj.RODATA)
1463 // typeParamMethodExprsOffset returns the offset of the runtime
1464 // dictionary's type parameter method expressions section, in words.
1465 func (dict *readerDict) typeParamMethodExprsOffset() int {
1469 // subdictsOffset returns the offset of the runtime dictionary's
1470 // subdictionary section, in words.
1471 func (dict *readerDict) subdictsOffset() int {
1472 return dict.typeParamMethodExprsOffset() + len(dict.typeParamMethodExprs)
1475 // rtypesOffset returns the offset of the runtime dictionary's rtypes
1476 // section, in words.
1477 func (dict *readerDict) rtypesOffset() int {
1478 return dict.subdictsOffset() + len(dict.subdicts)
1481 // itabsOffset returns the offset of the runtime dictionary's itabs
1482 // section, in words.
1483 func (dict *readerDict) itabsOffset() int {
1484 return dict.rtypesOffset() + len(dict.rtypes)
1487 // numWords returns the total number of words that comprise dict's
1488 // runtime dictionary variable.
1489 func (dict *readerDict) numWords() int64 {
1490 return int64(dict.itabsOffset() + len(dict.itabs))
1493 // varType returns the type of dict's runtime dictionary variable.
1494 func (dict *readerDict) varType() *types.Type {
1495 return types.NewArray(types.Types[types.TUINTPTR], dict.numWords())
1498 func (r *reader) funcargs(fn *ir.Func) {
1499 sig := fn.Nname.Type()
1501 if recv := sig.Recv(); recv != nil {
1502 r.funcarg(recv, recv.Sym, ir.PPARAM)
1504 for _, param := range sig.Params().FieldSlice() {
1505 r.funcarg(param, param.Sym, ir.PPARAM)
1508 for i, param := range sig.Results().FieldSlice() {
1509 sym := types.OrigSym(param.Sym)
1511 if sym == nil || sym.IsBlank() {
1513 if r.inlCall != nil {
1515 } else if sym != nil {
1518 sym = typecheck.LookupNum(prefix, i)
1521 r.funcarg(param, sym, ir.PPARAMOUT)
1525 func (r *reader) funcarg(param *types.Field, sym *types.Sym, ctxt ir.Class) {
1527 assert(ctxt == ir.PPARAM)
1528 if r.inlCall != nil {
1529 r.inlvars.Append(ir.BlankNode)
1534 name := r.addLocal(r.inlPos(param.Pos), sym, ctxt, param.Type)
1536 if r.inlCall == nil {
1542 if ctxt == ir.PPARAMOUT {
1543 r.retvars.Append(name)
1545 r.inlvars.Append(name)
1550 func (r *reader) addLocal(pos src.XPos, sym *types.Sym, ctxt ir.Class, typ *types.Type) *ir.Name {
1551 assert(ctxt == ir.PAUTO || ctxt == ir.PPARAM || ctxt == ir.PPARAMOUT)
1553 name := ir.NewNameAt(pos, sym, typ)
1555 if name.Sym().Name == dictParamName {
1558 if r.synthetic == nil {
1559 r.Sync(pkgbits.SyncAddLocal)
1560 if r.p.SyncMarkers() {
1562 if have := len(r.locals); have != want {
1563 base.FatalfAt(name.Pos(), "locals table has desynced")
1566 r.varDictIndex(name)
1569 r.locals = append(r.locals, name)
1574 // TODO(mdempsky): Move earlier.
1575 if ir.IsBlank(name) {
1579 if r.inlCall != nil {
1580 if ctxt == ir.PAUTO {
1581 name.SetInlLocal(true)
1583 name.SetInlFormal(true)
1589 name.Curfn = r.curfn
1591 r.curfn.Dcl = append(r.curfn.Dcl, name)
1593 if ctxt == ir.PAUTO {
1594 name.SetFrameOffset(0)
1600 func (r *reader) useLocal() *ir.Name {
1601 r.Sync(pkgbits.SyncUseObjLocal)
1603 return r.locals[r.Len()]
1605 return r.closureVars[r.Len()]
1608 func (r *reader) openScope() {
1609 r.Sync(pkgbits.SyncOpenScope)
1612 if base.Flag.Dwarf {
1613 r.scopeVars = append(r.scopeVars, len(r.curfn.Dcl))
1618 func (r *reader) closeScope() {
1619 r.Sync(pkgbits.SyncCloseScope)
1620 r.lastCloseScopePos = r.pos()
1622 r.closeAnotherScope()
1625 // closeAnotherScope is like closeScope, but it reuses the same mark
1626 // position as the last closeScope call. This is useful for "for" and
1627 // "if" statements, as their implicit blocks always end at the same
1628 // position as an explicit block.
1629 func (r *reader) closeAnotherScope() {
1630 r.Sync(pkgbits.SyncCloseAnotherScope)
1632 if base.Flag.Dwarf {
1633 scopeVars := r.scopeVars[len(r.scopeVars)-1]
1634 r.scopeVars = r.scopeVars[:len(r.scopeVars)-1]
1636 // Quirkish: noder decides which scopes to keep before
1637 // typechecking, whereas incremental typechecking during IR
1638 // construction can result in new autotemps being allocated. To
1639 // produce identical output, we ignore autotemps here for the
1640 // purpose of deciding whether to retract the scope.
1642 // This is important for net/http/fcgi, because it contains:
1644 // var body io.ReadCloser
1645 // if len(content) > 0 {
1646 // body, req.pw = io.Pipe()
1649 // Notably, io.Pipe is inlinable, and inlining it introduces a ~R0
1650 // variable at the call site.
1652 // Noder does not preserve the scope where the io.Pipe() call
1653 // resides, because it doesn't contain any declared variables in
1654 // source. So the ~R0 variable ends up being assigned to the
1655 // enclosing scope instead.
1657 // However, typechecking this assignment also introduces
1658 // autotemps, because io.Pipe's results need conversion before
1659 // they can be assigned to their respective destination variables.
1661 // TODO(mdempsky): We should probably just keep all scopes, and
1662 // let dwarfgen take care of pruning them instead.
1664 for _, n := range r.curfn.Dcl[scopeVars:] {
1672 // no variables were declared in this scope, so we can retract it.
1675 r.marker.Pop(r.lastCloseScopePos)
1682 func (r *reader) stmt() ir.Node {
1683 switch stmts := r.stmts(); len(stmts) {
1689 return ir.NewBlockStmt(stmts[0].Pos(), stmts)
1693 func (r *reader) stmts() []ir.Node {
1694 assert(ir.CurFunc == r.curfn)
1697 r.Sync(pkgbits.SyncStmts)
1699 tag := codeStmt(r.Code(pkgbits.SyncStmt1))
1701 r.Sync(pkgbits.SyncStmtsEnd)
1705 if n := r.stmt1(tag, &res); n != nil {
1706 res.Append(typecheck.Stmt(n))
1711 func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node {
1712 var label *types.Sym
1713 if n := len(*out); n > 0 {
1714 if ls, ok := (*out)[n-1].(*ir.LabelStmt); ok {
1721 panic("unexpected statement")
1725 names, lhs := r.assignList()
1726 rhs := r.multiExpr()
1729 for _, name := range names {
1730 as := ir.NewAssignStmt(pos, name, nil)
1731 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name))
1732 out.Append(typecheck.Stmt(as))
1737 if len(lhs) == 1 && len(rhs) == 1 {
1738 n := ir.NewAssignStmt(pos, lhs[0], rhs[0])
1739 n.Def = r.initDefn(n, names)
1743 n := ir.NewAssignListStmt(pos, ir.OAS2, lhs, rhs)
1744 n.Def = r.initDefn(n, names)
1752 return ir.NewAssignOpStmt(pos, op, lhs, rhs)
1758 n := ir.NewAssignOpStmt(pos, op, lhs, ir.NewBasicLit(pos, one))
1763 out.Append(r.blockStmt()...)
1770 return ir.NewBranchStmt(pos, op, sym)
1776 return ir.NewGoDeferStmt(pos, op, call)
1782 return r.forStmt(label)
1790 return ir.NewLabelStmt(pos, sym)
1794 results := r.multiExpr()
1795 return ir.NewReturnStmt(pos, results)
1798 return r.selectStmt(label)
1804 return ir.NewSendStmt(pos, ch, value)
1807 return r.switchStmt(label)
1811 func (r *reader) assignList() ([]*ir.Name, []ir.Node) {
1812 lhs := make([]ir.Node, r.Len())
1813 var names []*ir.Name
1815 for i := range lhs {
1816 expr, def := r.assign()
1819 names = append(names, expr.(*ir.Name))
1826 // assign returns an assignee expression. It also reports whether the
1827 // returned expression is a newly declared variable.
1828 func (r *reader) assign() (ir.Node, bool) {
1829 switch tag := codeAssign(r.Code(pkgbits.SyncAssign)); tag {
1831 panic("unhandled assignee expression")
1834 return typecheck.AssignExpr(ir.BlankNode), false
1839 _, sym := r.localIdent()
1842 name := r.addLocal(pos, sym, ir.PAUTO, typ)
1846 return r.expr(), false
1850 func (r *reader) blockStmt() []ir.Node {
1851 r.Sync(pkgbits.SyncBlockStmt)
1858 func (r *reader) forStmt(label *types.Sym) ir.Node {
1859 r.Sync(pkgbits.SyncForStmt)
1865 rang := ir.NewRangeStmt(pos, nil, nil, nil, nil, false)
1868 names, lhs := r.assignList()
1875 rang.Def = r.initDefn(rang, names)
1878 if rang.X.Type().IsMap() {
1879 rang.RType = r.rtype(pos)
1881 if rang.Key != nil && !ir.IsBlank(rang.Key) {
1882 rang.KeyTypeWord, rang.KeySrcRType = r.convRTTI(pos)
1884 if rang.Value != nil && !ir.IsBlank(rang.Value) {
1885 rang.ValueTypeWord, rang.ValueSrcRType = r.convRTTI(pos)
1888 rang.Body = r.blockStmt()
1889 rang.DistinctVars = r.Bool()
1890 r.closeAnotherScope()
1899 body := r.blockStmt()
1900 perLoopVars := r.Bool()
1901 r.closeAnotherScope()
1903 if ir.IsConst(cond, constant.Bool) && !ir.BoolVal(cond) {
1904 return init // simplify "for init; false; post { ... }" into "init"
1907 stmt := ir.NewForStmt(pos, init, cond, post, body, perLoopVars)
1912 func (r *reader) ifStmt() ir.Node {
1913 r.Sync(pkgbits.SyncIfStmt)
1918 then := r.blockStmt()
1920 r.closeAnotherScope()
1922 if ir.IsConst(cond, constant.Bool) && len(init)+len(then)+len(els) == 0 {
1923 return nil // drop empty if statement
1926 n := ir.NewIfStmt(pos, cond, then, els)
1931 func (r *reader) selectStmt(label *types.Sym) ir.Node {
1932 r.Sync(pkgbits.SyncSelectStmt)
1935 clauses := make([]*ir.CommClause, r.Len())
1936 for i := range clauses {
1946 // "case i = <-c: ..." may require an implicit conversion (e.g.,
1947 // see fixedbugs/bug312.go). Currently, typecheck throws away the
1948 // implicit conversion and relies on it being reinserted later,
1949 // but that would lose any explicit RTTI operands too. To preserve
1950 // RTTI, we rewrite this as "case tmp := <-c: i = tmp; ...".
1951 if as, ok := comm.(*ir.AssignStmt); ok && as.Op() == ir.OAS && !as.Def {
1952 if conv, ok := as.Y.(*ir.ConvExpr); ok && conv.Op() == ir.OCONVIFACE {
1953 base.AssertfAt(conv.Implicit(), conv.Pos(), "expected implicit conversion: %v", conv)
1956 base.AssertfAt(recv.Op() == ir.ORECV, recv.Pos(), "expected receive expression: %v", recv)
1958 tmp := r.temp(pos, recv.Type())
1960 // Replace comm with `tmp := <-c`.
1961 tmpAs := ir.NewAssignStmt(pos, tmp, recv)
1963 tmpAs.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
1966 // Change original assignment to `i = tmp`, and prepend to body.
1968 body = append([]ir.Node{as}, body...)
1972 // multiExpr will have desugared a comma-ok receive expression
1973 // into a separate statement. However, the rest of the compiler
1974 // expects comm to be the OAS2RECV statement itself, so we need to
1975 // shuffle things around to fit that pattern.
1976 if as2, ok := comm.(*ir.AssignListStmt); ok && as2.Op() == ir.OAS2 {
1977 init := ir.TakeInit(as2.Rhs[0])
1978 base.AssertfAt(len(init) == 1 && init[0].Op() == ir.OAS2RECV, as2.Pos(), "unexpected assignment: %+v", as2)
1981 body = append([]ir.Node{as2}, body...)
1984 clauses[i] = ir.NewCommStmt(pos, comm, body)
1986 if len(clauses) > 0 {
1989 n := ir.NewSelectStmt(pos, clauses)
1994 func (r *reader) switchStmt(label *types.Sym) ir.Node {
1995 r.Sync(pkgbits.SyncSwitchStmt)
2003 var iface *types.Type
2008 _, sym := r.localIdent()
2009 ident = ir.NewIdent(pos, sym)
2013 tag = ir.NewTypeSwitchGuard(pos, ident, x)
2018 clauses := make([]*ir.CaseClause, r.Len())
2019 for i := range clauses {
2026 var cases, rtypes []ir.Node
2028 cases = make([]ir.Node, r.Len())
2029 if len(cases) == 0 {
2030 cases = nil // TODO(mdempsky): Unclear if this matters.
2032 for i := range cases {
2033 if r.Bool() { // case nil
2034 cases[i] = typecheck.Expr(types.BuiltinPkg.Lookup("nil").Def.(*ir.NilExpr))
2036 cases[i] = r.exprType()
2040 cases = r.exprList()
2042 // For `switch { case any(true): }` (e.g., issue 3980 in
2043 // test/switch.go), the backend still creates a mixed bool/any
2044 // comparison, and we need to explicitly supply the RTTI for the
2047 // TODO(mdempsky): Change writer.go to desugar "switch {" into
2048 // "switch true {", which we already handle correctly.
2050 for i, cas := range cases {
2051 if cas.Type().IsEmptyInterface() {
2052 for len(rtypes) < i {
2053 rtypes = append(rtypes, nil)
2055 rtypes = append(rtypes, reflectdata.TypePtrAt(cas.Pos(), types.Types[types.TBOOL]))
2061 clause := ir.NewCaseStmt(pos, cases, nil)
2062 clause.RTypes = rtypes
2068 name := r.addLocal(pos, ident.Sym(), ir.PAUTO, typ)
2073 clause.Body = r.stmts()
2076 if len(clauses) > 0 {
2081 n := ir.NewSwitchStmt(pos, tag, clauses)
2084 n.SetInit([]ir.Node{init})
2089 func (r *reader) label() *types.Sym {
2090 r.Sync(pkgbits.SyncLabel)
2092 if r.inlCall != nil {
2093 name = fmt.Sprintf("~%s·%d", name, inlgen)
2095 return typecheck.Lookup(name)
2098 func (r *reader) optLabel() *types.Sym {
2099 r.Sync(pkgbits.SyncOptLabel)
2106 // initDefn marks the given names as declared by defn and populates
2107 // its Init field with ODCL nodes. It then reports whether any names
2108 // were so declared, which can be used to initialize defn.Def.
2109 func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool {
2110 if len(names) == 0 {
2114 init := make([]ir.Node, len(names))
2115 for i, name := range names {
2117 init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name)
2125 // expr reads and returns a typechecked expression.
2126 func (r *reader) expr() (res ir.Node) {
2128 if res != nil && res.Typecheck() == 0 {
2129 base.FatalfAt(res.Pos(), "%v missed typecheck", res)
2133 switch tag := codeExpr(r.Code(pkgbits.SyncExpr)); tag {
2135 panic("unhandled expression")
2138 return typecheck.Expr(r.useLocal())
2141 // Callee instead of Expr allows builtins
2142 // TODO(mdempsky): Handle builtins directly in exprCall, like method calls?
2143 return typecheck.Callee(r.obj())
2146 origPos, pos := r.origPos()
2147 wrapperFn, baseFn, dictPtr := r.funcInst(pos)
2148 if wrapperFn != nil {
2151 return r.curry(origPos, false, baseFn, dictPtr, nil)
2156 val := FixValue(typ, r.Value())
2159 return typecheck.Expr(OrigConst(pos, typ, val, op, orig))
2164 return Nil(pos, typ)
2175 _, sym := r.selector()
2177 return typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, x, sym)).(*ir.SelectorExpr)
2181 origPos, pos := r.origPos()
2182 wrapperFn, baseFn, dictPtr := r.methodExpr()
2184 // For simple wrapperFn values, the existing machinery for creating
2185 // and deduplicating wrapperFn value wrappers still works fine.
2186 if wrapperFn, ok := wrapperFn.(*ir.SelectorExpr); ok && wrapperFn.Op() == ir.OMETHEXPR {
2187 // The receiver expression we constructed may have a shape type.
2188 // For example, in fixedbugs/issue54343.go, `New[int]()` is
2189 // constructed as `New[go.shape.int](&.dict.New[int])`, which
2190 // has type `*T[go.shape.int]`, not `*T[int]`.
2192 // However, the method we want to select here is `(*T[int]).M`,
2193 // not `(*T[go.shape.int]).M`, so we need to manually convert
2194 // the type back so that the OXDOT resolves correctly.
2196 // TODO(mdempsky): Logically it might make more sense for
2197 // exprCall to take responsibility for setting a non-shaped
2198 // result type, but this is the only place where we care
2199 // currently. And only because existing ir.OMETHVALUE backend
2200 // code relies on n.X.Type() instead of n.Selection.Recv().Type
2201 // (because the latter is types.FakeRecvType() in the case of
2202 // interface method values).
2204 if recv.Type().HasShape() {
2205 typ := wrapperFn.Type().Params().Field(0).Type
2206 if !types.Identical(typ, recv.Type()) {
2207 base.FatalfAt(wrapperFn.Pos(), "receiver %L does not match %L", recv, wrapperFn)
2209 recv = typecheck.Expr(ir.NewConvExpr(recv.Pos(), ir.OCONVNOP, typ, recv))
2212 n := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, recv, wrapperFn.Sel)).(*ir.SelectorExpr)
2214 // As a consistency check here, we make sure "n" selected the
2215 // same method (represented by a types.Field) that wrapperFn
2216 // selected. However, for anonymous receiver types, there can be
2217 // multiple such types.Field instances (#58563). So we may need
2218 // to fallback to making sure Sym and Type (including the
2219 // receiver parameter's type) match.
2220 if n.Selection != wrapperFn.Selection {
2221 assert(n.Selection.Sym == wrapperFn.Selection.Sym)
2222 assert(types.Identical(n.Selection.Type, wrapperFn.Selection.Type))
2223 assert(types.Identical(n.Selection.Type.Recv().Type, wrapperFn.Selection.Type.Recv().Type))
2226 wrapper := methodValueWrapper{
2228 method: n.Selection,
2231 if r.importedDef() {
2232 haveMethodValueWrappers = append(haveMethodValueWrappers, wrapper)
2234 needMethodValueWrappers = append(needMethodValueWrappers, wrapper)
2239 // For more complicated method expressions, we construct a
2240 // function literal wrapper.
2241 return r.curry(origPos, true, baseFn, recv, dictPtr)
2243 case exprMethodExpr:
2246 implicits := make([]int, r.Len())
2247 for i := range implicits {
2248 implicits[i] = r.Len()
2250 var deref, addr bool
2253 } else if r.Bool() {
2257 origPos, pos := r.origPos()
2258 wrapperFn, baseFn, dictPtr := r.methodExpr()
2260 // If we already have a wrapper and don't need to do anything with
2261 // it, we can just return the wrapper directly.
2263 // N.B., we use implicits/deref/addr here as the source of truth
2264 // rather than types.Identical, because the latter can be confused
2265 // by tricky promoted methods (e.g., typeparam/mdempsky/21.go).
2266 if wrapperFn != nil && len(implicits) == 0 && !deref && !addr {
2267 if !types.Identical(recv, wrapperFn.Type().Params().Field(0).Type) {
2268 base.FatalfAt(pos, "want receiver type %v, but have method %L", recv, wrapperFn)
2273 // Otherwise, if the wrapper function is a static method
2274 // expression (OMETHEXPR) and the receiver type is unshaped, then
2275 // we can rely on a statically generated wrapper being available.
2276 if method, ok := wrapperFn.(*ir.SelectorExpr); ok && method.Op() == ir.OMETHEXPR && !recv.HasShape() {
2277 return typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, ir.TypeNode(recv), method.Sel)).(*ir.SelectorExpr)
2280 return r.methodExprWrap(origPos, recv, implicits, deref, addr, baseFn, dictPtr)
2286 n := typecheck.Expr(ir.NewIndexExpr(pos, x, index))
2289 n := n.(*ir.IndexExpr)
2290 n.RType = r.rtype(pos)
2297 var index [3]ir.Node
2298 for i := range index {
2299 index[i] = r.optExpr()
2302 if index[2] != nil {
2305 return typecheck.Expr(ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2]))
2311 srcRType := r.rtype(pos)
2313 // TODO(mdempsky): Always emit ODYNAMICDOTTYPE for uniformity?
2314 if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE {
2315 assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType)
2316 assert.SrcRType = srcRType
2317 assert.ITab = typ.ITab
2318 return typed(typ.Type(), assert)
2320 return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ.Type()))
2329 return typecheck.Expr(typecheck.NodAddrAt(pos, x))
2331 return typecheck.Expr(ir.NewStarExpr(pos, x))
2333 return typecheck.Expr(ir.NewUnaryExpr(pos, op, x))
2342 case ir.OANDAND, ir.OOROR:
2343 return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y))
2345 return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
2350 for i, n := 0, r.Len(); i < n; i++ {
2351 x = Implicit(DotField(pos, x, r.Len()))
2353 if r.Bool() { // needs deref
2354 x = Implicit(Deref(pos, x.Type().Elem(), x))
2355 } else if r.Bool() { // needs addr
2356 x = Implicit(Addr(pos, x))
2363 if r.Bool() { // method call
2365 _, method, dictPtr := r.methodExpr()
2367 if recv.Type().IsInterface() && method.Op() == ir.OMETHEXPR {
2368 method := method.(*ir.SelectorExpr)
2370 // The compiler backend (e.g., devirtualization) handle
2371 // OCALLINTER/ODOTINTER better than OCALLFUNC/OMETHEXPR for
2372 // interface calls, so we prefer to continue constructing
2373 // calls that way where possible.
2375 // There are also corner cases where semantically it's perhaps
2376 // significant; e.g., fixedbugs/issue15975.go, #38634, #52025.
2378 fun = typecheck.Callee(ir.NewSelectorExpr(method.Pos(), ir.OXDOT, recv, method.Sel))
2380 if recv.Type().IsInterface() {
2381 // N.B., this happens currently for typeparam/issue51521.go
2382 // and typeparam/typeswitch3.go.
2383 if base.Flag.LowerM != 0 {
2384 base.WarnfAt(method.Pos(), "imprecise interface call")
2392 args.Append(dictPtr)
2394 } else if r.Bool() { // call to instanced function
2396 _, shapedFn, dictPtr := r.funcInst(pos)
2398 args.Append(dictPtr)
2403 args.Append(r.multiExpr()...)
2405 n := typecheck.Call(pos, fun, args, dots)
2408 n := n.(*ir.CallExpr)
2409 n.RType = r.rtype(pos)
2410 // For append(a, b...), we don't need the implicit conversion. The typechecker already
2411 // ensured that a and b are both slices with the same base type, or []byte and string.
2413 if conv, ok := n.Args[1].(*ir.ConvExpr); ok && conv.Op() == ir.OCONVNOP && conv.Implicit() {
2418 n := n.(*ir.BinaryExpr)
2419 n.RType = r.rtype(pos)
2421 n := n.(*ir.CallExpr)
2422 n.RType = r.rtype(pos)
2423 case ir.OUNSAFESLICE:
2424 n := n.(*ir.BinaryExpr)
2425 n.RType = r.rtype(pos)
2433 n := typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr)
2434 n.RType = r.rtype(pos)
2440 return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, typ))
2446 if types.IdenticalStrict(x.Type(), typ) {
2450 // Comparison expressions are constructed as "untyped bool" still.
2452 // TODO(mdempsky): It should be safe to reshape them here too, but
2453 // maybe it's better to construct them with the proper type
2455 if x.Type() == types.UntypedBool && typ.IsBoolean() {
2459 base.AssertfAt(x.Type().HasShape() || typ.HasShape(), x.Pos(), "%L and %v are not shape types", x, typ)
2460 base.AssertfAt(types.Identical(x.Type(), typ), x.Pos(), "%L is not shape-identical to %v", x, typ)
2462 // We use ir.HasUniquePos here as a check that x only appears once
2463 // in the AST, so it's okay for us to call SetType without
2464 // breaking any other uses of it.
2466 // Notably, any ONAMEs should already have the exactly right shape
2467 // type and been caught by types.IdenticalStrict above.
2468 base.AssertfAt(ir.HasUniquePos(x), x.Pos(), "cannot call SetType(%v) on %L", typ, x)
2470 if base.Debug.Reshape != 0 {
2471 base.WarnfAt(x.Pos(), "reshaping %L to %v", x, typ)
2478 implicit := r.Bool()
2481 typeWord, srcRType := r.convRTTI(pos)
2482 dstTypeParam := r.Bool()
2483 identical := r.Bool()
2486 // TODO(mdempsky): Stop constructing expressions of untyped type.
2487 x = typecheck.DefaultLit(x, typ)
2489 ce := ir.NewConvExpr(pos, ir.OCONV, typ, x)
2490 ce.TypeWord, ce.SrcRType = typeWord, srcRType
2492 ce.SetImplicit(true)
2494 n := typecheck.Expr(ce)
2496 // Conversions between non-identical, non-empty interfaces always
2497 // requires a runtime call, even if they have identical underlying
2498 // interfaces. This is because we create separate itab instances
2499 // for each unique interface type, not merely each unique
2502 // However, due to shape types, typecheck.Expr might mistakenly
2503 // think a conversion between two non-empty interfaces are
2504 // identical and set ir.OCONVNOP, instead of ir.OCONVIFACE. To
2505 // ensure we update the itab field appropriately, we force it to
2506 // ir.OCONVIFACE instead when shape types are involved.
2508 // TODO(mdempsky): Are there other places we might get this wrong?
2509 // Should this be moved down into typecheck.{Assign,Convert}op?
2510 // This would be a non-issue if itabs were unique for each
2511 // *underlying* interface type instead.
2513 if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) {
2514 n.SetOp(ir.OCONVIFACE)
2518 // spec: "If the type is a type parameter, the constant is converted
2519 // into a non-constant value of the type parameter."
2520 if dstTypeParam && ir.IsConstNode(n) {
2521 // Wrap in an OCONVNOP node to ensure result is non-constant.
2522 n = Implicit(ir.NewConvExpr(pos, ir.OCONVNOP, n.Type(), n))
2529 // funcInst reads an instantiated function reference, and returns
2530 // three (possibly nil) expressions related to it:
2532 // baseFn is always non-nil: it's either a function of the appropriate
2533 // type already, or it has an extra dictionary parameter as the first
2536 // If dictPtr is non-nil, then it's a dictionary argument that must be
2537 // passed as the first argument to baseFn.
2539 // If wrapperFn is non-nil, then it's either the same as baseFn (if
2540 // dictPtr is nil), or it's semantically equivalent to currying baseFn
2541 // to pass dictPtr. (wrapperFn is nil when dictPtr is an expression
2542 // that needs to be computed dynamically.)
2544 // For callers that are creating a call to the returned function, it's
2545 // best to emit a call to baseFn, and include dictPtr in the arguments
2546 // list as appropriate.
2548 // For callers that want to return the function without invoking it,
2549 // they may return wrapperFn if it's non-nil; but otherwise, they need
2550 // to create their own wrapper.
2551 func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) {
2552 // Like in methodExpr, I'm pretty sure this isn't needed.
2553 var implicits []*types.Type
2555 implicits = r.dict.targs
2558 if r.Bool() { // dynamic subdictionary
2560 info := r.dict.subdicts[idx]
2561 explicits := r.p.typListIdx(info.explicits, r.dict)
2563 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2565 // TODO(mdempsky): Is there a more robust way to get the
2566 // dictionary pointer type here?
2567 dictPtrType := baseFn.Type().Params().Field(0).Type
2568 dictPtr = typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2574 explicits := r.p.typListIdx(info.explicits, r.dict)
2576 wrapperFn = r.p.objIdx(info.idx, implicits, explicits, false).(*ir.Name)
2577 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2579 dictName := r.p.objDictName(info.idx, implicits, explicits)
2580 dictPtr = typecheck.Expr(ir.NewAddrExpr(pos, dictName))
2585 func (pr *pkgReader) objDictName(idx pkgbits.Index, implicits, explicits []*types.Type) *ir.Name {
2586 rname := pr.newReader(pkgbits.RelocName, idx, pkgbits.SyncObject1)
2587 _, sym := rname.qualifiedIdent()
2588 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
2590 if tag == pkgbits.ObjStub {
2591 assert(!sym.IsBlank())
2592 if pri, ok := objReader[sym]; ok {
2593 return pri.pr.objDictName(pri.idx, nil, explicits)
2595 base.Fatalf("unresolved stub: %v", sym)
2598 dict := pr.objDictIdx(sym, idx, implicits, explicits, false)
2600 return pr.dictNameOf(dict)
2603 // curry returns a function literal that calls fun with arg0 and
2604 // (optionally) arg1, accepting additional arguments to the function
2605 // literal as necessary to satisfy fun's signature.
2607 // If nilCheck is true and arg0 is an interface value, then it's
2608 // checked to be non-nil as an initial step at the point of evaluating
2609 // the function literal itself.
2610 func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node {
2611 var captured ir.Nodes
2612 captured.Append(fun, arg0)
2614 captured.Append(arg1)
2617 params, results := syntheticSig(fun.Type())
2618 params = params[len(captured)-1:] // skip curried parameters
2619 typ := types.NewSignature(nil, params, results)
2621 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2622 recvs, params := r.syntheticArgs(pos)
2623 assert(len(recvs) == 0)
2628 args.Append(captured[1:]...)
2629 args.Append(params...)
2631 r.syntheticTailCall(pos, fun, args)
2634 return r.syntheticClosure(origPos, typ, ifaceHack, captured, addBody)
2637 // methodExprWrap returns a function literal that changes method's
2638 // first parameter's type to recv, and uses implicits/deref/addr to
2639 // select the appropriate receiver parameter to pass to method.
2640 func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node {
2641 var captured ir.Nodes
2642 captured.Append(method)
2644 params, results := syntheticSig(method.Type())
2646 // Change first parameter to recv.
2647 params[0].Type = recv
2649 // If we have a dictionary pointer argument to pass, then omit the
2650 // underlying method expression's dictionary parameter from the
2651 // returned signature too.
2653 captured.Append(dictPtr)
2654 params = append(params[:1], params[2:]...)
2657 typ := types.NewSignature(nil, params, results)
2659 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2660 recvs, args := r.syntheticArgs(pos)
2661 assert(len(recvs) == 0)
2665 // Rewrite first argument based on implicits/deref/addr.
2668 for _, ix := range implicits {
2669 arg = Implicit(DotField(pos, arg, ix))
2672 arg = Implicit(Deref(pos, arg.Type().Elem(), arg))
2674 arg = Implicit(Addr(pos, arg))
2679 // Insert dictionary argument, if provided.
2681 newArgs := make([]ir.Node, len(args)+1)
2682 newArgs[0] = args[0]
2683 newArgs[1] = captured[1]
2684 copy(newArgs[2:], args[1:])
2688 r.syntheticTailCall(pos, fn, args)
2691 return r.syntheticClosure(origPos, typ, false, captured, addBody)
2694 // syntheticClosure constructs a synthetic function literal for
2695 // currying dictionary arguments. origPos is the position used for the
2696 // closure, which must be a non-inlined position. typ is the function
2697 // literal's signature type.
2699 // captures is a list of expressions that need to be evaluated at the
2700 // point of function literal evaluation and captured by the function
2701 // literal. If ifaceHack is true and captures[1] is an interface type,
2702 // it's checked to be non-nil after evaluation.
2704 // addBody is a callback function to populate the function body. The
2705 // list of captured values passed back has the captured variables for
2706 // use within the function literal, corresponding to the expressions
2708 func (r *reader) syntheticClosure(origPos src.XPos, typ *types.Type, ifaceHack bool, captures ir.Nodes, addBody func(pos src.XPos, r *reader, captured []ir.Node)) ir.Node {
2709 // isSafe reports whether n is an expression that we can safely
2710 // defer to evaluating inside the closure instead, to avoid storing
2711 // them into the closure.
2713 // In practice this is always (and only) the wrappee function.
2714 isSafe := func(n ir.Node) bool {
2715 if n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PFUNC {
2718 if n.Op() == ir.OMETHEXPR {
2725 fn := r.inlClosureFunc(origPos, typ)
2732 for i, n := range captures {
2734 continue // skip capture; can reference directly
2737 tmp := r.tempCopy(inlPos, n, &init)
2738 ir.NewClosureVar(origPos, fn, tmp)
2740 // We need to nil check interface receivers at the point of method
2741 // value evaluation, ugh.
2742 if ifaceHack && i == 1 && n.Type().IsInterface() {
2743 check := ir.NewUnaryExpr(inlPos, ir.OCHECKNIL, ir.NewUnaryExpr(inlPos, ir.OITAB, tmp))
2744 init.Append(typecheck.Stmt(check))
2748 pri := pkgReaderIndex{synthetic: func(pos src.XPos, r *reader) {
2749 captured := make([]ir.Node, len(captures))
2751 for i, n := range captures {
2755 captured[i] = r.closureVars[next]
2759 assert(next == len(r.closureVars))
2761 addBody(origPos, r, captured)
2763 bodyReader[fn] = pri
2766 return ir.InitExpr(init, clo)
2769 // syntheticSig duplicates and returns the params and results lists
2770 // for sig, but renaming anonymous parameters so they can be assigned
2772 func syntheticSig(sig *types.Type) (params, results []*types.Field) {
2773 clone := func(params []*types.Field) []*types.Field {
2774 res := make([]*types.Field, len(params))
2775 for i, param := range params {
2777 if sym == nil || sym.Name == "_" {
2778 sym = typecheck.LookupNum(".anon", i)
2780 // TODO(mdempsky): It would be nice to preserve the original
2781 // parameter positions here instead, but at least
2782 // typecheck.NewMethodType replaces them with base.Pos, making
2783 // them useless. Worse, the positions copied from base.Pos may
2784 // have inlining contexts, which we definitely don't want here
2786 res[i] = types.NewField(base.AutogeneratedPos, sym, param.Type)
2787 res[i].SetIsDDD(param.IsDDD())
2792 return clone(sig.Params().FieldSlice()), clone(sig.Results().FieldSlice())
2795 func (r *reader) optExpr() ir.Node {
2802 // methodExpr reads a method expression reference, and returns three
2803 // (possibly nil) expressions related to it:
2805 // baseFn is always non-nil: it's either a function of the appropriate
2806 // type already, or it has an extra dictionary parameter as the second
2807 // parameter (i.e., immediately after the promoted receiver
2810 // If dictPtr is non-nil, then it's a dictionary argument that must be
2811 // passed as the second argument to baseFn.
2813 // If wrapperFn is non-nil, then it's either the same as baseFn (if
2814 // dictPtr is nil), or it's semantically equivalent to currying baseFn
2815 // to pass dictPtr. (wrapperFn is nil when dictPtr is an expression
2816 // that needs to be computed dynamically.)
2818 // For callers that are creating a call to the returned method, it's
2819 // best to emit a call to baseFn, and include dictPtr in the arguments
2820 // list as appropriate.
2822 // For callers that want to return a method expression without
2823 // invoking it, they may return wrapperFn if it's non-nil; but
2824 // otherwise, they need to create their own wrapper.
2825 func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) {
2829 _, sym := r.selector()
2831 // Signature type to return (i.e., recv prepended to the method's
2832 // normal parameters list).
2833 sig := typecheck.NewMethodType(sig0, recv)
2835 if r.Bool() { // type parameter method expression
2837 word := r.dictWord(pos, r.dict.typeParamMethodExprsOffset()+idx)
2839 // TODO(mdempsky): If the type parameter was instantiated with an
2840 // interface type (i.e., embed.IsInterface()), then we could
2841 // return the OMETHEXPR instead and save an indirection.
2843 // We wrote the method expression's entry point PC into the
2844 // dictionary, but for Go `func` values we need to return a
2845 // closure (i.e., pointer to a structure with the PC as the first
2846 // field). Because method expressions don't have any closure
2847 // variables, we pun the dictionary entry as the closure struct.
2848 fn := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, sig, ir.NewAddrExpr(pos, word)))
2852 // TODO(mdempsky): I'm pretty sure this isn't needed: implicits is
2853 // only relevant to locally defined types, but they can't have
2854 // (non-promoted) methods.
2855 var implicits []*types.Type
2857 implicits = r.dict.targs
2860 if r.Bool() { // dynamic subdictionary
2862 info := r.dict.subdicts[idx]
2863 explicits := r.p.typListIdx(info.explicits, r.dict)
2865 shapedObj := r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2866 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
2868 // TODO(mdempsky): Is there a more robust way to get the
2869 // dictionary pointer type here?
2870 dictPtrType := shapedFn.Type().Params().Field(1).Type
2871 dictPtr := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2873 return nil, shapedFn, dictPtr
2876 if r.Bool() { // static dictionary
2878 explicits := r.p.typListIdx(info.explicits, r.dict)
2880 shapedObj := r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2881 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
2883 dict := r.p.objDictName(info.idx, implicits, explicits)
2884 dictPtr := typecheck.Expr(ir.NewAddrExpr(pos, dict))
2886 // Check that dictPtr matches shapedFn's dictionary parameter.
2887 if !types.Identical(dictPtr.Type(), shapedFn.Type().Params().Field(1).Type) {
2888 base.FatalfAt(pos, "dict %L, but shaped method %L", dict, shapedFn)
2891 // For statically known instantiations, we can take advantage of
2892 // the stenciled wrapper.
2893 base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv)
2894 wrapperFn := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, ir.TypeNode(recv), sym)).(*ir.SelectorExpr)
2895 base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig)
2897 return wrapperFn, shapedFn, dictPtr
2900 // Simple method expression; no dictionary needed.
2901 base.AssertfAt(!recv.HasShape() || recv.IsInterface(), pos, "shaped receiver %v", recv)
2902 fn := typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, ir.TypeNode(recv), sym)).(*ir.SelectorExpr)
2906 // shapedMethodExpr returns the specified method on the given shaped
2908 func shapedMethodExpr(pos src.XPos, obj *ir.Name, sym *types.Sym) *ir.SelectorExpr {
2909 assert(obj.Op() == ir.OTYPE)
2912 assert(typ.HasShape())
2914 method := func() *types.Field {
2915 for _, method := range typ.Methods().Slice() {
2916 if method.Sym == sym {
2921 base.FatalfAt(pos, "failed to find method %v in shaped type %v", sym, typ)
2922 panic("unreachable")
2925 // Construct an OMETHEXPR node.
2926 recv := method.Type.Recv().Type
2927 return typecheck.Expr(ir.NewSelectorExpr(pos, ir.OXDOT, ir.TypeNode(recv), sym)).(*ir.SelectorExpr)
2930 func (r *reader) multiExpr() []ir.Node {
2931 r.Sync(pkgbits.SyncMultiExpr)
2933 if r.Bool() { // N:1
2937 results := make([]ir.Node, r.Len())
2938 as := ir.NewAssignListStmt(pos, ir.OAS2, nil, []ir.Node{expr})
2940 for i := range results {
2941 tmp := r.temp(pos, r.typ())
2942 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
2947 n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)
2948 n.TypeWord, n.SrcRType = r.convRTTI(pos)
2950 res = typecheck.Expr(n)
2955 // TODO(mdempsky): Could use ir.InlinedCallExpr instead?
2956 results[0] = ir.InitExpr([]ir.Node{typecheck.Stmt(as)}, results[0])
2961 exprs := make([]ir.Node, r.Len())
2962 if len(exprs) == 0 {
2965 for i := range exprs {
2971 // temp returns a new autotemp of the specified type.
2972 func (r *reader) temp(pos src.XPos, typ *types.Type) *ir.Name {
2973 // See typecheck.typecheckargs.
2976 curfn = typecheck.InitTodoFunc
2979 return typecheck.TempAt(pos, curfn, typ)
2982 // tempCopy declares and returns a new autotemp initialized to the
2984 func (r *reader) tempCopy(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name {
2986 // Escape analysis doesn't know how to handle package-scope
2987 // function literals with free variables (i.e., that capture
2988 // temporary variables added to typecheck.InitTodoFunc).
2990 // stencil.go works around this limitation by spilling values to
2991 // global variables instead, but that causes the value to stay
2992 // alive indefinitely; see go.dev/issue/54343.
2994 // This code path (which implements the same workaround) isn't
2995 // actually needed by unified IR, because it creates uses normal
2996 // OMETHEXPR/OMETHVALUE nodes when statically-known instantiated
2997 // types are used. But it's kept around for now because it's handy
2998 // for testing that the generic fallback paths work correctly.
2999 base.Fatalf("tempCopy called at package scope")
3001 tmp := staticinit.StaticName(expr.Type())
3003 assign := ir.NewAssignStmt(pos, tmp, expr)
3007 // TODO(mdempsky): This code doesn't work anymore, because we now
3008 // rely on types2 to compute InitOrder. If it's going to be used
3009 // for testing again, the assignment here probably needs to be
3010 // added to typecheck.Target.InitOrder somewhere.
3012 // Probably just easier to address the escape analysis limitation.
3014 // typecheck.Target.Decls = append(typecheck.Target.Decls, typecheck.Stmt(assign))
3019 tmp := r.temp(pos, expr.Type())
3021 init.Append(typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)))
3023 assign := ir.NewAssignStmt(pos, tmp, expr)
3025 init.Append(typecheck.Stmt(ir.NewAssignStmt(pos, tmp, expr)))
3032 func (r *reader) compLit() ir.Node {
3033 r.Sync(pkgbits.SyncCompLit)
3041 if typ.Kind() == types.TFORW {
3042 base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
3046 rtype = r.rtype(pos)
3048 isStruct := typ.Kind() == types.TSTRUCT
3050 elems := make([]ir.Node, r.Len())
3051 for i := range elems {
3055 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.Len()), nil)
3056 *elemp, elemp = sk, &sk.Value
3057 } else if r.Bool() {
3058 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3059 *elemp, elemp = kv, &kv.Value
3062 *elemp = wrapName(r.pos(), r.expr())
3065 lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems))
3067 lit := lit.(*ir.CompLitExpr)
3071 lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit))
3077 func wrapName(pos src.XPos, x ir.Node) ir.Node {
3078 // These nodes do not carry line numbers.
3079 // Introduce a wrapper node to give them the correct line.
3080 switch ir.Orig(x).Op() {
3081 case ir.OTYPE, ir.OLITERAL:
3086 case ir.ONAME, ir.ONONAME, ir.ONIL:
3087 p := ir.NewParenExpr(pos, x)
3094 func (r *reader) funcLit() ir.Node {
3095 r.Sync(pkgbits.SyncFuncLit)
3097 // The underlying function declaration (including its parameters'
3098 // positions, if any) need to remain the original, uninlined
3099 // positions. This is because we track inlining-context on nodes so
3100 // we can synthesize the extra implied stack frames dynamically when
3101 // generating tracebacks, whereas those stack frames don't make
3102 // sense *within* the function literal. (Any necessary inlining
3103 // adjustments will have been applied to the call expression
3106 // This is subtle, and getting it wrong leads to cycles in the
3107 // inlining tree, which lead to infinite loops during stack
3108 // unwinding (#46234, #54625).
3110 // Note that we *do* want the inline-adjusted position for the
3111 // OCLOSURE node, because that position represents where any heap
3112 // allocation of the closure is credited (#49171).
3115 sig := r.signature(nil)
3118 fn := r.inlClosureFunc(origPos, sig)
3120 fn.ClosureVars = make([]*ir.Name, 0, r.Len())
3121 for len(fn.ClosureVars) < cap(fn.ClosureVars) {
3122 // TODO(mdempsky): I think these should be original positions too
3123 // (i.e., not inline-adjusted).
3124 ir.NewClosureVar(r.pos(), fn, r.useLocal())
3126 if param := r.dictParam; param != nil {
3127 // If we have a dictionary parameter, capture it too. For
3128 // simplicity, we capture it last and unconditionally.
3129 ir.NewClosureVar(param.Pos(), fn, param)
3137 // inlClosureFunc constructs a new closure function, but correctly
3138 // handles inlining.
3139 func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type) *ir.Func {
3140 curfn := r.inlCaller
3145 // TODO(mdempsky): Remove hard-coding of typecheck.Target.
3146 return ir.NewClosureFunc(origPos, r.inlPos(origPos), ir.OCLOSURE, sig, curfn, typecheck.Target)
3149 func (r *reader) exprList() []ir.Node {
3150 r.Sync(pkgbits.SyncExprList)
3154 func (r *reader) exprs() []ir.Node {
3155 r.Sync(pkgbits.SyncExprs)
3156 nodes := make([]ir.Node, r.Len())
3157 if len(nodes) == 0 {
3158 return nil // TODO(mdempsky): Unclear if this matters.
3160 for i := range nodes {
3166 // dictWord returns an expression to return the specified
3167 // uintptr-typed word from the dictionary parameter.
3168 func (r *reader) dictWord(pos src.XPos, idx int) ir.Node {
3169 base.AssertfAt(r.dictParam != nil, pos, "expected dictParam in %v", r.curfn)
3170 return typecheck.Expr(ir.NewIndexExpr(pos, r.dictParam, ir.NewBasicLit(pos, constant.MakeInt64(int64(idx)))))
3173 // rttiWord is like dictWord, but converts it to *byte (the type used
3174 // internally to represent *runtime._type and *runtime.itab).
3175 func (r *reader) rttiWord(pos src.XPos, idx int) ir.Node {
3176 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TUINT8]), r.dictWord(pos, idx)))
3179 // rtype reads a type reference from the element bitstream, and
3180 // returns an expression of type *runtime._type representing that
3182 func (r *reader) rtype(pos src.XPos) ir.Node {
3183 _, rtype := r.rtype0(pos)
3187 func (r *reader) rtype0(pos src.XPos) (typ *types.Type, rtype ir.Node) {
3188 r.Sync(pkgbits.SyncRType)
3189 if r.Bool() { // derived type
3191 info := r.dict.rtypes[idx]
3192 typ = r.p.typIdx(info, r.dict, true)
3193 rtype = r.rttiWord(pos, r.dict.rtypesOffset()+idx)
3198 rtype = reflectdata.TypePtrAt(pos, typ)
3202 // varDictIndex populates name.DictIndex if name is a derived type.
3203 func (r *reader) varDictIndex(name *ir.Name) {
3205 idx := 1 + r.dict.rtypesOffset() + r.Len()
3206 if int(uint16(idx)) != idx {
3207 base.FatalfAt(name.Pos(), "DictIndex overflow for %v: %v", name, idx)
3209 name.DictIndex = uint16(idx)
3213 // itab returns a (typ, iface) pair of types.
3215 // typRType and ifaceRType are expressions that evaluate to the
3216 // *runtime._type for typ and iface, respectively.
3218 // If typ is a concrete type and iface is a non-empty interface type,
3219 // then itab is an expression that evaluates to the *runtime.itab for
3220 // the pair. Otherwise, itab is nil.
3221 func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) {
3222 typ, typRType = r.rtype0(pos)
3223 iface, ifaceRType = r.rtype0(pos)
3230 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
3232 itab = r.rttiWord(pos, r.dict.itabsOffset()+idx)
3234 base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ)
3235 base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface)
3237 lsym := reflectdata.ITabLsym(typ, iface)
3238 itab = typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
3245 // convRTTI returns expressions appropriate for populating an
3246 // ir.ConvExpr's TypeWord and SrcRType fields, respectively.
3247 func (r *reader) convRTTI(pos src.XPos) (typeWord, srcRType ir.Node) {
3248 r.Sync(pkgbits.SyncConvRTTI)
3249 src, srcRType0, dst, dstRType, itab := r.itab(pos)
3250 if !dst.IsInterface() {
3254 // See reflectdata.ConvIfaceTypeWord.
3256 case dst.IsEmptyInterface():
3257 if !src.IsInterface() {
3258 typeWord = srcRType0 // direct eface construction
3260 case !src.IsInterface():
3261 typeWord = itab // direct iface construction
3263 typeWord = dstRType // convI2I
3266 // See reflectdata.ConvIfaceSrcRType.
3267 if !src.IsInterface() {
3268 srcRType = srcRType0
3274 func (r *reader) exprType() ir.Node {
3275 r.Sync(pkgbits.SyncExprType)
3279 var rtype, itab ir.Node
3282 typ, rtype, _, _, itab = r.itab(pos)
3283 if !typ.IsInterface() {
3284 rtype = nil // TODO(mdempsky): Leave set?
3287 typ, rtype = r.rtype0(pos)
3289 if !r.Bool() { // not derived
3290 // TODO(mdempsky): ir.TypeNode should probably return a typecheck'd node.
3291 n := ir.TypeNode(typ)
3297 dt := ir.NewDynamicType(pos, rtype)
3299 return typed(typ, dt)
3302 func (r *reader) op() ir.Op {
3303 r.Sync(pkgbits.SyncOp)
3304 return ir.Op(r.Len())
3307 // @@@ Package initialization
3309 func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) {
3310 cgoPragmas := make([][]string, r.Len())
3311 for i := range cgoPragmas {
3312 cgoPragmas[i] = r.Strings()
3314 target.CgoPragmas = cgoPragmas
3318 initOrder := make([]ir.Node, r.Len())
3319 for i := range initOrder {
3320 lhs := make([]ir.Node, r.Len())
3321 for j := range lhs {
3329 as = typecheck.Stmt(ir.NewAssignStmt(pos, lhs[0], rhs))
3331 as = typecheck.Stmt(ir.NewAssignListStmt(pos, ir.OAS2, lhs, []ir.Node{rhs}))
3334 for _, v := range lhs {
3335 v.(*ir.Name).Defn = as
3340 target.InitOrder = initOrder
3342 r.Sync(pkgbits.SyncEOF)
3345 func (r *reader) pkgDecls(target *ir.Package) {
3346 r.Sync(pkgbits.SyncDecls)
3348 switch code := codeDecl(r.Code(pkgbits.SyncDecl)); code {
3350 panic(fmt.Sprintf("unhandled decl: %v", code))
3356 names := r.pkgObjs(target)
3357 assert(len(names) == 1)
3358 target.Funcs = append(target.Funcs, names[0].Func)
3362 _, sym := r.selector()
3364 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
3365 target.Funcs = append(target.Funcs, method.Nname.(*ir.Name).Func)
3368 names := r.pkgObjs(target)
3370 if n := r.Len(); n > 0 {
3371 assert(len(names) == 1)
3372 embeds := make([]ir.Embed, n)
3373 for i := range embeds {
3374 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.Strings()}
3376 names[0].Embed = &embeds
3377 target.Embeds = append(target.Embeds, names[0])
3386 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
3387 r.Sync(pkgbits.SyncDeclNames)
3388 nodes := make([]*ir.Name, r.Len())
3389 for i := range nodes {
3390 r.Sync(pkgbits.SyncDeclName)
3392 name := r.obj().(*ir.Name)
3402 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
3405 target.Externs = append(target.Externs, name)
3408 assert(name.Type().Recv() == nil)
3410 // TODO(mdempsky): Cleaner way to recognize init?
3411 if strings.HasPrefix(sym.Name, "init.") {
3412 target.Inits = append(target.Inits, name.Func)
3416 if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME {
3417 assert(!sym.OnExportList())
3418 target.PluginExports = append(target.PluginExports, name)
3419 sym.SetOnExportList(true)
3422 if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) {
3424 target.AsmHdrDecls = append(target.AsmHdrDecls, name)
3434 // unifiedHaveInlineBody reports whether we have the function body for
3435 // fn, so we can inline it.
3436 func unifiedHaveInlineBody(fn *ir.Func) bool {
3441 _, ok := bodyReaderFor(fn)
3447 // unifiedInlineCall implements inline.NewInline by re-reading the function
3448 // body from its Unified IR export data.
3449 func unifiedInlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
3450 // TODO(mdempsky): Turn callerfn into an explicit parameter.
3451 callerfn := ir.CurFunc
3453 pri, ok := bodyReaderFor(fn)
3455 base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
3458 if fn.Inl.Body == nil {
3459 expandInline(fn, pri)
3462 r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody)
3464 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type())
3468 r.inlCaller = callerfn
3471 r.inlTreeIndex = inlIndex
3472 r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
3474 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
3475 for i, cv := range r.inlFunc.ClosureVars {
3476 // TODO(mdempsky): It should be possible to support this case, but
3477 // for now we rely on the inliner avoiding it.
3478 if cv.Outer.Curfn != callerfn {
3479 base.FatalfAt(call.Pos(), "inlining closure call across frames")
3481 r.closureVars[i] = cv.Outer
3483 if len(r.closureVars) != 0 && r.hasTypeParams() {
3484 r.dictParam = r.closureVars[len(r.closureVars)-1] // dictParam is last; see reader.funcLit
3489 r.delayResults = fn.Inl.CanDelayResults
3491 r.retlabel = typecheck.AutoLabel(".i")
3494 init := ir.TakeInit(call)
3496 // For normal function calls, the function callee expression
3497 // may contain side effects. Make sure to preserve these,
3498 // if necessary (#42703).
3499 if call.Op() == ir.OCALLFUNC {
3500 inline.CalleeEffects(&init, call.X)
3504 if call.Op() == ir.OCALLMETH {
3505 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
3507 args.Append(call.Args...)
3509 // Create assignment to declare and initialize inlvars.
3510 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, r.inlvars, args)
3512 var as2init ir.Nodes
3513 for _, name := range r.inlvars {
3514 if ir.IsBlank(name) {
3517 // TODO(mdempsky): Use inlined position of name.Pos() instead?
3518 name := name.(*ir.Name)
3519 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3522 as2.SetInit(as2init)
3523 init.Append(typecheck.Stmt(as2))
3525 if !r.delayResults {
3526 // If not delaying retvars, declare and zero initialize the
3527 // result variables now.
3528 for _, name := range r.retvars {
3529 // TODO(mdempsky): Use inlined position of name.Pos() instead?
3530 name := name.(*ir.Name)
3531 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3532 ras := ir.NewAssignStmt(call.Pos(), name, nil)
3533 init.Append(typecheck.Stmt(ras))
3537 // Add an inline mark just before the inlined body.
3538 // This mark is inline in the code so that it's a reasonable spot
3539 // to put a breakpoint. Not sure if that's really necessary or not
3540 // (in which case it could go at the end of the function instead).
3541 // Note issue 28603.
3542 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
3544 ir.WithFunc(r.curfn, func() {
3545 if !r.syntheticBody(call.Pos()) {
3546 assert(r.Bool()) // have body
3548 r.curfn.Body = r.stmts()
3549 r.curfn.Endlineno = r.pos()
3552 // TODO(mdempsky): This shouldn't be necessary. Inlining might
3553 // read in new function/method declarations, which could
3554 // potentially be recursively inlined themselves; but we shouldn't
3555 // need to read in the non-inlined bodies for the declarations
3556 // themselves. But currently it's an easy fix to #50552.
3557 readBodies(typecheck.Target, true)
3559 // Replace any "return" statements within the function body.
3560 var edit func(ir.Node) ir.Node
3561 edit = func(n ir.Node) ir.Node {
3562 if ret, ok := n.(*ir.ReturnStmt); ok {
3563 n = typecheck.Stmt(r.inlReturn(ret))
3565 ir.EditChildren(n, edit)
3571 body := ir.Nodes(r.curfn.Body)
3573 // Reparent any declarations into the caller function.
3574 for _, name := range r.curfn.Dcl {
3575 name.Curfn = callerfn
3576 callerfn.Dcl = append(callerfn.Dcl, name)
3578 if name.AutoTemp() {
3579 name.SetEsc(ir.EscUnknown)
3580 name.SetInlLocal(true)
3584 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
3586 res := ir.NewInlinedCallExpr(call.Pos(), body, append([]ir.Node(nil), r.retvars...))
3588 res.SetType(call.Type())
3591 // Inlining shouldn't add any functions to todoBodies.
3592 assert(len(todoBodies) == 0)
3597 // inlReturn returns a statement that can substitute for the given
3598 // return statement when inlining.
3599 func (r *reader) inlReturn(ret *ir.ReturnStmt) *ir.BlockStmt {
3600 pos := r.inlCall.Pos()
3602 block := ir.TakeInit(ret)
3604 if results := ret.Results; len(results) != 0 {
3605 assert(len(r.retvars) == len(results))
3607 as2 := ir.NewAssignListStmt(pos, ir.OAS2, append([]ir.Node(nil), r.retvars...), ret.Results)
3610 for _, name := range r.retvars {
3611 // TODO(mdempsky): Use inlined position of name.Pos() instead?
3612 name := name.(*ir.Name)
3613 block.Append(ir.NewDecl(pos, ir.ODCL, name))
3621 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
3622 return ir.NewBlockStmt(pos, block)
3625 // expandInline reads in an extra copy of IR to populate
3626 // fn.Inl.{Dcl,Body}.
3627 func expandInline(fn *ir.Func, pri pkgReaderIndex) {
3628 // TODO(mdempsky): Remove this function. It's currently needed by
3629 // dwarfgen/dwarf.go:preInliningDcls, which requires fn.Inl.Dcl to
3630 // create abstract function DIEs. But we should be able to provide it
3631 // with the same information some other way.
3633 fndcls := len(fn.Dcl)
3634 topdcls := len(typecheck.Target.Funcs)
3636 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type())
3637 tmpfn.ClosureVars = fn.ClosureVars
3640 r := pri.asReader(pkgbits.RelocBody, pkgbits.SyncFuncBody)
3642 // Don't change parameter's Sym/Nname fields.
3648 used := usedLocals(tmpfn.Body)
3650 for _, name := range tmpfn.Dcl {
3651 if name.Class != ir.PAUTO || used.Has(name) {
3653 fn.Inl.Dcl = append(fn.Inl.Dcl, name)
3656 fn.Inl.Body = tmpfn.Body
3658 // Double check that we didn't change fn.Dcl by accident.
3659 assert(fndcls == len(fn.Dcl))
3661 // typecheck.Stmts may have added function literals to
3662 // typecheck.Target.Decls. Remove them again so we don't risk trying
3663 // to compile them multiple times.
3664 typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
3667 // usedLocals returns a set of local variables that are used within body.
3668 func usedLocals(body []ir.Node) ir.NameSet {
3670 ir.VisitList(body, func(n ir.Node) {
3671 if n, ok := n.(*ir.Name); ok && n.Op() == ir.ONAME && n.Class == ir.PAUTO {
3678 // @@@ Method wrappers
3680 // needWrapperTypes lists types for which we may need to generate
3682 var needWrapperTypes []*types.Type
3684 // haveWrapperTypes lists types for which we know we already have
3685 // method wrappers, because we found the type in an imported package.
3686 var haveWrapperTypes []*types.Type
3688 // needMethodValueWrappers lists methods for which we may need to
3689 // generate method value wrappers.
3690 var needMethodValueWrappers []methodValueWrapper
3692 // haveMethodValueWrappers lists methods for which we know we already
3693 // have method value wrappers, because we found it in an imported
3695 var haveMethodValueWrappers []methodValueWrapper
3697 type methodValueWrapper struct {
3702 func (r *reader) needWrapper(typ *types.Type) {
3707 // If a type was found in an imported package, then we can assume
3708 // that package (or one of its transitive dependencies) already
3709 // generated method wrappers for it.
3710 if r.importedDef() {
3711 haveWrapperTypes = append(haveWrapperTypes, typ)
3713 needWrapperTypes = append(needWrapperTypes, typ)
3717 // importedDef reports whether r is reading from an imported and
3718 // non-generic element.
3720 // If a type was found in an imported package, then we can assume that
3721 // package (or one of its transitive dependencies) already generated
3722 // method wrappers for it.
3724 // Exception: If we're instantiating an imported generic type or
3725 // function, we might be instantiating it with type arguments not
3726 // previously seen before.
3728 // TODO(mdempsky): Distinguish when a generic function or type was
3729 // instantiated in an imported package so that we can add types to
3730 // haveWrapperTypes instead.
3731 func (r *reader) importedDef() bool {
3732 return r.p != localPkgReader && !r.hasTypeParams()
3735 func MakeWrappers(target *ir.Package) {
3736 // always generate a wrapper for error.Error (#29304)
3737 needWrapperTypes = append(needWrapperTypes, types.ErrorType)
3739 seen := make(map[string]*types.Type)
3741 for _, typ := range haveWrapperTypes {
3742 wrapType(typ, target, seen, false)
3744 haveWrapperTypes = nil
3746 for _, typ := range needWrapperTypes {
3747 wrapType(typ, target, seen, true)
3749 needWrapperTypes = nil
3751 for _, wrapper := range haveMethodValueWrappers {
3752 wrapMethodValue(wrapper.rcvr, wrapper.method, target, false)
3754 haveMethodValueWrappers = nil
3756 for _, wrapper := range needMethodValueWrappers {
3757 wrapMethodValue(wrapper.rcvr, wrapper.method, target, true)
3759 needMethodValueWrappers = nil
3762 func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) {
3763 key := typ.LinkString()
3764 if prev := seen[key]; prev != nil {
3765 if !types.Identical(typ, prev) {
3766 base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key)
3773 // Only called to add to 'seen'.
3777 if !typ.IsInterface() {
3778 typecheck.CalcMethods(typ)
3780 for _, meth := range typ.AllMethods().Slice() {
3781 if meth.Sym.IsBlank() || !meth.IsMethod() {
3782 base.FatalfAt(meth.Pos, "invalid method: %v", meth)
3785 methodWrapper(0, typ, meth, target)
3787 // For non-interface types, we also want *T wrappers.
3788 if !typ.IsInterface() {
3789 methodWrapper(1, typ, meth, target)
3791 // For not-in-heap types, *T is a scalar, not pointer shaped,
3792 // so the interface wrappers use **T.
3793 if typ.NotInHeap() {
3794 methodWrapper(2, typ, meth, target)
3800 func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) {
3802 for i := 0; i < derefs; i++ {
3803 wrapper = types.NewPtr(wrapper)
3806 sym := ir.MethodSym(wrapper, method.Sym)
3807 base.Assertf(!sym.Siggen(), "already generated wrapper %v", sym)
3810 wrappee := method.Type.Recv().Type
3811 if types.Identical(wrapper, wrappee) ||
3812 !types.IsMethodApplicable(wrapper, method) ||
3813 !reflectdata.NeedEmit(tbase) {
3817 // TODO(mdempsky): Use method.Pos instead?
3818 pos := base.AutogeneratedPos
3820 fn := newWrapperFunc(pos, sym, wrapper, method)
3822 var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
3824 // For simple *T wrappers around T methods, panicwrap produces a
3825 // nicer panic message.
3826 if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) {
3827 cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node))
3828 then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)}
3829 fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil))
3832 // typecheck will add one implicit deref, if necessary,
3833 // but not-in-heap types require more for their **T wrappers.
3834 for i := 1; i < derefs; i++ {
3835 recv = Implicit(ir.NewStarExpr(pos, recv))
3838 addTailCall(pos, fn, recv, method)
3840 finishWrapperFunc(fn, target)
3843 func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) {
3844 sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm")
3850 // TODO(mdempsky): Use method.Pos instead?
3851 pos := base.AutogeneratedPos
3853 fn := newWrapperFunc(pos, sym, nil, method)
3856 // Declare and initialize variable holding receiver.
3857 recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
3863 addTailCall(pos, fn, recv, method)
3865 finishWrapperFunc(fn, target)
3868 func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
3869 sig := newWrapperType(wrapper, method)
3871 fn := ir.NewFunc(pos, pos, sym, sig)
3872 fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers?
3874 // TODO(mdempsky): De-duplicate with similar logic in funcargs.
3875 defParams := func(class ir.Class, params *types.Type) {
3876 for _, param := range params.FieldSlice() {
3877 param.Nname = fn.NewLocal(param.Pos, param.Sym, class, param.Type)
3881 defParams(ir.PPARAM, sig.Recvs())
3882 defParams(ir.PPARAM, sig.Params())
3883 defParams(ir.PPARAMOUT, sig.Results())
3888 func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
3889 ir.WithFunc(fn, func() {
3890 typecheck.Stmts(fn.Body)
3893 // We generate wrappers after the global inlining pass,
3894 // so we're responsible for applying inlining ourselves here.
3895 // TODO(prattmic): plumb PGO.
3896 inline.InlineCalls(fn, nil)
3898 // The body of wrapper function after inlining may reveal new ir.OMETHVALUE node,
3899 // we don't know whether wrapper function has been generated for it or not, so
3900 // generate one immediately here.
3902 // Further, after CL 492017, function that construct closures is allowed to be inlined,
3903 // even though the closure itself can't be inline. So we also need to visit body of any
3904 // closure that we see when visiting body of the wrapper function.
3905 ir.VisitFuncAndClosures(fn, func(n ir.Node) {
3906 if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
3907 wrapMethodValue(n.X.Type(), n.Selection, target, true)
3912 target.Funcs = append(target.Funcs, fn)
3915 // newWrapperType returns a copy of the given signature type, but with
3916 // the receiver parameter type substituted with recvType.
3917 // If recvType is nil, newWrapperType returns a signature
3918 // without a receiver parameter.
3919 func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
3920 clone := func(params []*types.Field) []*types.Field {
3921 res := make([]*types.Field, len(params))
3922 for i, param := range params {
3924 if sym == nil || sym.Name == "_" {
3925 sym = typecheck.LookupNum(".anon", i)
3927 res[i] = types.NewField(param.Pos, sym, param.Type)
3928 res[i].SetIsDDD(param.IsDDD())
3935 var recv *types.Field
3936 if recvType != nil {
3937 recv = types.NewField(sig.Recv().Pos, typecheck.Lookup(".this"), recvType)
3939 params := clone(sig.Params().FieldSlice())
3940 results := clone(sig.Results().FieldSlice())
3942 return types.NewSignature(recv, params, results)
3945 func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) {
3946 sig := fn.Nname.Type()
3947 args := make([]ir.Node, sig.NumParams())
3948 for i, param := range sig.Params().FieldSlice() {
3949 args[i] = param.Nname.(*ir.Name)
3952 // TODO(mdempsky): Support creating OTAILCALL, when possible. See reflectdata.methodWrapper.
3953 // Not urgent though, because tail calls are currently incompatible with regabi anyway.
3955 fn.SetWrapper(true) // TODO(mdempsky): Leave unset for tail calls?
3957 dot := ir.NewSelectorExpr(pos, ir.OXDOT, recv, method.Sym)
3958 call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr)
3960 if method.Type.NumResults() == 0 {
3961 fn.Body.Append(call)
3965 ret := ir.NewReturnStmt(pos, nil)
3966 ret.Results = []ir.Node{call}
3970 func setBasePos(pos src.XPos) {
3971 // Set the position for any error messages we might print (e.g. too large types).
3975 // dictParamName is the name of the synthetic dictionary parameter
3976 // added to shaped functions.
3978 // N.B., this variable name is known to Delve:
3979 // https://github.com/go-delve/delve/blob/cb91509630529e6055be845688fd21eb89ae8714/pkg/proc/eval.go#L28
3980 const dictParamName = typecheck.LocalDictName
3982 // shapeSig returns a copy of fn's signature, except adding a
3983 // dictionary parameter and promoting the receiver parameter (if any)
3984 // to a normal parameter.
3986 // The parameter types.Fields are all copied too, so their Nname
3987 // fields can be initialized for use by the shape function.
3988 func shapeSig(fn *ir.Func, dict *readerDict) *types.Type {
3989 sig := fn.Nname.Type()
3990 oldRecv := sig.Recv()
3992 var recv *types.Field
3994 recv = types.NewField(oldRecv.Pos, oldRecv.Sym, oldRecv.Type)
3997 params := make([]*types.Field, 1+sig.Params().Fields().Len())
3998 params[0] = types.NewField(fn.Pos(), fn.Sym().Pkg.Lookup(dictParamName), types.NewPtr(dict.varType()))
3999 for i, param := range sig.Params().Fields().Slice() {
4000 d := types.NewField(param.Pos, param.Sym, param.Type)
4001 d.SetIsDDD(param.IsDDD())
4005 results := make([]*types.Field, sig.Results().Fields().Len())
4006 for i, result := range sig.Results().Fields().Slice() {
4007 results[i] = types.NewField(result.Pos, result.Sym, result.Type)
4010 return types.NewSignature(recv, params, results)