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