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