1
2
3
4
5 package noder
6
7 import (
8 "encoding/hex"
9 "fmt"
10 "go/constant"
11 "internal/buildcfg"
12 "internal/pkgbits"
13 "path/filepath"
14 "slices"
15 "strings"
16
17 "cmd/compile/internal/base"
18 "cmd/compile/internal/dwarfgen"
19 "cmd/compile/internal/inline"
20 "cmd/compile/internal/inline/interleaved"
21 "cmd/compile/internal/ir"
22 "cmd/compile/internal/objw"
23 "cmd/compile/internal/pgoir"
24 "cmd/compile/internal/reflectdata"
25 "cmd/compile/internal/staticinit"
26 "cmd/compile/internal/typecheck"
27 "cmd/compile/internal/types"
28 "cmd/internal/hash"
29 "cmd/internal/obj"
30 "cmd/internal/objabi"
31 "cmd/internal/src"
32 )
33
34
35
36
37
38 type pkgReader struct {
39 pkgbits.PkgDecoder
40
41
42
43
44
45
46 posBases []*src.PosBase
47 pkgs []*types.Pkg
48 typs []*types.Type
49
50
51
52
53 newindex []index
54 }
55
56 func newPkgReader(pr pkgbits.PkgDecoder) *pkgReader {
57 return &pkgReader{
58 PkgDecoder: pr,
59
60 posBases: make([]*src.PosBase, pr.NumElems(pkgbits.SectionPosBase)),
61 pkgs: make([]*types.Pkg, pr.NumElems(pkgbits.SectionPkg)),
62 typs: make([]*types.Type, pr.NumElems(pkgbits.SectionType)),
63
64 newindex: make([]index, pr.TotalElems()),
65 }
66 }
67
68
69
70 type pkgReaderIndex struct {
71 pr *pkgReader
72 idx index
73 dict *readerDict
74 methodSym *types.Sym
75
76 synthetic func(pos src.XPos, r *reader)
77 }
78
79 func (pri pkgReaderIndex) asReader(k pkgbits.SectionKind, marker pkgbits.SyncMarker) *reader {
80 if pri.synthetic != nil {
81 return &reader{synthetic: pri.synthetic}
82 }
83
84 r := pri.pr.newReader(k, pri.idx, marker)
85 r.dict = pri.dict
86 r.methodSym = pri.methodSym
87 return r
88 }
89
90 func (pr *pkgReader) newReader(k pkgbits.SectionKind, idx index, marker pkgbits.SyncMarker) *reader {
91 return &reader{
92 Decoder: pr.NewDecoder(k, idx, marker),
93 p: pr,
94 }
95 }
96
97
98 type reader struct {
99 pkgbits.Decoder
100
101 p *pkgReader
102
103 dict *readerDict
104
105
106 funcLitGen int
107
108 rangeLitGen int
109
110
111
112
113
114
115 curfn *ir.Func
116 locals []*ir.Name
117 closureVars []*ir.Name
118
119
120
121
122
123
124 funarghack bool
125
126
127
128 methodSym *types.Sym
129
130
131 dictParam *ir.Name
132
133
134
135
136 synthetic func(pos src.XPos, r *reader)
137
138
139
140 scopeVars []int
141 marker dwarfgen.ScopeMarker
142 lastCloseScopePos src.XPos
143
144
145
146
147
148 inlCaller *ir.Func
149 inlCall *ir.CallExpr
150 inlFunc *ir.Func
151 inlTreeIndex int
152 inlPosBases map[*src.PosBase]*src.PosBase
153
154
155
156 suppressInlPos int
157
158 delayResults bool
159
160
161 retlabel *types.Sym
162 }
163
164
165
166
167
168
169
170
171
172
173 type readerDict struct {
174 shaped bool
175
176
177
178
179 baseSym *types.Sym
180
181
182
183 shapedObj *ir.Name
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 targs []*types.Type
204
205
206
207 implicits int
208
209
210 receivers int
211
212 derived []derivedInfo
213 derivedTypes []*types.Type
214
215
216 typeParamMethodExprs []readerMethodExprInfo
217 subdicts []objInfo
218 rtypes []typeInfo
219 itabs []itabInfo
220 }
221
222 type readerMethodExprInfo struct {
223 typeParamIdx int
224 method *types.Sym
225 }
226
227 func setType(n ir.Node, typ *types.Type) {
228 n.SetType(typ)
229 n.SetTypecheck(1)
230 }
231
232 func setValue(name *ir.Name, val constant.Value) {
233 name.SetVal(val)
234 name.Defn = nil
235 }
236
237
238
239
240 func (r *reader) pos() src.XPos {
241 return base.Ctxt.PosTable.XPos(r.pos0())
242 }
243
244
245
246 func (r *reader) origPos() (origPos, inlPos src.XPos) {
247 r.suppressInlPos++
248 origPos = r.pos()
249 r.suppressInlPos--
250 inlPos = r.inlPos(origPos)
251 return
252 }
253
254 func (r *reader) pos0() src.Pos {
255 r.Sync(pkgbits.SyncPos)
256 if !r.Bool() {
257 return src.NoPos
258 }
259
260 posBase := r.posBase()
261 line := r.Uint()
262 col := r.Uint()
263 return src.MakePos(posBase, line, col)
264 }
265
266
267 func (r *reader) posBase() *src.PosBase {
268 return r.inlPosBase(r.p.posBaseIdx(r.Reloc(pkgbits.SectionPosBase)))
269 }
270
271
272
273 func (pr *pkgReader) posBaseIdx(idx index) *src.PosBase {
274 if b := pr.posBases[idx]; b != nil {
275 return b
276 }
277
278 r := pr.newReader(pkgbits.SectionPosBase, idx, pkgbits.SyncPosBase)
279 var b *src.PosBase
280
281 absFilename := r.String()
282 filename := absFilename
283
284
285
286
287
288
289
290
291
292
293
294
295
296 const dollarGOROOT = "$GOROOT"
297 if buildcfg.GOROOT != "" && strings.HasPrefix(filename, dollarGOROOT) {
298 filename = filepath.FromSlash(buildcfg.GOROOT + filename[len(dollarGOROOT):])
299 }
300
301 if r.Bool() {
302 b = src.NewFileBase(filename, absFilename)
303 } else {
304 pos := r.pos0()
305 line := r.Uint()
306 col := r.Uint()
307 b = src.NewLinePragmaBase(pos, filename, absFilename, line, col)
308 }
309
310 pr.posBases[idx] = b
311 return b
312 }
313
314
315
316
317 func (r *reader) inlPosBase(oldBase *src.PosBase) *src.PosBase {
318 if index := oldBase.InliningIndex(); index >= 0 {
319 base.Fatalf("oldBase %v already has inlining index %v", oldBase, index)
320 }
321
322 if r.inlCall == nil || r.suppressInlPos != 0 {
323 return oldBase
324 }
325
326 if newBase, ok := r.inlPosBases[oldBase]; ok {
327 return newBase
328 }
329
330 newBase := src.NewInliningBase(oldBase, r.inlTreeIndex)
331 r.inlPosBases[oldBase] = newBase
332 return newBase
333 }
334
335
336
337
338 func (r *reader) inlPos(xpos src.XPos) src.XPos {
339 pos := base.Ctxt.PosTable.Pos(xpos)
340 pos.SetBase(r.inlPosBase(pos.Base()))
341 return base.Ctxt.PosTable.XPos(pos)
342 }
343
344
345
346
347 func (r *reader) pkg() *types.Pkg {
348 r.Sync(pkgbits.SyncPkg)
349 return r.p.pkgIdx(r.Reloc(pkgbits.SectionPkg))
350 }
351
352
353
354 func (pr *pkgReader) pkgIdx(idx index) *types.Pkg {
355 if pkg := pr.pkgs[idx]; pkg != nil {
356 return pkg
357 }
358
359 pkg := pr.newReader(pkgbits.SectionPkg, idx, pkgbits.SyncPkgDef).doPkg()
360 pr.pkgs[idx] = pkg
361 return pkg
362 }
363
364
365 func (r *reader) doPkg() *types.Pkg {
366 path := r.String()
367 switch path {
368 case "":
369 path = r.p.PkgPath()
370 case "builtin":
371 return types.BuiltinPkg
372 case "unsafe":
373 return types.UnsafePkg
374 }
375
376 name := r.String()
377
378 pkg := types.NewPkg(path, "")
379
380 if pkg.Name == "" {
381 pkg.Name = name
382 } else {
383 base.Assertf(pkg.Name == name, "package %q has name %q, but want %q", pkg.Path, pkg.Name, name)
384 }
385
386 return pkg
387 }
388
389
390
391 func (r *reader) typ() *types.Type {
392 return r.typWrapped(true)
393 }
394
395
396
397 func (r *reader) typWrapped(wrapped bool) *types.Type {
398 return r.p.typIdx(r.typInfo(), r.dict, wrapped)
399 }
400
401 func (r *reader) typInfo() typeInfo {
402 r.Sync(pkgbits.SyncType)
403 if r.Bool() {
404 return typeInfo{idx: index(r.Len()), derived: true}
405 }
406 return typeInfo{idx: r.Reloc(pkgbits.SectionType), derived: false}
407 }
408
409
410
411 func (pr *pkgReader) typListIdx(infos []typeInfo, dict *readerDict) []*types.Type {
412 typs := make([]*types.Type, len(infos))
413 for i, info := range infos {
414 typs[i] = pr.typIdx(info, dict, true)
415 }
416 return typs
417 }
418
419
420
421
422 func (pr *pkgReader) typIdx(info typeInfo, dict *readerDict, wrapped bool) *types.Type {
423 idx := info.idx
424 var where **types.Type
425 if info.derived {
426 where = &dict.derivedTypes[idx]
427 idx = dict.derived[idx].idx
428 } else {
429 where = &pr.typs[idx]
430 }
431
432 if typ := *where; typ != nil {
433 return typ
434 }
435
436 r := pr.newReader(pkgbits.SectionType, idx, pkgbits.SyncTypeIdx)
437 r.dict = dict
438
439 typ := r.doTyp()
440 if typ == nil {
441 base.Fatalf("doTyp returned nil for info=%v", info)
442 }
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484 if prev := *where; prev != nil {
485 return prev
486 }
487
488 if wrapped {
489
490
491 *where = typ
492
493 r.needWrapper(typ)
494 }
495
496 if !typ.IsUntyped() {
497 types.CheckSize(typ)
498 }
499
500 return typ
501 }
502
503 func (r *reader) doTyp() *types.Type {
504 switch tag := pkgbits.CodeType(r.Code(pkgbits.SyncType)); tag {
505 default:
506 panic(fmt.Sprintf("unexpected type: %v", tag))
507
508 case pkgbits.TypeBasic:
509 return *basics[r.Len()]
510
511 case pkgbits.TypeNamed:
512 obj := r.obj()
513 assert(obj.Op() == ir.OTYPE)
514 return obj.Type()
515
516 case pkgbits.TypeTypeParam:
517 return r.dict.targs[r.Len()]
518
519 case pkgbits.TypeArray:
520 len := int64(r.Uint64())
521 return types.NewArray(r.typ(), len)
522 case pkgbits.TypeChan:
523 dir := dirs[r.Len()]
524 return types.NewChan(r.typ(), dir)
525 case pkgbits.TypeMap:
526 return types.NewMap(r.typ(), r.typ())
527 case pkgbits.TypePointer:
528 return types.NewPtr(r.typ())
529 case pkgbits.TypeSignature:
530 return r.signature(nil)
531 case pkgbits.TypeSlice:
532 return types.NewSlice(r.typ())
533 case pkgbits.TypeStruct:
534 return r.structType()
535 case pkgbits.TypeInterface:
536 return r.interfaceType()
537 case pkgbits.TypeUnion:
538 return r.unionType()
539 }
540 }
541
542 func (r *reader) unionType() *types.Type {
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560 if false {
561 pure := false
562 for i, n := 0, r.Len(); i < n; i++ {
563 _ = r.Bool()
564 term := r.typ()
565 if term.IsEmptyInterface() {
566 pure = true
567 }
568 }
569 if !pure {
570 base.Fatalf("impure type set used in value type")
571 }
572 }
573
574 return types.Types[types.TINTER]
575 }
576
577 func (r *reader) interfaceType() *types.Type {
578 nmethods, nembeddeds := r.Len(), r.Len()
579 implicit := nmethods == 0 && nembeddeds == 1 && r.Bool()
580 assert(!implicit)
581
582 fields := make([]*types.Field, nmethods+nembeddeds)
583 methods, embeddeds := fields[:nmethods], fields[nmethods:]
584
585 for i := range methods {
586 methods[i] = types.NewField(r.pos(), r.selector(), r.signature(types.FakeRecv()))
587 }
588 for i := range embeddeds {
589 embeddeds[i] = types.NewField(src.NoXPos, nil, r.typ())
590 }
591
592 if len(fields) == 0 {
593 return types.Types[types.TINTER]
594 }
595 return types.NewInterface(fields)
596 }
597
598 func (r *reader) structType() *types.Type {
599 fields := make([]*types.Field, r.Len())
600 for i := range fields {
601 field := types.NewField(r.pos(), r.selector(), r.typ())
602 field.Note = r.String()
603 if r.Bool() {
604 field.Embedded = 1
605 }
606 fields[i] = field
607 }
608 return types.NewStruct(fields)
609 }
610
611 func (r *reader) signature(recv *types.Field) *types.Type {
612 r.Sync(pkgbits.SyncSignature)
613
614 params := r.params()
615 results := r.params()
616 if r.Bool() {
617 params[len(params)-1].SetIsDDD(true)
618 }
619
620 return types.NewSignature(recv, params, results)
621 }
622
623 func (r *reader) params() []*types.Field {
624 r.Sync(pkgbits.SyncParams)
625 params := make([]*types.Field, r.Len())
626 for i := range params {
627 params[i] = r.param()
628 }
629 return params
630 }
631
632 func (r *reader) param() *types.Field {
633 r.Sync(pkgbits.SyncParam)
634 return types.NewField(r.pos(), r.localIdent(), r.typ())
635 }
636
637
638
639
640
641
642 var objReader = map[*types.Sym]pkgReaderIndex{}
643
644
645 func (r *reader) obj() ir.Node {
646 return r.p.objInstIdx(r.objInfo(), r.dict, false)
647 }
648
649
650
651 func (r *reader) objInfo() objInfo {
652 r.Sync(pkgbits.SyncObject)
653 if r.Version().Has(pkgbits.DerivedFuncInstance) {
654 assert(!r.Bool())
655 }
656 idx := r.Reloc(pkgbits.SectionObj)
657
658 explicits := make([]typeInfo, r.Len())
659 for i := range explicits {
660 explicits[i] = r.typInfo()
661 }
662
663 return objInfo{idx, explicits}
664 }
665
666
667
668 func (pr *pkgReader) objInstIdx(info objInfo, dict *readerDict, shaped bool) ir.Node {
669 explicits := pr.typListIdx(info.explicits, dict)
670
671 var implicits []*types.Type
672 if dict != nil {
673 implicits = dict.targs
674 }
675
676 return pr.objIdx(info.idx, implicits, explicits, shaped)
677 }
678
679
680
681
682
683 func (pr *pkgReader) objIdx(idx index, implicits, explicits []*types.Type, shaped bool) ir.Node {
684 n, err := pr.objIdxMayFail(idx, implicits, explicits, shaped)
685 if err != nil {
686 base.Fatalf("%v", err)
687 }
688 return n
689 }
690
691
692
693
694
695
696
697 func (pr *pkgReader) objIdxMayFail(idx index, implicits, explicits []*types.Type, shaped bool) (ir.Node, error) {
698 rname := pr.newReader(pkgbits.SectionName, idx, pkgbits.SyncObject1)
699 _, sym := rname.qualifiedIdent()
700 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
701
702 if tag == pkgbits.ObjStub {
703 assert(!sym.IsBlank())
704 switch sym.Pkg {
705 case types.BuiltinPkg, types.UnsafePkg:
706 return sym.Def.(ir.Node), nil
707 }
708 if pri, ok := objReader[sym]; ok {
709 return pri.pr.objIdxMayFail(pri.idx, nil, explicits, shaped)
710 }
711 if sym.Pkg.Path == "runtime" {
712 return typecheck.LookupRuntime(sym.Name), nil
713 }
714 base.Fatalf("unresolved stub: %v", sym)
715 }
716
717 dict, err := pr.objDictIdx(sym, idx, implicits, explicits, shaped)
718 if err != nil {
719 return nil, err
720 }
721
722 sym = dict.baseSym
723 if !sym.IsBlank() && sym.Def != nil {
724 return sym.Def.(*ir.Name), nil
725 }
726
727 r := pr.newReader(pkgbits.SectionObj, idx, pkgbits.SyncObject1)
728 rext := pr.newReader(pkgbits.SectionObjExt, idx, pkgbits.SyncObject1)
729
730 r.dict = dict
731 rext.dict = dict
732
733 do := func(op ir.Op, hasTParams bool) *ir.Name {
734 pos := r.pos()
735 setBasePos(pos)
736 if hasTParams {
737 r.typeParamNames()
738 }
739
740 name := ir.NewDeclNameAt(pos, op, sym)
741 name.Class = ir.PEXTERN
742 if !sym.IsBlank() {
743 if sym.Def != nil {
744 base.FatalfAt(name.Pos(), "already have a definition for %v", name)
745 }
746 assert(sym.Def == nil)
747 sym.Def = name
748 }
749 return name
750 }
751
752 switch tag {
753 default:
754 panic("unexpected object")
755
756 case pkgbits.ObjAlias:
757 name := do(ir.OTYPE, false)
758
759 if r.Version().Has(pkgbits.AliasTypeParamNames) {
760 r.typeParamNames()
761 }
762
763
764
765
766
767 hack := sym.Def == name
768 if hack {
769 sym.Def = nil
770 }
771 typ := r.typ()
772 if hack {
773 if sym.Def != nil {
774 name = sym.Def.(*ir.Name)
775 assert(types.IdenticalStrict(name.Type(), typ))
776 return name, nil
777 }
778 sym.Def = name
779 }
780
781 setType(name, typ)
782 name.SetAlias(true)
783 return name, nil
784
785 case pkgbits.ObjConst:
786 name := do(ir.OLITERAL, false)
787 typ := r.typ()
788 val := FixValue(typ, r.Value())
789 setType(name, typ)
790 setValue(name, val)
791 return name, nil
792
793 case pkgbits.ObjFunc:
794 npos := r.pos()
795 setBasePos(npos)
796
797 var sel *types.Sym
798 var recv *types.Field
799 if r.Version().Has(pkgbits.GenericMethods) && r.Bool() {
800 sel = r.selector()
801 r.recvTypeParamNames()
802 recv = r.param()
803 if r.Version().Has(pkgbits.PreserveMethodOrder) {
804 _ = r.Len()
805 }
806 } else {
807 if sym.Name == "init" {
808 sym = Renameinit()
809 }
810 }
811 r.typeParamNames()
812 typ := r.signature(recv)
813 fpos := r.pos()
814
815 fn := ir.NewFunc(fpos, npos, sym, typ)
816 if r.hasTypeParams() && r.dict.shaped {
817 typ.SetHasShape(true)
818 }
819
820 name := fn.Nname
821 if !sym.IsBlank() {
822 if sym.Def != nil {
823 base.FatalfAt(name.Pos(), "already have a definition for %v", name)
824 }
825 assert(sym.Def == nil)
826 sym.Def = name
827 }
828
829 if r.hasTypeParams() {
830 name.Func.SetDupok(true)
831 if r.dict.shaped {
832 setType(name, shapeSig(name.Func, r.dict))
833 } else {
834 todoDicts = append(todoDicts, func() {
835 r.dict.shapedObj = pr.objIdx(idx, implicits, explicits, true).(*ir.Name)
836 })
837 }
838 }
839
840 rext.funcExt(name, sel)
841 return name, nil
842
843 case pkgbits.ObjType:
844 name := do(ir.OTYPE, true)
845 typ := types.NewNamed(name)
846 setType(name, typ)
847 if r.hasTypeParams() && r.dict.shaped {
848 typ.SetHasShape(true)
849 }
850
851
852 rext.typeExt(name)
853
854
855
856 types.DeferCheckSize()
857 typ.SetUnderlying(r.typWrapped(false))
858 types.ResumeCheckSize()
859
860 if r.hasTypeParams() && !r.dict.shaped {
861 todoDicts = append(todoDicts, func() {
862 r.dict.shapedObj = pr.objIdx(idx, implicits, explicits, true).(*ir.Name)
863 })
864 }
865
866 methods := make([]*types.Field, r.Len())
867 for i := range methods {
868 methods[i] = r.method(rext)
869 }
870 if len(methods) != 0 {
871 typ.SetMethods(methods)
872 }
873
874 if !r.dict.shaped {
875 r.needWrapper(typ)
876 }
877
878 return name, nil
879
880 case pkgbits.ObjVar:
881 name := do(ir.ONAME, false)
882 setType(name, r.typ())
883 rext.varExt(name)
884 return name, nil
885 }
886 }
887
888
889 func (dict *readerDict) mangle(sym *types.Sym) *types.Sym {
890 if !dict.hasTypeParams() {
891 return sym
892 }
893
894 var buf strings.Builder
895
896
897
898 n0, vsuff := types.SplitVargenSuffix(sym.Name)
899 n1, msuff := types.SplitMethSuffix(sym.Name)
900
901
902 var n string
903 assert(vsuff == "" || msuff == "")
904 if vsuff != "" {
905 n = n0
906 } else {
907 n = n1
908 }
909
910 var j int
911 assert(dict.implicits == 0 || dict.receivers == 0)
912 if msuff != "" {
913 j = dict.receivers
914 } else {
915 j = len(dict.targs)
916 }
917
918
919 n, ok := strings.CutSuffix(n, ")")
920
921
922 buf.WriteString(n)
923 if j > 0 {
924 buf.WriteByte('[')
925 for i := 0; i < j; i++ {
926 if i > 0 {
927 if i == dict.implicits {
928 buf.WriteByte(';')
929 } else {
930 buf.WriteByte(',')
931 }
932 }
933 buf.WriteString(dict.targs[i].LinkString())
934 }
935 buf.WriteByte(']')
936 }
937
938 if ok {
939 buf.WriteString(")")
940 }
941
942 buf.WriteString(vsuff)
943 buf.WriteString(msuff)
944
945
946 if msuff != "" {
947 buf.WriteByte('[')
948 for i := j; i < len(dict.targs); i++ {
949 if i > j {
950 buf.WriteByte(',')
951 }
952 buf.WriteString(dict.targs[i].LinkString())
953 }
954 buf.WriteByte(']')
955 }
956
957 return sym.Pkg.Lookup(buf.String())
958 }
959
960
961
962
963
964 func Shapify(targ *types.Type, basic bool) *types.Type {
965 if targ.Kind() == types.TFORW {
966 if targ.IsFullyInstantiated() {
967
968
969
970
971 if base.Debug.Shapify != 0 {
972 base.Warn("skipping shaping of recursive type %v", targ)
973 }
974 if targ.HasShape() {
975 return targ
976 }
977 } else {
978 base.Fatalf("%v is missing its underlying type", targ)
979 }
980 }
981
982
983 if targ.Kind() == types.TINTER && targ.IsFullyInstantiated() && targ.HasShape() {
984 return targ
985 }
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002 under := targ.Underlying()
1003 if basic && targ.IsPtr() && !targ.Elem().NotInHeap() {
1004 under = types.NewPtr(types.Types[types.TUINT8])
1005 }
1006
1007
1008
1009 uls := under.LinkString()
1010 if base.Debug.MaxShapeLen != 0 &&
1011 len(uls) > base.Debug.MaxShapeLen {
1012 h := hash.Sum32([]byte(uls))
1013 uls = hex.EncodeToString(h[:])
1014 }
1015
1016 sym := types.ShapePkg.Lookup(uls)
1017 if sym.Def == nil {
1018 name := ir.NewDeclNameAt(under.Pos(), ir.OTYPE, sym)
1019 typ := types.NewNamed(name)
1020 typ.SetUnderlying(under)
1021 sym.Def = typed(typ, name)
1022 }
1023 res := sym.Def.Type()
1024 assert(res.IsShape())
1025 assert(res.HasShape())
1026 return res
1027 }
1028
1029
1030 func (pr *pkgReader) objDictIdx(sym *types.Sym, idx index, implicits, explicits []*types.Type, shaped bool) (*readerDict, error) {
1031 r := pr.newReader(pkgbits.SectionObjDict, idx, pkgbits.SyncObject1)
1032
1033 dict := readerDict{
1034 shaped: shaped,
1035 }
1036
1037 nimplicits := r.Len()
1038 nreceivers := 0
1039 if r.Version().Has(pkgbits.GenericMethods) {
1040 nreceivers = r.Len()
1041 }
1042 nexplicits := r.Len() + nreceivers
1043
1044 if nimplicits > len(implicits) || nexplicits != len(explicits) {
1045 return nil, fmt.Errorf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits))
1046 }
1047
1048 dict.targs = append(implicits[:nimplicits:nimplicits], explicits...)
1049 dict.implicits = nimplicits
1050 dict.receivers = nreceivers
1051
1052
1053 for range dict.targs[dict.implicits:] {
1054
1055 r.typInfo()
1056 }
1057
1058 dict.derived = make([]derivedInfo, r.Len())
1059 dict.derivedTypes = make([]*types.Type, len(dict.derived))
1060 for i := range dict.derived {
1061 dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.SectionType)}
1062 if r.Version().Has(pkgbits.DerivedInfoNeeded) {
1063 assert(!r.Bool())
1064 }
1065 }
1066
1067
1068
1069
1070
1071
1072
1073 for _, targ := range dict.targs {
1074 if targ.HasShape() {
1075 dict.shaped = true
1076 break
1077 }
1078 }
1079
1080
1081
1082 for i, targ := range dict.targs {
1083 basic := r.Bool()
1084 if dict.shaped {
1085 dict.targs[i] = Shapify(targ, basic)
1086 }
1087 }
1088
1089 dict.baseSym = dict.mangle(sym)
1090
1091 dict.typeParamMethodExprs = make([]readerMethodExprInfo, r.Len())
1092 for i := range dict.typeParamMethodExprs {
1093 typeParamIdx := r.Len()
1094 method := r.selector()
1095
1096 dict.typeParamMethodExprs[i] = readerMethodExprInfo{typeParamIdx, method}
1097 }
1098
1099 dict.subdicts = make([]objInfo, r.Len())
1100 for i := range dict.subdicts {
1101 dict.subdicts[i] = r.objInfo()
1102 }
1103
1104 dict.rtypes = make([]typeInfo, r.Len())
1105 for i := range dict.rtypes {
1106 dict.rtypes[i] = r.typInfo()
1107 }
1108
1109 dict.itabs = make([]itabInfo, r.Len())
1110 for i := range dict.itabs {
1111 dict.itabs[i] = itabInfo{typ: r.typInfo(), iface: r.typInfo()}
1112 }
1113
1114 return &dict, nil
1115 }
1116
1117 func (r *reader) recvTypeParamNames() {
1118 r.Sync(pkgbits.SyncTypeParamNames)
1119
1120 for range r.dict.targs[r.dict.implicits : r.dict.implicits+r.dict.receivers] {
1121 r.pos()
1122 r.localIdent()
1123 }
1124 }
1125
1126 func (r *reader) typeParamNames() {
1127 r.Sync(pkgbits.SyncTypeParamNames)
1128
1129 for range r.dict.targs[r.dict.implicits+r.dict.receivers:] {
1130 r.pos()
1131 r.localIdent()
1132 }
1133 }
1134
1135 func (r *reader) method(rext *reader) *types.Field {
1136 r.Sync(pkgbits.SyncMethod)
1137 if r.Version().Has(pkgbits.PreserveMethodOrder) {
1138 _ = r.Len()
1139 }
1140 npos := r.pos()
1141 sym := r.selector()
1142 r.typeParamNames()
1143 recv := r.param()
1144 typ := r.signature(recv)
1145
1146 fpos := r.pos()
1147 fn := ir.NewFunc(fpos, npos, ir.ReceiverMethodSym(recv.Type, sym), typ)
1148 name := fn.Nname
1149
1150 if r.hasTypeParams() {
1151 name.Func.SetDupok(true)
1152 if r.dict.shaped {
1153 typ = shapeSig(name.Func, r.dict)
1154 setType(name, typ)
1155 }
1156 }
1157
1158 rext.funcExt(name, sym)
1159
1160 meth := types.NewField(name.Func.Pos(), sym, typ)
1161 meth.Nname = name
1162 meth.SetNointerface(name.Func.Pragma&ir.Nointerface != 0)
1163
1164 return meth
1165 }
1166
1167 func (r *reader) qualifiedIdent() (pkg *types.Pkg, sym *types.Sym) {
1168 r.Sync(pkgbits.SyncSym)
1169 pkg = r.pkg()
1170 if name := r.String(); name != "" {
1171 sym = pkg.Lookup(name)
1172 }
1173 return
1174 }
1175
1176 func (r *reader) localIdent() *types.Sym {
1177 r.Sync(pkgbits.SyncLocalIdent)
1178 pkg := r.pkg()
1179 if name := r.String(); name != "" {
1180 return pkg.Lookup(name)
1181 }
1182 return nil
1183 }
1184
1185 func (r *reader) selector() *types.Sym {
1186 r.Sync(pkgbits.SyncSelector)
1187 pkg := r.pkg()
1188 name := r.String()
1189 if types.IsExported(name) {
1190 pkg = types.LocalPkg
1191 }
1192 return pkg.Lookup(name)
1193 }
1194
1195 func (r *reader) hasTypeParams() bool {
1196 return r.dict.hasTypeParams()
1197 }
1198
1199 func (dict *readerDict) hasTypeParams() bool {
1200 return dict != nil && len(dict.targs) != 0
1201 }
1202
1203
1204
1205 func (r *reader) funcExt(name *ir.Name, method *types.Sym) {
1206 r.Sync(pkgbits.SyncFuncExt)
1207
1208 fn := name.Func
1209
1210
1211 if !fn.Pos().IsKnown() {
1212 fn.SetPos(name.Pos())
1213 }
1214
1215
1216
1217
1218
1219
1220
1221
1222 if name.Sym().Pkg == types.LocalPkg || r.hasTypeParams() {
1223 name.Defn = fn
1224 }
1225
1226 fn.Pragma = r.pragmaFlag()
1227 r.linkname(name)
1228
1229 if buildcfg.GOARCH == "wasm" {
1230 importmod := r.String()
1231 importname := r.String()
1232 exportname := r.String()
1233
1234 if importmod != "" && importname != "" {
1235 fn.WasmImport = &ir.WasmImport{
1236 Module: importmod,
1237 Name: importname,
1238 }
1239 }
1240 if exportname != "" {
1241 if method != nil {
1242 base.ErrorfAt(fn.Pos(), 0, "cannot use //go:wasmexport on a method")
1243 }
1244 fn.WasmExport = &ir.WasmExport{Name: exportname}
1245 }
1246 }
1247
1248 if r.Bool() {
1249 assert(name.Defn == nil)
1250
1251 fn.ABI = obj.ABI(r.Uint64())
1252
1253
1254 for _, f := range name.Type().RecvParams() {
1255 f.Note = r.String()
1256 }
1257
1258 if r.Bool() {
1259 fn.Inl = &ir.Inline{
1260 Cost: int32(r.Len()),
1261 CanDelayResults: r.Bool(),
1262 }
1263 if buildcfg.Experiment.NewInliner {
1264 fn.Inl.Properties = r.String()
1265 }
1266 }
1267 } else {
1268 r.addBody(name.Func, method)
1269 }
1270 r.Sync(pkgbits.SyncEOF)
1271 }
1272
1273 func (r *reader) typeExt(name *ir.Name) {
1274 r.Sync(pkgbits.SyncTypeExt)
1275
1276 typ := name.Type()
1277
1278 if r.hasTypeParams() {
1279
1280
1281 typ.SetIsFullyInstantiated(true)
1282
1283 for _, targ := range r.dict.targs {
1284 if targ.HasShape() {
1285 typ.SetHasShape(true)
1286 break
1287 }
1288 }
1289 }
1290
1291 name.SetPragma(r.pragmaFlag())
1292
1293 typecheck.SetBaseTypeIndex(typ, r.Int64(), r.Int64())
1294 }
1295
1296 func (r *reader) varExt(name *ir.Name) {
1297 r.Sync(pkgbits.SyncVarExt)
1298 r.linkname(name)
1299 }
1300
1301 func (r *reader) linkname(name *ir.Name) {
1302 assert(name.Op() == ir.ONAME)
1303 r.Sync(pkgbits.SyncLinkname)
1304
1305 if idx := r.Int64(); idx >= 0 {
1306 lsym := name.Linksym()
1307 lsym.SymIdx = int32(idx)
1308 lsym.Set(obj.AttrIndexed, true)
1309 } else {
1310 linkname := r.String()
1311 std := r.Bool()
1312 sym := name.Sym()
1313 sym.Linkname = linkname
1314 if sym.Pkg == types.LocalPkg && linkname != "" {
1315
1316
1317
1318
1319
1320
1321 if std {
1322 sym.Linksym().Set(obj.AttrLinknameStd, true)
1323 } else {
1324 sym.Linksym().Set(obj.AttrLinkname, true)
1325 }
1326 }
1327 }
1328 }
1329
1330 func (r *reader) pragmaFlag() ir.PragmaFlag {
1331 r.Sync(pkgbits.SyncPragma)
1332 return ir.PragmaFlag(r.Int())
1333 }
1334
1335
1336
1337
1338
1339 var bodyReader = map[*ir.Func]pkgReaderIndex{}
1340
1341
1342
1343 var importBodyReader = map[*types.Sym]pkgReaderIndex{}
1344
1345
1346
1347 func bodyReaderFor(fn *ir.Func) (pri pkgReaderIndex, ok bool) {
1348 if fn.Nname.Defn != nil {
1349 pri, ok = bodyReader[fn]
1350 base.AssertfAt(ok, base.Pos, "must have bodyReader for %v", fn)
1351 } else {
1352 pri, ok = importBodyReader[fn.Sym()]
1353 }
1354 return
1355 }
1356
1357
1358
1359 var todoDicts []func()
1360
1361
1362
1363 var todoBodies []*ir.Func
1364
1365
1366
1367 func (r *reader) addBody(fn *ir.Func, method *types.Sym) {
1368
1369
1370 assert(fn.Nname.Defn != nil)
1371
1372 idx := r.Reloc(pkgbits.SectionBody)
1373
1374 pri := pkgReaderIndex{r.p, idx, r.dict, method, nil}
1375 bodyReader[fn] = pri
1376
1377 if r.curfn == nil {
1378 todoBodies = append(todoBodies, fn)
1379 return
1380 }
1381
1382 pri.funcBody(fn)
1383 }
1384
1385 func (pri pkgReaderIndex) funcBody(fn *ir.Func) {
1386 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
1387 panicking := true
1388 defer func() {
1389 if panicking {
1390
1391
1392
1393
1394 fmt.Printf("****** panic traversed funcBody of %v\n", fn)
1395 }
1396 }()
1397 r.funcBody(fn)
1398 panicking = false
1399
1400 }
1401
1402
1403
1404 func (r *reader) funcBody(fn *ir.Func) {
1405 r.curfn = fn
1406 r.closureVars = fn.ClosureVars
1407 if len(r.closureVars) != 0 && r.hasTypeParams() {
1408 r.dictParam = r.closureVars[len(r.closureVars)-1]
1409 }
1410
1411 ir.WithFunc(fn, func() {
1412 r.declareParams()
1413
1414 if r.syntheticBody(fn.Pos()) {
1415 return
1416 }
1417
1418 if !r.Bool() {
1419 return
1420 }
1421
1422 body := r.stmts()
1423 if body == nil {
1424 body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(src.NoXPos, nil))}
1425 }
1426 fn.Body = body
1427 fn.Endlineno = r.pos()
1428 })
1429
1430 r.marker.WriteTo(fn)
1431 }
1432
1433
1434
1435 func (r *reader) syntheticBody(pos src.XPos) bool {
1436 if r.synthetic != nil {
1437 r.synthetic(pos, r)
1438 return true
1439 }
1440
1441
1442
1443 if r.hasTypeParams() && !r.dict.shaped {
1444 r.callShaped(pos)
1445 return true
1446 }
1447
1448 return false
1449 }
1450
1451
1452
1453 func (r *reader) callShaped(pos src.XPos) {
1454 shapedObj := r.dict.shapedObj
1455 assert(shapedObj != nil)
1456
1457 var shapedFn ir.Node
1458 if r.methodSym == nil {
1459
1460 assert(shapedObj.Op() == ir.ONAME && shapedObj.Class == ir.PFUNC)
1461 shapedFn = shapedObj
1462 } else {
1463
1464
1465 shapedFn = shapedMethodExpr(pos, shapedObj, r.methodSym)
1466 }
1467
1468 params := r.syntheticArgs()
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479 var args ir.Nodes
1480 if r.methodSym != nil {
1481 args.Append(params[0])
1482 params = params[1:]
1483 }
1484 args.Append(typecheck.Expr(ir.NewAddrExpr(pos, r.p.dictNameOf(r.dict))))
1485 args.Append(params...)
1486
1487 r.syntheticTailCall(pos, shapedFn, args)
1488 }
1489
1490
1491
1492 func (r *reader) syntheticArgs() ir.Nodes {
1493 sig := r.curfn.Nname.Type()
1494 return ir.ToNodes(r.curfn.Dcl[:sig.NumRecvs()+sig.NumParams()])
1495 }
1496
1497
1498
1499 func (r *reader) syntheticTailCall(pos src.XPos, fn ir.Node, args ir.Nodes) {
1500
1501
1502 r.curfn.SetWrapper(true)
1503
1504 call := typecheck.Call(pos, fn, args, fn.Type().IsVariadic()).(*ir.CallExpr)
1505
1506 var stmt ir.Node
1507 if fn.Type().NumResults() != 0 {
1508 stmt = typecheck.Stmt(ir.NewReturnStmt(pos, []ir.Node{call}))
1509 } else {
1510 stmt = call
1511 }
1512 r.curfn.Body.Append(stmt)
1513 }
1514
1515
1516 func (pr *pkgReader) dictNameOf(dict *readerDict) *ir.Name {
1517 pos := base.AutogeneratedPos
1518
1519
1520 base.AssertfAt(!dict.shaped, pos, "runtime dictionary of shaped object %v", dict.baseSym)
1521
1522 sym := dict.baseSym.Pkg.Lookup(objabi.GlobalDictPrefix + "." + dict.baseSym.Name)
1523 if sym.Def != nil {
1524 return sym.Def.(*ir.Name)
1525 }
1526
1527 name := ir.NewNameAt(pos, sym, dict.varType())
1528 name.Class = ir.PEXTERN
1529 sym.Def = name
1530
1531 lsym := name.Linksym()
1532 ot := 0
1533
1534 assertOffset := func(section string, offset int) {
1535 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)
1536 }
1537
1538 assertOffset("type param method exprs", dict.typeParamMethodExprsOffset())
1539 for _, info := range dict.typeParamMethodExprs {
1540 typeParam := dict.targs[info.typeParamIdx]
1541 method := typecheck.NewMethodExpr(pos, typeParam, info.method)
1542
1543 rsym := method.FuncName().Linksym()
1544 assert(rsym.ABI() == obj.ABIInternal)
1545
1546 ot = objw.SymPtr(lsym, ot, rsym, 0)
1547 }
1548
1549 assertOffset("subdictionaries", dict.subdictsOffset())
1550 for _, info := range dict.subdicts {
1551 explicits := pr.typListIdx(info.explicits, dict)
1552
1553
1554
1555 name := pr.objDictName(info.idx, dict.targs, explicits)
1556
1557 ot = objw.SymPtr(lsym, ot, name.Linksym(), 0)
1558 }
1559
1560 assertOffset("rtypes", dict.rtypesOffset())
1561 for _, info := range dict.rtypes {
1562 typ := pr.typIdx(info, dict, true)
1563 ot = objw.SymPtr(lsym, ot, reflectdata.TypeLinksym(typ), 0)
1564
1565
1566 reflectdata.MarkTypeUsedInInterface(typ, lsym)
1567 }
1568
1569
1570
1571
1572
1573
1574
1575 assertOffset("itabs", dict.itabsOffset())
1576 for _, info := range dict.itabs {
1577 typ := pr.typIdx(info.typ, dict, true)
1578 iface := pr.typIdx(info.iface, dict, true)
1579
1580 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
1581 ot = objw.SymPtr(lsym, ot, reflectdata.ITabLsym(typ, iface), 0)
1582 } else {
1583 ot += types.PtrSize
1584 }
1585
1586
1587 reflectdata.MarkTypeUsedInInterface(typ, lsym)
1588 reflectdata.MarkTypeUsedInInterface(iface, lsym)
1589 }
1590
1591 objw.Global(lsym, int32(ot), obj.DUPOK|obj.RODATA)
1592
1593 return name
1594 }
1595
1596
1597
1598 func (dict *readerDict) typeParamMethodExprsOffset() int {
1599 return 0
1600 }
1601
1602
1603
1604 func (dict *readerDict) subdictsOffset() int {
1605 return dict.typeParamMethodExprsOffset() + len(dict.typeParamMethodExprs)
1606 }
1607
1608
1609
1610 func (dict *readerDict) rtypesOffset() int {
1611 return dict.subdictsOffset() + len(dict.subdicts)
1612 }
1613
1614
1615
1616 func (dict *readerDict) itabsOffset() int {
1617 return dict.rtypesOffset() + len(dict.rtypes)
1618 }
1619
1620
1621
1622 func (dict *readerDict) numWords() int64 {
1623 return int64(dict.itabsOffset() + len(dict.itabs))
1624 }
1625
1626
1627 func (dict *readerDict) varType() *types.Type {
1628 return types.NewArray(types.Types[types.TUINTPTR], dict.numWords())
1629 }
1630
1631 func (r *reader) declareParams() {
1632 r.curfn.DeclareParams(!r.funarghack)
1633
1634 for _, name := range r.curfn.Dcl {
1635 if name.Sym().Name == dictParamName {
1636 r.dictParam = name
1637 continue
1638 }
1639
1640 r.addLocal(name)
1641 }
1642 }
1643
1644 func (r *reader) addLocal(name *ir.Name) {
1645 if r.synthetic == nil {
1646 r.Sync(pkgbits.SyncAddLocal)
1647 if r.p.SyncMarkers() {
1648 want := r.Int()
1649 if have := len(r.locals); have != want {
1650 base.FatalfAt(name.Pos(), "locals table has desynced")
1651 }
1652 }
1653 r.varDictIndex(name)
1654 }
1655
1656 r.locals = append(r.locals, name)
1657 }
1658
1659 func (r *reader) useLocal() *ir.Name {
1660 r.Sync(pkgbits.SyncUseObjLocal)
1661 if r.Bool() {
1662 return r.locals[r.Len()]
1663 }
1664 return r.closureVars[r.Len()]
1665 }
1666
1667 func (r *reader) openScope() {
1668 r.Sync(pkgbits.SyncOpenScope)
1669 pos := r.pos()
1670
1671 if base.Flag.Dwarf {
1672 r.scopeVars = append(r.scopeVars, len(r.curfn.Dcl))
1673 r.marker.Push(pos)
1674 }
1675 }
1676
1677 func (r *reader) closeScope() {
1678 r.Sync(pkgbits.SyncCloseScope)
1679 r.lastCloseScopePos = r.pos()
1680
1681 r.closeAnotherScope()
1682 }
1683
1684
1685
1686
1687
1688 func (r *reader) closeAnotherScope() {
1689 r.Sync(pkgbits.SyncCloseAnotherScope)
1690
1691 if base.Flag.Dwarf {
1692 scopeVars := r.scopeVars[len(r.scopeVars)-1]
1693 r.scopeVars = r.scopeVars[:len(r.scopeVars)-1]
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722 retract := true
1723 for _, n := range r.curfn.Dcl[scopeVars:] {
1724 if !n.AutoTemp() {
1725 retract = false
1726 break
1727 }
1728 }
1729
1730 if retract {
1731
1732 r.marker.Unpush()
1733 } else {
1734 r.marker.Pop(r.lastCloseScopePos)
1735 }
1736 }
1737 }
1738
1739
1740
1741 func (r *reader) stmt() ir.Node {
1742 return block(r.stmts())
1743 }
1744
1745 func block(stmts []ir.Node) ir.Node {
1746 switch len(stmts) {
1747 case 0:
1748 return nil
1749 case 1:
1750 return stmts[0]
1751 default:
1752 return ir.NewBlockStmt(stmts[0].Pos(), stmts)
1753 }
1754 }
1755
1756 func (r *reader) stmts() ir.Nodes {
1757 assert(ir.CurFunc == r.curfn)
1758 var res ir.Nodes
1759
1760 r.Sync(pkgbits.SyncStmts)
1761 for {
1762 tag := codeStmt(r.Code(pkgbits.SyncStmt1))
1763 if tag == stmtEnd {
1764 r.Sync(pkgbits.SyncStmtsEnd)
1765 return res
1766 }
1767
1768 if n := r.stmt1(tag, &res); n != nil {
1769 res.Append(typecheck.Stmt(n))
1770 }
1771 }
1772 }
1773
1774 func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node {
1775 var label *types.Sym
1776 if n := len(*out); n > 0 {
1777 if ls, ok := (*out)[n-1].(*ir.LabelStmt); ok {
1778 label = ls.Label
1779 }
1780 }
1781
1782 switch tag {
1783 default:
1784 panic("unexpected statement")
1785
1786 case stmtAssign:
1787 pos := r.pos()
1788 names, lhs := r.assignList()
1789 rhs := r.multiExpr()
1790
1791 if len(rhs) == 0 {
1792 for _, name := range names {
1793 as := ir.NewAssignStmt(pos, name, nil)
1794 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name))
1795 out.Append(typecheck.Stmt(as))
1796 }
1797 return nil
1798 }
1799
1800 if len(lhs) == 1 && len(rhs) == 1 {
1801 n := ir.NewAssignStmt(pos, lhs[0], rhs[0])
1802 n.Def = r.initDefn(n, names)
1803 return n
1804 }
1805
1806 n := ir.NewAssignListStmt(pos, ir.OAS2, lhs, rhs)
1807 n.Def = r.initDefn(n, names)
1808 return n
1809
1810 case stmtAssignOp:
1811 op := r.op()
1812 lhs := r.expr()
1813 pos := r.pos()
1814 rhs := r.expr()
1815 return ir.NewAssignOpStmt(pos, op, lhs, rhs)
1816
1817 case stmtIncDec:
1818 op := r.op()
1819 lhs := r.expr()
1820 pos := r.pos()
1821 n := ir.NewAssignOpStmt(pos, op, lhs, ir.NewOne(pos, lhs.Type()))
1822 n.IncDec = true
1823 return n
1824
1825 case stmtBlock:
1826 out.Append(r.blockStmt()...)
1827 return nil
1828
1829 case stmtBranch:
1830 pos := r.pos()
1831 op := r.op()
1832 sym := r.optLabel()
1833 return ir.NewBranchStmt(pos, op, sym)
1834
1835 case stmtCall:
1836 pos := r.pos()
1837 op := r.op()
1838 call := r.expr()
1839 stmt := ir.NewGoDeferStmt(pos, op, call)
1840 if op == ir.ODEFER {
1841 x := r.optExpr()
1842 if x != nil {
1843 stmt.DeferAt = x.(ir.Expr)
1844 }
1845 }
1846 return stmt
1847
1848 case stmtExpr:
1849 return r.expr()
1850
1851 case stmtFor:
1852 return r.forStmt(label)
1853
1854 case stmtIf:
1855 return r.ifStmt()
1856
1857 case stmtLabel:
1858 pos := r.pos()
1859 sym := r.label()
1860 return ir.NewLabelStmt(pos, sym)
1861
1862 case stmtReturn:
1863 pos := r.pos()
1864 results := r.multiExpr()
1865 return ir.NewReturnStmt(pos, results)
1866
1867 case stmtSelect:
1868 return r.selectStmt(label)
1869
1870 case stmtSend:
1871 pos := r.pos()
1872 ch := r.expr()
1873 value := r.expr()
1874 return ir.NewSendStmt(pos, ch, value)
1875
1876 case stmtSwitch:
1877 return r.switchStmt(label)
1878 }
1879 }
1880
1881 func (r *reader) assignList() ([]*ir.Name, []ir.Node) {
1882 lhs := make([]ir.Node, r.Len())
1883 var names []*ir.Name
1884
1885 for i := range lhs {
1886 expr, def := r.assign()
1887 lhs[i] = expr
1888 if def {
1889 names = append(names, expr.(*ir.Name))
1890 }
1891 }
1892
1893 return names, lhs
1894 }
1895
1896
1897
1898 func (r *reader) assign() (ir.Node, bool) {
1899 switch tag := codeAssign(r.Code(pkgbits.SyncAssign)); tag {
1900 default:
1901 panic("unhandled assignee expression")
1902
1903 case assignBlank:
1904 return typecheck.AssignExpr(ir.BlankNode), false
1905
1906 case assignDef:
1907 pos := r.pos()
1908 setBasePos(pos)
1909 name := r.curfn.NewLocal(pos, r.localIdent(), r.typ())
1910 r.addLocal(name)
1911 return name, true
1912
1913 case assignExpr:
1914 return r.expr(), false
1915 }
1916 }
1917
1918 func (r *reader) blockStmt() []ir.Node {
1919 r.Sync(pkgbits.SyncBlockStmt)
1920 r.openScope()
1921 stmts := r.stmts()
1922 r.closeScope()
1923 return stmts
1924 }
1925
1926 func (r *reader) forStmt(label *types.Sym) ir.Node {
1927 r.Sync(pkgbits.SyncForStmt)
1928
1929 r.openScope()
1930
1931 if r.Bool() {
1932 pos := r.pos()
1933 rang := ir.NewRangeStmt(pos, nil, nil, nil, nil, false)
1934 rang.Label = label
1935
1936 names, lhs := r.assignList()
1937 if len(lhs) >= 1 {
1938 rang.Key = lhs[0]
1939 if len(lhs) >= 2 {
1940 rang.Value = lhs[1]
1941 }
1942 }
1943 rang.Def = r.initDefn(rang, names)
1944
1945 rang.X = r.expr()
1946 if rang.X.Type().IsMap() {
1947 rang.RType = r.rtype(pos)
1948 }
1949 if rang.Key != nil && !ir.IsBlank(rang.Key) {
1950 rang.KeyTypeWord, rang.KeySrcRType = r.convRTTI(pos)
1951 }
1952 if rang.Value != nil && !ir.IsBlank(rang.Value) {
1953 rang.ValueTypeWord, rang.ValueSrcRType = r.convRTTI(pos)
1954 }
1955
1956 rang.Body = r.blockStmt()
1957 rang.DistinctVars = r.Bool()
1958 r.closeAnotherScope()
1959
1960 return rang
1961 }
1962
1963 pos := r.pos()
1964 init := r.stmt()
1965 cond := r.optExpr()
1966 post := r.stmt()
1967 body := r.blockStmt()
1968 perLoopVars := r.Bool()
1969 r.closeAnotherScope()
1970
1971 if ir.IsConst(cond, constant.Bool) && !ir.BoolVal(cond) {
1972 return init
1973 }
1974
1975 stmt := ir.NewForStmt(pos, init, cond, post, body, perLoopVars)
1976 stmt.Label = label
1977 return stmt
1978 }
1979
1980 func (r *reader) ifStmt() ir.Node {
1981 r.Sync(pkgbits.SyncIfStmt)
1982 r.openScope()
1983 pos := r.pos()
1984 init := r.stmts()
1985 cond := r.expr()
1986 staticCond := r.Int()
1987 var then, els []ir.Node
1988 if staticCond >= 0 {
1989 then = r.blockStmt()
1990 } else {
1991 r.lastCloseScopePos = r.pos()
1992 }
1993 if staticCond <= 0 {
1994 els = r.stmts()
1995 }
1996 r.closeAnotherScope()
1997
1998 if staticCond != 0 {
1999
2000
2001
2002
2003 if cond.Op() != ir.OLITERAL {
2004 init.Append(typecheck.Stmt(ir.NewAssignStmt(pos, ir.BlankNode, cond)))
2005 }
2006 init.Append(then...)
2007 init.Append(els...)
2008 return block(init)
2009 }
2010
2011 n := ir.NewIfStmt(pos, cond, then, els)
2012 n.SetInit(init)
2013 return n
2014 }
2015
2016 func (r *reader) selectStmt(label *types.Sym) ir.Node {
2017 r.Sync(pkgbits.SyncSelectStmt)
2018
2019 pos := r.pos()
2020 clauses := make([]*ir.CommClause, r.Len())
2021 for i := range clauses {
2022 if i > 0 {
2023 r.closeScope()
2024 }
2025 r.openScope()
2026
2027 pos := r.pos()
2028 comm := r.stmt()
2029 body := r.stmts()
2030
2031
2032
2033
2034
2035
2036 if as, ok := comm.(*ir.AssignStmt); ok && as.Op() == ir.OAS && !as.Def {
2037 if conv, ok := as.Y.(*ir.ConvExpr); ok && conv.Op() == ir.OCONVIFACE {
2038 base.AssertfAt(conv.Implicit(), conv.Pos(), "expected implicit conversion: %v", conv)
2039
2040 recv := conv.X
2041 base.AssertfAt(recv.Op() == ir.ORECV, recv.Pos(), "expected receive expression: %v", recv)
2042
2043 tmp := r.temp(pos, recv.Type())
2044
2045
2046 tmpAs := ir.NewAssignStmt(pos, tmp, recv)
2047 tmpAs.Def = true
2048 tmpAs.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
2049 comm = tmpAs
2050
2051
2052 conv.X = tmp
2053 body = append([]ir.Node{as}, body...)
2054 }
2055 }
2056
2057
2058
2059
2060
2061 if as2, ok := comm.(*ir.AssignListStmt); ok && as2.Op() == ir.OAS2 {
2062 init := ir.TakeInit(as2.Rhs[0])
2063 base.AssertfAt(len(init) == 1 && init[0].Op() == ir.OAS2RECV, as2.Pos(), "unexpected assignment: %+v", as2)
2064
2065 comm = init[0]
2066 body = append([]ir.Node{as2}, body...)
2067 }
2068
2069 clauses[i] = ir.NewCommStmt(pos, comm, body)
2070 }
2071 if len(clauses) > 0 {
2072 r.closeScope()
2073 }
2074 n := ir.NewSelectStmt(pos, clauses)
2075 n.Label = label
2076 return n
2077 }
2078
2079 func (r *reader) switchStmt(label *types.Sym) ir.Node {
2080 r.Sync(pkgbits.SyncSwitchStmt)
2081
2082 r.openScope()
2083 pos := r.pos()
2084 init := r.stmt()
2085
2086 var tag ir.Node
2087 var ident *ir.Ident
2088 var iface *types.Type
2089 if r.Bool() {
2090 pos := r.pos()
2091 if r.Bool() {
2092 ident = ir.NewIdent(r.pos(), r.localIdent())
2093 }
2094 x := r.expr()
2095 iface = x.Type()
2096 tag = ir.NewTypeSwitchGuard(pos, ident, x)
2097 } else {
2098 tag = r.optExpr()
2099 }
2100
2101 clauses := make([]*ir.CaseClause, r.Len())
2102 for i := range clauses {
2103 if i > 0 {
2104 r.closeScope()
2105 }
2106 r.openScope()
2107
2108 pos := r.pos()
2109 var cases, rtypes []ir.Node
2110 if iface != nil {
2111 cases = make([]ir.Node, r.Len())
2112 if len(cases) == 0 {
2113 cases = nil
2114 }
2115 for i := range cases {
2116 if r.Bool() {
2117 cases[i] = typecheck.Expr(types.BuiltinPkg.Lookup("nil").Def.(*ir.NilExpr))
2118 } else {
2119 cases[i] = r.exprType()
2120 }
2121 }
2122 } else {
2123 cases = r.exprList()
2124
2125
2126
2127
2128
2129
2130
2131
2132 if tag == nil {
2133 for i, cas := range cases {
2134 if cas.Type().IsEmptyInterface() {
2135 for len(rtypes) < i {
2136 rtypes = append(rtypes, nil)
2137 }
2138 rtypes = append(rtypes, reflectdata.TypePtrAt(cas.Pos(), types.Types[types.TBOOL]))
2139 }
2140 }
2141 }
2142 }
2143
2144 clause := ir.NewCaseStmt(pos, cases, nil)
2145 clause.RTypes = rtypes
2146
2147 if ident != nil {
2148 name := r.curfn.NewLocal(r.pos(), ident.Sym(), r.typ())
2149 r.addLocal(name)
2150 clause.Var = name
2151 name.Defn = tag
2152 }
2153
2154 clause.Body = r.stmts()
2155 clauses[i] = clause
2156 }
2157 if len(clauses) > 0 {
2158 r.closeScope()
2159 }
2160 r.closeScope()
2161
2162 n := ir.NewSwitchStmt(pos, tag, clauses)
2163 n.Label = label
2164 if init != nil {
2165 n.SetInit([]ir.Node{init})
2166 }
2167 return n
2168 }
2169
2170 func (r *reader) label() *types.Sym {
2171 r.Sync(pkgbits.SyncLabel)
2172 name := r.String()
2173 if r.inlCall != nil && name != "_" {
2174 name = fmt.Sprintf("~%s·%d", name, inlgen)
2175 }
2176 return typecheck.Lookup(name)
2177 }
2178
2179 func (r *reader) optLabel() *types.Sym {
2180 r.Sync(pkgbits.SyncOptLabel)
2181 if r.Bool() {
2182 return r.label()
2183 }
2184 return nil
2185 }
2186
2187
2188
2189
2190 func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool {
2191 if len(names) == 0 {
2192 return false
2193 }
2194
2195 init := make([]ir.Node, len(names))
2196 for i, name := range names {
2197 name.Defn = defn
2198 init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name)
2199 }
2200 defn.SetInit(init)
2201 return true
2202 }
2203
2204
2205
2206
2207 func (r *reader) expr() (res ir.Node) {
2208 defer func() {
2209 if res != nil && res.Typecheck() == 0 {
2210 base.FatalfAt(res.Pos(), "%v missed typecheck", res)
2211 }
2212 }()
2213
2214 switch tag := codeExpr(r.Code(pkgbits.SyncExpr)); tag {
2215 default:
2216 panic("unhandled expression")
2217
2218 case exprLocal:
2219 return typecheck.Expr(r.useLocal())
2220
2221 case exprGlobal:
2222
2223
2224 return typecheck.Callee(r.obj())
2225
2226 case exprFuncInst:
2227 origPos, pos := r.origPos()
2228 wrapperFn, baseFn, dictPtr := r.funcInst(pos)
2229 if wrapperFn != nil {
2230 return wrapperFn
2231 }
2232 return r.curry(origPos, false, baseFn, dictPtr, nil)
2233
2234 case exprConst:
2235 pos := r.pos()
2236 typ := r.typ()
2237 val := FixValue(typ, r.Value())
2238 return ir.NewBasicLit(pos, typ, val)
2239
2240 case exprZero:
2241 pos := r.pos()
2242 typ := r.typ()
2243 return ir.NewZero(pos, typ)
2244
2245 case exprCompLit:
2246 return r.compLit()
2247
2248 case exprFuncLit:
2249 return r.funcLit()
2250
2251 case exprFieldVal:
2252 x := r.expr()
2253 pos := r.pos()
2254 sym := r.selector()
2255
2256 return typecheck.XDotField(pos, x, sym)
2257
2258 case exprMethodVal:
2259 recv := r.expr()
2260 origPos, pos := r.origPos()
2261 wrapperFn, baseFn, dictPtr := r.methodExpr()
2262
2263
2264
2265 if wrapperFn, ok := wrapperFn.(*ir.SelectorExpr); ok && wrapperFn.Op() == ir.OMETHEXPR {
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283 if recv.Type().HasShape() {
2284 typ := wrapperFn.Type().Param(0).Type
2285 if !types.Identical(typ, recv.Type()) {
2286 base.FatalfAt(wrapperFn.Pos(), "receiver %L does not match %L", recv, wrapperFn)
2287 }
2288 recv = typecheck.Expr(ir.NewConvExpr(recv.Pos(), ir.OCONVNOP, typ, recv))
2289 }
2290
2291 n := typecheck.XDotMethod(pos, recv, wrapperFn.Sel, false)
2292
2293
2294
2295
2296
2297
2298
2299 if n.Selection != wrapperFn.Selection {
2300 assert(n.Selection.Sym == wrapperFn.Selection.Sym)
2301 assert(types.Identical(n.Selection.Type, wrapperFn.Selection.Type))
2302 assert(types.Identical(n.Selection.Type.Recv().Type, wrapperFn.Selection.Type.Recv().Type))
2303 }
2304
2305 wrapper := methodValueWrapper{
2306 rcvr: n.X.Type(),
2307 method: n.Selection,
2308 }
2309
2310 if r.importedDef() {
2311 haveMethodValueWrappers = append(haveMethodValueWrappers, wrapper)
2312 } else {
2313 needMethodValueWrappers = append(needMethodValueWrappers, wrapper)
2314 }
2315 return n
2316 }
2317
2318
2319
2320 return r.curry(origPos, true, baseFn, recv, dictPtr)
2321
2322 case exprMethodExpr:
2323 recv := r.typ()
2324
2325 implicits := make([]int, r.Len())
2326 for i := range implicits {
2327 implicits[i] = r.Len()
2328 }
2329 var deref, addr bool
2330 if r.Bool() {
2331 deref = true
2332 } else if r.Bool() {
2333 addr = true
2334 }
2335
2336 origPos, pos := r.origPos()
2337 wrapperFn, baseFn, dictPtr := r.methodExpr()
2338
2339
2340
2341
2342
2343
2344
2345 if wrapperFn != nil && len(implicits) == 0 && !deref && !addr {
2346 if !types.Identical(recv, wrapperFn.Type().Param(0).Type) {
2347 base.FatalfAt(pos, "want receiver type %v, but have method %L", recv, wrapperFn)
2348 }
2349 return wrapperFn
2350 }
2351
2352
2353
2354
2355 if method, ok := wrapperFn.(*ir.SelectorExpr); ok && method.Op() == ir.OMETHEXPR && !recv.HasShape() {
2356 return typecheck.NewMethodExpr(pos, recv, method.Sel)
2357 }
2358
2359 return r.methodExprWrap(origPos, recv, implicits, deref, addr, baseFn, dictPtr)
2360
2361 case exprIndex:
2362 x := r.expr()
2363 pos := r.pos()
2364 index := r.expr()
2365 n := typecheck.Expr(ir.NewIndexExpr(pos, x, index))
2366 switch n.Op() {
2367 case ir.OINDEXMAP:
2368 n := n.(*ir.IndexExpr)
2369 n.RType = r.rtype(pos)
2370 }
2371 return n
2372
2373 case exprSlice:
2374 x := r.expr()
2375 pos := r.pos()
2376 var index [3]ir.Node
2377 for i := range index {
2378 index[i] = r.optExpr()
2379 }
2380 op := ir.OSLICE
2381 if index[2] != nil {
2382 op = ir.OSLICE3
2383 }
2384 return typecheck.Expr(ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2]))
2385
2386 case exprAssert:
2387 x := r.expr()
2388 pos := r.pos()
2389 typ := r.exprType()
2390 srcRType := r.rtype(pos)
2391
2392
2393 if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE {
2394 assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType)
2395 assert.SrcRType = srcRType
2396 assert.ITab = typ.ITab
2397 return typed(typ.Type(), assert)
2398 }
2399 return typecheck.Expr(ir.NewTypeAssertExpr(pos, x, typ.Type()))
2400
2401 case exprUnaryOp:
2402 op := r.op()
2403 pos := r.pos()
2404 x := r.expr()
2405
2406 switch op {
2407 case ir.OADDR:
2408 return typecheck.Expr(typecheck.NodAddrAt(pos, x))
2409 case ir.ODEREF:
2410 return typecheck.Expr(ir.NewStarExpr(pos, x))
2411 }
2412 return typecheck.Expr(ir.NewUnaryExpr(pos, op, x))
2413
2414 case exprBinaryOp:
2415 op := r.op()
2416 x := r.expr()
2417 pos := r.pos()
2418 y := r.expr()
2419
2420 switch op {
2421 case ir.OANDAND, ir.OOROR:
2422 return typecheck.Expr(ir.NewLogicalExpr(pos, op, x, y))
2423 case ir.OLSH, ir.ORSH:
2424
2425
2426 if ir.IsConstNode(y) {
2427 val := constant.ToInt(y.Val())
2428 assert(val.Kind() == constant.Int && constant.Sign(val) >= 0)
2429 }
2430 }
2431 return typecheck.Expr(ir.NewBinaryExpr(pos, op, x, y))
2432
2433 case exprRecv:
2434 x := r.expr()
2435 pos := r.pos()
2436 for i, n := 0, r.Len(); i < n; i++ {
2437 x = Implicit(typecheck.DotField(pos, x, r.Len()))
2438 }
2439 if r.Bool() {
2440 x = Implicit(Deref(pos, x.Type().Elem(), x))
2441 } else if r.Bool() {
2442 x = Implicit(Addr(pos, x))
2443 }
2444 return x
2445
2446 case exprCall:
2447 var fun ir.Node
2448 var args ir.Nodes
2449 if r.Bool() {
2450 recv := r.expr()
2451 _, method, dictPtr := r.methodExpr()
2452
2453 if recv.Type().IsInterface() && method.Op() == ir.OMETHEXPR {
2454 method := method.(*ir.SelectorExpr)
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464 fun = typecheck.XDotMethod(method.Pos(), recv, method.Sel, true)
2465 } else {
2466 if recv.Type().IsInterface() {
2467
2468
2469 if base.Flag.LowerM != 0 {
2470 base.WarnfAt(method.Pos(), "imprecise interface call")
2471 }
2472 }
2473
2474 fun = method
2475 args.Append(recv)
2476 }
2477 if dictPtr != nil {
2478 args.Append(dictPtr)
2479 }
2480 } else if r.Bool() {
2481 pos := r.pos()
2482 _, shapedFn, dictPtr := r.funcInst(pos)
2483 fun = shapedFn
2484 args.Append(dictPtr)
2485 } else {
2486 fun = r.expr()
2487 }
2488 pos := r.pos()
2489 args.Append(r.multiExpr()...)
2490 dots := r.Bool()
2491 n := typecheck.Call(pos, fun, args, dots)
2492 switch n.Op() {
2493 case ir.OAPPEND:
2494 n := n.(*ir.CallExpr)
2495 n.RType = r.rtype(pos)
2496
2497
2498 if n.IsDDD {
2499 if conv, ok := n.Args[1].(*ir.ConvExpr); ok && conv.Op() == ir.OCONVNOP && conv.Implicit() {
2500 n.Args[1] = conv.X
2501 }
2502 }
2503 case ir.OCOPY:
2504 n := n.(*ir.BinaryExpr)
2505 n.RType = r.rtype(pos)
2506 case ir.ODELETE:
2507 n := n.(*ir.CallExpr)
2508 n.RType = r.rtype(pos)
2509 case ir.OUNSAFESLICE:
2510 n := n.(*ir.BinaryExpr)
2511 n.RType = r.rtype(pos)
2512 }
2513 return n
2514
2515 case exprMake:
2516 pos := r.pos()
2517 typ := r.exprType()
2518 extra := r.exprs()
2519 n := typecheck.Expr(ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr)
2520 n.RType = r.rtype(pos)
2521 return n
2522
2523 case exprNew:
2524 pos := r.pos()
2525 if r.Bool() {
2526
2527 x := r.expr()
2528 x = typecheck.DefaultLit(x, nil)
2529 var init ir.Nodes
2530 addr := ir.NewAddrExpr(pos, r.tempCopy(pos, x, &init))
2531 addr.SetInit(init)
2532 return typecheck.Expr(addr)
2533 }
2534
2535 return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, r.exprType()))
2536
2537 case exprSizeof:
2538 return ir.NewUintptr(r.pos(), r.typ().Size())
2539
2540 case exprAlignof:
2541 return ir.NewUintptr(r.pos(), r.typ().Alignment())
2542
2543 case exprOffsetof:
2544 pos := r.pos()
2545 typ := r.typ()
2546 types.CalcSize(typ)
2547
2548 var offset int64
2549 for i := r.Len(); i >= 0; i-- {
2550 field := typ.Field(r.Len())
2551 offset += field.Offset
2552 typ = field.Type
2553 }
2554
2555 return ir.NewUintptr(pos, offset)
2556
2557 case exprReshape:
2558 typ := r.typ()
2559 x := r.expr()
2560
2561 if types.IdenticalStrict(x.Type(), typ) {
2562 return x
2563 }
2564
2565
2566
2567
2568
2569
2570 if x.Type() == types.UntypedBool && typ.IsBoolean() {
2571 return x
2572 }
2573
2574 base.AssertfAt(x.Type().HasShape() || typ.HasShape(), x.Pos(), "%L and %v are not shape types", x, typ)
2575 base.AssertfAt(types.Identical(x.Type(), typ), x.Pos(), "%L is not shape-identical to %v", x, typ)
2576
2577
2578
2579
2580
2581
2582
2583 base.AssertfAt(ir.HasUniquePos(x), x.Pos(), "cannot call SetType(%v) on %L", typ, x)
2584
2585 if base.Debug.Reshape != 0 {
2586 base.WarnfAt(x.Pos(), "reshaping %L to %v", x, typ)
2587 }
2588
2589 x.SetType(typ)
2590
2591 if call, ok := x.(*ir.CallExpr); ok {
2592 call.Reshape = true
2593 }
2594
2595 return x
2596
2597 case exprConvert:
2598 implicit := r.Bool()
2599 typ := r.typ()
2600 pos := r.pos()
2601 typeWord, srcRType := r.convRTTI(pos)
2602 dstTypeParam := r.Bool()
2603 identical := r.Bool()
2604 x := r.expr()
2605
2606
2607
2608 if dstTypeParam && ir.IsConstNode(x) {
2609
2610 if v := typecheck.ConvertVal(x.Val(), typ, false); v.Kind() != constant.Unknown {
2611 x = ir.NewBasicLit(x.Pos(), typ, v)
2612
2613 n := Implicit(ir.NewConvExpr(pos, ir.OCONVNOP, typ, x))
2614 n.SetTypecheck(1)
2615 return n
2616 }
2617
2618
2619
2620 }
2621
2622
2623 x = typecheck.DefaultLit(x, typ)
2624
2625 ce := ir.NewConvExpr(pos, ir.OCONV, typ, x)
2626 ce.TypeWord, ce.SrcRType = typeWord, srcRType
2627 if implicit {
2628 ce.SetImplicit(true)
2629 }
2630 n := typecheck.Expr(ce)
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648 if !identical {
2649 if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) {
2650 n.SetOp(ir.OCONVIFACE)
2651 }
2652 }
2653
2654 return n
2655
2656 case exprRuntimeBuiltin:
2657 builtin := typecheck.LookupRuntime(r.String())
2658 return builtin
2659 }
2660 }
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684 func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) {
2685
2686 var implicits []*types.Type
2687 if r.dict != nil {
2688 implicits = r.dict.targs
2689 }
2690
2691 if r.Bool() {
2692 idx := r.Len()
2693 info := r.dict.subdicts[idx]
2694 explicits := r.p.typListIdx(info.explicits, r.dict)
2695
2696 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2697
2698
2699
2700 dictPtrType := baseFn.Type().Param(0).Type
2701 dictPtr = typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2702
2703 return
2704 }
2705
2706 info := r.objInfo()
2707 explicits := r.p.typListIdx(info.explicits, r.dict)
2708
2709 wrapperFn = r.p.objIdx(info.idx, implicits, explicits, false).(*ir.Name)
2710 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2711
2712 dictName := r.p.objDictName(info.idx, implicits, explicits)
2713 dictPtr = typecheck.Expr(ir.NewAddrExpr(pos, dictName))
2714
2715 return
2716 }
2717
2718 func (pr *pkgReader) objDictName(idx index, implicits, explicits []*types.Type) *ir.Name {
2719 rname := pr.newReader(pkgbits.SectionName, idx, pkgbits.SyncObject1)
2720 _, sym := rname.qualifiedIdent()
2721 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
2722
2723 if tag == pkgbits.ObjStub {
2724 assert(!sym.IsBlank())
2725 if pri, ok := objReader[sym]; ok {
2726 return pri.pr.objDictName(pri.idx, nil, explicits)
2727 }
2728 base.Fatalf("unresolved stub: %v", sym)
2729 }
2730
2731 dict, err := pr.objDictIdx(sym, idx, implicits, explicits, false)
2732 if err != nil {
2733 base.Fatalf("%v", err)
2734 }
2735
2736 return pr.dictNameOf(dict)
2737 }
2738
2739
2740
2741
2742
2743
2744
2745
2746 func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node {
2747 var captured ir.Nodes
2748 captured.Append(fun, arg0)
2749 if arg1 != nil {
2750 captured.Append(arg1)
2751 }
2752
2753 params, results := syntheticSig(fun.Type())
2754 params = params[len(captured)-1:]
2755 typ := types.NewSignature(nil, params, results)
2756
2757 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2758 fun := captured[0]
2759
2760 var args ir.Nodes
2761 args.Append(captured[1:]...)
2762 args.Append(r.syntheticArgs()...)
2763
2764 r.syntheticTailCall(pos, fun, args)
2765 }
2766
2767 return r.syntheticClosure(origPos, typ, ifaceHack, captured, addBody)
2768 }
2769
2770
2771
2772
2773 func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node {
2774 var captured ir.Nodes
2775 captured.Append(method)
2776
2777 params, results := syntheticSig(method.Type())
2778
2779
2780 params[0].Type = recv
2781
2782
2783
2784
2785 if dictPtr != nil {
2786 captured.Append(dictPtr)
2787 params = append(params[:1], params[2:]...)
2788 }
2789
2790 typ := types.NewSignature(nil, params, results)
2791
2792 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2793 fn := captured[0]
2794 args := r.syntheticArgs()
2795
2796
2797 {
2798 arg := args[0]
2799 for _, ix := range implicits {
2800 arg = Implicit(typecheck.DotField(pos, arg, ix))
2801 }
2802 if deref {
2803 arg = Implicit(Deref(pos, arg.Type().Elem(), arg))
2804 } else if addr {
2805 arg = Implicit(Addr(pos, arg))
2806 }
2807 args[0] = arg
2808 }
2809
2810
2811 if dictPtr != nil {
2812 newArgs := make([]ir.Node, len(args)+1)
2813 newArgs[0] = args[0]
2814 newArgs[1] = captured[1]
2815 copy(newArgs[2:], args[1:])
2816 args = newArgs
2817 }
2818
2819 r.syntheticTailCall(pos, fn, args)
2820 }
2821
2822 return r.syntheticClosure(origPos, typ, false, captured, addBody)
2823 }
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839 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 {
2840
2841
2842
2843
2844
2845 isSafe := func(n ir.Node) bool {
2846 if n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PFUNC {
2847 return true
2848 }
2849 if n.Op() == ir.OMETHEXPR {
2850 return true
2851 }
2852
2853 return false
2854 }
2855
2856 fn := r.inlClosureFunc(origPos, typ, ir.OCLOSURE)
2857 fn.SetWrapper(true)
2858
2859 clo := fn.OClosure
2860 inlPos := clo.Pos()
2861
2862 var init ir.Nodes
2863 for i, n := range captures {
2864 if isSafe(n) {
2865 continue
2866 }
2867
2868 tmp := r.tempCopy(inlPos, n, &init)
2869 ir.NewClosureVar(origPos, fn, tmp)
2870
2871
2872
2873 if ifaceHack && i == 1 && n.Type().IsInterface() {
2874 check := ir.NewUnaryExpr(inlPos, ir.OCHECKNIL, ir.NewUnaryExpr(inlPos, ir.OITAB, tmp))
2875 init.Append(typecheck.Stmt(check))
2876 }
2877 }
2878
2879 pri := pkgReaderIndex{synthetic: func(pos src.XPos, r *reader) {
2880 captured := make([]ir.Node, len(captures))
2881 next := 0
2882 for i, n := range captures {
2883 if isSafe(n) {
2884 captured[i] = n
2885 } else {
2886 captured[i] = r.closureVars[next]
2887 next++
2888 }
2889 }
2890 assert(next == len(r.closureVars))
2891
2892 addBody(origPos, r, captured)
2893 }}
2894 bodyReader[fn] = pri
2895 pri.funcBody(fn)
2896
2897 return ir.InitExpr(init, clo)
2898 }
2899
2900
2901
2902
2903 func syntheticSig(sig *types.Type) (params, results []*types.Field) {
2904 clone := func(params []*types.Field) []*types.Field {
2905 res := make([]*types.Field, len(params))
2906 for i, param := range params {
2907
2908
2909
2910
2911
2912
2913 res[i] = types.NewField(base.AutogeneratedPos, param.Sym, param.Type)
2914 res[i].SetIsDDD(param.IsDDD())
2915 }
2916 return res
2917 }
2918
2919 return clone(sig.Params()), clone(sig.Results())
2920 }
2921
2922 func (r *reader) optExpr() ir.Node {
2923 if r.Bool() {
2924 return r.expr()
2925 }
2926 return nil
2927 }
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952 func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) {
2953 recv := r.typ()
2954
2955 var sig *types.Type
2956 generic := r.Version().Has(pkgbits.GenericMethods) && r.Bool()
2957 if !generic {
2958
2959
2960 sig = typecheck.NewMethodType(r.typ(), recv)
2961 }
2962
2963 pos := r.pos()
2964 sym := r.selector()
2965
2966 if r.Bool() {
2967 idx := r.Len()
2968 word := r.dictWord(pos, r.dict.typeParamMethodExprsOffset()+idx)
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979 fn := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, sig, ir.NewAddrExpr(pos, word)))
2980 return fn, fn, nil
2981 }
2982
2983 if r.Bool() {
2984 idx := r.Len()
2985 info := r.dict.subdicts[idx]
2986 explicits := r.p.typListIdx(info.explicits, r.dict)
2987
2988 shapedObj := r.p.objIdx(info.idx, nil, explicits, true).(*ir.Name)
2989 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
2990
2991
2992
2993 dictPtrType := shapedFn.Type().Param(1).Type
2994 dictPtr := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2995
2996 return nil, shapedFn, dictPtr
2997 }
2998
2999 if r.Bool() {
3000 info := r.objInfo()
3001 explicits := r.p.typListIdx(info.explicits, r.dict)
3002
3003 shapedObj := r.p.objIdx(info.idx, nil, explicits, true).(*ir.Name)
3004 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
3005
3006 dict := r.p.objDictName(info.idx, nil, explicits)
3007 dictPtr := typecheck.Expr(ir.NewAddrExpr(pos, dict))
3008
3009
3010 if !types.Identical(dictPtr.Type(), shapedFn.Type().Param(1).Type) {
3011 base.FatalfAt(pos, "dict %L, but shaped method %L", dict, shapedFn)
3012 }
3013
3014 if !generic {
3015
3016
3017 base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv)
3018 wrapperFn := typecheck.NewMethodExpr(pos, recv, sym)
3019 base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig)
3020 return wrapperFn, shapedFn, dictPtr
3021 } else {
3022
3023
3024
3025
3026 return nil, shapedFn, dictPtr
3027 }
3028 }
3029
3030
3031 base.AssertfAt(!recv.HasShape() || recv.IsInterface(), pos, "shaped receiver %v", recv)
3032 fn := typecheck.NewMethodExpr(pos, recv, sym)
3033 return fn, fn, nil
3034 }
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058 func shapedMethodExpr(pos src.XPos, obj *ir.Name, sym *types.Sym) ir.Node {
3059 if obj.Op() == ir.OTYPE {
3060
3061 typ := obj.Type()
3062 assert(typ.HasShape())
3063
3064 method := func() *types.Field {
3065 for _, m := range typ.Methods() {
3066 if m.Sym == sym {
3067 return m
3068 }
3069 }
3070
3071 base.FatalfAt(pos, "failed to find method %v in shaped type %v", sym, typ)
3072 panic("unreachable")
3073 }()
3074
3075 return typecheck.NewMethodExpr(pos, method.Type.Recv().Type, sym)
3076 } else {
3077
3078 assert(obj.Op() == ir.ONAME && obj.Class == ir.PFUNC)
3079 typ := obj.Type()
3080 assert(typ.HasShape())
3081
3082
3083
3084
3085
3086
3087
3088 lsym := obj.Linksym().Name
3089
3090
3091 idx := func() int {
3092 depth, i := 0, len(lsym)-1
3093 for {
3094 switch lsym[i] {
3095 case ']':
3096 depth++
3097 case '[':
3098 depth--
3099 }
3100 if depth == 0 {
3101 return i
3102 }
3103 i--
3104 }
3105 }()
3106 msym := sym.Pkg.Lookup(lsym[idx-len(sym.Name):])
3107
3108
3109
3110 m := types.NewField(obj.Pos(), msym, typ)
3111 m.Nname = obj
3112
3113 n := ir.NewSelectorExpr(pos, ir.OMETHEXPR, ir.TypeNode(typ.Recv().Type), msym)
3114 n.Selection = m
3115 n.SetType(typecheck.NewMethodType(typ, typ.Recv().Type))
3116 n.SetTypecheck(1)
3117
3118 return n
3119 }
3120 }
3121
3122 func (r *reader) multiExpr() []ir.Node {
3123 r.Sync(pkgbits.SyncMultiExpr)
3124
3125 if r.Bool() {
3126 pos := r.pos()
3127 expr := r.expr()
3128
3129 results := make([]ir.Node, r.Len())
3130 as := ir.NewAssignListStmt(pos, ir.OAS2, nil, []ir.Node{expr})
3131 as.Def = true
3132 for i := range results {
3133 tmp := r.temp(pos, r.typ())
3134 tmp.Defn = as
3135 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
3136 as.Lhs.Append(tmp)
3137
3138 res := ir.Node(tmp)
3139 if r.Bool() {
3140 n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)
3141 n.TypeWord, n.SrcRType = r.convRTTI(pos)
3142 n.SetImplicit(true)
3143 res = typecheck.Expr(n)
3144 }
3145 results[i] = res
3146 }
3147
3148
3149 results[0] = ir.InitExpr([]ir.Node{typecheck.Stmt(as)}, results[0])
3150 return results
3151 }
3152
3153
3154 exprs := make([]ir.Node, r.Len())
3155 if len(exprs) == 0 {
3156 return nil
3157 }
3158 for i := range exprs {
3159 exprs[i] = r.expr()
3160 }
3161 return exprs
3162 }
3163
3164
3165 func (r *reader) temp(pos src.XPos, typ *types.Type) *ir.Name {
3166 return typecheck.TempAt(pos, r.curfn, typ)
3167 }
3168
3169
3170
3171 func (r *reader) tempCopy(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name {
3172 tmp := r.temp(pos, expr.Type())
3173
3174 init.Append(typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)))
3175
3176 assign := ir.NewAssignStmt(pos, tmp, expr)
3177 assign.Def = true
3178 init.Append(typecheck.Stmt(assign))
3179
3180 tmp.Defn = assign
3181
3182 return tmp
3183 }
3184
3185 func (r *reader) compLit() ir.Node {
3186 r.Sync(pkgbits.SyncCompLit)
3187 pos := r.pos()
3188 typ0 := r.typ()
3189
3190 typ := typ0
3191 if typ.IsPtr() {
3192 typ = typ.Elem()
3193 }
3194 if typ.Kind() == types.TFORW {
3195 base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
3196 }
3197 var rtype ir.Node
3198 if typ.IsMap() {
3199 rtype = r.rtype(pos)
3200 }
3201
3202 var elems []ir.Node
3203 if r.Version().Has(pkgbits.CompactCompLiterals) {
3204 n := r.Int()
3205 elems = make([]ir.Node, max(n, -n) )
3206 switch typ.Kind() {
3207 default:
3208 base.FatalfAt(pos, "unexpected composite literal type: %v", typ)
3209 case types.TARRAY:
3210 r.arrayElems(n >= 0, elems)
3211 case types.TMAP:
3212 r.mapElems(elems)
3213 case types.TSLICE:
3214 r.arrayElems(n >= 0, elems)
3215 case types.TSTRUCT:
3216 r.structElems(typ, n >= 0, elems)
3217 }
3218 } else {
3219 elems = make([]ir.Node, r.Len())
3220 isStruct := typ.Kind() == types.TSTRUCT
3221 for i := range elems {
3222 elemp := &elems[i]
3223 if isStruct {
3224 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.Len()), nil)
3225 *elemp, elemp = sk, &sk.Value
3226 } else if r.Bool() {
3227 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3228 *elemp, elemp = kv, &kv.Value
3229 }
3230 *elemp = r.expr()
3231 }
3232 }
3233
3234 lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems))
3235 if rtype != nil {
3236 lit := lit.(*ir.CompLitExpr)
3237 lit.RType = rtype
3238 }
3239 if typ0.IsPtr() {
3240 lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit))
3241 lit.SetType(typ0)
3242 }
3243 return lit
3244 }
3245
3246 func (r *reader) arrayElems(valuesOnly bool, elems []ir.Node) {
3247 if valuesOnly {
3248 for i := range elems {
3249 elems[i] = r.expr()
3250 }
3251 return
3252 }
3253
3254 for i := range elems {
3255 if r.Bool() {
3256 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3257 kv.Value = r.expr()
3258 elems[i] = kv
3259 } else {
3260 elems[i] = r.expr()
3261 }
3262 }
3263 }
3264
3265 func (r *reader) mapElems(elems []ir.Node) {
3266
3267 for i := range elems {
3268 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3269 kv.Value = r.expr()
3270 elems[i] = kv
3271 }
3272 }
3273
3274 func (r *reader) structElems(typ *types.Type, valuesOnly bool, elems []ir.Node) {
3275 if valuesOnly {
3276 for i := range elems {
3277 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(i), nil)
3278 sk.Value = r.expr()
3279 elems[i] = sk
3280 }
3281 return
3282 }
3283
3284
3285 for i := range elems {
3286 pos := r.pos()
3287 var fld *types.Field
3288 if n := r.Int(); n < 0 {
3289
3290 typ := typ
3291 for range -n {
3292 fld = typ.Field(r.Int())
3293 typ = fld.Type
3294 }
3295 } else {
3296 fld = typ.Field(n)
3297 }
3298 sk := ir.NewStructKeyExpr(pos, fld, nil)
3299 sk.Value = r.expr()
3300 elems[i] = sk
3301 }
3302 }
3303
3304 func (r *reader) funcLit() ir.Node {
3305 r.Sync(pkgbits.SyncFuncLit)
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323 r.suppressInlPos++
3324 origPos := r.pos()
3325 sig := r.signature(nil)
3326 r.suppressInlPos--
3327 why := ir.OCLOSURE
3328 if r.Bool() {
3329 why = ir.ORANGE
3330 }
3331
3332 fn := r.inlClosureFunc(origPos, sig, why)
3333
3334 fn.ClosureVars = make([]*ir.Name, 0, r.Len())
3335 for len(fn.ClosureVars) < cap(fn.ClosureVars) {
3336
3337
3338 ir.NewClosureVar(r.pos(), fn, r.useLocal())
3339 }
3340 if param := r.dictParam; param != nil {
3341
3342
3343 ir.NewClosureVar(param.Pos(), fn, param)
3344 }
3345
3346 r.addBody(fn, nil)
3347
3348 return fn.OClosure
3349 }
3350
3351
3352
3353 func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type, why ir.Op) *ir.Func {
3354 curfn := r.inlCaller
3355 if curfn == nil {
3356 curfn = r.curfn
3357 }
3358
3359 var gen int
3360 if why == ir.ORANGE {
3361 r.rangeLitGen++
3362 gen = r.rangeLitGen
3363 } else {
3364 r.funcLitGen++
3365 gen = r.funcLitGen
3366 }
3367
3368
3369 return ir.NewClosureFunc(origPos, r.inlPos(origPos), why, sig, curfn, typecheck.Target, gen)
3370 }
3371
3372 func (r *reader) exprList() []ir.Node {
3373 r.Sync(pkgbits.SyncExprList)
3374 return r.exprs()
3375 }
3376
3377 func (r *reader) exprs() []ir.Node {
3378 r.Sync(pkgbits.SyncExprs)
3379 nodes := make([]ir.Node, r.Len())
3380 if len(nodes) == 0 {
3381 return nil
3382 }
3383 for i := range nodes {
3384 nodes[i] = r.expr()
3385 }
3386 return nodes
3387 }
3388
3389
3390
3391 func (r *reader) dictWord(pos src.XPos, idx int) ir.Node {
3392 base.AssertfAt(r.dictParam != nil, pos, "expected dictParam in %v", r.curfn)
3393 return typecheck.Expr(ir.NewIndexExpr(pos, r.dictParam, ir.NewInt(pos, int64(idx))))
3394 }
3395
3396
3397
3398 func (r *reader) rttiWord(pos src.XPos, idx int) ir.Node {
3399 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TUINT8]), r.dictWord(pos, idx)))
3400 }
3401
3402
3403
3404
3405 func (r *reader) rtype(pos src.XPos) ir.Node {
3406 _, rtype := r.rtype0(pos)
3407 return rtype
3408 }
3409
3410 func (r *reader) rtype0(pos src.XPos) (typ *types.Type, rtype ir.Node) {
3411 r.Sync(pkgbits.SyncRType)
3412 if r.Bool() {
3413 idx := r.Len()
3414 info := r.dict.rtypes[idx]
3415 typ = r.p.typIdx(info, r.dict, true)
3416 rtype = r.rttiWord(pos, r.dict.rtypesOffset()+idx)
3417 return
3418 }
3419
3420 typ = r.typ()
3421 rtype = reflectdata.TypePtrAt(pos, typ)
3422 return
3423 }
3424
3425
3426 func (r *reader) varDictIndex(name *ir.Name) {
3427 if r.Bool() {
3428 idx := 1 + r.dict.rtypesOffset() + r.Len()
3429 if int(uint16(idx)) != idx {
3430 base.FatalfAt(name.Pos(), "DictIndex overflow for %v: %v", name, idx)
3431 }
3432 name.DictIndex = uint16(idx)
3433 }
3434 }
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444 func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) {
3445 typ, typRType = r.rtype0(pos)
3446 iface, ifaceRType = r.rtype0(pos)
3447
3448 idx := -1
3449 if r.Bool() {
3450 idx = r.Len()
3451 }
3452
3453 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
3454 if idx >= 0 {
3455 itab = r.rttiWord(pos, r.dict.itabsOffset()+idx)
3456 } else {
3457 base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ)
3458 base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface)
3459
3460 lsym := reflectdata.ITabLsym(typ, iface)
3461 itab = typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
3462 }
3463 }
3464
3465 return
3466 }
3467
3468
3469
3470 func (r *reader) convRTTI(pos src.XPos) (typeWord, srcRType ir.Node) {
3471 r.Sync(pkgbits.SyncConvRTTI)
3472 src, srcRType0, dst, dstRType, itab := r.itab(pos)
3473 if !dst.IsInterface() {
3474 return
3475 }
3476
3477
3478 switch {
3479 case dst.IsEmptyInterface():
3480 if !src.IsInterface() {
3481 typeWord = srcRType0
3482 }
3483 case !src.IsInterface():
3484 typeWord = itab
3485 default:
3486 typeWord = dstRType
3487 }
3488
3489
3490 if !src.IsInterface() {
3491 srcRType = srcRType0
3492 }
3493
3494 return
3495 }
3496
3497 func (r *reader) exprType() ir.Node {
3498 r.Sync(pkgbits.SyncExprType)
3499 pos := r.pos()
3500
3501 var typ *types.Type
3502 var rtype, itab ir.Node
3503
3504 if r.Bool() {
3505
3506 typ, rtype, _, _, itab = r.itab(pos)
3507 if !typ.IsInterface() {
3508 rtype = nil
3509 }
3510 } else {
3511 typ, rtype = r.rtype0(pos)
3512
3513 if !r.Bool() {
3514 return ir.TypeNode(typ)
3515 }
3516 }
3517
3518 dt := ir.NewDynamicType(pos, rtype)
3519 dt.ITab = itab
3520 dt = typed(typ, dt).(*ir.DynamicType)
3521 if st := dt.ToStatic(); st != nil {
3522 return st
3523 }
3524 return dt
3525 }
3526
3527 func (r *reader) op() ir.Op {
3528 r.Sync(pkgbits.SyncOp)
3529 return ir.Op(r.Len())
3530 }
3531
3532
3533
3534 func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) {
3535 cgoPragmas := make([][]string, r.Len())
3536 for i := range cgoPragmas {
3537 cgoPragmas[i] = r.Strings()
3538 }
3539 target.CgoPragmas = cgoPragmas
3540
3541 r.pkgInitOrder(target)
3542
3543 r.pkgDecls(target)
3544
3545 r.Sync(pkgbits.SyncEOF)
3546 }
3547
3548
3549
3550 func (r *reader) pkgInitOrder(target *ir.Package) {
3551 initOrder := make([]ir.Node, r.Len())
3552 if len(initOrder) == 0 {
3553 return
3554 }
3555
3556
3557 pos := base.AutogeneratedPos
3558 base.Pos = pos
3559
3560 fn := ir.NewFunc(pos, pos, typecheck.Lookup("init"), types.NewSignature(nil, nil, nil))
3561 fn.SetIsPackageInit(true)
3562 fn.SetInlinabilityChecked(true)
3563
3564 typecheck.DeclFunc(fn)
3565 r.curfn = fn
3566
3567 var varInitFns []*ir.Func
3568 if len(initOrder) <= maxInitStatements {
3569 fn.Body = r.doPkgInitOrder(initOrder)
3570 } else {
3571 varInitFns = r.splitLargeInitOrder(initOrder)
3572 calls := make([]ir.Node, len(varInitFns))
3573 for i, varInitFn := range varInitFns {
3574 ir.WithFunc(fn, func() {
3575 calls[i] = typecheck.Call(varInitFn.Pos(), varInitFn.Nname, nil, false)
3576 })
3577 }
3578 fn.Body = calls
3579 }
3580
3581 typecheck.FinishFuncBody()
3582 r.curfn = nil
3583 r.locals = nil
3584
3585
3586 staticinit.OutlineMapInits(fn)
3587 for _, varInitFn := range varInitFns {
3588 staticinit.OutlineMapInits(varInitFn)
3589 }
3590
3591 target.Inits = append(target.Inits, fn)
3592 }
3593
3594 const maxInitStatements = 1000
3595
3596 func (r *reader) generateVarInitFunc(body []ir.Node) *ir.Func {
3597 fn := staticinit.GenerateVarInitFunc()
3598 typecheck.DeclFunc(fn)
3599
3600 old := r.curfn
3601 r.curfn = fn
3602 fn.Body = r.doPkgInitOrder(body)
3603 r.curfn = old
3604
3605 typecheck.FinishFuncBody()
3606
3607 return fn
3608 }
3609
3610 func (r *reader) doPkgInitOrder(initOrder []ir.Node) []ir.Node {
3611 for i := range initOrder {
3612 lhs := make([]ir.Node, r.Len())
3613 for j := range lhs {
3614 lhs[j] = r.obj()
3615 }
3616 rhs := r.expr()
3617 pos := lhs[0].Pos()
3618
3619 var as ir.Node
3620 if len(lhs) == 1 {
3621 as = typecheck.Stmt(ir.NewAssignStmt(pos, lhs[0], rhs))
3622 } else {
3623 as = typecheck.Stmt(ir.NewAssignListStmt(pos, ir.OAS2, lhs, []ir.Node{rhs}))
3624 }
3625
3626 for _, v := range lhs {
3627 v.(*ir.Name).Defn = as
3628 }
3629
3630 initOrder[i] = as
3631 }
3632 return initOrder
3633 }
3634
3635 func (r *reader) splitLargeInitOrder(initOrder []ir.Node) []*ir.Func {
3636 var initFuncs []*ir.Func
3637 for chunk := range slices.Chunk(initOrder, maxInitStatements) {
3638 initFuncs = append(initFuncs, r.generateVarInitFunc(chunk))
3639 }
3640 return initFuncs
3641 }
3642
3643 func (r *reader) pkgDecls(target *ir.Package) {
3644 r.Sync(pkgbits.SyncDecls)
3645 for {
3646 switch code := codeDecl(r.Code(pkgbits.SyncDecl)); code {
3647 default:
3648 panic(fmt.Sprintf("unhandled decl: %v", code))
3649
3650 case declEnd:
3651 return
3652
3653 case declFunc:
3654 names := r.pkgObjs(target)
3655 assert(len(names) == 1)
3656 target.Funcs = append(target.Funcs, names[0].Func)
3657
3658 case declMethod:
3659 typ := r.typ()
3660 sym := r.selector()
3661
3662 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
3663 target.Funcs = append(target.Funcs, method.Nname.(*ir.Name).Func)
3664
3665 case declVar:
3666 names := r.pkgObjs(target)
3667
3668 if n := r.Len(); n > 0 {
3669 assert(len(names) == 1)
3670 embeds := make([]ir.Embed, n)
3671 for i := range embeds {
3672 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.Strings()}
3673 }
3674 names[0].Embed = &embeds
3675 target.Embeds = append(target.Embeds, names[0])
3676 }
3677
3678 case declOther:
3679 r.pkgObjs(target)
3680 }
3681 }
3682 }
3683
3684 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
3685 r.Sync(pkgbits.SyncDeclNames)
3686 nodes := make([]*ir.Name, r.Len())
3687 for i := range nodes {
3688 r.Sync(pkgbits.SyncDeclName)
3689
3690 name := r.obj().(*ir.Name)
3691 nodes[i] = name
3692
3693 sym := name.Sym()
3694 if sym.IsBlank() {
3695 continue
3696 }
3697
3698 switch name.Class {
3699 default:
3700 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
3701
3702 case ir.PEXTERN:
3703 target.Externs = append(target.Externs, name)
3704
3705 case ir.PFUNC:
3706 assert(name.Type().Recv() == nil)
3707
3708
3709 if strings.HasPrefix(sym.Name, "init.") {
3710 target.Inits = append(target.Inits, name.Func)
3711 }
3712 }
3713
3714 if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME {
3715 assert(!sym.OnExportList())
3716 target.PluginExports = append(target.PluginExports, name)
3717 sym.SetOnExportList(true)
3718 }
3719
3720 if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) {
3721 assert(!sym.Asm())
3722 target.AsmHdrDecls = append(target.AsmHdrDecls, name)
3723 sym.SetAsm(true)
3724 }
3725 }
3726
3727 return nodes
3728 }
3729
3730
3731
3732
3733
3734 func unifiedHaveInlineBody(fn *ir.Func) bool {
3735 if fn.Inl == nil {
3736 return false
3737 }
3738
3739 _, ok := bodyReaderFor(fn)
3740 return ok
3741 }
3742
3743 var inlgen = 0
3744
3745
3746
3747 func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int, profile *pgoir.Profile) *ir.InlinedCallExpr {
3748 pri, ok := bodyReaderFor(fn)
3749 if !ok {
3750 base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
3751 }
3752
3753 if !fn.Inl.HaveDcl {
3754 expandInline(fn, pri)
3755 }
3756
3757 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3758
3759 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type())
3760
3761 r.curfn = tmpfn
3762
3763 r.inlCaller = callerfn
3764 r.inlCall = call
3765 r.inlFunc = fn
3766 r.inlTreeIndex = inlIndex
3767 r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
3768 r.funarghack = true
3769
3770 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
3771 for i, cv := range r.inlFunc.ClosureVars {
3772
3773
3774 if cv.Outer.Curfn != callerfn {
3775 base.FatalfAt(call.Pos(), "inlining closure call across frames")
3776 }
3777 r.closureVars[i] = cv.Outer
3778 }
3779 if len(r.closureVars) != 0 && r.hasTypeParams() {
3780 r.dictParam = r.closureVars[len(r.closureVars)-1]
3781 }
3782
3783 r.declareParams()
3784
3785 var inlvars, retvars []*ir.Name
3786 {
3787 sig := r.curfn.Type()
3788 endParams := sig.NumRecvs() + sig.NumParams()
3789 endResults := endParams + sig.NumResults()
3790
3791 inlvars = r.curfn.Dcl[:endParams]
3792 retvars = r.curfn.Dcl[endParams:endResults]
3793 }
3794
3795 r.delayResults = fn.Inl.CanDelayResults
3796
3797 r.retlabel = typecheck.AutoLabel(".i")
3798 inlgen++
3799
3800 init := ir.TakeInit(call)
3801
3802
3803
3804
3805 if call.Op() == ir.OCALLFUNC {
3806 inline.CalleeEffects(&init, call.Fun)
3807 }
3808
3809 var args ir.Nodes
3810 if call.Op() == ir.OCALLMETH {
3811 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
3812 }
3813 args.Append(call.Args...)
3814
3815
3816 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, ir.ToNodes(inlvars), args)
3817 as2.Def = true
3818 var as2init ir.Nodes
3819 for _, name := range inlvars {
3820 if ir.IsBlank(name) {
3821 continue
3822 }
3823
3824 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3825 name.Defn = as2
3826 }
3827 as2.SetInit(as2init)
3828 init.Append(typecheck.Stmt(as2))
3829
3830 if !r.delayResults {
3831
3832
3833 for _, name := range retvars {
3834
3835 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3836 ras := ir.NewAssignStmt(call.Pos(), name, nil)
3837 init.Append(typecheck.Stmt(ras))
3838 }
3839 }
3840
3841
3842
3843
3844
3845
3846 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
3847
3848 ir.WithFunc(r.curfn, func() {
3849 if !r.syntheticBody(call.Pos()) {
3850 assert(r.Bool())
3851
3852 r.curfn.Body = r.stmts()
3853 r.curfn.Endlineno = r.pos()
3854 }
3855
3856
3857
3858
3859
3860
3861 readBodies(typecheck.Target, true, profile)
3862
3863
3864 var edit func(ir.Node) ir.Node
3865 edit = func(n ir.Node) ir.Node {
3866 if ret, ok := n.(*ir.ReturnStmt); ok {
3867 n = typecheck.Stmt(r.inlReturn(ret, retvars))
3868 }
3869 ir.EditChildren(n, edit)
3870 return n
3871 }
3872 edit(r.curfn)
3873 })
3874
3875 body := r.curfn.Body
3876
3877
3878 for _, name := range r.curfn.Dcl {
3879 name.Curfn = callerfn
3880
3881 if name.Class != ir.PAUTO {
3882 name.SetPos(r.inlPos(name.Pos()))
3883 name.SetInlFormal(true)
3884 name.Class = ir.PAUTO
3885 } else {
3886 name.SetInlLocal(true)
3887 }
3888 }
3889 callerfn.Dcl = append(callerfn.Dcl, r.curfn.Dcl...)
3890
3891 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
3892
3893 res := ir.NewInlinedCallExpr(call.Pos(), body, ir.ToNodes(retvars))
3894 res.SetInit(init)
3895 res.SetType(call.Type())
3896 res.SetTypecheck(1)
3897 res.Reshape = call.Reshape
3898
3899
3900 assert(len(todoBodies) == 0)
3901
3902 return res
3903 }
3904
3905
3906
3907 func (r *reader) inlReturn(ret *ir.ReturnStmt, retvars []*ir.Name) *ir.BlockStmt {
3908 pos := r.inlCall.Pos()
3909
3910 block := ir.TakeInit(ret)
3911
3912 if results := ret.Results; len(results) != 0 {
3913 assert(len(retvars) == len(results))
3914
3915 as2 := ir.NewAssignListStmt(pos, ir.OAS2, ir.ToNodes(retvars), ret.Results)
3916
3917 if r.delayResults {
3918 for _, name := range retvars {
3919
3920 block.Append(ir.NewDecl(pos, ir.ODCL, name))
3921 name.Defn = as2
3922 }
3923 }
3924
3925 block.Append(as2)
3926 }
3927
3928 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
3929 return ir.NewBlockStmt(pos, block)
3930 }
3931
3932
3933
3934 func expandInline(fn *ir.Func, pri pkgReaderIndex) {
3935
3936
3937
3938
3939
3940 fndcls := len(fn.Dcl)
3941 topdcls := len(typecheck.Target.Funcs)
3942
3943 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type())
3944 tmpfn.ClosureVars = fn.ClosureVars
3945
3946 {
3947 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3948
3949
3950 r.funarghack = true
3951
3952 r.funcBody(tmpfn)
3953 }
3954
3955
3956 for _, name := range tmpfn.Dcl {
3957 name.Curfn = fn
3958 }
3959 fn.Inl.Dcl = tmpfn.Dcl
3960 fn.Inl.HaveDcl = true
3961
3962
3963 assert(fndcls == len(fn.Dcl))
3964
3965
3966
3967
3968 typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
3969 }
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026 var needWrapperTypes []*types.Type
4027
4028
4029
4030 var haveWrapperTypes []*types.Type
4031
4032
4033
4034 var needMethodValueWrappers []methodValueWrapper
4035
4036
4037
4038
4039 var haveMethodValueWrappers []methodValueWrapper
4040
4041 type methodValueWrapper struct {
4042 rcvr *types.Type
4043 method *types.Field
4044 }
4045
4046
4047
4048 func (r *reader) needWrapper(typ *types.Type) {
4049 if typ.IsPtr() || typ.IsKind(types.TFORW) {
4050 return
4051 }
4052
4053
4054 forceNeed := typ == types.ErrorType && base.Ctxt.Pkgpath == "runtime"
4055
4056
4057
4058
4059 if r.importedDef() && !forceNeed {
4060 haveWrapperTypes = append(haveWrapperTypes, typ)
4061 } else {
4062 needWrapperTypes = append(needWrapperTypes, typ)
4063 }
4064 }
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080 func (r *reader) importedDef() bool {
4081 return r.p != localPkgReader && !r.hasTypeParams()
4082 }
4083
4084
4085
4086 func MakeWrappers(target *ir.Package) {
4087
4088 needWrapperTypes = append(needWrapperTypes, types.ErrorType)
4089
4090 seen := make(map[string]*types.Type)
4091
4092 for _, typ := range haveWrapperTypes {
4093 wrapType(typ, target, seen, false)
4094 }
4095 haveWrapperTypes = nil
4096
4097 for _, typ := range needWrapperTypes {
4098 wrapType(typ, target, seen, true)
4099 }
4100 needWrapperTypes = nil
4101
4102 for _, wrapper := range haveMethodValueWrappers {
4103 wrapMethodValue(wrapper.rcvr, wrapper.method, target, false)
4104 }
4105 haveMethodValueWrappers = nil
4106
4107 for _, wrapper := range needMethodValueWrappers {
4108 wrapMethodValue(wrapper.rcvr, wrapper.method, target, true)
4109 }
4110 needMethodValueWrappers = nil
4111 }
4112
4113 func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) {
4114 key := typ.LinkString()
4115 if prev := seen[key]; prev != nil {
4116 if !types.Identical(typ, prev) {
4117 base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key)
4118 }
4119
4120
4121 typ.CopyTFlagFrom(prev)
4122 return
4123 }
4124 seen[key] = typ
4125
4126 if !needed {
4127
4128 return
4129 }
4130
4131 if !typ.IsInterface() {
4132 typecheck.CalcMethods(typ)
4133 }
4134 if !typ.IsUntyped() {
4135 typ.TFlag()
4136 }
4137 for _, meth := range typ.AllMethods() {
4138 if meth.Sym.IsBlank() || !meth.IsMethod() {
4139 base.FatalfAt(meth.Pos, "invalid method: %v", meth)
4140 }
4141
4142 methodWrapper(0, typ, meth, target)
4143
4144
4145 if !typ.IsInterface() {
4146 methodWrapper(1, typ, meth, target)
4147
4148
4149
4150 if typ.NotInHeap() {
4151 methodWrapper(2, typ, meth, target)
4152 }
4153 }
4154 }
4155 }
4156
4157 func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) {
4158 wrapper := tbase
4159 for i := 0; i < derefs; i++ {
4160 wrapper = types.NewPtr(wrapper)
4161 }
4162
4163 wrappee := method.Type.Recv().Type
4164 if types.Identical(wrapper, wrappee) ||
4165 !types.IsMethodApplicable(wrapper, method) ||
4166 !reflectdata.NeedEmit(tbase) {
4167 return
4168 }
4169 sym, sharedPromoted := ir.MethodSym(wrapper, method)
4170 if sym.Siggen() {
4171 if sharedPromoted {
4172 return
4173 }
4174 base.Fatalf("already generated wrapper %v", sym)
4175 }
4176 sym.SetSiggen(true)
4177
4178
4179 pos := base.AutogeneratedPos
4180
4181 fn := newWrapperFunc(pos, sym, wrapper, method)
4182
4183 var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
4184
4185
4186
4187 if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) {
4188 cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node))
4189 then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)}
4190 fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil))
4191 }
4192
4193
4194
4195 for i := 1; i < derefs; i++ {
4196 recv = Implicit(ir.NewStarExpr(pos, recv))
4197 }
4198
4199 addTailCall(pos, fn, recv, method)
4200
4201 finishWrapperFunc(fn, target)
4202 }
4203
4204 func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) {
4205 sym := ir.ReceiverMethodSymSuffix(recvType, method.Sym, "-fm")
4206 if sym.Uniq() {
4207 return
4208 }
4209 sym.SetUniq(true)
4210
4211
4212 pos := base.AutogeneratedPos
4213
4214 fn := newWrapperFunc(pos, sym, nil, method)
4215 sym.Def = fn.Nname
4216
4217
4218 recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
4219
4220 if !needed {
4221 return
4222 }
4223
4224 addTailCall(pos, fn, recv, method)
4225
4226 finishWrapperFunc(fn, target)
4227 }
4228
4229 func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
4230 sig := newWrapperType(wrapper, method)
4231 fn := ir.NewFunc(pos, pos, sym, sig)
4232 fn.DeclareParams(true)
4233 fn.SetDupok(true)
4234
4235 return fn
4236 }
4237
4238 func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
4239 ir.WithFunc(fn, func() {
4240 typecheck.Stmts(fn.Body)
4241 })
4242
4243
4244
4245
4246 interleaved.DevirtualizeAndInlineFunc(fn, nil)
4247
4248
4249
4250
4251
4252
4253
4254
4255 ir.VisitFuncAndClosures(fn, func(n ir.Node) {
4256 if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
4257 wrapMethodValue(n.X.Type(), n.Selection, target, true)
4258 }
4259 })
4260
4261 fn.Nname.Defn = fn
4262 target.Funcs = append(target.Funcs, fn)
4263 }
4264
4265
4266
4267
4268
4269 func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
4270 clone := func(params []*types.Field) []*types.Field {
4271 res := make([]*types.Field, len(params))
4272 for i, param := range params {
4273 res[i] = types.NewField(param.Pos, param.Sym, param.Type)
4274 res[i].SetIsDDD(param.IsDDD())
4275 }
4276 return res
4277 }
4278
4279 sig := method.Type
4280
4281 var recv *types.Field
4282 if recvType != nil {
4283 recv = types.NewField(sig.Recv().Pos, sig.Recv().Sym, recvType)
4284 }
4285 params := clone(sig.Params())
4286 results := clone(sig.Results())
4287
4288 return types.NewSignature(recv, params, results)
4289 }
4290
4291 func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) {
4292 sig := fn.Nname.Type()
4293 args := make([]ir.Node, sig.NumParams())
4294 for i, param := range sig.Params() {
4295 args[i] = param.Nname.(*ir.Name)
4296 }
4297
4298 dot := typecheck.XDotMethod(pos, recv, method.Sym, true)
4299 call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr)
4300
4301 if recv.Type() != nil && recv.Type().IsPtr() && method.Type.Recv().Type.IsPtr() &&
4302 method.Embedded != 0 &&
4303 (types.IsInterfaceMethod(method.Type) && base.Ctxt.Arch.Name != "wasm" ||
4304 !types.IsInterfaceMethod(method.Type) && !unifiedHaveInlineBody(ir.MethodExprName(dot).Func)) &&
4305
4306
4307 !((base.Ctxt.Arch.Name == "ppc64le" || base.Ctxt.Arch.Name == "ppc64") && base.Ctxt.Flag_dynlink) {
4308 if base.Debug.TailCall != 0 {
4309 base.WarnfAt(fn.Nname.Type().Recv().Type.Elem().Pos(), "tail call emitted for the method %v wrapper", method.Nname)
4310 }
4311
4312 fn.Body.Append(ir.NewTailCallStmt(pos, call))
4313 return
4314 }
4315
4316 fn.SetWrapper(true)
4317
4318 if method.Type.NumResults() == 0 {
4319 fn.Body.Append(call)
4320 return
4321 }
4322
4323 ret := ir.NewReturnStmt(pos, nil)
4324 ret.Results = []ir.Node{call}
4325 fn.Body.Append(ret)
4326 }
4327
4328 func setBasePos(pos src.XPos) {
4329
4330 base.Pos = pos
4331 }
4332
4333
4334
4335
4336
4337
4338 const dictParamName = typecheck.LocalDictName
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348 func shapeSig(fn *ir.Func, dict *readerDict) *types.Type {
4349 sig := fn.Nname.Type()
4350 oldRecv := sig.Recv()
4351
4352 var recv *types.Field
4353 if oldRecv != nil {
4354 recv = types.NewField(oldRecv.Pos, oldRecv.Sym, oldRecv.Type)
4355 }
4356
4357 params := make([]*types.Field, 1+sig.NumParams())
4358 params[0] = types.NewField(fn.Pos(), fn.Sym().Pkg.Lookup(dictParamName), types.NewPtr(dict.varType()))
4359 for i, param := range sig.Params() {
4360 d := types.NewField(param.Pos, param.Sym, param.Type)
4361 d.SetIsDDD(param.IsDDD())
4362 params[1+i] = d
4363 }
4364
4365 results := make([]*types.Field, sig.NumResults())
4366 for i, result := range sig.Results() {
4367 results[i] = types.NewField(result.Pos, result.Sym, result.Type)
4368 }
4369
4370 typ := types.NewSignature(recv, params, results)
4371 typ.SetHasShape(true)
4372 return typ
4373 }
4374
View as plain text