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