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.WithPos(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(r.curfn, 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(r.curfn, 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(r.curfn, pos, fn, args, fn.Type().IsVariadic()).(*ir.CallExpr)
1505
1506 var stmt ir.Node
1507 if fn.Type().NumResults() != 0 {
1508 stmt = typecheck.Stmt(r.curfn, 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(r.curfn == 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(r.curfn, 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 lno := base.Pos
1789 defer func() { base.Pos = lno }()
1790 base.Pos = pos
1791 names, lhs := r.assignList()
1792 rhs := r.multiExpr()
1793
1794 if len(rhs) == 0 {
1795 for _, name := range names {
1796 as := ir.NewAssignStmt(pos, name, nil)
1797 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name))
1798 out.Append(typecheck.Stmt(r.curfn, as))
1799 }
1800 return nil
1801 }
1802
1803 if len(lhs) == 1 && len(rhs) == 1 {
1804 n := ir.NewAssignStmt(pos, lhs[0], rhs[0])
1805 n.Def = r.initDefn(n, names)
1806 return n
1807 }
1808
1809 n := ir.NewAssignListStmt(pos, ir.OAS2, lhs, rhs)
1810 n.Def = r.initDefn(n, names)
1811 return n
1812
1813 case stmtAssignOp:
1814 op := r.op()
1815 lhs := r.expr()
1816 pos := r.pos()
1817 rhs := r.expr()
1818 return ir.NewAssignOpStmt(pos, op, lhs, rhs)
1819
1820 case stmtIncDec:
1821 op := r.op()
1822 lhs := r.expr()
1823 pos := r.pos()
1824 n := ir.NewAssignOpStmt(pos, op, lhs, ir.NewOne(pos, lhs.Type()))
1825 n.IncDec = true
1826 return n
1827
1828 case stmtBlock:
1829 out.Append(r.blockStmt()...)
1830 return nil
1831
1832 case stmtBranch:
1833 pos := r.pos()
1834 op := r.op()
1835 sym := r.optLabel()
1836 return ir.NewBranchStmt(pos, op, sym)
1837
1838 case stmtCall:
1839 pos := r.pos()
1840 op := r.op()
1841 call := r.expr()
1842 stmt := ir.NewGoDeferStmt(pos, op, call)
1843 if op == ir.ODEFER {
1844 x := r.optExpr()
1845 if x != nil {
1846 stmt.DeferAt = x.(ir.Expr)
1847 }
1848 }
1849 return stmt
1850
1851 case stmtExpr:
1852 return r.expr()
1853
1854 case stmtFor:
1855 return r.forStmt(label)
1856
1857 case stmtIf:
1858 return r.ifStmt()
1859
1860 case stmtLabel:
1861 pos := r.pos()
1862 sym := r.label()
1863 return ir.NewLabelStmt(pos, sym)
1864
1865 case stmtReturn:
1866 pos := r.pos()
1867 results := r.multiExpr()
1868 return ir.NewReturnStmt(pos, results)
1869
1870 case stmtSelect:
1871 return r.selectStmt(label)
1872
1873 case stmtSend:
1874 pos := r.pos()
1875 ch := r.expr()
1876 value := r.expr()
1877 return ir.NewSendStmt(pos, ch, value)
1878
1879 case stmtSwitch:
1880 return r.switchStmt(label)
1881 }
1882 }
1883
1884 func (r *reader) assignList() ([]*ir.Name, []ir.Node) {
1885 lhs := make([]ir.Node, r.Len())
1886 var names []*ir.Name
1887
1888 for i := range lhs {
1889 expr, def := r.assign()
1890 lhs[i] = expr
1891 if def {
1892 names = append(names, expr.(*ir.Name))
1893 }
1894 }
1895
1896 return names, lhs
1897 }
1898
1899
1900
1901 func (r *reader) assign() (ir.Node, bool) {
1902 switch tag := codeAssign(r.Code(pkgbits.SyncAssign)); tag {
1903 default:
1904 panic("unhandled assignee expression")
1905
1906 case assignBlank:
1907 return typecheck.AssignExpr(r.curfn, ir.BlankNode), false
1908
1909 case assignDef:
1910 pos := r.pos()
1911 lno := base.Pos
1912 defer func() { base.Pos = lno }()
1913 setBasePos(pos)
1914 name := r.curfn.NewLocal(pos, r.localIdent(), r.typ())
1915 r.addLocal(name)
1916 return name, true
1917
1918 case assignExpr:
1919 return r.expr(), false
1920 }
1921 }
1922
1923 func (r *reader) blockStmt() []ir.Node {
1924 r.Sync(pkgbits.SyncBlockStmt)
1925 r.openScope()
1926 stmts := r.stmts()
1927 r.closeScope()
1928 return stmts
1929 }
1930
1931 func (r *reader) forStmt(label *types.Sym) ir.Node {
1932 r.Sync(pkgbits.SyncForStmt)
1933
1934 r.openScope()
1935
1936 isRange := r.Bool()
1937 pos := r.pos()
1938 lno := base.Pos
1939 defer func() { base.Pos = lno }()
1940 base.Pos = pos
1941
1942 if isRange {
1943 rang := ir.NewRangeStmt(pos, nil, nil, nil, nil, false)
1944 rang.Label = label
1945
1946 names, lhs := r.assignList()
1947 if len(lhs) >= 1 {
1948 rang.Key = lhs[0]
1949 if len(lhs) >= 2 {
1950 rang.Value = lhs[1]
1951 }
1952 }
1953 rang.Def = r.initDefn(rang, names)
1954
1955 rang.X = r.expr()
1956 if rang.X.Type().IsMap() {
1957 rang.RType = r.rtype(pos)
1958 }
1959 if rang.Key != nil && !ir.IsBlank(rang.Key) {
1960 rang.KeyTypeWord, rang.KeySrcRType = r.convRTTI(pos)
1961 }
1962 if rang.Value != nil && !ir.IsBlank(rang.Value) {
1963 rang.ValueTypeWord, rang.ValueSrcRType = r.convRTTI(pos)
1964 }
1965
1966 rang.Body = r.blockStmt()
1967 rang.DistinctVars = r.Bool()
1968 r.closeAnotherScope()
1969
1970 return rang
1971 }
1972
1973 init := r.stmt()
1974 if init != nil && init.Pos().IsKnown() {
1975 lno := base.Pos
1976 defer func() { base.Pos = lno }()
1977 base.Pos = init.Pos()
1978 }
1979 cond := r.optExpr()
1980 post := r.stmt()
1981 body := r.blockStmt()
1982 perLoopVars := r.Bool()
1983 r.closeAnotherScope()
1984
1985 if ir.IsConst(cond, constant.Bool) && !ir.BoolVal(cond) {
1986 return init
1987 }
1988
1989 stmt := ir.NewForStmt(pos, init, cond, post, body, perLoopVars)
1990 stmt.Label = label
1991 return stmt
1992 }
1993
1994 func (r *reader) ifStmt() ir.Node {
1995 r.Sync(pkgbits.SyncIfStmt)
1996 r.openScope()
1997 pos := r.pos()
1998 lno := base.Pos
1999 defer func() { base.Pos = lno }()
2000 base.Pos = pos
2001 init := r.stmts()
2002 if len(init) > 0 && init[len(init)-1].Pos().IsKnown() {
2003 lno := base.Pos
2004 defer func() { base.Pos = lno }()
2005 base.Pos = init[len(init)-1].Pos()
2006 }
2007 cond := r.expr()
2008 staticCond := r.Int()
2009 var then, els []ir.Node
2010 if staticCond >= 0 {
2011 then = r.blockStmt()
2012 } else {
2013 r.lastCloseScopePos = r.pos()
2014 }
2015 if staticCond <= 0 {
2016 els = r.stmts()
2017 }
2018 r.closeAnotherScope()
2019
2020 if staticCond != 0 {
2021
2022
2023
2024
2025 if cond.Op() != ir.OLITERAL {
2026 init.Append(typecheck.Stmt(r.curfn, ir.NewAssignStmt(pos, ir.BlankNode, cond)))
2027 }
2028 init.Append(then...)
2029 init.Append(els...)
2030 return block(init)
2031 }
2032
2033 n := ir.NewIfStmt(pos, cond, then, els)
2034 n.SetInit(init)
2035 return n
2036 }
2037
2038 func (r *reader) selectStmt(label *types.Sym) ir.Node {
2039 r.Sync(pkgbits.SyncSelectStmt)
2040
2041 pos := r.pos()
2042 clauses := make([]*ir.CommClause, r.Len())
2043 for i := range clauses {
2044 if i > 0 {
2045 r.closeScope()
2046 }
2047 r.openScope()
2048
2049 pos := r.pos()
2050 comm := r.stmt()
2051 body := r.stmts()
2052
2053
2054
2055
2056
2057
2058 if as, ok := comm.(*ir.AssignStmt); ok && as.Op() == ir.OAS && !as.Def {
2059 if conv, ok := as.Y.(*ir.ConvExpr); ok && conv.Op() == ir.OCONVIFACE {
2060 base.AssertfAt(conv.Implicit(), conv.Pos(), "expected implicit conversion: %v", conv)
2061
2062 recv := conv.X
2063 base.AssertfAt(recv.Op() == ir.ORECV, recv.Pos(), "expected receive expression: %v", recv)
2064
2065 tmp := r.temp(pos, recv.Type())
2066
2067
2068 tmpAs := ir.NewAssignStmt(pos, tmp, recv)
2069 tmpAs.Def = true
2070 tmpAs.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
2071 comm = tmpAs
2072
2073
2074 conv.X = tmp
2075 body = append([]ir.Node{as}, body...)
2076 }
2077 }
2078
2079
2080
2081
2082
2083 if as2, ok := comm.(*ir.AssignListStmt); ok && as2.Op() == ir.OAS2 {
2084 init := ir.TakeInit(as2.Rhs[0])
2085 base.AssertfAt(len(init) == 1 && init[0].Op() == ir.OAS2RECV, as2.Pos(), "unexpected assignment: %+v", as2)
2086
2087 comm = init[0]
2088 body = append([]ir.Node{as2}, body...)
2089 }
2090
2091 clauses[i] = ir.NewCommStmt(pos, comm, body)
2092 }
2093 if len(clauses) > 0 {
2094 r.closeScope()
2095 }
2096 n := ir.NewSelectStmt(pos, clauses)
2097 n.Label = label
2098 return n
2099 }
2100
2101 func (r *reader) switchStmt(label *types.Sym) ir.Node {
2102 r.Sync(pkgbits.SyncSwitchStmt)
2103
2104 r.openScope()
2105 pos := r.pos()
2106 lno := base.Pos
2107 defer func() { base.Pos = lno }()
2108 base.Pos = pos
2109 init := r.stmt()
2110 if init != nil && init.Pos().IsKnown() {
2111 lno := base.Pos
2112 defer func() { base.Pos = lno }()
2113 base.Pos = init.Pos()
2114 }
2115
2116 var tag ir.Node
2117 var ident *ir.Ident
2118 var iface *types.Type
2119 if r.Bool() {
2120 pos := r.pos()
2121 lno := base.Pos
2122 defer func() { base.Pos = lno }()
2123 base.Pos = pos
2124 if r.Bool() {
2125 ident = ir.NewIdent(r.pos(), r.localIdent())
2126 }
2127 x := r.expr()
2128 iface = x.Type()
2129 tag = ir.NewTypeSwitchGuard(pos, ident, x)
2130 } else {
2131 tag = r.optExpr()
2132 }
2133
2134 clauses := make([]*ir.CaseClause, r.Len())
2135 for i := range clauses {
2136 if i > 0 {
2137 r.closeScope()
2138 }
2139 r.openScope()
2140
2141 pos := r.pos()
2142 lno := base.Pos
2143 base.Pos = pos
2144 var cases, rtypes []ir.Node
2145 if iface != nil {
2146 cases = make([]ir.Node, r.Len())
2147 if len(cases) == 0 {
2148 cases = nil
2149 }
2150 for i := range cases {
2151 if r.Bool() {
2152 cases[i] = typecheck.Expr(r.curfn, types.BuiltinPkg.Lookup("nil").Def.(*ir.NilExpr))
2153 } else {
2154 cases[i] = r.exprType()
2155 }
2156 }
2157 } else {
2158 cases = r.exprList()
2159
2160
2161
2162
2163
2164
2165
2166
2167 if tag == nil {
2168 for i, cas := range cases {
2169 if cas.Type().IsEmptyInterface() {
2170 for len(rtypes) < i {
2171 rtypes = append(rtypes, nil)
2172 }
2173 rtypes = append(rtypes, reflectdata.TypePtrAt(r.curfn, cas.Pos(), types.Types[types.TBOOL]))
2174 }
2175 }
2176 }
2177 }
2178
2179 clause := ir.NewCaseStmt(pos, cases, nil)
2180 clause.RTypes = rtypes
2181
2182 if ident != nil {
2183 name := r.curfn.NewLocal(r.pos(), ident.Sym(), r.typ())
2184 r.addLocal(name)
2185 clause.Var = name
2186 name.Defn = tag
2187 }
2188
2189 clause.Body = r.stmts()
2190 clauses[i] = clause
2191 base.Pos = lno
2192 }
2193 if len(clauses) > 0 {
2194 r.closeScope()
2195 }
2196 r.closeScope()
2197
2198 n := ir.NewSwitchStmt(pos, tag, clauses)
2199 n.Label = label
2200 if init != nil {
2201 n.SetInit([]ir.Node{init})
2202 }
2203 return n
2204 }
2205
2206 func (r *reader) label() *types.Sym {
2207 r.Sync(pkgbits.SyncLabel)
2208 name := r.String()
2209 if r.inlCall != nil && name != "_" {
2210 name = fmt.Sprintf("~%s·%d", name, inlgen)
2211 }
2212 return typecheck.Lookup(name)
2213 }
2214
2215 func (r *reader) optLabel() *types.Sym {
2216 r.Sync(pkgbits.SyncOptLabel)
2217 if r.Bool() {
2218 return r.label()
2219 }
2220 return nil
2221 }
2222
2223
2224
2225
2226 func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool {
2227 if len(names) == 0 {
2228 return false
2229 }
2230
2231 init := make([]ir.Node, len(names))
2232 for i, name := range names {
2233 name.Defn = defn
2234 init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name)
2235 }
2236 defn.SetInit(init)
2237 return true
2238 }
2239
2240
2241
2242
2243 func (r *reader) expr() (res ir.Node) {
2244 defer func() {
2245 if res != nil && res.Typecheck() == 0 {
2246 base.FatalfAt(res.Pos(), "%v missed typecheck", res)
2247 }
2248 }()
2249
2250 switch tag := codeExpr(r.Code(pkgbits.SyncExpr)); tag {
2251 default:
2252 panic("unhandled expression")
2253
2254 case exprLocal:
2255 return typecheck.Expr(r.curfn, r.useLocal())
2256
2257 case exprGlobal:
2258
2259
2260 return typecheck.Callee(r.curfn, r.obj())
2261
2262 case exprFuncInst:
2263 origPos, pos := r.origPos()
2264 wrapperFn, baseFn, dictPtr := r.funcInst(pos)
2265 if wrapperFn != nil {
2266 return wrapperFn
2267 }
2268 return r.curry(origPos, false, baseFn, dictPtr, nil)
2269
2270 case exprConst:
2271 pos := r.pos()
2272 typ := r.typ()
2273 val := FixValue(typ, r.Value())
2274 return ir.NewBasicLit(pos, typ, val)
2275
2276 case exprZero:
2277 pos := r.pos()
2278 typ := r.typ()
2279 return ir.NewZero(pos, typ)
2280
2281 case exprCompLit:
2282 return r.compLit()
2283
2284 case exprFuncLit:
2285 return r.funcLit()
2286
2287 case exprFieldVal:
2288 x := r.expr()
2289 pos := r.pos()
2290 sym := r.selector()
2291
2292 return typecheck.XDotField(r.curfn, pos, x, sym)
2293
2294 case exprMethodVal:
2295 recv := r.expr()
2296 origPos, pos := r.origPos()
2297 wrapperFn, baseFn, dictPtr := r.methodExpr()
2298
2299
2300
2301 if wrapperFn, ok := wrapperFn.(*ir.SelectorExpr); ok && wrapperFn.Op() == ir.OMETHEXPR {
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319 if recv.Type().HasShape() {
2320 typ := wrapperFn.Type().Param(0).Type
2321 if !types.Identical(typ, recv.Type()) {
2322 base.FatalfAt(wrapperFn.Pos(), "receiver %L does not match %L", recv, wrapperFn)
2323 }
2324 recv = typecheck.Expr(r.curfn, ir.NewConvExpr(recv.Pos(), ir.OCONVNOP, typ, recv))
2325 }
2326
2327 n := typecheck.XDotMethod(r.curfn, pos, recv, wrapperFn.Sel, false)
2328
2329
2330
2331
2332
2333
2334
2335 if n.Selection != wrapperFn.Selection {
2336 assert(n.Selection.Sym == wrapperFn.Selection.Sym)
2337 assert(types.Identical(n.Selection.Type, wrapperFn.Selection.Type))
2338 assert(types.Identical(n.Selection.Type.Recv().Type, wrapperFn.Selection.Type.Recv().Type))
2339 }
2340
2341 wrapper := methodValueWrapper{
2342 rcvr: n.X.Type(),
2343 method: n.Selection,
2344 }
2345
2346 if r.importedDef() {
2347 haveMethodValueWrappers = append(haveMethodValueWrappers, wrapper)
2348 } else {
2349 needMethodValueWrappers = append(needMethodValueWrappers, wrapper)
2350 }
2351 return n
2352 }
2353
2354
2355
2356 return r.curry(origPos, true, baseFn, recv, dictPtr)
2357
2358 case exprMethodExpr:
2359 recv := r.typ()
2360
2361 implicits := make([]int, r.Len())
2362 for i := range implicits {
2363 implicits[i] = r.Len()
2364 }
2365 var deref, addr bool
2366 if r.Bool() {
2367 deref = true
2368 } else if r.Bool() {
2369 addr = true
2370 }
2371
2372 origPos, pos := r.origPos()
2373 wrapperFn, baseFn, dictPtr := r.methodExpr()
2374
2375
2376
2377
2378
2379
2380
2381 if wrapperFn != nil && len(implicits) == 0 && !deref && !addr {
2382 if !types.Identical(recv, wrapperFn.Type().Param(0).Type) {
2383 base.FatalfAt(pos, "want receiver type %v, but have method %L", recv, wrapperFn)
2384 }
2385 return wrapperFn
2386 }
2387
2388
2389
2390
2391 if method, ok := wrapperFn.(*ir.SelectorExpr); ok && method.Op() == ir.OMETHEXPR && !recv.HasShape() {
2392 return typecheck.NewMethodExpr(pos, recv, method.Sel)
2393 }
2394
2395 return r.methodExprWrap(origPos, recv, implicits, deref, addr, baseFn, dictPtr)
2396
2397 case exprIndex:
2398 x := r.expr()
2399 pos := r.pos()
2400 index := r.expr()
2401 n := typecheck.Expr(r.curfn, ir.NewIndexExpr(pos, x, index))
2402 switch n.Op() {
2403 case ir.OINDEXMAP:
2404 n := n.(*ir.IndexExpr)
2405 n.RType = r.rtype(pos)
2406 }
2407 return n
2408
2409 case exprSlice:
2410 x := r.expr()
2411 pos := r.pos()
2412 var index [3]ir.Node
2413 for i := range index {
2414 index[i] = r.optExpr()
2415 }
2416 op := ir.OSLICE
2417 if index[2] != nil {
2418 op = ir.OSLICE3
2419 }
2420 return typecheck.Expr(r.curfn, ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2]))
2421
2422 case exprAssert:
2423 x := r.expr()
2424 pos := r.pos()
2425 typ := r.exprType()
2426 srcRType := r.rtype(pos)
2427
2428
2429 if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE {
2430 assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType)
2431 assert.SrcRType = srcRType
2432 assert.ITab = typ.ITab
2433 return typed(typ.Type(), assert)
2434 }
2435 return typecheck.Expr(r.curfn, ir.NewTypeAssertExpr(pos, x, typ.Type()))
2436
2437 case exprUnaryOp:
2438 op := r.op()
2439 pos := r.pos()
2440 x := r.expr()
2441
2442 switch op {
2443 case ir.OADDR:
2444 return typecheck.Expr(r.curfn, typecheck.NodAddrAt(r.curfn, pos, x))
2445 case ir.ODEREF:
2446 return typecheck.Expr(r.curfn, ir.NewStarExpr(pos, x))
2447 }
2448 return typecheck.Expr(r.curfn, ir.NewUnaryExpr(pos, op, x))
2449
2450 case exprBinaryOp:
2451 op := r.op()
2452 x := r.expr()
2453 pos := r.pos()
2454 y := r.expr()
2455
2456 switch op {
2457 case ir.OANDAND, ir.OOROR:
2458 return typecheck.Expr(r.curfn, ir.NewLogicalExpr(pos, op, x, y))
2459 case ir.OLSH, ir.ORSH:
2460
2461
2462 if ir.IsConstNode(y) {
2463 val := constant.ToInt(y.Val())
2464 assert(val.Kind() == constant.Int && constant.Sign(val) >= 0)
2465 }
2466 }
2467 return typecheck.Expr(r.curfn, ir.NewBinaryExpr(pos, op, x, y))
2468
2469 case exprRecv:
2470 x := r.expr()
2471 pos := r.pos()
2472 for i, n := 0, r.Len(); i < n; i++ {
2473 x = Implicit(typecheck.DotField(pos, x, r.Len()))
2474 }
2475 if r.Bool() {
2476 x = Implicit(Deref(pos, x.Type().Elem(), x))
2477 } else if r.Bool() {
2478 x = Implicit(Addr(r.curfn, pos, x))
2479 }
2480 return x
2481
2482 case exprCall:
2483 var fun ir.Node
2484 var args ir.Nodes
2485 if r.Bool() {
2486 recv := r.expr()
2487 _, method, dictPtr := r.methodExpr()
2488
2489 if recv.Type().IsInterface() && method.Op() == ir.OMETHEXPR {
2490 method := method.(*ir.SelectorExpr)
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500 fun = typecheck.XDotMethod(r.curfn, method.Pos(), recv, method.Sel, true)
2501 } else {
2502 if recv.Type().IsInterface() {
2503
2504
2505 if base.Flag.LowerM != 0 {
2506 base.WarnfAt(method.Pos(), "imprecise interface call")
2507 }
2508 }
2509
2510 fun = method
2511 args.Append(recv)
2512 }
2513 if dictPtr != nil {
2514 args.Append(dictPtr)
2515 }
2516 } else if r.Bool() {
2517 pos := r.pos()
2518 _, shapedFn, dictPtr := r.funcInst(pos)
2519 fun = shapedFn
2520 args.Append(dictPtr)
2521 } else {
2522 fun = r.expr()
2523 }
2524 pos := r.pos()
2525 args.Append(r.multiExpr()...)
2526 dots := r.Bool()
2527 n := typecheck.Call(r.curfn, pos, fun, args, dots)
2528 switch n.Op() {
2529 case ir.OAPPEND:
2530 n := n.(*ir.CallExpr)
2531 n.RType = r.rtype(pos)
2532
2533
2534 if n.IsDDD {
2535 if conv, ok := n.Args[1].(*ir.ConvExpr); ok && conv.Op() == ir.OCONVNOP && conv.Implicit() {
2536 n.Args[1] = conv.X
2537 }
2538 }
2539 case ir.OCOPY:
2540 n := n.(*ir.BinaryExpr)
2541 n.RType = r.rtype(pos)
2542 case ir.ODELETE:
2543 n := n.(*ir.CallExpr)
2544 n.RType = r.rtype(pos)
2545 case ir.OUNSAFESLICE:
2546 n := n.(*ir.BinaryExpr)
2547 n.RType = r.rtype(pos)
2548 }
2549 return n
2550
2551 case exprMake:
2552 pos := r.pos()
2553 typ := r.exprType()
2554 extra := r.exprs()
2555 n := typecheck.Expr(r.curfn, ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr)
2556 n.RType = r.rtype(pos)
2557 return n
2558
2559 case exprNew:
2560 pos := r.pos()
2561 if r.Bool() {
2562
2563 x := r.expr()
2564 x = typecheck.DefaultLit(x, nil)
2565 var init ir.Nodes
2566 addr := ir.NewAddrExpr(pos, r.tempCopy(pos, x, &init))
2567 addr.SetInit(init)
2568 return typecheck.Expr(r.curfn, addr)
2569 }
2570
2571 return typecheck.Expr(r.curfn, ir.NewUnaryExpr(pos, ir.ONEW, r.exprType()))
2572
2573 case exprSizeof:
2574 return ir.NewUintptr(r.pos(), r.typ().Size())
2575
2576 case exprAlignof:
2577 return ir.NewUintptr(r.pos(), r.typ().Alignment())
2578
2579 case exprOffsetof:
2580 pos := r.pos()
2581 typ := r.typ()
2582 types.CalcSize(typ)
2583
2584 var offset int64
2585 for i := r.Len(); i >= 0; i-- {
2586 field := typ.Field(r.Len())
2587 offset += field.Offset
2588 typ = field.Type
2589 }
2590
2591 return ir.NewUintptr(pos, offset)
2592
2593 case exprReshape:
2594 typ := r.typ()
2595 x := r.expr()
2596
2597 if types.IdenticalStrict(x.Type(), typ) {
2598 return x
2599 }
2600
2601
2602
2603
2604
2605
2606 if x.Type() == types.UntypedBool && typ.IsBoolean() {
2607 return x
2608 }
2609
2610 base.AssertfAt(x.Type().HasShape() || typ.HasShape(), x.Pos(), "%L and %v are not shape types", x, typ)
2611 base.AssertfAt(types.Identical(x.Type(), typ), x.Pos(), "%L is not shape-identical to %v", x, typ)
2612
2613
2614
2615
2616
2617
2618
2619 base.AssertfAt(ir.HasUniquePos(x), x.Pos(), "cannot call SetType(%v) on %L", typ, x)
2620
2621 if base.Debug.Reshape != 0 {
2622 base.WarnfAt(x.Pos(), "reshaping %L to %v", x, typ)
2623 }
2624
2625 x.SetType(typ)
2626
2627 if call, ok := x.(*ir.CallExpr); ok {
2628 call.Reshape = true
2629 }
2630
2631 return x
2632
2633 case exprConvert:
2634 implicit := r.Bool()
2635 typ := r.typ()
2636 pos := r.pos()
2637 typeWord, srcRType := r.convRTTI(pos)
2638 dstTypeParam := r.Bool()
2639 identical := r.Bool()
2640 x := r.expr()
2641
2642
2643
2644 if dstTypeParam && ir.IsConstNode(x) {
2645
2646 if v := typecheck.ConvertVal(x.Val(), typ, false); v.Kind() != constant.Unknown {
2647 x = ir.NewBasicLit(x.Pos(), typ, v)
2648
2649 n := Implicit(ir.NewConvExpr(pos, ir.OCONVNOP, typ, x))
2650 n.SetTypecheck(1)
2651 return n
2652 }
2653
2654
2655
2656 }
2657
2658
2659 x = typecheck.DefaultLit(x, typ)
2660
2661 ce := ir.NewConvExpr(pos, ir.OCONV, typ, x)
2662 ce.TypeWord, ce.SrcRType = typeWord, srcRType
2663 if implicit {
2664 ce.SetImplicit(true)
2665 }
2666 n := typecheck.Expr(r.curfn, ce)
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684 if !identical {
2685 if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) {
2686 n.SetOp(ir.OCONVIFACE)
2687 }
2688 }
2689
2690 return n
2691
2692 case exprRuntimeBuiltin:
2693 builtin := typecheck.LookupRuntime(r.String())
2694 return builtin
2695 }
2696 }
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720 func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) {
2721
2722 var implicits []*types.Type
2723 if r.dict != nil {
2724 implicits = r.dict.targs
2725 }
2726
2727 if r.Bool() {
2728 idx := r.Len()
2729 info := r.dict.subdicts[idx]
2730 explicits := r.p.typListIdx(info.explicits, r.dict)
2731
2732 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2733
2734
2735
2736 dictPtrType := baseFn.Type().Param(0).Type
2737 dictPtr = typecheck.Expr(r.curfn, ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2738
2739 return
2740 }
2741
2742 info := r.objInfo()
2743 explicits := r.p.typListIdx(info.explicits, r.dict)
2744
2745 wrapperFn = r.p.objIdx(info.idx, implicits, explicits, false).(*ir.Name)
2746 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2747
2748 dictName := r.p.objDictName(info.idx, implicits, explicits)
2749 dictPtr = typecheck.Expr(r.curfn, ir.NewAddrExpr(pos, dictName))
2750
2751 return
2752 }
2753
2754 func (pr *pkgReader) objDictName(idx index, implicits, explicits []*types.Type) *ir.Name {
2755 rname := pr.newReader(pkgbits.SectionName, idx, pkgbits.SyncObject1)
2756 _, sym := rname.qualifiedIdent()
2757 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
2758
2759 if tag == pkgbits.ObjStub {
2760 assert(!sym.IsBlank())
2761 if pri, ok := objReader[sym]; ok {
2762 return pri.pr.objDictName(pri.idx, nil, explicits)
2763 }
2764 base.Fatalf("unresolved stub: %v", sym)
2765 }
2766
2767 dict, err := pr.objDictIdx(sym, idx, implicits, explicits, false)
2768 if err != nil {
2769 base.Fatalf("%v", err)
2770 }
2771
2772 return pr.dictNameOf(dict)
2773 }
2774
2775
2776
2777
2778
2779
2780
2781
2782 func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node {
2783 var captured ir.Nodes
2784 captured.Append(fun, arg0)
2785 if arg1 != nil {
2786 captured.Append(arg1)
2787 }
2788
2789 params, results := syntheticSig(fun.Type())
2790 params = params[len(captured)-1:]
2791 typ := types.NewSignature(nil, params, results)
2792
2793 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2794 fun := captured[0]
2795
2796 var args ir.Nodes
2797 args.Append(captured[1:]...)
2798 args.Append(r.syntheticArgs()...)
2799
2800 r.syntheticTailCall(pos, fun, args)
2801 }
2802
2803 return r.syntheticClosure(origPos, typ, ifaceHack, captured, addBody)
2804 }
2805
2806
2807
2808
2809 func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node {
2810 var captured ir.Nodes
2811 captured.Append(method)
2812
2813 params, results := syntheticSig(method.Type())
2814
2815
2816 params[0].Type = recv
2817
2818
2819
2820
2821 if dictPtr != nil {
2822 captured.Append(dictPtr)
2823 params = append(params[:1], params[2:]...)
2824 }
2825
2826 typ := types.NewSignature(nil, params, results)
2827
2828 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2829 fn := captured[0]
2830 args := r.syntheticArgs()
2831
2832
2833 {
2834 arg := args[0]
2835 for _, ix := range implicits {
2836 arg = Implicit(typecheck.DotField(pos, arg, ix))
2837 }
2838 if deref {
2839 arg = Implicit(Deref(pos, arg.Type().Elem(), arg))
2840 } else if addr {
2841 arg = Implicit(Addr(r.curfn, pos, arg))
2842 }
2843 args[0] = arg
2844 }
2845
2846
2847 if dictPtr != nil {
2848 newArgs := make([]ir.Node, len(args)+1)
2849 newArgs[0] = args[0]
2850 newArgs[1] = captured[1]
2851 copy(newArgs[2:], args[1:])
2852 args = newArgs
2853 }
2854
2855 r.syntheticTailCall(pos, fn, args)
2856 }
2857
2858 return r.syntheticClosure(origPos, typ, false, captured, addBody)
2859 }
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875 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 {
2876
2877
2878
2879
2880
2881 isSafe := func(n ir.Node) bool {
2882 if n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PFUNC {
2883 return true
2884 }
2885 if n.Op() == ir.OMETHEXPR {
2886 return true
2887 }
2888
2889 return false
2890 }
2891
2892 fn := r.inlClosureFunc(origPos, typ, ir.OCLOSURE)
2893 fn.SetWrapper(true)
2894
2895 clo := fn.OClosure
2896 inlPos := clo.Pos()
2897
2898 var init ir.Nodes
2899 for i, n := range captures {
2900 if isSafe(n) {
2901 continue
2902 }
2903
2904 tmp := r.tempCopy(inlPos, n, &init)
2905 ir.NewClosureVar(origPos, fn, tmp)
2906
2907
2908
2909 if ifaceHack && i == 1 && n.Type().IsInterface() {
2910 check := ir.NewUnaryExpr(inlPos, ir.OCHECKNIL, ir.NewUnaryExpr(inlPos, ir.OITAB, tmp))
2911 init.Append(typecheck.Stmt(r.curfn, check))
2912 }
2913 }
2914
2915 pri := pkgReaderIndex{synthetic: func(pos src.XPos, r *reader) {
2916 captured := make([]ir.Node, len(captures))
2917 next := 0
2918 for i, n := range captures {
2919 if isSafe(n) {
2920 captured[i] = n
2921 } else {
2922 captured[i] = r.closureVars[next]
2923 next++
2924 }
2925 }
2926 assert(next == len(r.closureVars))
2927
2928 addBody(origPos, r, captured)
2929 }}
2930 bodyReader[fn] = pri
2931 pri.funcBody(fn)
2932
2933 return ir.InitExpr(init, clo)
2934 }
2935
2936
2937
2938
2939 func syntheticSig(sig *types.Type) (params, results []*types.Field) {
2940 clone := func(params []*types.Field) []*types.Field {
2941 res := make([]*types.Field, len(params))
2942 for i, param := range params {
2943
2944
2945
2946
2947
2948
2949 res[i] = types.NewField(base.AutogeneratedPos, param.Sym, param.Type)
2950 res[i].SetIsDDD(param.IsDDD())
2951 }
2952 return res
2953 }
2954
2955 return clone(sig.Params()), clone(sig.Results())
2956 }
2957
2958 func (r *reader) optExpr() ir.Node {
2959 if r.Bool() {
2960 return r.expr()
2961 }
2962 return nil
2963 }
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988 func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) {
2989 recv := r.typ()
2990
2991 var sig *types.Type
2992 generic := r.Version().Has(pkgbits.GenericMethods) && r.Bool()
2993 if !generic {
2994
2995
2996 sig = typecheck.NewMethodType(r.typ(), recv)
2997 }
2998
2999 pos := r.pos()
3000 sym := r.selector()
3001
3002 if r.Bool() {
3003 idx := r.Len()
3004 word := r.dictWord(pos, r.dict.typeParamMethodExprsOffset()+idx)
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015 fn := typecheck.Expr(r.curfn, ir.NewConvExpr(pos, ir.OCONVNOP, sig, ir.NewAddrExpr(pos, word)))
3016 return fn, fn, nil
3017 }
3018
3019 if r.Bool() {
3020 idx := r.Len()
3021 info := r.dict.subdicts[idx]
3022 explicits := r.p.typListIdx(info.explicits, r.dict)
3023
3024 shapedObj := r.p.objIdx(info.idx, nil, explicits, true).(*ir.Name)
3025 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
3026
3027
3028
3029 dictPtrType := shapedFn.Type().Param(1).Type
3030 dictPtr := typecheck.Expr(r.curfn, ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
3031
3032 return nil, shapedFn, dictPtr
3033 }
3034
3035 if r.Bool() {
3036 info := r.objInfo()
3037 explicits := r.p.typListIdx(info.explicits, r.dict)
3038
3039 shapedObj := r.p.objIdx(info.idx, nil, explicits, true).(*ir.Name)
3040 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
3041
3042 dict := r.p.objDictName(info.idx, nil, explicits)
3043 dictPtr := typecheck.Expr(r.curfn, ir.NewAddrExpr(pos, dict))
3044
3045
3046 if !types.Identical(dictPtr.Type(), shapedFn.Type().Param(1).Type) {
3047 base.FatalfAt(pos, "dict %L, but shaped method %L", dict, shapedFn)
3048 }
3049
3050 if !generic {
3051
3052
3053 base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv)
3054 wrapperFn := typecheck.NewMethodExpr(pos, recv, sym)
3055 base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig)
3056 return wrapperFn, shapedFn, dictPtr
3057 } else {
3058
3059
3060
3061
3062 return nil, shapedFn, dictPtr
3063 }
3064 }
3065
3066
3067 base.AssertfAt(!recv.HasShape() || recv.IsInterface(), pos, "shaped receiver %v", recv)
3068 fn := typecheck.NewMethodExpr(pos, recv, sym)
3069 return fn, fn, nil
3070 }
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094 func shapedMethodExpr(pos src.XPos, obj *ir.Name, sym *types.Sym) ir.Node {
3095 if obj.Op() == ir.OTYPE {
3096
3097 typ := obj.Type()
3098 assert(typ.HasShape())
3099
3100 method := func() *types.Field {
3101 for _, m := range typ.Methods() {
3102 if m.Sym == sym {
3103 return m
3104 }
3105 }
3106
3107 base.FatalfAt(pos, "failed to find method %v in shaped type %v", sym, typ)
3108 panic("unreachable")
3109 }()
3110
3111 return typecheck.NewMethodExpr(pos, method.Type.Recv().Type, sym)
3112 } else {
3113
3114 assert(obj.Op() == ir.ONAME && obj.Class == ir.PFUNC)
3115 typ := obj.Type()
3116 assert(typ.HasShape())
3117
3118
3119
3120
3121
3122
3123
3124 lsym := obj.Linksym().Name
3125
3126
3127 idx := func() int {
3128 depth, i := 0, len(lsym)-1
3129 for {
3130 switch lsym[i] {
3131 case ']':
3132 depth++
3133 case '[':
3134 depth--
3135 }
3136 if depth == 0 {
3137 return i
3138 }
3139 i--
3140 }
3141 }()
3142 msym := sym.Pkg.Lookup(lsym[idx-len(sym.Name):])
3143
3144
3145
3146 m := types.NewField(obj.Pos(), msym, typ)
3147 m.Nname = obj
3148
3149 n := ir.NewSelectorExpr(pos, ir.OMETHEXPR, ir.TypeNode(typ.Recv().Type), msym)
3150 n.Selection = m
3151 n.SetType(typecheck.NewMethodType(typ, typ.Recv().Type))
3152 n.SetTypecheck(1)
3153
3154 return n
3155 }
3156 }
3157
3158 func (r *reader) multiExpr() []ir.Node {
3159 r.Sync(pkgbits.SyncMultiExpr)
3160
3161 if r.Bool() {
3162 pos := r.pos()
3163 expr := r.expr()
3164
3165 results := make([]ir.Node, r.Len())
3166 as := ir.NewAssignListStmt(pos, ir.OAS2, nil, []ir.Node{expr})
3167 as.Def = true
3168 for i := range results {
3169 tmp := r.temp(pos, r.typ())
3170 tmp.Defn = as
3171 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
3172 as.Lhs.Append(tmp)
3173
3174 res := ir.Node(tmp)
3175 if r.Bool() {
3176 n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)
3177 n.TypeWord, n.SrcRType = r.convRTTI(pos)
3178 n.SetImplicit(true)
3179 res = typecheck.Expr(r.curfn, n)
3180 }
3181 results[i] = res
3182 }
3183
3184
3185 results[0] = ir.InitExpr([]ir.Node{typecheck.Stmt(r.curfn, as)}, results[0])
3186 return results
3187 }
3188
3189
3190 exprs := make([]ir.Node, r.Len())
3191 if len(exprs) == 0 {
3192 return nil
3193 }
3194 for i := range exprs {
3195 exprs[i] = r.expr()
3196 }
3197 return exprs
3198 }
3199
3200
3201 func (r *reader) temp(pos src.XPos, typ *types.Type) *ir.Name {
3202 return typecheck.TempAt(pos, r.curfn, typ)
3203 }
3204
3205
3206
3207 func (r *reader) tempCopy(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name {
3208 tmp := r.temp(pos, expr.Type())
3209
3210 init.Append(typecheck.Stmt(r.curfn, ir.NewDecl(pos, ir.ODCL, tmp)))
3211
3212 assign := ir.NewAssignStmt(pos, tmp, expr)
3213 assign.Def = true
3214 init.Append(typecheck.Stmt(r.curfn, assign))
3215
3216 tmp.Defn = assign
3217
3218 return tmp
3219 }
3220
3221 func (r *reader) compLit() ir.Node {
3222 r.Sync(pkgbits.SyncCompLit)
3223 pos := r.pos()
3224 typ0 := r.typ()
3225
3226 typ := typ0
3227 if typ.IsPtr() {
3228 typ = typ.Elem()
3229 }
3230 if typ.Kind() == types.TFORW {
3231 base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
3232 }
3233 var rtype ir.Node
3234 if typ.IsMap() {
3235 rtype = r.rtype(pos)
3236 }
3237
3238 var elems []ir.Node
3239 if r.Version().Has(pkgbits.CompactCompLiterals) {
3240 n := r.Int()
3241 elems = make([]ir.Node, max(n, -n) )
3242 switch typ.Kind() {
3243 default:
3244 base.FatalfAt(pos, "unexpected composite literal type: %v", typ)
3245 case types.TARRAY:
3246 r.arrayElems(n >= 0, elems)
3247 case types.TMAP:
3248 r.mapElems(elems)
3249 case types.TSLICE:
3250 r.arrayElems(n >= 0, elems)
3251 case types.TSTRUCT:
3252 r.structElems(typ, n >= 0, elems)
3253 }
3254 } else {
3255 elems = make([]ir.Node, r.Len())
3256 isStruct := typ.Kind() == types.TSTRUCT
3257 for i := range elems {
3258 elemp := &elems[i]
3259 if isStruct {
3260 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.Len()), nil)
3261 *elemp, elemp = sk, &sk.Value
3262 } else if r.Bool() {
3263 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3264 *elemp, elemp = kv, &kv.Value
3265 }
3266 *elemp = r.expr()
3267 }
3268 }
3269
3270 lit := typecheck.Expr(r.curfn, ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems))
3271 if rtype != nil {
3272 lit := lit.(*ir.CompLitExpr)
3273 lit.RType = rtype
3274 }
3275 if typ0.IsPtr() {
3276 lit = typecheck.Expr(r.curfn, typecheck.NodAddrAt(r.curfn, pos, lit))
3277 lit.SetType(typ0)
3278 }
3279 return lit
3280 }
3281
3282 func (r *reader) arrayElems(valuesOnly bool, elems []ir.Node) {
3283 if valuesOnly {
3284 for i := range elems {
3285 elems[i] = r.expr()
3286 }
3287 return
3288 }
3289
3290 for i := range elems {
3291 if r.Bool() {
3292 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3293 kv.Value = r.expr()
3294 elems[i] = kv
3295 } else {
3296 elems[i] = r.expr()
3297 }
3298 }
3299 }
3300
3301 func (r *reader) mapElems(elems []ir.Node) {
3302
3303 for i := range elems {
3304 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3305 kv.Value = r.expr()
3306 elems[i] = kv
3307 }
3308 }
3309
3310 func (r *reader) structElems(typ *types.Type, valuesOnly bool, elems []ir.Node) {
3311 if valuesOnly {
3312 for i := range elems {
3313 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(i), nil)
3314 sk.Value = r.expr()
3315 elems[i] = sk
3316 }
3317 return
3318 }
3319
3320
3321 for i := range elems {
3322 pos := r.pos()
3323 var fld *types.Field
3324 if n := r.Int(); n < 0 {
3325
3326 typ := typ
3327 for range -n {
3328 fld = typ.Field(r.Int())
3329 typ = fld.Type
3330 }
3331 } else {
3332 fld = typ.Field(n)
3333 }
3334 sk := ir.NewStructKeyExpr(pos, fld, nil)
3335 sk.Value = r.expr()
3336 elems[i] = sk
3337 }
3338 }
3339
3340 func (r *reader) funcLit() ir.Node {
3341 r.Sync(pkgbits.SyncFuncLit)
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359 r.suppressInlPos++
3360 origPos := r.pos()
3361 sig := r.signature(nil)
3362 r.suppressInlPos--
3363 why := ir.OCLOSURE
3364 if r.Bool() {
3365 why = ir.ORANGE
3366 }
3367
3368 fn := r.inlClosureFunc(origPos, sig, why)
3369
3370 fn.ClosureVars = make([]*ir.Name, 0, r.Len())
3371 for len(fn.ClosureVars) < cap(fn.ClosureVars) {
3372
3373
3374 ir.NewClosureVar(r.pos(), fn, r.useLocal())
3375 }
3376 if param := r.dictParam; param != nil {
3377
3378
3379 ir.NewClosureVar(param.Pos(), fn, param)
3380 }
3381
3382 r.addBody(fn, nil)
3383
3384 return fn.OClosure
3385 }
3386
3387
3388
3389 func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type, why ir.Op) *ir.Func {
3390 curfn := r.inlCaller
3391 if curfn == nil {
3392 curfn = r.curfn
3393 }
3394
3395 var gen int
3396 if why == ir.ORANGE {
3397 r.rangeLitGen++
3398 gen = r.rangeLitGen
3399 } else {
3400 r.funcLitGen++
3401 gen = r.funcLitGen
3402 }
3403
3404
3405 return ir.NewClosureFunc(origPos, r.inlPos(origPos), why, sig, curfn, typecheck.Target, gen)
3406 }
3407
3408 func (r *reader) exprList() []ir.Node {
3409 r.Sync(pkgbits.SyncExprList)
3410 return r.exprs()
3411 }
3412
3413 func (r *reader) exprs() []ir.Node {
3414 r.Sync(pkgbits.SyncExprs)
3415 nodes := make([]ir.Node, r.Len())
3416 if len(nodes) == 0 {
3417 return nil
3418 }
3419 for i := range nodes {
3420 nodes[i] = r.expr()
3421 }
3422 return nodes
3423 }
3424
3425
3426
3427 func (r *reader) dictWord(pos src.XPos, idx int) ir.Node {
3428 base.AssertfAt(r.dictParam != nil, pos, "expected dictParam in %v", r.curfn)
3429 return typecheck.Expr(r.curfn, ir.NewIndexExpr(pos, r.dictParam, ir.NewInt(pos, int64(idx))))
3430 }
3431
3432
3433
3434 func (r *reader) rttiWord(pos src.XPos, idx int) ir.Node {
3435 return typecheck.Expr(r.curfn, ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TUINT8]), r.dictWord(pos, idx)))
3436 }
3437
3438
3439
3440
3441 func (r *reader) rtype(pos src.XPos) ir.Node {
3442 _, rtype := r.rtype0(pos)
3443 return rtype
3444 }
3445
3446 func (r *reader) rtype0(pos src.XPos) (typ *types.Type, rtype ir.Node) {
3447 r.Sync(pkgbits.SyncRType)
3448 if r.Bool() {
3449 idx := r.Len()
3450 info := r.dict.rtypes[idx]
3451 typ = r.p.typIdx(info, r.dict, true)
3452 rtype = r.rttiWord(pos, r.dict.rtypesOffset()+idx)
3453 return
3454 }
3455
3456 typ = r.typ()
3457 rtype = reflectdata.TypePtrAt(r.curfn, pos, typ)
3458 return
3459 }
3460
3461
3462 func (r *reader) varDictIndex(name *ir.Name) {
3463 if r.Bool() {
3464 idx := 1 + r.dict.rtypesOffset() + r.Len()
3465 if int(uint16(idx)) != idx {
3466 base.FatalfAt(name.Pos(), "DictIndex overflow for %v: %v", name, idx)
3467 }
3468 name.DictIndex = uint16(idx)
3469 }
3470 }
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480 func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) {
3481 typ, typRType = r.rtype0(pos)
3482 iface, ifaceRType = r.rtype0(pos)
3483
3484 idx := -1
3485 if r.Bool() {
3486 idx = r.Len()
3487 }
3488
3489 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
3490 if idx >= 0 {
3491 itab = r.rttiWord(pos, r.dict.itabsOffset()+idx)
3492 } else {
3493 base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ)
3494 base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface)
3495
3496 lsym := reflectdata.ITabLsym(typ, iface)
3497 itab = typecheck.LinksymAddr(r.curfn, pos, lsym, types.Types[types.TUINT8])
3498 }
3499 }
3500
3501 return
3502 }
3503
3504
3505
3506 func (r *reader) convRTTI(pos src.XPos) (typeWord, srcRType ir.Node) {
3507 r.Sync(pkgbits.SyncConvRTTI)
3508 src, srcRType0, dst, dstRType, itab := r.itab(pos)
3509 if !dst.IsInterface() {
3510 return
3511 }
3512
3513
3514 switch {
3515 case dst.IsEmptyInterface():
3516 if !src.IsInterface() {
3517 typeWord = srcRType0
3518 }
3519 case !src.IsInterface():
3520 typeWord = itab
3521 default:
3522 typeWord = dstRType
3523 }
3524
3525
3526 if !src.IsInterface() {
3527 srcRType = srcRType0
3528 }
3529
3530 return
3531 }
3532
3533 func (r *reader) exprType() ir.Node {
3534 r.Sync(pkgbits.SyncExprType)
3535 pos := r.pos()
3536
3537 var typ *types.Type
3538 var rtype, itab ir.Node
3539
3540 if r.Bool() {
3541
3542 typ, rtype, _, _, itab = r.itab(pos)
3543 if !typ.IsInterface() {
3544 rtype = nil
3545 }
3546 } else {
3547 typ, rtype = r.rtype0(pos)
3548
3549 if !r.Bool() {
3550 return ir.TypeNode(typ)
3551 }
3552 }
3553
3554 dt := ir.NewDynamicType(pos, rtype)
3555 dt.ITab = itab
3556 dt = typed(typ, dt).(*ir.DynamicType)
3557 if st := dt.ToStatic(); st != nil {
3558 return st
3559 }
3560 return dt
3561 }
3562
3563 func (r *reader) op() ir.Op {
3564 r.Sync(pkgbits.SyncOp)
3565 return ir.Op(r.Len())
3566 }
3567
3568
3569
3570 func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) {
3571 cgoPragmas := make([][]string, r.Len())
3572 for i := range cgoPragmas {
3573 cgoPragmas[i] = r.Strings()
3574 }
3575 target.CgoPragmas = cgoPragmas
3576
3577 r.pkgInitOrder(target)
3578
3579 r.pkgDecls(target)
3580
3581 r.Sync(pkgbits.SyncEOF)
3582 }
3583
3584
3585
3586 func (r *reader) pkgInitOrder(target *ir.Package) {
3587 initOrder := make([]ir.Node, r.Len())
3588 if len(initOrder) == 0 {
3589 return
3590 }
3591
3592
3593 pos := base.AutogeneratedPos
3594 lno := base.Pos
3595 defer func() { base.Pos = lno }()
3596 base.Pos = pos
3597
3598 fn := ir.NewFunc(pos, pos, typecheck.Lookup("init"), types.NewSignature(nil, nil, nil))
3599 fn.SetIsPackageInit(true)
3600 fn.SetInlinabilityChecked(true)
3601
3602 typecheck.DeclFunc(fn)
3603 r.curfn = fn
3604
3605 var varInitFns []*ir.Func
3606 if len(initOrder) <= maxInitStatements {
3607 fn.Body = r.doPkgInitOrder(initOrder)
3608 } else {
3609 varInitFns = r.splitLargeInitOrder(initOrder)
3610 calls := make([]ir.Node, len(varInitFns))
3611 for i, varInitFn := range varInitFns {
3612 ir.WithPos(fn, func() {
3613 calls[i] = typecheck.Call(r.curfn, varInitFn.Pos(), varInitFn.Nname, nil, false)
3614 })
3615 }
3616 fn.Body = calls
3617 }
3618
3619 r.curfn = nil
3620 r.locals = nil
3621
3622
3623 staticinit.OutlineMapInits(fn)
3624 for _, varInitFn := range varInitFns {
3625 staticinit.OutlineMapInits(varInitFn)
3626 }
3627
3628 target.Inits = append(target.Inits, fn)
3629 }
3630
3631 const maxInitStatements = 1000
3632
3633 func (r *reader) generateVarInitFunc(body []ir.Node) *ir.Func {
3634 fn := staticinit.GenerateVarInitFunc()
3635 typecheck.DeclFunc(fn)
3636
3637 old := r.curfn
3638 r.curfn = fn
3639 fn.Body = r.doPkgInitOrder(body)
3640 r.curfn = old
3641
3642 return fn
3643 }
3644
3645 func (r *reader) doPkgInitOrder(initOrder []ir.Node) []ir.Node {
3646 for i := range initOrder {
3647 lhs := make([]ir.Node, r.Len())
3648 for j := range lhs {
3649 lhs[j] = r.obj()
3650 }
3651 rhs := r.expr()
3652 pos := lhs[0].Pos()
3653
3654 var as ir.Node
3655 if len(lhs) == 1 {
3656 as = typecheck.Stmt(r.curfn, ir.NewAssignStmt(pos, lhs[0], rhs))
3657 } else {
3658 as = typecheck.Stmt(r.curfn, ir.NewAssignListStmt(pos, ir.OAS2, lhs, []ir.Node{rhs}))
3659 }
3660
3661 for _, v := range lhs {
3662 v.(*ir.Name).Defn = as
3663 }
3664
3665 initOrder[i] = as
3666 }
3667 return initOrder
3668 }
3669
3670 func (r *reader) splitLargeInitOrder(initOrder []ir.Node) []*ir.Func {
3671 var initFuncs []*ir.Func
3672 for chunk := range slices.Chunk(initOrder, maxInitStatements) {
3673 initFuncs = append(initFuncs, r.generateVarInitFunc(chunk))
3674 }
3675 return initFuncs
3676 }
3677
3678 func (r *reader) pkgDecls(target *ir.Package) {
3679 r.Sync(pkgbits.SyncDecls)
3680 for {
3681 switch code := codeDecl(r.Code(pkgbits.SyncDecl)); code {
3682 default:
3683 panic(fmt.Sprintf("unhandled decl: %v", code))
3684
3685 case declEnd:
3686 return
3687
3688 case declFunc:
3689 names := r.pkgObjs(target)
3690 assert(len(names) == 1)
3691 target.Funcs = append(target.Funcs, names[0].Func)
3692
3693 case declMethod:
3694 typ := r.typ()
3695 sym := r.selector()
3696
3697 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
3698 target.Funcs = append(target.Funcs, method.Nname.(*ir.Name).Func)
3699
3700 case declVar:
3701 names := r.pkgObjs(target)
3702
3703 if n := r.Len(); n > 0 {
3704 assert(len(names) == 1)
3705 embeds := make([]ir.Embed, n)
3706 for i := range embeds {
3707 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.Strings()}
3708 }
3709 names[0].Embed = &embeds
3710 target.Embeds = append(target.Embeds, names[0])
3711 }
3712
3713 case declOther:
3714 r.pkgObjs(target)
3715 }
3716 }
3717 }
3718
3719 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
3720 r.Sync(pkgbits.SyncDeclNames)
3721 nodes := make([]*ir.Name, r.Len())
3722 for i := range nodes {
3723 r.Sync(pkgbits.SyncDeclName)
3724
3725 name := r.obj().(*ir.Name)
3726 nodes[i] = name
3727
3728 sym := name.Sym()
3729 if sym.IsBlank() {
3730 continue
3731 }
3732
3733 switch name.Class {
3734 default:
3735 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
3736
3737 case ir.PEXTERN:
3738 target.Externs = append(target.Externs, name)
3739
3740 case ir.PFUNC:
3741 assert(name.Type().Recv() == nil)
3742
3743
3744 if strings.HasPrefix(sym.Name, "init.") {
3745 target.Inits = append(target.Inits, name.Func)
3746 }
3747 }
3748
3749 if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME {
3750 assert(!sym.OnExportList())
3751 target.PluginExports = append(target.PluginExports, name)
3752 sym.SetOnExportList(true)
3753 }
3754
3755 if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) {
3756 assert(!sym.Asm())
3757 target.AsmHdrDecls = append(target.AsmHdrDecls, name)
3758 sym.SetAsm(true)
3759 }
3760 }
3761
3762 return nodes
3763 }
3764
3765
3766
3767
3768
3769 func unifiedHaveInlineBody(fn *ir.Func) bool {
3770 if fn.Inl == nil {
3771 return false
3772 }
3773
3774 _, ok := bodyReaderFor(fn)
3775 return ok
3776 }
3777
3778 var inlgen = 0
3779
3780
3781
3782 func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int, profile *pgoir.Profile) *ir.InlinedCallExpr {
3783 pri, ok := bodyReaderFor(fn)
3784 if !ok {
3785 base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
3786 }
3787
3788 if !fn.Inl.HaveDcl {
3789 expandInline(fn, pri)
3790 }
3791
3792 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3793
3794 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type())
3795
3796 r.curfn = tmpfn
3797
3798 r.inlCaller = callerfn
3799 r.inlCall = call
3800 r.inlFunc = fn
3801 r.inlTreeIndex = inlIndex
3802 r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
3803 r.funarghack = true
3804
3805 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
3806 for i, cv := range r.inlFunc.ClosureVars {
3807
3808
3809 if cv.Outer.Curfn != callerfn {
3810 base.FatalfAt(call.Pos(), "inlining closure call across frames")
3811 }
3812 r.closureVars[i] = cv.Outer
3813 }
3814 if len(r.closureVars) != 0 && r.hasTypeParams() {
3815 r.dictParam = r.closureVars[len(r.closureVars)-1]
3816 }
3817
3818 r.declareParams()
3819
3820 var inlvars, retvars []*ir.Name
3821 {
3822 sig := r.curfn.Type()
3823 endParams := sig.NumRecvs() + sig.NumParams()
3824 endResults := endParams + sig.NumResults()
3825
3826 inlvars = r.curfn.Dcl[:endParams]
3827 retvars = r.curfn.Dcl[endParams:endResults]
3828 }
3829
3830 r.delayResults = fn.Inl.CanDelayResults
3831
3832 r.retlabel = typecheck.AutoLabel(callerfn, ".i")
3833 inlgen++
3834
3835 init := ir.TakeInit(call)
3836
3837
3838
3839
3840 if call.Op() == ir.OCALLFUNC {
3841 inline.CalleeEffects(&init, call.Fun)
3842 }
3843
3844 var args ir.Nodes
3845 if call.Op() == ir.OCALLMETH {
3846 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
3847 }
3848 args.Append(call.Args...)
3849
3850
3851 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, ir.ToNodes(inlvars), args)
3852 as2.Def = true
3853 var as2init ir.Nodes
3854 for _, name := range inlvars {
3855 if ir.IsBlank(name) {
3856 continue
3857 }
3858
3859 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3860 name.Defn = as2
3861 }
3862 as2.SetInit(as2init)
3863 init.Append(typecheck.Stmt(callerfn, as2))
3864
3865 if !r.delayResults {
3866
3867
3868 for _, name := range retvars {
3869
3870 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3871 ras := ir.NewAssignStmt(call.Pos(), name, nil)
3872 init.Append(typecheck.Stmt(callerfn, ras))
3873 }
3874 }
3875
3876
3877
3878
3879
3880
3881 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
3882
3883 ir.WithPos(r.curfn, func() {
3884 if !r.syntheticBody(call.Pos()) {
3885 assert(r.Bool())
3886
3887 r.curfn.Body = r.stmts()
3888 r.curfn.Endlineno = r.pos()
3889 }
3890
3891
3892
3893
3894
3895
3896 readBodies(typecheck.Target, true, profile)
3897
3898
3899 var edit func(ir.Node) ir.Node
3900 edit = func(n ir.Node) ir.Node {
3901 if ret, ok := n.(*ir.ReturnStmt); ok {
3902 n = typecheck.Stmt(callerfn, r.inlReturn(ret, retvars))
3903 }
3904 ir.EditChildren(n, edit)
3905 return n
3906 }
3907 edit(r.curfn)
3908 })
3909
3910 body := r.curfn.Body
3911
3912
3913 for _, name := range r.curfn.Dcl {
3914 name.Curfn = callerfn
3915
3916 if name.Class != ir.PAUTO {
3917 name.SetPos(r.inlPos(name.Pos()))
3918 name.SetInlFormal(true)
3919 name.Class = ir.PAUTO
3920 } else {
3921 name.SetInlLocal(true)
3922 }
3923 }
3924 callerfn.Dcl = append(callerfn.Dcl, r.curfn.Dcl...)
3925
3926 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
3927
3928 res := ir.NewInlinedCallExpr(call.Pos(), body, ir.ToNodes(retvars))
3929 res.SetInit(init)
3930 res.SetType(call.Type())
3931 res.SetTypecheck(1)
3932 res.Reshape = call.Reshape
3933
3934
3935 assert(len(todoBodies) == 0)
3936
3937 return res
3938 }
3939
3940
3941
3942 func (r *reader) inlReturn(ret *ir.ReturnStmt, retvars []*ir.Name) *ir.BlockStmt {
3943 pos := r.inlCall.Pos()
3944
3945 block := ir.TakeInit(ret)
3946
3947 if results := ret.Results; len(results) != 0 {
3948 assert(len(retvars) == len(results))
3949
3950 as2 := ir.NewAssignListStmt(pos, ir.OAS2, ir.ToNodes(retvars), ret.Results)
3951
3952 if r.delayResults {
3953 for _, name := range retvars {
3954
3955 block.Append(ir.NewDecl(pos, ir.ODCL, name))
3956 name.Defn = as2
3957 }
3958 }
3959
3960 block.Append(as2)
3961 }
3962
3963 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
3964 return ir.NewBlockStmt(pos, block)
3965 }
3966
3967
3968
3969 func expandInline(fn *ir.Func, pri pkgReaderIndex) {
3970
3971
3972
3973
3974
3975 fndcls := len(fn.Dcl)
3976 topdcls := len(typecheck.Target.Funcs)
3977
3978 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type())
3979 tmpfn.ClosureVars = fn.ClosureVars
3980
3981 {
3982 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3983
3984
3985 r.funarghack = true
3986
3987 r.funcBody(tmpfn)
3988 }
3989
3990
3991 for _, name := range tmpfn.Dcl {
3992 name.Curfn = fn
3993 }
3994 fn.Inl.Dcl = tmpfn.Dcl
3995 fn.Inl.HaveDcl = true
3996
3997
3998 assert(fndcls == len(fn.Dcl))
3999
4000
4001
4002
4003 typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
4004 }
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061 var needWrapperTypes []*types.Type
4062
4063
4064
4065 var haveWrapperTypes []*types.Type
4066
4067
4068
4069 var needMethodValueWrappers []methodValueWrapper
4070
4071
4072
4073
4074 var haveMethodValueWrappers []methodValueWrapper
4075
4076 type methodValueWrapper struct {
4077 rcvr *types.Type
4078 method *types.Field
4079 }
4080
4081
4082
4083 func (r *reader) needWrapper(typ *types.Type) {
4084
4085
4086
4087 if typ.IsPtr() || typ.IsKind(types.TFORW) || typ.HasShape() && !typ.IsInterface() {
4088 return
4089 }
4090
4091
4092 forceNeed := typ == types.ErrorType && base.Ctxt.Pkgpath == "runtime"
4093
4094
4095
4096
4097 if r.importedDef() && !forceNeed {
4098 haveWrapperTypes = append(haveWrapperTypes, typ)
4099 } else {
4100 needWrapperTypes = append(needWrapperTypes, typ)
4101 }
4102 }
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118 func (r *reader) importedDef() bool {
4119 return r.p != localPkgReader && !r.hasTypeParams()
4120 }
4121
4122
4123
4124 func MakeWrappers(target *ir.Package) {
4125
4126 needWrapperTypes = append(needWrapperTypes, types.ErrorType)
4127
4128 seen := make(map[string]*types.Type)
4129
4130 for _, typ := range haveWrapperTypes {
4131 wrapType(typ, target, seen, false)
4132 }
4133 haveWrapperTypes = nil
4134
4135 for _, typ := range needWrapperTypes {
4136 wrapType(typ, target, seen, true)
4137 }
4138 needWrapperTypes = nil
4139
4140 for _, wrapper := range haveMethodValueWrappers {
4141 wrapMethodValue(wrapper.rcvr, wrapper.method, target, false)
4142 }
4143 haveMethodValueWrappers = nil
4144
4145 for _, wrapper := range needMethodValueWrappers {
4146 wrapMethodValue(wrapper.rcvr, wrapper.method, target, true)
4147 }
4148 needMethodValueWrappers = nil
4149 }
4150
4151 func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) {
4152 key := typ.LinkString()
4153 if prev := seen[key]; prev != nil {
4154 if !types.Identical(typ, prev) {
4155 base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key)
4156 }
4157
4158
4159 typ.CopyTFlagFrom(prev)
4160 return
4161 }
4162 seen[key] = typ
4163
4164 if !needed {
4165
4166 return
4167 }
4168
4169 if !typ.IsInterface() {
4170 typecheck.CalcMethods(typ)
4171 }
4172 if !typ.IsUntyped() {
4173 typ.TFlag()
4174 }
4175 for _, meth := range typ.AllMethods() {
4176 if meth.Sym.IsBlank() || !meth.IsMethod() {
4177 base.FatalfAt(meth.Pos, "invalid method: %v", meth)
4178 }
4179
4180 methodWrapper(0, typ, meth, target)
4181
4182
4183 if !typ.IsInterface() {
4184 methodWrapper(1, typ, meth, target)
4185
4186
4187
4188 if typ.NotInHeap() {
4189 methodWrapper(2, typ, meth, target)
4190 }
4191 }
4192 }
4193 }
4194
4195 func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) {
4196 wrapper := tbase
4197 for i := 0; i < derefs; i++ {
4198 wrapper = types.NewPtr(wrapper)
4199 }
4200
4201 wrappee := method.Type.Recv().Type
4202 if types.Identical(wrapper, wrappee) ||
4203 !types.IsMethodApplicable(wrapper, method) ||
4204 !reflectdata.NeedEmit(tbase) {
4205 return
4206 }
4207 sym, sharedPromoted := ir.MethodSym(wrapper, method)
4208 if sym.Siggen() {
4209 if sharedPromoted {
4210 return
4211 }
4212 base.Fatalf("already generated wrapper %v", sym)
4213 }
4214 sym.SetSiggen(true)
4215
4216
4217 pos := base.AutogeneratedPos
4218
4219 fn := newWrapperFunc(pos, sym, wrapper, method)
4220
4221 var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
4222
4223
4224
4225 if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) {
4226 cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node))
4227 then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)}
4228 fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil))
4229 }
4230
4231
4232
4233 for i := 1; i < derefs; i++ {
4234 recv = Implicit(ir.NewStarExpr(pos, recv))
4235 }
4236
4237 addTailCall(pos, fn, recv, method)
4238
4239 finishWrapperFunc(fn, target)
4240 }
4241
4242 func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) {
4243 sym := ir.ReceiverMethodSymSuffix(recvType, method.Sym, "-fm")
4244 if sym.Uniq() {
4245 return
4246 }
4247 sym.SetUniq(true)
4248
4249
4250 pos := base.AutogeneratedPos
4251
4252 fn := newWrapperFunc(pos, sym, nil, method)
4253 sym.Def = fn.Nname
4254
4255
4256 recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
4257
4258 if !needed {
4259 return
4260 }
4261
4262 addTailCall(pos, fn, recv, method)
4263
4264 finishWrapperFunc(fn, target)
4265 }
4266
4267 func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
4268 sig := newWrapperType(wrapper, method)
4269 fn := ir.NewFunc(pos, pos, sym, sig)
4270 fn.DeclareParams(true)
4271 fn.SetDupok(true)
4272
4273 return fn
4274 }
4275
4276 func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
4277 ir.WithPos(fn, func() {
4278 typecheck.Stmts(fn, fn.Body)
4279 })
4280
4281
4282
4283
4284 interleaved.DevirtualizeAndInlineFunc(fn, nil)
4285
4286
4287
4288
4289
4290
4291
4292
4293 ir.VisitFuncAndClosures(fn, func(n ir.Node) {
4294 if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
4295 wrapMethodValue(n.X.Type(), n.Selection, target, true)
4296 }
4297 })
4298
4299 fn.Nname.Defn = fn
4300 target.Funcs = append(target.Funcs, fn)
4301 }
4302
4303
4304
4305
4306
4307 func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
4308 clone := func(params []*types.Field) []*types.Field {
4309 res := make([]*types.Field, len(params))
4310 for i, param := range params {
4311 res[i] = types.NewField(param.Pos, param.Sym, param.Type)
4312 res[i].SetIsDDD(param.IsDDD())
4313 }
4314 return res
4315 }
4316
4317 sig := method.Type
4318
4319 var recv *types.Field
4320 if recvType != nil {
4321 recv = types.NewField(sig.Recv().Pos, sig.Recv().Sym, recvType)
4322 }
4323 params := clone(sig.Params())
4324 results := clone(sig.Results())
4325
4326 return types.NewSignature(recv, params, results)
4327 }
4328
4329 func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) {
4330 sig := fn.Nname.Type()
4331 args := make([]ir.Node, sig.NumParams())
4332 for i, param := range sig.Params() {
4333 args[i] = param.Nname.(*ir.Name)
4334 }
4335
4336 dot := typecheck.XDotMethod(fn, pos, recv, method.Sym, true)
4337 call := typecheck.Call(fn, pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr)
4338
4339 if recv.Type() != nil && recv.Type().IsPtr() && method.Type.Recv().Type.IsPtr() &&
4340 method.Embedded != 0 &&
4341 (types.IsInterfaceMethod(method.Type) && base.Ctxt.Arch.Name != "wasm" ||
4342 !types.IsInterfaceMethod(method.Type) && !unifiedHaveInlineBody(ir.MethodExprName(dot).Func)) &&
4343
4344
4345 !((base.Ctxt.Arch.Name == "ppc64le" || base.Ctxt.Arch.Name == "ppc64") && base.Ctxt.Flag_dynlink) {
4346 if base.Debug.TailCall != 0 {
4347 base.WarnfAt(fn.Nname.Type().Recv().Type.Elem().Pos(), "tail call emitted for the method %v wrapper", method.Nname)
4348 }
4349
4350 fn.Body.Append(ir.NewTailCallStmt(pos, call))
4351 return
4352 }
4353
4354 fn.SetWrapper(true)
4355
4356 if method.Type.NumResults() == 0 {
4357 fn.Body.Append(call)
4358 return
4359 }
4360
4361 ret := ir.NewReturnStmt(pos, nil)
4362 ret.Results = []ir.Node{call}
4363 fn.Body.Append(ret)
4364 }
4365
4366 func setBasePos(pos src.XPos) {
4367
4368 base.Pos = pos
4369 }
4370
4371
4372
4373
4374
4375
4376 const dictParamName = typecheck.LocalDictName
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386 func shapeSig(fn *ir.Func, dict *readerDict) *types.Type {
4387 sig := fn.Nname.Type()
4388 oldRecv := sig.Recv()
4389
4390 var recv *types.Field
4391 if oldRecv != nil {
4392 recv = types.NewField(oldRecv.Pos, oldRecv.Sym, oldRecv.Type)
4393 }
4394
4395 params := make([]*types.Field, 1+sig.NumParams())
4396 params[0] = types.NewField(fn.Pos(), fn.Sym().Pkg.Lookup(dictParamName), types.NewPtr(dict.varType()))
4397 for i, param := range sig.Params() {
4398 d := types.NewField(param.Pos, param.Sym, param.Type)
4399 d.SetIsDDD(param.IsDDD())
4400 params[1+i] = d
4401 }
4402
4403 results := make([]*types.Field, sig.NumResults())
4404 for i, result := range sig.Results() {
4405 results[i] = types.NewField(result.Pos, result.Sym, result.Type)
4406 }
4407
4408 typ := types.NewSignature(recv, params, results)
4409 typ.SetHasShape(true)
4410 return typ
4411 }
4412
View as plain text