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
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027 uls := under.LinkString()
1028 if base.Debug.MaxShapeLen != 0 && len(uls) > base.Debug.MaxShapeLen {
1029 switch targLS := targ.LinkString(); {
1030 case targ.IsShape():
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044 uls = targ.Sym().Name
1045
1046 case targ.Sym() != nil && len(targLS) <= base.Debug.MaxShapeLen:
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056 uls = targLS
1057
1058 default:
1059
1060
1061 h := hash.Sum32([]byte(uls))
1062 uls = hex.EncodeToString(h[:])
1063 }
1064 }
1065
1066 sym := types.ShapePkg.Lookup(uls)
1067 if sym.Def == nil {
1068 name := ir.NewDeclNameAt(under.Pos(), ir.OTYPE, sym)
1069 typ := types.NewNamed(name)
1070 typ.SetUnderlying(under)
1071 sym.Def = typed(typ, name)
1072 }
1073 res := sym.Def.Type()
1074 assert(res.IsShape())
1075 assert(res.HasShape())
1076 return res
1077 }
1078
1079
1080 func (pr *pkgReader) objDictIdx(sym *types.Sym, idx index, implicits, explicits []*types.Type, shaped bool) (*readerDict, error) {
1081 r := pr.newReader(pkgbits.SectionObjDict, idx, pkgbits.SyncObject1)
1082
1083 dict := readerDict{
1084 shaped: shaped,
1085 }
1086
1087 nimplicits := r.Len()
1088 nreceivers := 0
1089 if r.Version().Has(pkgbits.GenericMethods) {
1090 nreceivers = r.Len()
1091 }
1092 nexplicits := r.Len() + nreceivers
1093
1094 if nimplicits > len(implicits) || nexplicits != len(explicits) {
1095 return nil, fmt.Errorf("%v has %v+%v params, but instantiated with %v+%v args", sym, nimplicits, nexplicits, len(implicits), len(explicits))
1096 }
1097
1098 dict.targs = append(implicits[:nimplicits:nimplicits], explicits...)
1099 dict.implicits = nimplicits
1100 dict.receivers = nreceivers
1101
1102
1103 for range dict.targs[dict.implicits:] {
1104
1105 r.typInfo()
1106 }
1107
1108 dict.derived = make([]derivedInfo, r.Len())
1109 dict.derivedTypes = make([]*types.Type, len(dict.derived))
1110 for i := range dict.derived {
1111 dict.derived[i] = derivedInfo{idx: r.Reloc(pkgbits.SectionType)}
1112 if r.Version().Has(pkgbits.DerivedInfoNeeded) {
1113 assert(!r.Bool())
1114 }
1115 }
1116
1117
1118
1119
1120
1121
1122
1123 for _, targ := range dict.targs {
1124 if targ.HasShape() {
1125 dict.shaped = true
1126 break
1127 }
1128 }
1129
1130
1131
1132 for i, targ := range dict.targs {
1133 basic := r.Bool()
1134 if dict.shaped {
1135 dict.targs[i] = Shapify(targ, basic)
1136 }
1137 }
1138
1139 dict.baseSym = dict.mangle(sym)
1140
1141 dict.typeParamMethodExprs = make([]readerMethodExprInfo, r.Len())
1142 for i := range dict.typeParamMethodExprs {
1143 typeParamIdx := r.Len()
1144 method := r.selector()
1145
1146 dict.typeParamMethodExprs[i] = readerMethodExprInfo{typeParamIdx, method}
1147 }
1148
1149 dict.subdicts = make([]objInfo, r.Len())
1150 for i := range dict.subdicts {
1151 dict.subdicts[i] = r.objInfo()
1152 }
1153
1154 dict.rtypes = make([]typeInfo, r.Len())
1155 for i := range dict.rtypes {
1156 dict.rtypes[i] = r.typInfo()
1157 }
1158
1159 dict.itabs = make([]itabInfo, r.Len())
1160 for i := range dict.itabs {
1161 dict.itabs[i] = itabInfo{typ: r.typInfo(), iface: r.typInfo()}
1162 }
1163
1164 return &dict, nil
1165 }
1166
1167 func (r *reader) recvTypeParamNames() {
1168 r.Sync(pkgbits.SyncTypeParamNames)
1169
1170 for range r.dict.targs[r.dict.implicits : r.dict.implicits+r.dict.receivers] {
1171 r.pos()
1172 r.localIdent()
1173 }
1174 }
1175
1176 func (r *reader) typeParamNames() {
1177 r.Sync(pkgbits.SyncTypeParamNames)
1178
1179 for range r.dict.targs[r.dict.implicits+r.dict.receivers:] {
1180 r.pos()
1181 r.localIdent()
1182 }
1183 }
1184
1185 func (r *reader) method(rext *reader) *types.Field {
1186 r.Sync(pkgbits.SyncMethod)
1187 if r.Version().Has(pkgbits.PreserveMethodOrder) {
1188 _ = r.Len()
1189 }
1190 npos := r.pos()
1191 sym := r.selector()
1192 r.typeParamNames()
1193 recv := r.param()
1194 typ := r.signature(recv)
1195
1196 fpos := r.pos()
1197 fn := ir.NewFunc(fpos, npos, ir.ReceiverMethodSym(recv.Type, sym), typ)
1198 name := fn.Nname
1199
1200 if r.hasTypeParams() {
1201 name.Func.SetDupok(true)
1202 if r.dict.shaped {
1203 typ = shapeSig(name.Func, r.dict)
1204 setType(name, typ)
1205 }
1206 }
1207
1208 rext.funcExt(name, sym)
1209
1210 meth := types.NewField(name.Func.Pos(), sym, typ)
1211 meth.Nname = name
1212 meth.SetNointerface(name.Func.Pragma&ir.Nointerface != 0)
1213
1214 return meth
1215 }
1216
1217 func (r *reader) qualifiedIdent() (pkg *types.Pkg, sym *types.Sym) {
1218 r.Sync(pkgbits.SyncSym)
1219 pkg = r.pkg()
1220 if name := r.String(); name != "" {
1221 sym = pkg.Lookup(name)
1222 }
1223 return
1224 }
1225
1226 func (r *reader) localIdent() *types.Sym {
1227 r.Sync(pkgbits.SyncLocalIdent)
1228 pkg := r.pkg()
1229 if name := r.String(); name != "" {
1230 return pkg.Lookup(name)
1231 }
1232 return nil
1233 }
1234
1235 func (r *reader) selector() *types.Sym {
1236 r.Sync(pkgbits.SyncSelector)
1237 pkg := r.pkg()
1238 name := r.String()
1239 if types.IsExported(name) {
1240 pkg = types.LocalPkg
1241 }
1242 return pkg.Lookup(name)
1243 }
1244
1245 func (r *reader) hasTypeParams() bool {
1246 return r.dict.hasTypeParams()
1247 }
1248
1249 func (dict *readerDict) hasTypeParams() bool {
1250 return dict != nil && len(dict.targs) != 0
1251 }
1252
1253
1254
1255 func (r *reader) funcExt(name *ir.Name, method *types.Sym) {
1256 r.Sync(pkgbits.SyncFuncExt)
1257
1258 fn := name.Func
1259
1260
1261 if !fn.Pos().IsKnown() {
1262 fn.SetPos(name.Pos())
1263 }
1264
1265
1266
1267
1268
1269
1270
1271
1272 if name.Sym().Pkg == types.LocalPkg || r.hasTypeParams() {
1273 name.Defn = fn
1274 }
1275
1276 fn.Pragma = r.pragmaFlag()
1277 r.linkname(name)
1278
1279 if buildcfg.GOARCH == "wasm" {
1280 importmod := r.String()
1281 importname := r.String()
1282 exportname := r.String()
1283
1284 if importmod != "" && importname != "" {
1285 fn.WasmImport = &ir.WasmImport{
1286 Module: importmod,
1287 Name: importname,
1288 }
1289 }
1290 if exportname != "" {
1291 if method != nil {
1292 base.ErrorfAt(fn.Pos(), 0, "cannot use //go:wasmexport on a method")
1293 }
1294 fn.WasmExport = &ir.WasmExport{Name: exportname}
1295 }
1296 }
1297
1298 if r.Bool() {
1299 assert(name.Defn == nil)
1300
1301 fn.ABI = obj.ABI(r.Uint64())
1302
1303
1304 for _, f := range name.Type().RecvParams() {
1305 f.Note = r.String()
1306 }
1307
1308 if r.Bool() {
1309 fn.Inl = &ir.Inline{
1310 Cost: int32(r.Len()),
1311 CanDelayResults: r.Bool(),
1312 }
1313 if buildcfg.Experiment.NewInliner {
1314 fn.Inl.Properties = r.String()
1315 }
1316 }
1317 } else {
1318 r.addBody(name.Func, method)
1319 }
1320 r.Sync(pkgbits.SyncEOF)
1321 }
1322
1323 func (r *reader) typeExt(name *ir.Name) {
1324 r.Sync(pkgbits.SyncTypeExt)
1325
1326 typ := name.Type()
1327
1328 if r.hasTypeParams() {
1329
1330
1331 typ.SetIsFullyInstantiated(true)
1332
1333 for _, targ := range r.dict.targs {
1334 if targ.HasShape() {
1335 typ.SetHasShape(true)
1336 break
1337 }
1338 }
1339 }
1340
1341 name.SetPragma(r.pragmaFlag())
1342
1343 typecheck.SetBaseTypeIndex(typ, r.Int64(), r.Int64())
1344 }
1345
1346 func (r *reader) varExt(name *ir.Name) {
1347 r.Sync(pkgbits.SyncVarExt)
1348 r.linkname(name)
1349 }
1350
1351 func (r *reader) linkname(name *ir.Name) {
1352 assert(name.Op() == ir.ONAME)
1353 r.Sync(pkgbits.SyncLinkname)
1354
1355 if idx := r.Int64(); idx >= 0 {
1356 lsym := name.Linksym()
1357 lsym.SymIdx = int32(idx)
1358 lsym.Set(obj.AttrIndexed, true)
1359 } else {
1360 linkname := r.String()
1361 std := r.Bool()
1362 sym := name.Sym()
1363 sym.Linkname = linkname
1364 if sym.Pkg == types.LocalPkg && linkname != "" {
1365
1366
1367
1368
1369
1370
1371 if std {
1372 sym.Linksym().Set(obj.AttrLinknameStd, true)
1373 } else {
1374 sym.Linksym().Set(obj.AttrLinkname, true)
1375 }
1376 }
1377 }
1378 }
1379
1380 func (r *reader) pragmaFlag() ir.PragmaFlag {
1381 r.Sync(pkgbits.SyncPragma)
1382 return ir.PragmaFlag(r.Int())
1383 }
1384
1385
1386
1387
1388
1389 var bodyReader = map[*ir.Func]pkgReaderIndex{}
1390
1391
1392
1393 var importBodyReader = map[*types.Sym]pkgReaderIndex{}
1394
1395
1396
1397 func bodyReaderFor(fn *ir.Func) (pri pkgReaderIndex, ok bool) {
1398 if fn.Nname.Defn != nil {
1399 pri, ok = bodyReader[fn]
1400 base.AssertfAt(ok, base.Pos, "must have bodyReader for %v", fn)
1401 } else {
1402 pri, ok = importBodyReader[fn.Sym()]
1403 }
1404 return
1405 }
1406
1407
1408
1409 var todoDicts []func()
1410
1411
1412
1413 var todoBodies []*ir.Func
1414
1415
1416
1417 func (r *reader) addBody(fn *ir.Func, method *types.Sym) {
1418
1419
1420 assert(fn.Nname.Defn != nil)
1421
1422 idx := r.Reloc(pkgbits.SectionBody)
1423
1424 pri := pkgReaderIndex{r.p, idx, r.dict, method, nil}
1425 bodyReader[fn] = pri
1426
1427 if r.curfn == nil {
1428 todoBodies = append(todoBodies, fn)
1429 return
1430 }
1431
1432 pri.funcBody(fn)
1433 }
1434
1435 func (pri pkgReaderIndex) funcBody(fn *ir.Func) {
1436 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
1437 panicking := true
1438 defer func() {
1439 if panicking {
1440
1441
1442
1443
1444 fmt.Printf("****** panic traversed funcBody of %v\n", fn)
1445 }
1446 }()
1447 r.funcBody(fn)
1448 panicking = false
1449
1450 }
1451
1452
1453
1454 func (r *reader) funcBody(fn *ir.Func) {
1455 r.curfn = fn
1456 r.closureVars = fn.ClosureVars
1457 if len(r.closureVars) != 0 && r.hasTypeParams() {
1458 r.dictParam = r.closureVars[len(r.closureVars)-1]
1459 }
1460
1461 ir.WithPos(fn, func() {
1462 r.declareParams()
1463
1464 if r.syntheticBody(fn.Pos()) {
1465 return
1466 }
1467
1468 if !r.Bool() {
1469 return
1470 }
1471
1472 body := r.stmts()
1473 if body == nil {
1474 body = []ir.Node{typecheck.Stmt(r.curfn, ir.NewBlockStmt(src.NoXPos, nil))}
1475 }
1476 fn.Body = body
1477 fn.Endlineno = r.pos()
1478 })
1479
1480 r.marker.WriteTo(fn)
1481 }
1482
1483
1484
1485 func (r *reader) syntheticBody(pos src.XPos) bool {
1486 if r.synthetic != nil {
1487 r.synthetic(pos, r)
1488 return true
1489 }
1490
1491
1492
1493 if r.hasTypeParams() && !r.dict.shaped {
1494 r.callShaped(pos)
1495 return true
1496 }
1497
1498 return false
1499 }
1500
1501
1502
1503 func (r *reader) callShaped(pos src.XPos) {
1504 shapedObj := r.dict.shapedObj
1505 assert(shapedObj != nil)
1506
1507 var shapedFn ir.Node
1508 if r.methodSym == nil {
1509
1510 assert(shapedObj.Op() == ir.ONAME && shapedObj.Class == ir.PFUNC)
1511 shapedFn = shapedObj
1512 } else {
1513
1514
1515 shapedFn = shapedMethodExpr(pos, shapedObj, r.methodSym)
1516 }
1517
1518 params := r.syntheticArgs()
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529 var args ir.Nodes
1530 if r.methodSym != nil {
1531 args.Append(params[0])
1532 params = params[1:]
1533 }
1534 args.Append(typecheck.Expr(r.curfn, ir.NewAddrExpr(pos, r.p.dictNameOf(r.dict))))
1535 args.Append(params...)
1536
1537 r.syntheticTailCall(pos, shapedFn, args)
1538 }
1539
1540
1541
1542 func (r *reader) syntheticArgs() ir.Nodes {
1543 sig := r.curfn.Nname.Type()
1544 return ir.ToNodes(r.curfn.Dcl[:sig.NumRecvs()+sig.NumParams()])
1545 }
1546
1547
1548
1549 func (r *reader) syntheticTailCall(pos src.XPos, fn ir.Node, args ir.Nodes) {
1550
1551
1552 r.curfn.SetWrapper(true)
1553
1554 call := typecheck.Call(r.curfn, pos, fn, args, fn.Type().IsVariadic()).(*ir.CallExpr)
1555
1556 var stmt ir.Node
1557 if fn.Type().NumResults() != 0 {
1558 stmt = typecheck.Stmt(r.curfn, ir.NewReturnStmt(pos, []ir.Node{call}))
1559 } else {
1560 stmt = call
1561 }
1562 r.curfn.Body.Append(stmt)
1563 }
1564
1565
1566 func (pr *pkgReader) dictNameOf(dict *readerDict) *ir.Name {
1567 pos := base.AutogeneratedPos
1568
1569
1570 base.AssertfAt(!dict.shaped, pos, "runtime dictionary of shaped object %v", dict.baseSym)
1571
1572 sym := dict.baseSym.Pkg.Lookup(objabi.GlobalDictPrefix + "." + dict.baseSym.Name)
1573 if sym.Def != nil {
1574 return sym.Def.(*ir.Name)
1575 }
1576
1577 name := ir.NewNameAt(pos, sym, dict.varType())
1578 name.Class = ir.PEXTERN
1579 sym.Def = name
1580
1581 lsym := name.Linksym()
1582 ot := 0
1583
1584 assertOffset := func(section string, offset int) {
1585 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)
1586 }
1587
1588 assertOffset("type param method exprs", dict.typeParamMethodExprsOffset())
1589 for _, info := range dict.typeParamMethodExprs {
1590 typeParam := dict.targs[info.typeParamIdx]
1591 method := typecheck.NewMethodExpr(pos, typeParam, info.method)
1592
1593 rsym := method.FuncName().Linksym()
1594 assert(rsym.ABI() == obj.ABIInternal)
1595
1596 ot = objw.SymPtr(lsym, ot, rsym, 0)
1597 }
1598
1599 assertOffset("subdictionaries", dict.subdictsOffset())
1600 for _, info := range dict.subdicts {
1601 explicits := pr.typListIdx(info.explicits, dict)
1602
1603
1604
1605 name := pr.objDictName(info.idx, dict.targs, explicits)
1606
1607 ot = objw.SymPtr(lsym, ot, name.Linksym(), 0)
1608 }
1609
1610 assertOffset("rtypes", dict.rtypesOffset())
1611 for _, info := range dict.rtypes {
1612 typ := pr.typIdx(info, dict, true)
1613 ot = objw.SymPtr(lsym, ot, reflectdata.TypeLinksym(typ), 0)
1614
1615
1616 reflectdata.MarkTypeUsedInInterface(typ, lsym)
1617 }
1618
1619
1620
1621
1622
1623
1624
1625 assertOffset("itabs", dict.itabsOffset())
1626 for _, info := range dict.itabs {
1627 typ := pr.typIdx(info.typ, dict, true)
1628 iface := pr.typIdx(info.iface, dict, true)
1629
1630 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
1631 ot = objw.SymPtr(lsym, ot, reflectdata.ITabLsym(typ, iface), 0)
1632 } else {
1633 ot += types.PtrSize
1634 }
1635
1636
1637 reflectdata.MarkTypeUsedInInterface(typ, lsym)
1638 reflectdata.MarkTypeUsedInInterface(iface, lsym)
1639 }
1640
1641 objw.Global(lsym, int32(ot), obj.DUPOK|obj.RODATA)
1642
1643 return name
1644 }
1645
1646
1647
1648 func (dict *readerDict) typeParamMethodExprsOffset() int {
1649 return 0
1650 }
1651
1652
1653
1654 func (dict *readerDict) subdictsOffset() int {
1655 return dict.typeParamMethodExprsOffset() + len(dict.typeParamMethodExprs)
1656 }
1657
1658
1659
1660 func (dict *readerDict) rtypesOffset() int {
1661 return dict.subdictsOffset() + len(dict.subdicts)
1662 }
1663
1664
1665
1666 func (dict *readerDict) itabsOffset() int {
1667 return dict.rtypesOffset() + len(dict.rtypes)
1668 }
1669
1670
1671
1672 func (dict *readerDict) numWords() int64 {
1673 return int64(dict.itabsOffset() + len(dict.itabs))
1674 }
1675
1676
1677 func (dict *readerDict) varType() *types.Type {
1678 return types.NewArray(types.Types[types.TUINTPTR], dict.numWords())
1679 }
1680
1681 func (r *reader) declareParams() {
1682 r.curfn.DeclareParams(!r.funarghack)
1683
1684 for _, name := range r.curfn.Dcl {
1685 if name.Sym().Name == dictParamName {
1686 r.dictParam = name
1687 continue
1688 }
1689
1690 r.addLocal(name)
1691 }
1692 }
1693
1694 func (r *reader) addLocal(name *ir.Name) {
1695 if r.synthetic == nil {
1696 r.Sync(pkgbits.SyncAddLocal)
1697 if r.p.SyncMarkers() {
1698 want := r.Int()
1699 if have := len(r.locals); have != want {
1700 base.FatalfAt(name.Pos(), "locals table has desynced")
1701 }
1702 }
1703 r.varDictIndex(name)
1704 }
1705
1706 r.locals = append(r.locals, name)
1707 }
1708
1709 func (r *reader) useLocal() *ir.Name {
1710 r.Sync(pkgbits.SyncUseObjLocal)
1711 if r.Bool() {
1712 return r.locals[r.Len()]
1713 }
1714 return r.closureVars[r.Len()]
1715 }
1716
1717 func (r *reader) openScope() {
1718 r.Sync(pkgbits.SyncOpenScope)
1719 pos := r.pos()
1720
1721 if base.Flag.Dwarf {
1722 r.scopeVars = append(r.scopeVars, len(r.curfn.Dcl))
1723 r.marker.Push(pos)
1724 }
1725 }
1726
1727 func (r *reader) closeScope() {
1728 r.Sync(pkgbits.SyncCloseScope)
1729 r.lastCloseScopePos = r.pos()
1730
1731 r.closeAnotherScope()
1732 }
1733
1734
1735
1736
1737
1738 func (r *reader) closeAnotherScope() {
1739 r.Sync(pkgbits.SyncCloseAnotherScope)
1740
1741 if base.Flag.Dwarf {
1742 scopeVars := r.scopeVars[len(r.scopeVars)-1]
1743 r.scopeVars = r.scopeVars[:len(r.scopeVars)-1]
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772 retract := true
1773 for _, n := range r.curfn.Dcl[scopeVars:] {
1774 if !n.AutoTemp() {
1775 retract = false
1776 break
1777 }
1778 }
1779
1780 if retract {
1781
1782 r.marker.Unpush()
1783 } else {
1784 r.marker.Pop(r.lastCloseScopePos)
1785 }
1786 }
1787 }
1788
1789
1790
1791 func (r *reader) stmt() ir.Node {
1792 return block(r.stmts())
1793 }
1794
1795 func block(stmts []ir.Node) ir.Node {
1796 switch len(stmts) {
1797 case 0:
1798 return nil
1799 case 1:
1800 return stmts[0]
1801 default:
1802 return ir.NewBlockStmt(stmts[0].Pos(), stmts)
1803 }
1804 }
1805
1806 func (r *reader) stmts() ir.Nodes {
1807 assert(r.curfn == r.curfn)
1808 var res ir.Nodes
1809
1810 r.Sync(pkgbits.SyncStmts)
1811 for {
1812 tag := codeStmt(r.Code(pkgbits.SyncStmt1))
1813 if tag == stmtEnd {
1814 r.Sync(pkgbits.SyncStmtsEnd)
1815 return res
1816 }
1817
1818 if n := r.stmt1(tag, &res); n != nil {
1819 res.Append(typecheck.Stmt(r.curfn, n))
1820 }
1821 }
1822 }
1823
1824 func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node {
1825 var label *types.Sym
1826 if n := len(*out); n > 0 {
1827 if ls, ok := (*out)[n-1].(*ir.LabelStmt); ok {
1828 label = ls.Label
1829 }
1830 }
1831
1832 switch tag {
1833 default:
1834 panic("unexpected statement")
1835
1836 case stmtAssign:
1837 pos := r.pos()
1838 lno := base.Pos
1839 defer func() { base.Pos = lno }()
1840 base.Pos = pos
1841 names, lhs := r.assignList()
1842 rhs := r.multiExpr()
1843
1844 if len(rhs) == 0 {
1845 for _, name := range names {
1846 as := ir.NewAssignStmt(pos, name, nil)
1847 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, name))
1848 out.Append(typecheck.Stmt(r.curfn, as))
1849 }
1850 return nil
1851 }
1852
1853 if len(lhs) == 1 && len(rhs) == 1 {
1854 n := ir.NewAssignStmt(pos, lhs[0], rhs[0])
1855 n.Def = r.initDefn(n, names)
1856 return n
1857 }
1858
1859 n := ir.NewAssignListStmt(pos, ir.OAS2, lhs, rhs)
1860 n.Def = r.initDefn(n, names)
1861 return n
1862
1863 case stmtAssignOp:
1864 op := r.op()
1865 lhs := r.expr()
1866 pos := r.pos()
1867 rhs := r.expr()
1868 return ir.NewAssignOpStmt(pos, op, lhs, rhs)
1869
1870 case stmtIncDec:
1871 op := r.op()
1872 lhs := r.expr()
1873 pos := r.pos()
1874 n := ir.NewAssignOpStmt(pos, op, lhs, ir.NewOne(pos, lhs.Type()))
1875 n.IncDec = true
1876 return n
1877
1878 case stmtBlock:
1879 out.Append(r.blockStmt()...)
1880 return nil
1881
1882 case stmtBranch:
1883 pos := r.pos()
1884 op := r.op()
1885 sym := r.optLabel()
1886 return ir.NewBranchStmt(pos, op, sym)
1887
1888 case stmtCall:
1889 pos := r.pos()
1890 op := r.op()
1891 call := r.expr()
1892 stmt := ir.NewGoDeferStmt(pos, op, call)
1893 if op == ir.ODEFER {
1894 x := r.optExpr()
1895 if x != nil {
1896 stmt.DeferAt = x.(ir.Expr)
1897 }
1898 }
1899 return stmt
1900
1901 case stmtExpr:
1902 return r.expr()
1903
1904 case stmtFor:
1905 return r.forStmt(label)
1906
1907 case stmtIf:
1908 return r.ifStmt()
1909
1910 case stmtLabel:
1911 pos := r.pos()
1912 sym := r.label()
1913 return ir.NewLabelStmt(pos, sym)
1914
1915 case stmtReturn:
1916 pos := r.pos()
1917 results := r.multiExpr()
1918 return ir.NewReturnStmt(pos, results)
1919
1920 case stmtSelect:
1921 return r.selectStmt(label)
1922
1923 case stmtSend:
1924 pos := r.pos()
1925 ch := r.expr()
1926 value := r.expr()
1927 return ir.NewSendStmt(pos, ch, value)
1928
1929 case stmtSwitch:
1930 return r.switchStmt(label)
1931 }
1932 }
1933
1934 func (r *reader) assignList() ([]*ir.Name, []ir.Node) {
1935 lhs := make([]ir.Node, r.Len())
1936 var names []*ir.Name
1937
1938 for i := range lhs {
1939 expr, def := r.assign()
1940 lhs[i] = expr
1941 if def {
1942 names = append(names, expr.(*ir.Name))
1943 }
1944 }
1945
1946 return names, lhs
1947 }
1948
1949
1950
1951 func (r *reader) assign() (ir.Node, bool) {
1952 switch tag := codeAssign(r.Code(pkgbits.SyncAssign)); tag {
1953 default:
1954 panic("unhandled assignee expression")
1955
1956 case assignBlank:
1957 return typecheck.AssignExpr(r.curfn, ir.BlankNode), false
1958
1959 case assignDef:
1960 pos := r.pos()
1961 lno := base.Pos
1962 defer func() { base.Pos = lno }()
1963 setBasePos(pos)
1964 name := r.curfn.NewLocal(pos, r.localIdent(), r.typ())
1965 r.addLocal(name)
1966 return name, true
1967
1968 case assignExpr:
1969 return r.expr(), false
1970 }
1971 }
1972
1973 func (r *reader) blockStmt() []ir.Node {
1974 r.Sync(pkgbits.SyncBlockStmt)
1975 r.openScope()
1976 stmts := r.stmts()
1977 r.closeScope()
1978 return stmts
1979 }
1980
1981 func (r *reader) forStmt(label *types.Sym) ir.Node {
1982 r.Sync(pkgbits.SyncForStmt)
1983
1984 r.openScope()
1985
1986 isRange := r.Bool()
1987 pos := r.pos()
1988 lno := base.Pos
1989 defer func() { base.Pos = lno }()
1990 base.Pos = pos
1991
1992 if isRange {
1993 rang := ir.NewRangeStmt(pos, nil, nil, nil, nil, false)
1994 rang.Label = label
1995
1996 names, lhs := r.assignList()
1997 if len(lhs) >= 1 {
1998 rang.Key = lhs[0]
1999 if len(lhs) >= 2 {
2000 rang.Value = lhs[1]
2001 }
2002 }
2003 rang.Def = r.initDefn(rang, names)
2004
2005 rang.X = r.expr()
2006 if rang.X.Type().IsMap() {
2007 rang.RType = r.rtype(pos)
2008 }
2009 if rang.Key != nil && !ir.IsBlank(rang.Key) {
2010 rang.KeyTypeWord, rang.KeySrcRType = r.convRTTI(pos)
2011 }
2012 if rang.Value != nil && !ir.IsBlank(rang.Value) {
2013 rang.ValueTypeWord, rang.ValueSrcRType = r.convRTTI(pos)
2014 }
2015
2016 rang.Body = r.blockStmt()
2017 rang.DistinctVars = r.Bool()
2018 r.closeAnotherScope()
2019
2020 return rang
2021 }
2022
2023 init := r.stmt()
2024 if init != nil && init.Pos().IsKnown() {
2025 lno := base.Pos
2026 defer func() { base.Pos = lno }()
2027 base.Pos = init.Pos()
2028 }
2029 cond := r.optExpr()
2030 post := r.stmt()
2031 body := r.blockStmt()
2032 perLoopVars := r.Bool()
2033 r.closeAnotherScope()
2034
2035 if ir.IsConst(cond, constant.Bool) && !ir.BoolVal(cond) {
2036 return init
2037 }
2038
2039 stmt := ir.NewForStmt(pos, init, cond, post, body, perLoopVars)
2040 stmt.Label = label
2041 return stmt
2042 }
2043
2044 func (r *reader) ifStmt() ir.Node {
2045 r.Sync(pkgbits.SyncIfStmt)
2046 r.openScope()
2047 pos := r.pos()
2048 lno := base.Pos
2049 defer func() { base.Pos = lno }()
2050 base.Pos = pos
2051 init := r.stmts()
2052 if len(init) > 0 && init[len(init)-1].Pos().IsKnown() {
2053 lno := base.Pos
2054 defer func() { base.Pos = lno }()
2055 base.Pos = init[len(init)-1].Pos()
2056 }
2057 cond := r.expr()
2058 staticCond := r.Int()
2059 var then, els []ir.Node
2060 if staticCond >= 0 {
2061 then = r.blockStmt()
2062 } else {
2063 r.lastCloseScopePos = r.pos()
2064 }
2065 if staticCond <= 0 {
2066 els = r.stmts()
2067 }
2068 r.closeAnotherScope()
2069
2070 if staticCond != 0 {
2071
2072
2073
2074
2075 if cond.Op() != ir.OLITERAL {
2076 init.Append(typecheck.Stmt(r.curfn, ir.NewAssignStmt(pos, ir.BlankNode, cond)))
2077 }
2078 init.Append(then...)
2079 init.Append(els...)
2080 return block(init)
2081 }
2082
2083 n := ir.NewIfStmt(pos, cond, then, els)
2084 n.SetInit(init)
2085 return n
2086 }
2087
2088 func (r *reader) selectStmt(label *types.Sym) ir.Node {
2089 r.Sync(pkgbits.SyncSelectStmt)
2090
2091 pos := r.pos()
2092 clauses := make([]*ir.CommClause, r.Len())
2093 for i := range clauses {
2094 if i > 0 {
2095 r.closeScope()
2096 }
2097 r.openScope()
2098
2099 pos := r.pos()
2100 comm := r.stmt()
2101 body := r.stmts()
2102
2103
2104
2105
2106
2107
2108 if as, ok := comm.(*ir.AssignStmt); ok && as.Op() == ir.OAS && !as.Def {
2109 if conv, ok := as.Y.(*ir.ConvExpr); ok && conv.Op() == ir.OCONVIFACE {
2110 base.AssertfAt(conv.Implicit(), conv.Pos(), "expected implicit conversion: %v", conv)
2111
2112 recv := conv.X
2113 base.AssertfAt(recv.Op() == ir.ORECV, recv.Pos(), "expected receive expression: %v", recv)
2114
2115 tmp := r.temp(pos, recv.Type())
2116
2117
2118 tmpAs := ir.NewAssignStmt(pos, tmp, recv)
2119 tmpAs.Def = true
2120 tmpAs.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
2121 comm = tmpAs
2122
2123
2124 conv.X = tmp
2125 body = append([]ir.Node{as}, body...)
2126 }
2127 }
2128
2129
2130
2131
2132
2133 if as2, ok := comm.(*ir.AssignListStmt); ok && as2.Op() == ir.OAS2 {
2134 init := ir.TakeInit(as2.Rhs[0])
2135 base.AssertfAt(len(init) == 1 && init[0].Op() == ir.OAS2RECV, as2.Pos(), "unexpected assignment: %+v", as2)
2136
2137 comm = init[0]
2138 body = append([]ir.Node{as2}, body...)
2139 }
2140
2141 clauses[i] = ir.NewCommStmt(pos, comm, body)
2142 }
2143 if len(clauses) > 0 {
2144 r.closeScope()
2145 }
2146 n := ir.NewSelectStmt(pos, clauses)
2147 n.Label = label
2148 return n
2149 }
2150
2151 func (r *reader) switchStmt(label *types.Sym) ir.Node {
2152 r.Sync(pkgbits.SyncSwitchStmt)
2153
2154 r.openScope()
2155 pos := r.pos()
2156 lno := base.Pos
2157 defer func() { base.Pos = lno }()
2158 base.Pos = pos
2159 init := r.stmt()
2160 if init != nil && init.Pos().IsKnown() {
2161 lno := base.Pos
2162 defer func() { base.Pos = lno }()
2163 base.Pos = init.Pos()
2164 }
2165
2166 var tag ir.Node
2167 var ident *ir.Ident
2168 var iface *types.Type
2169 if r.Bool() {
2170 pos := r.pos()
2171 lno := base.Pos
2172 defer func() { base.Pos = lno }()
2173 base.Pos = pos
2174 if r.Bool() {
2175 ident = ir.NewIdent(r.pos(), r.localIdent())
2176 }
2177 x := r.expr()
2178 iface = x.Type()
2179 tag = ir.NewTypeSwitchGuard(pos, ident, x)
2180 } else {
2181 tag = r.optExpr()
2182 }
2183
2184 clauses := make([]*ir.CaseClause, r.Len())
2185 for i := range clauses {
2186 if i > 0 {
2187 r.closeScope()
2188 }
2189 r.openScope()
2190
2191 pos := r.pos()
2192 lno := base.Pos
2193 base.Pos = pos
2194 var cases, rtypes []ir.Node
2195 if iface != nil {
2196 cases = make([]ir.Node, r.Len())
2197 if len(cases) == 0 {
2198 cases = nil
2199 }
2200 for i := range cases {
2201 if r.Bool() {
2202 cases[i] = typecheck.Expr(r.curfn, types.BuiltinPkg.Lookup("nil").Def.(*ir.NilExpr))
2203 } else {
2204 cases[i] = r.exprType()
2205 }
2206 }
2207 } else {
2208 cases = r.exprList()
2209
2210
2211
2212
2213
2214
2215
2216
2217 if tag == nil {
2218 for i, cas := range cases {
2219 if cas.Type().IsEmptyInterface() {
2220 for len(rtypes) < i {
2221 rtypes = append(rtypes, nil)
2222 }
2223 rtypes = append(rtypes, reflectdata.TypePtrAt(r.curfn, cas.Pos(), types.Types[types.TBOOL]))
2224 }
2225 }
2226 }
2227 }
2228
2229 clause := ir.NewCaseStmt(pos, cases, nil)
2230 clause.RTypes = rtypes
2231
2232 if ident != nil {
2233 name := r.curfn.NewLocal(r.pos(), ident.Sym(), r.typ())
2234 r.addLocal(name)
2235 clause.Var = name
2236 name.Defn = tag
2237 }
2238
2239 clause.Body = r.stmts()
2240 clauses[i] = clause
2241 base.Pos = lno
2242 }
2243 if len(clauses) > 0 {
2244 r.closeScope()
2245 }
2246 r.closeScope()
2247
2248 n := ir.NewSwitchStmt(pos, tag, clauses)
2249 n.Label = label
2250 if init != nil {
2251 n.SetInit([]ir.Node{init})
2252 }
2253 return n
2254 }
2255
2256 func (r *reader) label() *types.Sym {
2257 r.Sync(pkgbits.SyncLabel)
2258 name := r.String()
2259 if r.inlCall != nil && name != "_" {
2260 name = fmt.Sprintf("~%s·%d", name, inlgen)
2261 }
2262 return typecheck.Lookup(name)
2263 }
2264
2265 func (r *reader) optLabel() *types.Sym {
2266 r.Sync(pkgbits.SyncOptLabel)
2267 if r.Bool() {
2268 return r.label()
2269 }
2270 return nil
2271 }
2272
2273
2274
2275
2276 func (r *reader) initDefn(defn ir.InitNode, names []*ir.Name) bool {
2277 if len(names) == 0 {
2278 return false
2279 }
2280
2281 init := make([]ir.Node, len(names))
2282 for i, name := range names {
2283 name.Defn = defn
2284 init[i] = ir.NewDecl(name.Pos(), ir.ODCL, name)
2285 }
2286 defn.SetInit(init)
2287 return true
2288 }
2289
2290
2291
2292
2293 func (r *reader) expr() (res ir.Node) {
2294 defer func() {
2295 if res != nil && res.Typecheck() == 0 {
2296 base.FatalfAt(res.Pos(), "%v missed typecheck", res)
2297 }
2298 }()
2299
2300 switch tag := codeExpr(r.Code(pkgbits.SyncExpr)); tag {
2301 default:
2302 panic("unhandled expression")
2303
2304 case exprLocal:
2305 return typecheck.Expr(r.curfn, r.useLocal())
2306
2307 case exprGlobal:
2308
2309
2310 return typecheck.Callee(r.curfn, r.obj())
2311
2312 case exprFuncInst:
2313 origPos, pos := r.origPos()
2314 wrapperFn, baseFn, dictPtr := r.funcInst(pos)
2315 if wrapperFn != nil {
2316 return wrapperFn
2317 }
2318 return r.curry(origPos, false, baseFn, dictPtr, nil)
2319
2320 case exprConst:
2321 pos := r.pos()
2322 typ := r.typ()
2323 val := FixValue(typ, r.Value())
2324 return ir.NewBasicLit(pos, typ, val)
2325
2326 case exprZero:
2327 pos := r.pos()
2328 typ := r.typ()
2329 return ir.NewZero(pos, typ)
2330
2331 case exprCompLit:
2332 return r.compLit()
2333
2334 case exprFuncLit:
2335 return r.funcLit()
2336
2337 case exprFieldVal:
2338 x := r.expr()
2339 pos := r.pos()
2340 sym := r.selector()
2341
2342 return typecheck.XDotField(r.curfn, pos, x, sym)
2343
2344 case exprMethodVal:
2345 recv := r.expr()
2346 origPos, pos := r.origPos()
2347 wrapperFn, baseFn, dictPtr := r.methodExpr()
2348
2349
2350
2351 if wrapperFn, ok := wrapperFn.(*ir.SelectorExpr); ok && wrapperFn.Op() == ir.OMETHEXPR {
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369 if recv.Type().HasShape() {
2370 typ := wrapperFn.Type().Param(0).Type
2371 if !types.Identical(typ, recv.Type()) {
2372 base.FatalfAt(wrapperFn.Pos(), "receiver %L does not match %L", recv, wrapperFn)
2373 }
2374 recv = typecheck.Expr(r.curfn, ir.NewConvExpr(recv.Pos(), ir.OCONVNOP, typ, recv))
2375 }
2376
2377 n := typecheck.XDotMethod(r.curfn, pos, recv, wrapperFn.Sel, false)
2378
2379
2380
2381
2382
2383
2384
2385 if n.Selection != wrapperFn.Selection {
2386 assert(n.Selection.Sym == wrapperFn.Selection.Sym)
2387 assert(types.Identical(n.Selection.Type, wrapperFn.Selection.Type))
2388 assert(types.Identical(n.Selection.Type.Recv().Type, wrapperFn.Selection.Type.Recv().Type))
2389 }
2390
2391 wrapper := methodValueWrapper{
2392 rcvr: n.X.Type(),
2393 method: n.Selection,
2394 }
2395
2396 if r.importedDef() {
2397 haveMethodValueWrappers = append(haveMethodValueWrappers, wrapper)
2398 } else {
2399 needMethodValueWrappers = append(needMethodValueWrappers, wrapper)
2400 }
2401 return n
2402 }
2403
2404
2405
2406 return r.curry(origPos, true, baseFn, recv, dictPtr)
2407
2408 case exprMethodExpr:
2409 recv := r.typ()
2410
2411 implicits := make([]int, r.Len())
2412 for i := range implicits {
2413 implicits[i] = r.Len()
2414 }
2415 var deref, addr bool
2416 if r.Bool() {
2417 deref = true
2418 } else if r.Bool() {
2419 addr = true
2420 }
2421
2422 origPos, pos := r.origPos()
2423 wrapperFn, baseFn, dictPtr := r.methodExpr()
2424
2425
2426
2427
2428
2429
2430
2431 if wrapperFn != nil && len(implicits) == 0 && !deref && !addr {
2432 if !types.Identical(recv, wrapperFn.Type().Param(0).Type) {
2433 base.FatalfAt(pos, "want receiver type %v, but have method %L", recv, wrapperFn)
2434 }
2435 return wrapperFn
2436 }
2437
2438
2439
2440
2441 if method, ok := wrapperFn.(*ir.SelectorExpr); ok && method.Op() == ir.OMETHEXPR && !recv.HasShape() {
2442 return typecheck.NewMethodExpr(pos, recv, method.Sel)
2443 }
2444
2445 return r.methodExprWrap(origPos, recv, implicits, deref, addr, baseFn, dictPtr)
2446
2447 case exprIndex:
2448 x := r.expr()
2449 pos := r.pos()
2450 index := r.expr()
2451 n := typecheck.Expr(r.curfn, ir.NewIndexExpr(pos, x, index))
2452 switch n.Op() {
2453 case ir.OINDEXMAP:
2454 n := n.(*ir.IndexExpr)
2455 n.RType = r.rtype(pos)
2456 }
2457 return n
2458
2459 case exprSlice:
2460 x := r.expr()
2461 pos := r.pos()
2462 var index [3]ir.Node
2463 for i := range index {
2464 index[i] = r.optExpr()
2465 }
2466 op := ir.OSLICE
2467 if index[2] != nil {
2468 op = ir.OSLICE3
2469 }
2470 return typecheck.Expr(r.curfn, ir.NewSliceExpr(pos, op, x, index[0], index[1], index[2]))
2471
2472 case exprAssert:
2473 x := r.expr()
2474 pos := r.pos()
2475 typ := r.exprType()
2476 srcRType := r.rtype(pos)
2477
2478
2479 if typ, ok := typ.(*ir.DynamicType); ok && typ.Op() == ir.ODYNAMICTYPE {
2480 assert := ir.NewDynamicTypeAssertExpr(pos, ir.ODYNAMICDOTTYPE, x, typ.RType)
2481 assert.SrcRType = srcRType
2482 assert.ITab = typ.ITab
2483 return typed(typ.Type(), assert)
2484 }
2485 return typecheck.Expr(r.curfn, ir.NewTypeAssertExpr(pos, x, typ.Type()))
2486
2487 case exprUnaryOp:
2488 op := r.op()
2489 pos := r.pos()
2490 x := r.expr()
2491
2492 switch op {
2493 case ir.OADDR:
2494 return typecheck.Expr(r.curfn, typecheck.NodAddrAt(r.curfn, pos, x))
2495 case ir.ODEREF:
2496 return typecheck.Expr(r.curfn, ir.NewStarExpr(pos, x))
2497 }
2498 return typecheck.Expr(r.curfn, ir.NewUnaryExpr(pos, op, x))
2499
2500 case exprBinaryOp:
2501 op := r.op()
2502 x := r.expr()
2503 pos := r.pos()
2504 y := r.expr()
2505
2506 switch op {
2507 case ir.OANDAND, ir.OOROR:
2508 return typecheck.Expr(r.curfn, ir.NewLogicalExpr(pos, op, x, y))
2509 case ir.OLSH, ir.ORSH:
2510
2511
2512 if ir.IsConstNode(y) {
2513 val := constant.ToInt(y.Val())
2514 assert(val.Kind() == constant.Int && constant.Sign(val) >= 0)
2515 }
2516 }
2517 return typecheck.Expr(r.curfn, ir.NewBinaryExpr(pos, op, x, y))
2518
2519 case exprRecv:
2520 x := r.expr()
2521 pos := r.pos()
2522 for i, n := 0, r.Len(); i < n; i++ {
2523 x = Implicit(typecheck.DotField(pos, x, r.Len()))
2524 }
2525 if r.Bool() {
2526 x = Implicit(Deref(pos, x.Type().Elem(), x))
2527 } else if r.Bool() {
2528 x = Implicit(Addr(r.curfn, pos, x))
2529 }
2530 return x
2531
2532 case exprCall:
2533 var fun ir.Node
2534 var args ir.Nodes
2535 if r.Bool() {
2536 recv := r.expr()
2537 _, method, dictPtr := r.methodExpr()
2538
2539 if recv.Type().IsInterface() && method.Op() == ir.OMETHEXPR {
2540 method := method.(*ir.SelectorExpr)
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550 fun = typecheck.XDotMethod(r.curfn, method.Pos(), recv, method.Sel, true)
2551 } else {
2552 if recv.Type().IsInterface() {
2553
2554
2555 if base.Flag.LowerM != 0 {
2556 base.WarnfAt(method.Pos(), "imprecise interface call")
2557 }
2558 }
2559
2560 fun = method
2561 args.Append(recv)
2562 }
2563 if dictPtr != nil {
2564 args.Append(dictPtr)
2565 }
2566 } else if r.Bool() {
2567 pos := r.pos()
2568 _, shapedFn, dictPtr := r.funcInst(pos)
2569 fun = shapedFn
2570 args.Append(dictPtr)
2571 } else {
2572 fun = r.expr()
2573 }
2574 pos := r.pos()
2575 args.Append(r.multiExpr()...)
2576 dots := r.Bool()
2577 n := typecheck.Call(r.curfn, pos, fun, args, dots)
2578 switch n.Op() {
2579 case ir.OAPPEND:
2580 n := n.(*ir.CallExpr)
2581 n.RType = r.rtype(pos)
2582
2583
2584 if n.IsDDD {
2585 if conv, ok := n.Args[1].(*ir.ConvExpr); ok && conv.Op() == ir.OCONVNOP && conv.Implicit() {
2586 n.Args[1] = conv.X
2587 }
2588 }
2589 case ir.OCOPY:
2590 n := n.(*ir.BinaryExpr)
2591 n.RType = r.rtype(pos)
2592 case ir.ODELETE:
2593 n := n.(*ir.CallExpr)
2594 n.RType = r.rtype(pos)
2595 case ir.OUNSAFESLICE:
2596 n := n.(*ir.BinaryExpr)
2597 n.RType = r.rtype(pos)
2598 }
2599 return n
2600
2601 case exprMake:
2602 pos := r.pos()
2603 typ := r.exprType()
2604 extra := r.exprs()
2605 n := typecheck.Expr(r.curfn, ir.NewCallExpr(pos, ir.OMAKE, nil, append([]ir.Node{typ}, extra...))).(*ir.MakeExpr)
2606 n.RType = r.rtype(pos)
2607 return n
2608
2609 case exprNew:
2610 pos := r.pos()
2611 if r.Bool() {
2612
2613 x := r.expr()
2614 x = typecheck.DefaultLit(x, nil)
2615 var init ir.Nodes
2616 addr := ir.NewAddrExpr(pos, r.tempCopy(pos, x, &init))
2617 addr.SetInit(init)
2618 return typecheck.Expr(r.curfn, addr)
2619 }
2620
2621 return typecheck.Expr(r.curfn, ir.NewUnaryExpr(pos, ir.ONEW, r.exprType()))
2622
2623 case exprSizeof:
2624 return ir.NewUintptr(r.pos(), r.typ().Size())
2625
2626 case exprAlignof:
2627 return ir.NewUintptr(r.pos(), r.typ().Alignment())
2628
2629 case exprOffsetof:
2630 pos := r.pos()
2631 typ := r.typ()
2632 types.CalcSize(typ)
2633
2634 var offset int64
2635 for i := r.Len(); i >= 0; i-- {
2636 field := typ.Field(r.Len())
2637 offset += field.Offset
2638 typ = field.Type
2639 }
2640
2641 return ir.NewUintptr(pos, offset)
2642
2643 case exprReshape:
2644 typ := r.typ()
2645 x := r.expr()
2646
2647 if types.IdenticalStrict(x.Type(), typ) {
2648 return x
2649 }
2650
2651
2652
2653
2654
2655
2656 if x.Type() == types.UntypedBool && typ.IsBoolean() {
2657 return x
2658 }
2659
2660 base.AssertfAt(x.Type().HasShape() || typ.HasShape(), x.Pos(), "%L and %v are not shape types", x, typ)
2661 base.AssertfAt(types.Identical(x.Type(), typ), x.Pos(), "%L is not shape-identical to %v", x, typ)
2662
2663
2664
2665
2666
2667
2668
2669 base.AssertfAt(ir.HasUniquePos(x), x.Pos(), "cannot call SetType(%v) on %L", typ, x)
2670
2671 if base.Debug.Reshape != 0 {
2672 base.WarnfAt(x.Pos(), "reshaping %L to %v", x, typ)
2673 }
2674
2675 x.SetType(typ)
2676
2677 if call, ok := x.(*ir.CallExpr); ok {
2678 call.Reshape = true
2679 }
2680
2681 return x
2682
2683 case exprConvert:
2684 implicit := r.Bool()
2685 typ := r.typ()
2686 pos := r.pos()
2687 typeWord, srcRType := r.convRTTI(pos)
2688 dstTypeParam := r.Bool()
2689 identical := r.Bool()
2690 x := r.expr()
2691
2692
2693
2694 if dstTypeParam && ir.IsConstNode(x) {
2695
2696 if v := typecheck.ConvertVal(x.Val(), typ, false); v.Kind() != constant.Unknown {
2697 x = ir.NewBasicLit(x.Pos(), typ, v)
2698
2699 n := Implicit(ir.NewConvExpr(pos, ir.OCONVNOP, typ, x))
2700 n.SetTypecheck(1)
2701 return n
2702 }
2703
2704
2705
2706 }
2707
2708
2709 x = typecheck.DefaultLit(x, typ)
2710
2711 ce := ir.NewConvExpr(pos, ir.OCONV, typ, x)
2712 ce.TypeWord, ce.SrcRType = typeWord, srcRType
2713 if implicit {
2714 ce.SetImplicit(true)
2715 }
2716 n := typecheck.Expr(r.curfn, ce)
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734 if !identical {
2735 if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) {
2736 n.SetOp(ir.OCONVIFACE)
2737 }
2738 }
2739
2740 return n
2741
2742 case exprRuntimeBuiltin:
2743 builtin := typecheck.LookupRuntime(r.String())
2744 return builtin
2745 }
2746 }
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770 func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) {
2771
2772 var implicits []*types.Type
2773 if r.dict != nil {
2774 implicits = r.dict.targs
2775 }
2776
2777 if r.Bool() {
2778 idx := r.Len()
2779 info := r.dict.subdicts[idx]
2780 explicits := r.p.typListIdx(info.explicits, r.dict)
2781
2782 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2783
2784
2785
2786 dictPtrType := baseFn.Type().Param(0).Type
2787 dictPtr = typecheck.Expr(r.curfn, ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2788
2789 return
2790 }
2791
2792 info := r.objInfo()
2793 explicits := r.p.typListIdx(info.explicits, r.dict)
2794
2795 wrapperFn = r.p.objIdx(info.idx, implicits, explicits, false).(*ir.Name)
2796 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2797
2798 dictName := r.p.objDictName(info.idx, implicits, explicits)
2799 dictPtr = typecheck.Expr(r.curfn, ir.NewAddrExpr(pos, dictName))
2800
2801 return
2802 }
2803
2804 func (pr *pkgReader) objDictName(idx index, implicits, explicits []*types.Type) *ir.Name {
2805 rname := pr.newReader(pkgbits.SectionName, idx, pkgbits.SyncObject1)
2806 _, sym := rname.qualifiedIdent()
2807 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
2808
2809 if tag == pkgbits.ObjStub {
2810 assert(!sym.IsBlank())
2811 if pri, ok := objReader[sym]; ok {
2812 return pri.pr.objDictName(pri.idx, nil, explicits)
2813 }
2814 base.Fatalf("unresolved stub: %v", sym)
2815 }
2816
2817 dict, err := pr.objDictIdx(sym, idx, implicits, explicits, false)
2818 if err != nil {
2819 base.Fatalf("%v", err)
2820 }
2821
2822 return pr.dictNameOf(dict)
2823 }
2824
2825
2826
2827
2828
2829
2830
2831
2832 func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node {
2833 var captured ir.Nodes
2834 captured.Append(fun, arg0)
2835 if arg1 != nil {
2836 captured.Append(arg1)
2837 }
2838
2839 params, results := syntheticSig(fun.Type())
2840 params = params[len(captured)-1:]
2841 typ := types.NewSignature(nil, params, results)
2842
2843 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2844 fun := captured[0]
2845
2846 var args ir.Nodes
2847 args.Append(captured[1:]...)
2848 args.Append(r.syntheticArgs()...)
2849
2850 r.syntheticTailCall(pos, fun, args)
2851 }
2852
2853 return r.syntheticClosure(origPos, typ, ifaceHack, captured, addBody)
2854 }
2855
2856
2857
2858
2859 func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node {
2860 var captured ir.Nodes
2861 captured.Append(method)
2862
2863 params, results := syntheticSig(method.Type())
2864
2865
2866 params[0].Type = recv
2867
2868
2869
2870
2871 if dictPtr != nil {
2872 captured.Append(dictPtr)
2873 params = append(params[:1], params[2:]...)
2874 }
2875
2876 typ := types.NewSignature(nil, params, results)
2877
2878 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2879 fn := captured[0]
2880 args := r.syntheticArgs()
2881
2882
2883 {
2884 arg := args[0]
2885 for _, ix := range implicits {
2886 arg = Implicit(typecheck.DotField(pos, arg, ix))
2887 }
2888 if deref {
2889 arg = Implicit(Deref(pos, arg.Type().Elem(), arg))
2890 } else if addr {
2891 arg = Implicit(Addr(r.curfn, pos, arg))
2892 }
2893 args[0] = arg
2894 }
2895
2896
2897 if dictPtr != nil {
2898 newArgs := make([]ir.Node, len(args)+1)
2899 newArgs[0] = args[0]
2900 newArgs[1] = captured[1]
2901 copy(newArgs[2:], args[1:])
2902 args = newArgs
2903 }
2904
2905 r.syntheticTailCall(pos, fn, args)
2906 }
2907
2908 return r.syntheticClosure(origPos, typ, false, captured, addBody)
2909 }
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925 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 {
2926
2927
2928
2929
2930
2931 isSafe := func(n ir.Node) bool {
2932 if n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PFUNC {
2933 return true
2934 }
2935 if n.Op() == ir.OMETHEXPR {
2936 return true
2937 }
2938
2939 return false
2940 }
2941
2942 fn := r.inlClosureFunc(origPos, typ, ir.OCLOSURE)
2943 fn.SetWrapper(true)
2944
2945 clo := fn.OClosure
2946 inlPos := clo.Pos()
2947
2948 var init ir.Nodes
2949 for i, n := range captures {
2950 if isSafe(n) {
2951 continue
2952 }
2953
2954 tmp := r.tempCopy(inlPos, n, &init)
2955 ir.NewClosureVar(origPos, fn, tmp)
2956
2957
2958
2959 if ifaceHack && i == 1 && n.Type().IsInterface() {
2960 check := ir.NewUnaryExpr(inlPos, ir.OCHECKNIL, ir.NewUnaryExpr(inlPos, ir.OITAB, tmp))
2961 init.Append(typecheck.Stmt(r.curfn, check))
2962 }
2963 }
2964
2965 pri := pkgReaderIndex{synthetic: func(pos src.XPos, r *reader) {
2966 captured := make([]ir.Node, len(captures))
2967 next := 0
2968 for i, n := range captures {
2969 if isSafe(n) {
2970 captured[i] = n
2971 } else {
2972 captured[i] = r.closureVars[next]
2973 next++
2974 }
2975 }
2976 assert(next == len(r.closureVars))
2977
2978 addBody(origPos, r, captured)
2979 }}
2980 bodyReader[fn] = pri
2981 pri.funcBody(fn)
2982
2983 return ir.InitExpr(init, clo)
2984 }
2985
2986
2987
2988
2989 func syntheticSig(sig *types.Type) (params, results []*types.Field) {
2990 clone := func(params []*types.Field) []*types.Field {
2991 res := make([]*types.Field, len(params))
2992 for i, param := range params {
2993
2994
2995
2996
2997
2998
2999 res[i] = types.NewField(base.AutogeneratedPos, param.Sym, param.Type)
3000 res[i].SetIsDDD(param.IsDDD())
3001 }
3002 return res
3003 }
3004
3005 return clone(sig.Params()), clone(sig.Results())
3006 }
3007
3008 func (r *reader) optExpr() ir.Node {
3009 if r.Bool() {
3010 return r.expr()
3011 }
3012 return nil
3013 }
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038 func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) {
3039 recv := r.typ()
3040
3041 var sig *types.Type
3042 generic := r.Version().Has(pkgbits.GenericMethods) && r.Bool()
3043 if !generic {
3044
3045
3046 sig = typecheck.NewMethodType(r.typ(), recv)
3047 }
3048
3049 pos := r.pos()
3050 sym := r.selector()
3051
3052 if r.Bool() {
3053 idx := r.Len()
3054 word := r.dictWord(pos, r.dict.typeParamMethodExprsOffset()+idx)
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065 fn := typecheck.Expr(r.curfn, ir.NewConvExpr(pos, ir.OCONVNOP, sig, ir.NewAddrExpr(pos, word)))
3066 return fn, fn, nil
3067 }
3068
3069 if r.Bool() {
3070 idx := r.Len()
3071 info := r.dict.subdicts[idx]
3072 explicits := r.p.typListIdx(info.explicits, r.dict)
3073
3074 shapedObj := r.p.objIdx(info.idx, nil, explicits, true).(*ir.Name)
3075 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
3076
3077
3078
3079 dictPtrType := shapedFn.Type().Param(1).Type
3080 dictPtr := typecheck.Expr(r.curfn, ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
3081
3082 return nil, shapedFn, dictPtr
3083 }
3084
3085 if r.Bool() {
3086 info := r.objInfo()
3087 explicits := r.p.typListIdx(info.explicits, r.dict)
3088
3089 shapedObj := r.p.objIdx(info.idx, nil, explicits, true).(*ir.Name)
3090 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
3091
3092 dict := r.p.objDictName(info.idx, nil, explicits)
3093 dictPtr := typecheck.Expr(r.curfn, ir.NewAddrExpr(pos, dict))
3094
3095
3096 if !types.Identical(dictPtr.Type(), shapedFn.Type().Param(1).Type) {
3097 base.FatalfAt(pos, "dict %L, but shaped method %L", dict, shapedFn)
3098 }
3099
3100 if !generic {
3101
3102
3103 base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv)
3104 wrapperFn := typecheck.NewMethodExpr(pos, recv, sym)
3105 base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig)
3106 return wrapperFn, shapedFn, dictPtr
3107 } else {
3108
3109
3110
3111
3112 return nil, shapedFn, dictPtr
3113 }
3114 }
3115
3116
3117 base.AssertfAt(!recv.HasShape() || recv.IsInterface(), pos, "shaped receiver %v", recv)
3118 fn := typecheck.NewMethodExpr(pos, recv, sym)
3119 return fn, fn, nil
3120 }
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144 func shapedMethodExpr(pos src.XPos, obj *ir.Name, sym *types.Sym) ir.Node {
3145 if obj.Op() == ir.OTYPE {
3146
3147 typ := obj.Type()
3148 assert(typ.HasShape())
3149
3150 method := func() *types.Field {
3151 for _, m := range typ.Methods() {
3152 if m.Sym == sym {
3153 return m
3154 }
3155 }
3156
3157 base.FatalfAt(pos, "failed to find method %v in shaped type %v", sym, typ)
3158 panic("unreachable")
3159 }()
3160
3161 return typecheck.NewMethodExpr(pos, method.Type.Recv().Type, sym)
3162 } else {
3163
3164 assert(obj.Op() == ir.ONAME && obj.Class == ir.PFUNC)
3165 typ := obj.Type()
3166 assert(typ.HasShape())
3167
3168
3169
3170
3171
3172
3173
3174 lsym := obj.Linksym().Name
3175
3176
3177 idx := func() int {
3178 depth, i := 0, len(lsym)-1
3179 for {
3180 switch lsym[i] {
3181 case ']':
3182 depth++
3183 case '[':
3184 depth--
3185 }
3186 if depth == 0 {
3187 return i
3188 }
3189 i--
3190 }
3191 }()
3192 msym := sym.Pkg.Lookup(lsym[idx-len(sym.Name):])
3193
3194
3195
3196 m := types.NewField(obj.Pos(), msym, typ)
3197 m.Nname = obj
3198
3199 n := ir.NewSelectorExpr(pos, ir.OMETHEXPR, ir.TypeNode(typ.Recv().Type), msym)
3200 n.Selection = m
3201 n.SetType(typecheck.NewMethodType(typ, typ.Recv().Type))
3202 n.SetTypecheck(1)
3203
3204 return n
3205 }
3206 }
3207
3208 func (r *reader) multiExpr() []ir.Node {
3209 r.Sync(pkgbits.SyncMultiExpr)
3210
3211 if r.Bool() {
3212 pos := r.pos()
3213 expr := r.expr()
3214
3215 results := make([]ir.Node, r.Len())
3216 as := ir.NewAssignListStmt(pos, ir.OAS2, nil, []ir.Node{expr})
3217 as.Def = true
3218 for i := range results {
3219 tmp := r.temp(pos, r.typ())
3220 tmp.Defn = as
3221 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
3222 as.Lhs.Append(tmp)
3223
3224 res := ir.Node(tmp)
3225 if r.Bool() {
3226 n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)
3227 n.TypeWord, n.SrcRType = r.convRTTI(pos)
3228 n.SetImplicit(true)
3229 res = typecheck.Expr(r.curfn, n)
3230 }
3231 results[i] = res
3232 }
3233
3234
3235 results[0] = ir.InitExpr([]ir.Node{typecheck.Stmt(r.curfn, as)}, results[0])
3236 return results
3237 }
3238
3239
3240 exprs := make([]ir.Node, r.Len())
3241 if len(exprs) == 0 {
3242 return nil
3243 }
3244 for i := range exprs {
3245 exprs[i] = r.expr()
3246 }
3247 return exprs
3248 }
3249
3250
3251 func (r *reader) temp(pos src.XPos, typ *types.Type) *ir.Name {
3252 return typecheck.TempAt(pos, r.curfn, typ)
3253 }
3254
3255
3256
3257 func (r *reader) tempCopy(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name {
3258 tmp := r.temp(pos, expr.Type())
3259
3260 init.Append(typecheck.Stmt(r.curfn, ir.NewDecl(pos, ir.ODCL, tmp)))
3261
3262 assign := ir.NewAssignStmt(pos, tmp, expr)
3263 assign.Def = true
3264 init.Append(typecheck.Stmt(r.curfn, assign))
3265
3266 tmp.Defn = assign
3267
3268 return tmp
3269 }
3270
3271 func (r *reader) compLit() ir.Node {
3272 r.Sync(pkgbits.SyncCompLit)
3273 pos := r.pos()
3274 typ0 := r.typ()
3275
3276 typ := typ0
3277 if typ.IsPtr() {
3278 typ = typ.Elem()
3279 }
3280 if typ.Kind() == types.TFORW {
3281 base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
3282 }
3283 var rtype ir.Node
3284 if typ.IsMap() {
3285 rtype = r.rtype(pos)
3286 }
3287
3288 var elems []ir.Node
3289 if r.Version().Has(pkgbits.CompactCompLiterals) {
3290 n := r.Int()
3291 elems = make([]ir.Node, max(n, -n) )
3292 switch typ.Kind() {
3293 default:
3294 base.FatalfAt(pos, "unexpected composite literal type: %v", typ)
3295 case types.TARRAY:
3296 r.arrayElems(n >= 0, elems)
3297 case types.TMAP:
3298 r.mapElems(elems)
3299 case types.TSLICE:
3300 r.arrayElems(n >= 0, elems)
3301 case types.TSTRUCT:
3302 r.structElems(typ, n >= 0, elems)
3303 }
3304 } else {
3305 elems = make([]ir.Node, r.Len())
3306 isStruct := typ.Kind() == types.TSTRUCT
3307 for i := range elems {
3308 elemp := &elems[i]
3309 if isStruct {
3310 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.Len()), nil)
3311 *elemp, elemp = sk, &sk.Value
3312 } else if r.Bool() {
3313 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3314 *elemp, elemp = kv, &kv.Value
3315 }
3316 *elemp = r.expr()
3317 }
3318 }
3319
3320 lit := typecheck.Expr(r.curfn, ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems))
3321 if rtype != nil {
3322 lit := lit.(*ir.CompLitExpr)
3323 lit.RType = rtype
3324 }
3325 if typ0.IsPtr() {
3326 lit = typecheck.Expr(r.curfn, typecheck.NodAddrAt(r.curfn, pos, lit))
3327 lit.SetType(typ0)
3328 }
3329 return lit
3330 }
3331
3332 func (r *reader) arrayElems(valuesOnly bool, elems []ir.Node) {
3333 if valuesOnly {
3334 for i := range elems {
3335 elems[i] = r.expr()
3336 }
3337 return
3338 }
3339
3340 for i := range elems {
3341 if r.Bool() {
3342 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3343 kv.Value = r.expr()
3344 elems[i] = kv
3345 } else {
3346 elems[i] = r.expr()
3347 }
3348 }
3349 }
3350
3351 func (r *reader) mapElems(elems []ir.Node) {
3352
3353 for i := range elems {
3354 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3355 kv.Value = r.expr()
3356 elems[i] = kv
3357 }
3358 }
3359
3360 func (r *reader) structElems(typ *types.Type, valuesOnly bool, elems []ir.Node) {
3361 if valuesOnly {
3362 for i := range elems {
3363 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(i), nil)
3364 sk.Value = r.expr()
3365 elems[i] = sk
3366 }
3367 return
3368 }
3369
3370
3371 for i := range elems {
3372 pos := r.pos()
3373 var fld *types.Field
3374 if n := r.Int(); n < 0 {
3375
3376 typ := typ
3377 for range -n {
3378 fld = typ.Field(r.Int())
3379 typ = fld.Type
3380 }
3381 } else {
3382 fld = typ.Field(n)
3383 }
3384 sk := ir.NewStructKeyExpr(pos, fld, nil)
3385 sk.Value = r.expr()
3386 elems[i] = sk
3387 }
3388 }
3389
3390 func (r *reader) funcLit() ir.Node {
3391 r.Sync(pkgbits.SyncFuncLit)
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409 r.suppressInlPos++
3410 origPos := r.pos()
3411 sig := r.signature(nil)
3412 r.suppressInlPos--
3413 why := ir.OCLOSURE
3414 if r.Bool() {
3415 why = ir.ORANGE
3416 }
3417
3418 fn := r.inlClosureFunc(origPos, sig, why)
3419
3420 fn.ClosureVars = make([]*ir.Name, 0, r.Len())
3421 for len(fn.ClosureVars) < cap(fn.ClosureVars) {
3422
3423
3424 ir.NewClosureVar(r.pos(), fn, r.useLocal())
3425 }
3426 if param := r.dictParam; param != nil {
3427
3428
3429 ir.NewClosureVar(param.Pos(), fn, param)
3430 }
3431
3432 r.addBody(fn, nil)
3433
3434 return fn.OClosure
3435 }
3436
3437
3438
3439 func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type, why ir.Op) *ir.Func {
3440 curfn := r.inlCaller
3441 if curfn == nil {
3442 curfn = r.curfn
3443 }
3444
3445 var gen int
3446 if why == ir.ORANGE {
3447 r.rangeLitGen++
3448 gen = r.rangeLitGen
3449 } else {
3450 r.funcLitGen++
3451 gen = r.funcLitGen
3452 }
3453
3454
3455 return ir.NewClosureFunc(origPos, r.inlPos(origPos), why, sig, curfn, typecheck.Target, gen)
3456 }
3457
3458 func (r *reader) exprList() []ir.Node {
3459 r.Sync(pkgbits.SyncExprList)
3460 return r.exprs()
3461 }
3462
3463 func (r *reader) exprs() []ir.Node {
3464 r.Sync(pkgbits.SyncExprs)
3465 nodes := make([]ir.Node, r.Len())
3466 if len(nodes) == 0 {
3467 return nil
3468 }
3469 for i := range nodes {
3470 nodes[i] = r.expr()
3471 }
3472 return nodes
3473 }
3474
3475
3476
3477 func (r *reader) dictWord(pos src.XPos, idx int) ir.Node {
3478 base.AssertfAt(r.dictParam != nil, pos, "expected dictParam in %v", r.curfn)
3479 return typecheck.Expr(r.curfn, ir.NewIndexExpr(pos, r.dictParam, ir.NewInt(pos, int64(idx))))
3480 }
3481
3482
3483
3484 func (r *reader) rttiWord(pos src.XPos, idx int) ir.Node {
3485 return typecheck.Expr(r.curfn, ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TUINT8]), r.dictWord(pos, idx)))
3486 }
3487
3488
3489
3490
3491 func (r *reader) rtype(pos src.XPos) ir.Node {
3492 _, rtype := r.rtype0(pos)
3493 return rtype
3494 }
3495
3496 func (r *reader) rtype0(pos src.XPos) (typ *types.Type, rtype ir.Node) {
3497 r.Sync(pkgbits.SyncRType)
3498 if r.Bool() {
3499 idx := r.Len()
3500 info := r.dict.rtypes[idx]
3501 typ = r.p.typIdx(info, r.dict, true)
3502 rtype = r.rttiWord(pos, r.dict.rtypesOffset()+idx)
3503 return
3504 }
3505
3506 typ = r.typ()
3507 rtype = reflectdata.TypePtrAt(r.curfn, pos, typ)
3508 return
3509 }
3510
3511
3512 func (r *reader) varDictIndex(name *ir.Name) {
3513 if r.Bool() {
3514 idx := 1 + r.dict.rtypesOffset() + r.Len()
3515 if int(uint16(idx)) != idx {
3516 base.FatalfAt(name.Pos(), "DictIndex overflow for %v: %v", name, idx)
3517 }
3518 name.DictIndex = uint16(idx)
3519 }
3520 }
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530 func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) {
3531 typ, typRType = r.rtype0(pos)
3532 iface, ifaceRType = r.rtype0(pos)
3533
3534 idx := -1
3535 if r.Bool() {
3536 idx = r.Len()
3537 }
3538
3539 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
3540 if idx >= 0 {
3541 itab = r.rttiWord(pos, r.dict.itabsOffset()+idx)
3542 } else {
3543 base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ)
3544 base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface)
3545
3546 lsym := reflectdata.ITabLsym(typ, iface)
3547 itab = typecheck.LinksymAddr(r.curfn, pos, lsym, types.Types[types.TUINT8])
3548 }
3549 }
3550
3551 return
3552 }
3553
3554
3555
3556 func (r *reader) convRTTI(pos src.XPos) (typeWord, srcRType ir.Node) {
3557 r.Sync(pkgbits.SyncConvRTTI)
3558 src, srcRType0, dst, dstRType, itab := r.itab(pos)
3559 if !dst.IsInterface() {
3560 return
3561 }
3562
3563
3564 switch {
3565 case dst.IsEmptyInterface():
3566 if !src.IsInterface() {
3567 typeWord = srcRType0
3568 }
3569 case !src.IsInterface():
3570 typeWord = itab
3571 default:
3572 typeWord = dstRType
3573 }
3574
3575
3576 if !src.IsInterface() {
3577 srcRType = srcRType0
3578 }
3579
3580 return
3581 }
3582
3583 func (r *reader) exprType() ir.Node {
3584 r.Sync(pkgbits.SyncExprType)
3585 pos := r.pos()
3586
3587 var typ *types.Type
3588 var rtype, itab ir.Node
3589
3590 if r.Bool() {
3591
3592 typ, rtype, _, _, itab = r.itab(pos)
3593 if !typ.IsInterface() {
3594 rtype = nil
3595 }
3596 } else {
3597 typ, rtype = r.rtype0(pos)
3598
3599 if !r.Bool() {
3600 return ir.TypeNode(typ)
3601 }
3602 }
3603
3604 dt := ir.NewDynamicType(pos, rtype)
3605 dt.ITab = itab
3606 dt = typed(typ, dt).(*ir.DynamicType)
3607 if st := dt.ToStatic(); st != nil {
3608 return st
3609 }
3610 return dt
3611 }
3612
3613 func (r *reader) op() ir.Op {
3614 r.Sync(pkgbits.SyncOp)
3615 return ir.Op(r.Len())
3616 }
3617
3618
3619
3620 func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) {
3621 cgoPragmas := make([][]string, r.Len())
3622 for i := range cgoPragmas {
3623 cgoPragmas[i] = r.Strings()
3624 }
3625 target.CgoPragmas = cgoPragmas
3626
3627 r.pkgInitOrder(target)
3628
3629 r.pkgDecls(target)
3630
3631 r.Sync(pkgbits.SyncEOF)
3632 }
3633
3634
3635
3636 func (r *reader) pkgInitOrder(target *ir.Package) {
3637 initOrder := make([]ir.Node, r.Len())
3638 if len(initOrder) == 0 {
3639 return
3640 }
3641
3642
3643 pos := base.AutogeneratedPos
3644 lno := base.Pos
3645 defer func() { base.Pos = lno }()
3646 base.Pos = pos
3647
3648 fn := ir.NewFunc(pos, pos, typecheck.Lookup("init"), types.NewSignature(nil, nil, nil))
3649 fn.SetIsPackageInit(true)
3650 fn.SetInlinabilityChecked(true)
3651
3652 typecheck.DeclFunc(fn)
3653 r.curfn = fn
3654
3655 var varInitFns []*ir.Func
3656 if len(initOrder) <= maxInitStatements {
3657 fn.Body = r.doPkgInitOrder(initOrder)
3658 } else {
3659 varInitFns = r.splitLargeInitOrder(initOrder)
3660 calls := make([]ir.Node, len(varInitFns))
3661 for i, varInitFn := range varInitFns {
3662 ir.WithPos(fn, func() {
3663 calls[i] = typecheck.Call(r.curfn, varInitFn.Pos(), varInitFn.Nname, nil, false)
3664 })
3665 }
3666 fn.Body = calls
3667 }
3668
3669 r.curfn = nil
3670 r.locals = nil
3671
3672
3673 staticinit.OutlineMapInits(fn)
3674 for _, varInitFn := range varInitFns {
3675 staticinit.OutlineMapInits(varInitFn)
3676 }
3677
3678 target.Inits = append(target.Inits, fn)
3679 }
3680
3681 const maxInitStatements = 1000
3682
3683 func (r *reader) generateVarInitFunc(body []ir.Node) *ir.Func {
3684 fn := staticinit.GenerateVarInitFunc()
3685 typecheck.DeclFunc(fn)
3686
3687 old := r.curfn
3688 r.curfn = fn
3689 fn.Body = r.doPkgInitOrder(body)
3690 r.curfn = old
3691
3692 return fn
3693 }
3694
3695 func (r *reader) doPkgInitOrder(initOrder []ir.Node) []ir.Node {
3696 for i := range initOrder {
3697 lhs := make([]ir.Node, r.Len())
3698 for j := range lhs {
3699 lhs[j] = r.obj()
3700 }
3701 rhs := r.expr()
3702 pos := lhs[0].Pos()
3703
3704 var as ir.Node
3705 if len(lhs) == 1 {
3706 as = typecheck.Stmt(r.curfn, ir.NewAssignStmt(pos, lhs[0], rhs))
3707 } else {
3708 as = typecheck.Stmt(r.curfn, ir.NewAssignListStmt(pos, ir.OAS2, lhs, []ir.Node{rhs}))
3709 }
3710
3711 for _, v := range lhs {
3712 v.(*ir.Name).Defn = as
3713 }
3714
3715 initOrder[i] = as
3716 }
3717 return initOrder
3718 }
3719
3720 func (r *reader) splitLargeInitOrder(initOrder []ir.Node) []*ir.Func {
3721 var initFuncs []*ir.Func
3722 for chunk := range slices.Chunk(initOrder, maxInitStatements) {
3723 initFuncs = append(initFuncs, r.generateVarInitFunc(chunk))
3724 }
3725 return initFuncs
3726 }
3727
3728 func (r *reader) pkgDecls(target *ir.Package) {
3729 r.Sync(pkgbits.SyncDecls)
3730 for {
3731 switch code := codeDecl(r.Code(pkgbits.SyncDecl)); code {
3732 default:
3733 panic(fmt.Sprintf("unhandled decl: %v", code))
3734
3735 case declEnd:
3736 return
3737
3738 case declFunc:
3739 names := r.pkgObjs(target)
3740 assert(len(names) == 1)
3741 target.Funcs = append(target.Funcs, names[0].Func)
3742
3743 case declMethod:
3744 typ := r.typ()
3745 sym := r.selector()
3746
3747 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
3748 target.Funcs = append(target.Funcs, method.Nname.(*ir.Name).Func)
3749
3750 case declVar:
3751 names := r.pkgObjs(target)
3752
3753 if n := r.Len(); n > 0 {
3754 assert(len(names) == 1)
3755 embeds := make([]ir.Embed, n)
3756 for i := range embeds {
3757 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.Strings()}
3758 }
3759 names[0].Embed = &embeds
3760 target.Embeds = append(target.Embeds, names[0])
3761 }
3762
3763 case declOther:
3764 r.pkgObjs(target)
3765 }
3766 }
3767 }
3768
3769 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
3770 r.Sync(pkgbits.SyncDeclNames)
3771 nodes := make([]*ir.Name, r.Len())
3772 for i := range nodes {
3773 r.Sync(pkgbits.SyncDeclName)
3774
3775 name := r.obj().(*ir.Name)
3776 nodes[i] = name
3777
3778 sym := name.Sym()
3779 if sym.IsBlank() {
3780 continue
3781 }
3782
3783 switch name.Class {
3784 default:
3785 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
3786
3787 case ir.PEXTERN:
3788 target.Externs = append(target.Externs, name)
3789
3790 case ir.PFUNC:
3791 assert(name.Type().Recv() == nil)
3792
3793
3794 if strings.HasPrefix(sym.Name, "init.") {
3795 target.Inits = append(target.Inits, name.Func)
3796 }
3797 }
3798
3799 if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME {
3800 assert(!sym.OnExportList())
3801 target.PluginExports = append(target.PluginExports, name)
3802 sym.SetOnExportList(true)
3803 }
3804
3805 if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) {
3806 assert(!sym.Asm())
3807 target.AsmHdrDecls = append(target.AsmHdrDecls, name)
3808 sym.SetAsm(true)
3809 }
3810 }
3811
3812 return nodes
3813 }
3814
3815
3816
3817
3818
3819 func unifiedHaveInlineBody(fn *ir.Func) bool {
3820 if fn.Inl == nil {
3821 return false
3822 }
3823
3824 _, ok := bodyReaderFor(fn)
3825 return ok
3826 }
3827
3828 var inlgen = 0
3829
3830
3831
3832 func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int, profile *pgoir.Profile) *ir.InlinedCallExpr {
3833 pri, ok := bodyReaderFor(fn)
3834 if !ok {
3835 base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
3836 }
3837
3838 if !fn.Inl.HaveDcl {
3839 expandInline(fn, pri)
3840 }
3841
3842 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3843
3844 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type())
3845
3846 r.curfn = tmpfn
3847
3848 r.inlCaller = callerfn
3849 r.inlCall = call
3850 r.inlFunc = fn
3851 r.inlTreeIndex = inlIndex
3852 r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
3853 r.funarghack = true
3854
3855 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
3856 for i, cv := range r.inlFunc.ClosureVars {
3857
3858
3859 if cv.Outer.Curfn != callerfn {
3860 base.FatalfAt(call.Pos(), "inlining closure call across frames")
3861 }
3862 r.closureVars[i] = cv.Outer
3863 }
3864 if len(r.closureVars) != 0 && r.hasTypeParams() {
3865 r.dictParam = r.closureVars[len(r.closureVars)-1]
3866 }
3867
3868 r.declareParams()
3869
3870 var inlvars, retvars []*ir.Name
3871 {
3872 sig := r.curfn.Type()
3873 endParams := sig.NumRecvs() + sig.NumParams()
3874 endResults := endParams + sig.NumResults()
3875
3876 inlvars = r.curfn.Dcl[:endParams]
3877 retvars = r.curfn.Dcl[endParams:endResults]
3878 }
3879
3880 r.delayResults = fn.Inl.CanDelayResults
3881
3882 r.retlabel = typecheck.AutoLabel(callerfn, ".i")
3883 inlgen++
3884
3885 init := ir.TakeInit(call)
3886
3887
3888
3889
3890 if call.Op() == ir.OCALLFUNC {
3891 inline.CalleeEffects(&init, call.Fun)
3892 }
3893
3894 var args ir.Nodes
3895 if call.Op() == ir.OCALLMETH {
3896 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
3897 }
3898 args.Append(call.Args...)
3899
3900
3901 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, ir.ToNodes(inlvars), args)
3902 as2.Def = true
3903 var as2init ir.Nodes
3904 for _, name := range inlvars {
3905 if ir.IsBlank(name) {
3906 continue
3907 }
3908
3909 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3910 name.Defn = as2
3911 }
3912 as2.SetInit(as2init)
3913 init.Append(typecheck.Stmt(callerfn, as2))
3914
3915 if !r.delayResults {
3916
3917
3918 for _, name := range retvars {
3919
3920 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3921 ras := ir.NewAssignStmt(call.Pos(), name, nil)
3922 init.Append(typecheck.Stmt(callerfn, ras))
3923 }
3924 }
3925
3926
3927
3928
3929
3930
3931 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
3932
3933 ir.WithPos(r.curfn, func() {
3934 if !r.syntheticBody(call.Pos()) {
3935 assert(r.Bool())
3936
3937 r.curfn.Body = r.stmts()
3938 r.curfn.Endlineno = r.pos()
3939 }
3940
3941
3942
3943
3944
3945
3946 readBodies(typecheck.Target, true, profile)
3947
3948
3949 var edit func(ir.Node) ir.Node
3950 edit = func(n ir.Node) ir.Node {
3951 if ret, ok := n.(*ir.ReturnStmt); ok {
3952 n = typecheck.Stmt(callerfn, r.inlReturn(ret, retvars))
3953 }
3954 ir.EditChildren(n, edit)
3955 return n
3956 }
3957 edit(r.curfn)
3958 })
3959
3960 body := r.curfn.Body
3961
3962
3963 for _, name := range r.curfn.Dcl {
3964 name.Curfn = callerfn
3965
3966 if name.Class != ir.PAUTO {
3967 name.SetPos(r.inlPos(name.Pos()))
3968 name.SetInlFormal(true)
3969 name.Class = ir.PAUTO
3970 } else {
3971 name.SetInlLocal(true)
3972 }
3973 }
3974 callerfn.Dcl = append(callerfn.Dcl, r.curfn.Dcl...)
3975
3976 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
3977
3978 res := ir.NewInlinedCallExpr(call.Pos(), body, ir.ToNodes(retvars))
3979 res.SetInit(init)
3980 res.SetType(call.Type())
3981 res.SetTypecheck(1)
3982 res.Reshape = call.Reshape
3983
3984
3985 assert(len(todoBodies) == 0)
3986
3987 return res
3988 }
3989
3990
3991
3992 func (r *reader) inlReturn(ret *ir.ReturnStmt, retvars []*ir.Name) *ir.BlockStmt {
3993 pos := r.inlCall.Pos()
3994
3995 block := ir.TakeInit(ret)
3996
3997 if results := ret.Results; len(results) != 0 {
3998 assert(len(retvars) == len(results))
3999
4000 as2 := ir.NewAssignListStmt(pos, ir.OAS2, ir.ToNodes(retvars), ret.Results)
4001
4002 if r.delayResults {
4003 for _, name := range retvars {
4004
4005 block.Append(ir.NewDecl(pos, ir.ODCL, name))
4006 name.Defn = as2
4007 }
4008 }
4009
4010 block.Append(as2)
4011 }
4012
4013 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
4014 return ir.NewBlockStmt(pos, block)
4015 }
4016
4017
4018
4019 func expandInline(fn *ir.Func, pri pkgReaderIndex) {
4020
4021
4022
4023
4024
4025 fndcls := len(fn.Dcl)
4026 topdcls := len(typecheck.Target.Funcs)
4027
4028 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type())
4029 tmpfn.ClosureVars = fn.ClosureVars
4030
4031 {
4032 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
4033
4034
4035 r.funarghack = true
4036
4037 r.funcBody(tmpfn)
4038 }
4039
4040
4041 for _, name := range tmpfn.Dcl {
4042 name.Curfn = fn
4043 }
4044 fn.Inl.Dcl = tmpfn.Dcl
4045 fn.Inl.HaveDcl = true
4046
4047
4048 assert(fndcls == len(fn.Dcl))
4049
4050
4051
4052
4053 typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
4054 }
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111 var needWrapperTypes []*types.Type
4112
4113
4114
4115 var haveWrapperTypes []*types.Type
4116
4117
4118
4119 var needMethodValueWrappers []methodValueWrapper
4120
4121
4122
4123
4124 var haveMethodValueWrappers []methodValueWrapper
4125
4126 type methodValueWrapper struct {
4127 rcvr *types.Type
4128 method *types.Field
4129 }
4130
4131
4132
4133 func (r *reader) needWrapper(typ *types.Type) {
4134 if typ.IsPtr() || typ.IsKind(types.TFORW) {
4135 return
4136 }
4137
4138
4139 forceNeed := typ == types.ErrorType && base.Ctxt.Pkgpath == "runtime"
4140
4141
4142
4143
4144 if r.importedDef() && !forceNeed {
4145 haveWrapperTypes = append(haveWrapperTypes, typ)
4146 } else {
4147 needWrapperTypes = append(needWrapperTypes, typ)
4148 }
4149 }
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165 func (r *reader) importedDef() bool {
4166 return r.p != localPkgReader && !r.hasTypeParams()
4167 }
4168
4169
4170
4171 func MakeWrappers(target *ir.Package) {
4172
4173 needWrapperTypes = append(needWrapperTypes, types.ErrorType)
4174
4175 seen := make(map[string]*types.Type)
4176
4177 for _, typ := range haveWrapperTypes {
4178 wrapType(typ, target, seen, false)
4179 }
4180 haveWrapperTypes = nil
4181
4182 for _, typ := range needWrapperTypes {
4183 wrapType(typ, target, seen, true)
4184 }
4185 needWrapperTypes = nil
4186
4187 for _, wrapper := range haveMethodValueWrappers {
4188 wrapMethodValue(wrapper.rcvr, wrapper.method, target, false)
4189 }
4190 haveMethodValueWrappers = nil
4191
4192 for _, wrapper := range needMethodValueWrappers {
4193 wrapMethodValue(wrapper.rcvr, wrapper.method, target, true)
4194 }
4195 needMethodValueWrappers = nil
4196 }
4197
4198 func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) {
4199 key := typ.LinkString()
4200 if prev := seen[key]; prev != nil {
4201 if !types.Identical(typ, prev) {
4202 base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key)
4203 }
4204
4205
4206 typ.CopyTFlagFrom(prev)
4207 return
4208 }
4209 seen[key] = typ
4210
4211 if !needed {
4212
4213 return
4214 }
4215
4216 if !typ.IsInterface() {
4217 typecheck.CalcMethods(typ)
4218 }
4219 if !typ.IsUntyped() {
4220 typ.TFlag()
4221 }
4222 for _, meth := range typ.AllMethods() {
4223 if meth.Sym.IsBlank() || !meth.IsMethod() {
4224 base.FatalfAt(meth.Pos, "invalid method: %v", meth)
4225 }
4226
4227 methodWrapper(0, typ, meth, target)
4228
4229
4230 if !typ.IsInterface() {
4231 methodWrapper(1, typ, meth, target)
4232
4233
4234
4235 if typ.NotInHeap() {
4236 methodWrapper(2, typ, meth, target)
4237 }
4238 }
4239 }
4240 }
4241
4242 func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) {
4243 wrapper := tbase
4244 for i := 0; i < derefs; i++ {
4245 wrapper = types.NewPtr(wrapper)
4246 }
4247
4248 wrappee := method.Type.Recv().Type
4249 if types.Identical(wrapper, wrappee) ||
4250 !types.IsMethodApplicable(wrapper, method) ||
4251 !reflectdata.NeedEmit(tbase) {
4252 return
4253 }
4254 sym, sharedPromoted := ir.MethodSym(wrapper, method)
4255 if sym.Siggen() {
4256 if sharedPromoted {
4257 return
4258 }
4259 base.Fatalf("already generated wrapper %v", sym)
4260 }
4261 sym.SetSiggen(true)
4262
4263
4264 pos := base.AutogeneratedPos
4265
4266 fn := newWrapperFunc(pos, sym, wrapper, method)
4267
4268 var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
4269
4270
4271
4272 if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) {
4273 cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node))
4274 then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)}
4275 fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil))
4276 }
4277
4278
4279
4280 for i := 1; i < derefs; i++ {
4281 recv = Implicit(ir.NewStarExpr(pos, recv))
4282 }
4283
4284 addTailCall(pos, fn, recv, method)
4285
4286 finishWrapperFunc(fn, target)
4287 }
4288
4289 func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) {
4290 sym := ir.ReceiverMethodSymSuffix(recvType, method.Sym, "-fm")
4291 if sym.Uniq() {
4292 return
4293 }
4294 sym.SetUniq(true)
4295
4296
4297 pos := base.AutogeneratedPos
4298
4299 fn := newWrapperFunc(pos, sym, nil, method)
4300 sym.Def = fn.Nname
4301
4302
4303 recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
4304
4305 if !needed {
4306 return
4307 }
4308
4309 addTailCall(pos, fn, recv, method)
4310
4311 finishWrapperFunc(fn, target)
4312 }
4313
4314 func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
4315 sig := newWrapperType(wrapper, method)
4316 fn := ir.NewFunc(pos, pos, sym, sig)
4317 fn.DeclareParams(true)
4318 fn.SetDupok(true)
4319
4320 return fn
4321 }
4322
4323 func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
4324 ir.WithPos(fn, func() {
4325 typecheck.Stmts(fn, fn.Body)
4326 })
4327
4328
4329
4330
4331 interleaved.DevirtualizeAndInlineFunc(fn, nil)
4332
4333
4334
4335
4336
4337
4338
4339
4340 ir.VisitFuncAndClosures(fn, func(n ir.Node) {
4341 if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
4342 wrapMethodValue(n.X.Type(), n.Selection, target, true)
4343 }
4344 })
4345
4346 fn.Nname.Defn = fn
4347 target.Funcs = append(target.Funcs, fn)
4348 }
4349
4350
4351
4352
4353
4354 func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
4355 clone := func(params []*types.Field) []*types.Field {
4356 res := make([]*types.Field, len(params))
4357 for i, param := range params {
4358 res[i] = types.NewField(param.Pos, param.Sym, param.Type)
4359 res[i].SetIsDDD(param.IsDDD())
4360 }
4361 return res
4362 }
4363
4364 sig := method.Type
4365
4366 var recv *types.Field
4367 if recvType != nil {
4368 recv = types.NewField(sig.Recv().Pos, sig.Recv().Sym, recvType)
4369 }
4370 params := clone(sig.Params())
4371 results := clone(sig.Results())
4372
4373 return types.NewSignature(recv, params, results)
4374 }
4375
4376 func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) {
4377 sig := fn.Nname.Type()
4378 args := make([]ir.Node, sig.NumParams())
4379 for i, param := range sig.Params() {
4380 args[i] = param.Nname.(*ir.Name)
4381 }
4382
4383 dot := typecheck.XDotMethod(fn, pos, recv, method.Sym, true)
4384 call := typecheck.Call(fn, pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr)
4385
4386 if recv.Type() != nil && recv.Type().IsPtr() && method.Type.Recv().Type.IsPtr() &&
4387 method.Embedded != 0 &&
4388 (types.IsInterfaceMethod(method.Type) && base.Ctxt.Arch.Name != "wasm" ||
4389 !types.IsInterfaceMethod(method.Type) && !unifiedHaveInlineBody(ir.MethodExprName(dot).Func)) &&
4390
4391
4392 !((base.Ctxt.Arch.Name == "ppc64le" || base.Ctxt.Arch.Name == "ppc64") && base.Ctxt.Flag_dynlink) {
4393 if base.Debug.TailCall != 0 {
4394 base.WarnfAt(fn.Nname.Type().Recv().Type.Elem().Pos(), "tail call emitted for the method %v wrapper", method.Nname)
4395 }
4396
4397 fn.Body.Append(ir.NewTailCallStmt(pos, call))
4398 return
4399 }
4400
4401 fn.SetWrapper(true)
4402
4403 if method.Type.NumResults() == 0 {
4404 fn.Body.Append(call)
4405 return
4406 }
4407
4408 ret := ir.NewReturnStmt(pos, nil)
4409 ret.Results = []ir.Node{call}
4410 fn.Body.Append(ret)
4411 }
4412
4413 func setBasePos(pos src.XPos) {
4414
4415 base.Pos = pos
4416 }
4417
4418
4419
4420
4421
4422
4423 const dictParamName = typecheck.LocalDictName
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433 func shapeSig(fn *ir.Func, dict *readerDict) *types.Type {
4434 sig := fn.Nname.Type()
4435 oldRecv := sig.Recv()
4436
4437 var recv *types.Field
4438 if oldRecv != nil {
4439 recv = types.NewField(oldRecv.Pos, oldRecv.Sym, oldRecv.Type)
4440 }
4441
4442 params := make([]*types.Field, 1+sig.NumParams())
4443 params[0] = types.NewField(fn.Pos(), fn.Sym().Pkg.Lookup(dictParamName), types.NewPtr(dict.varType()))
4444 for i, param := range sig.Params() {
4445 d := types.NewField(param.Pos, param.Sym, param.Type)
4446 d.SetIsDDD(param.IsDDD())
4447 params[1+i] = d
4448 }
4449
4450 results := make([]*types.Field, sig.NumResults())
4451 for i, result := range sig.Results() {
4452 results[i] = types.NewField(result.Pos, result.Sym, result.Type)
4453 }
4454
4455 typ := types.NewSignature(recv, params, results)
4456 typ.SetHasShape(true)
4457 return typ
4458 }
4459
View as plain text