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