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 x = typecheck.DefaultLit(x, typ)
2600
2601 ce := ir.NewConvExpr(pos, ir.OCONV, typ, x)
2602 ce.TypeWord, ce.SrcRType = typeWord, srcRType
2603 if implicit {
2604 ce.SetImplicit(true)
2605 }
2606 n := typecheck.Expr(ce)
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624 if !identical {
2625 if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) {
2626 n.SetOp(ir.OCONVIFACE)
2627 }
2628 }
2629
2630
2631
2632 if dstTypeParam && ir.IsConstNode(n) {
2633
2634 n = Implicit(ir.NewConvExpr(pos, ir.OCONVNOP, n.Type(), n))
2635 n.SetTypecheck(1)
2636 }
2637 return n
2638
2639 case exprRuntimeBuiltin:
2640 builtin := typecheck.LookupRuntime(r.String())
2641 return builtin
2642 }
2643 }
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667 func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) {
2668
2669 var implicits []*types.Type
2670 if r.dict != nil {
2671 implicits = r.dict.targs
2672 }
2673
2674 if r.Bool() {
2675 idx := r.Len()
2676 info := r.dict.subdicts[idx]
2677 explicits := r.p.typListIdx(info.explicits, r.dict)
2678
2679 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2680
2681
2682
2683 dictPtrType := baseFn.Type().Param(0).Type
2684 dictPtr = typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2685
2686 return
2687 }
2688
2689 info := r.objInfo()
2690 explicits := r.p.typListIdx(info.explicits, r.dict)
2691
2692 wrapperFn = r.p.objIdx(info.idx, implicits, explicits, false).(*ir.Name)
2693 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2694
2695 dictName := r.p.objDictName(info.idx, implicits, explicits)
2696 dictPtr = typecheck.Expr(ir.NewAddrExpr(pos, dictName))
2697
2698 return
2699 }
2700
2701 func (pr *pkgReader) objDictName(idx index, implicits, explicits []*types.Type) *ir.Name {
2702 rname := pr.newReader(pkgbits.SectionName, idx, pkgbits.SyncObject1)
2703 _, sym := rname.qualifiedIdent()
2704 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
2705
2706 if tag == pkgbits.ObjStub {
2707 assert(!sym.IsBlank())
2708 if pri, ok := objReader[sym]; ok {
2709 return pri.pr.objDictName(pri.idx, nil, explicits)
2710 }
2711 base.Fatalf("unresolved stub: %v", sym)
2712 }
2713
2714 dict, err := pr.objDictIdx(sym, idx, implicits, explicits, false)
2715 if err != nil {
2716 base.Fatalf("%v", err)
2717 }
2718
2719 return pr.dictNameOf(dict)
2720 }
2721
2722
2723
2724
2725
2726
2727
2728
2729 func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node {
2730 var captured ir.Nodes
2731 captured.Append(fun, arg0)
2732 if arg1 != nil {
2733 captured.Append(arg1)
2734 }
2735
2736 params, results := syntheticSig(fun.Type())
2737 params = params[len(captured)-1:]
2738 typ := types.NewSignature(nil, params, results)
2739
2740 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2741 fun := captured[0]
2742
2743 var args ir.Nodes
2744 args.Append(captured[1:]...)
2745 args.Append(r.syntheticArgs()...)
2746
2747 r.syntheticTailCall(pos, fun, args)
2748 }
2749
2750 return r.syntheticClosure(origPos, typ, ifaceHack, captured, addBody)
2751 }
2752
2753
2754
2755
2756 func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node {
2757 var captured ir.Nodes
2758 captured.Append(method)
2759
2760 params, results := syntheticSig(method.Type())
2761
2762
2763 params[0].Type = recv
2764
2765
2766
2767
2768 if dictPtr != nil {
2769 captured.Append(dictPtr)
2770 params = append(params[:1], params[2:]...)
2771 }
2772
2773 typ := types.NewSignature(nil, params, results)
2774
2775 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2776 fn := captured[0]
2777 args := r.syntheticArgs()
2778
2779
2780 {
2781 arg := args[0]
2782 for _, ix := range implicits {
2783 arg = Implicit(typecheck.DotField(pos, arg, ix))
2784 }
2785 if deref {
2786 arg = Implicit(Deref(pos, arg.Type().Elem(), arg))
2787 } else if addr {
2788 arg = Implicit(Addr(pos, arg))
2789 }
2790 args[0] = arg
2791 }
2792
2793
2794 if dictPtr != nil {
2795 newArgs := make([]ir.Node, len(args)+1)
2796 newArgs[0] = args[0]
2797 newArgs[1] = captured[1]
2798 copy(newArgs[2:], args[1:])
2799 args = newArgs
2800 }
2801
2802 r.syntheticTailCall(pos, fn, args)
2803 }
2804
2805 return r.syntheticClosure(origPos, typ, false, captured, addBody)
2806 }
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822 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 {
2823
2824
2825
2826
2827
2828 isSafe := func(n ir.Node) bool {
2829 if n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PFUNC {
2830 return true
2831 }
2832 if n.Op() == ir.OMETHEXPR {
2833 return true
2834 }
2835
2836 return false
2837 }
2838
2839 fn := r.inlClosureFunc(origPos, typ, ir.OCLOSURE)
2840 fn.SetWrapper(true)
2841
2842 clo := fn.OClosure
2843 inlPos := clo.Pos()
2844
2845 var init ir.Nodes
2846 for i, n := range captures {
2847 if isSafe(n) {
2848 continue
2849 }
2850
2851 tmp := r.tempCopy(inlPos, n, &init)
2852 ir.NewClosureVar(origPos, fn, tmp)
2853
2854
2855
2856 if ifaceHack && i == 1 && n.Type().IsInterface() {
2857 check := ir.NewUnaryExpr(inlPos, ir.OCHECKNIL, ir.NewUnaryExpr(inlPos, ir.OITAB, tmp))
2858 init.Append(typecheck.Stmt(check))
2859 }
2860 }
2861
2862 pri := pkgReaderIndex{synthetic: func(pos src.XPos, r *reader) {
2863 captured := make([]ir.Node, len(captures))
2864 next := 0
2865 for i, n := range captures {
2866 if isSafe(n) {
2867 captured[i] = n
2868 } else {
2869 captured[i] = r.closureVars[next]
2870 next++
2871 }
2872 }
2873 assert(next == len(r.closureVars))
2874
2875 addBody(origPos, r, captured)
2876 }}
2877 bodyReader[fn] = pri
2878 pri.funcBody(fn)
2879
2880 return ir.InitExpr(init, clo)
2881 }
2882
2883
2884
2885
2886 func syntheticSig(sig *types.Type) (params, results []*types.Field) {
2887 clone := func(params []*types.Field) []*types.Field {
2888 res := make([]*types.Field, len(params))
2889 for i, param := range params {
2890
2891
2892
2893
2894
2895
2896 res[i] = types.NewField(base.AutogeneratedPos, param.Sym, param.Type)
2897 res[i].SetIsDDD(param.IsDDD())
2898 }
2899 return res
2900 }
2901
2902 return clone(sig.Params()), clone(sig.Results())
2903 }
2904
2905 func (r *reader) optExpr() ir.Node {
2906 if r.Bool() {
2907 return r.expr()
2908 }
2909 return nil
2910 }
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935 func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) {
2936 recv := r.typ()
2937
2938 var sig *types.Type
2939 generic := r.Version().Has(pkgbits.GenericMethods) && r.Bool()
2940 if !generic {
2941
2942
2943 sig = typecheck.NewMethodType(r.typ(), recv)
2944 }
2945
2946 pos := r.pos()
2947 sym := r.selector()
2948
2949 if r.Bool() {
2950 idx := r.Len()
2951 word := r.dictWord(pos, r.dict.typeParamMethodExprsOffset()+idx)
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962 fn := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, sig, ir.NewAddrExpr(pos, word)))
2963 return fn, fn, nil
2964 }
2965
2966 if r.Bool() {
2967 idx := r.Len()
2968 info := r.dict.subdicts[idx]
2969 explicits := r.p.typListIdx(info.explicits, r.dict)
2970
2971 shapedObj := r.p.objIdx(info.idx, nil, explicits, true).(*ir.Name)
2972 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
2973
2974
2975
2976 dictPtrType := shapedFn.Type().Param(1).Type
2977 dictPtr := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2978
2979 return nil, shapedFn, dictPtr
2980 }
2981
2982 if r.Bool() {
2983 info := r.objInfo()
2984 explicits := r.p.typListIdx(info.explicits, r.dict)
2985
2986 shapedObj := r.p.objIdx(info.idx, nil, explicits, true).(*ir.Name)
2987 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
2988
2989 dict := r.p.objDictName(info.idx, nil, explicits)
2990 dictPtr := typecheck.Expr(ir.NewAddrExpr(pos, dict))
2991
2992
2993 if !types.Identical(dictPtr.Type(), shapedFn.Type().Param(1).Type) {
2994 base.FatalfAt(pos, "dict %L, but shaped method %L", dict, shapedFn)
2995 }
2996
2997 if !generic {
2998
2999
3000 base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv)
3001 wrapperFn := typecheck.NewMethodExpr(pos, recv, sym)
3002 base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig)
3003 return wrapperFn, shapedFn, dictPtr
3004 } else {
3005
3006
3007
3008
3009 return nil, shapedFn, dictPtr
3010 }
3011 }
3012
3013
3014 base.AssertfAt(!recv.HasShape() || recv.IsInterface(), pos, "shaped receiver %v", recv)
3015 fn := typecheck.NewMethodExpr(pos, recv, sym)
3016 return fn, fn, nil
3017 }
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041 func shapedMethodExpr(pos src.XPos, obj *ir.Name, sym *types.Sym) ir.Node {
3042 if obj.Op() == ir.OTYPE {
3043
3044 typ := obj.Type()
3045 assert(typ.HasShape())
3046
3047 method := func() *types.Field {
3048 for _, m := range typ.Methods() {
3049 if m.Sym == sym {
3050 return m
3051 }
3052 }
3053
3054 base.FatalfAt(pos, "failed to find method %v in shaped type %v", sym, typ)
3055 panic("unreachable")
3056 }()
3057
3058 return typecheck.NewMethodExpr(pos, method.Type.Recv().Type, sym)
3059 } else {
3060
3061 assert(obj.Op() == ir.ONAME && obj.Class == ir.PFUNC)
3062 typ := obj.Type()
3063 assert(typ.HasShape())
3064
3065
3066
3067
3068
3069
3070
3071 lsym := obj.Linksym().Name
3072
3073
3074 msym := sym.Pkg.Lookup(lsym[strings.LastIndex(lsym, sym.Name+"["):])
3075
3076
3077
3078 m := types.NewField(obj.Pos(), msym, typ)
3079 m.Nname = obj
3080
3081 n := ir.NewSelectorExpr(pos, ir.OMETHEXPR, ir.TypeNode(typ.Recv().Type), msym)
3082 n.Selection = m
3083 n.SetType(typecheck.NewMethodType(typ, typ.Recv().Type))
3084 n.SetTypecheck(1)
3085
3086 return n
3087 }
3088 }
3089
3090 func (r *reader) multiExpr() []ir.Node {
3091 r.Sync(pkgbits.SyncMultiExpr)
3092
3093 if r.Bool() {
3094 pos := r.pos()
3095 expr := r.expr()
3096
3097 results := make([]ir.Node, r.Len())
3098 as := ir.NewAssignListStmt(pos, ir.OAS2, nil, []ir.Node{expr})
3099 as.Def = true
3100 for i := range results {
3101 tmp := r.temp(pos, r.typ())
3102 tmp.Defn = as
3103 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
3104 as.Lhs.Append(tmp)
3105
3106 res := ir.Node(tmp)
3107 if r.Bool() {
3108 n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)
3109 n.TypeWord, n.SrcRType = r.convRTTI(pos)
3110 n.SetImplicit(true)
3111 res = typecheck.Expr(n)
3112 }
3113 results[i] = res
3114 }
3115
3116
3117 results[0] = ir.InitExpr([]ir.Node{typecheck.Stmt(as)}, results[0])
3118 return results
3119 }
3120
3121
3122 exprs := make([]ir.Node, r.Len())
3123 if len(exprs) == 0 {
3124 return nil
3125 }
3126 for i := range exprs {
3127 exprs[i] = r.expr()
3128 }
3129 return exprs
3130 }
3131
3132
3133 func (r *reader) temp(pos src.XPos, typ *types.Type) *ir.Name {
3134 return typecheck.TempAt(pos, r.curfn, typ)
3135 }
3136
3137
3138
3139 func (r *reader) tempCopy(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name {
3140 tmp := r.temp(pos, expr.Type())
3141
3142 init.Append(typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)))
3143
3144 assign := ir.NewAssignStmt(pos, tmp, expr)
3145 assign.Def = true
3146 init.Append(typecheck.Stmt(assign))
3147
3148 tmp.Defn = assign
3149
3150 return tmp
3151 }
3152
3153 func (r *reader) compLit() ir.Node {
3154 r.Sync(pkgbits.SyncCompLit)
3155 pos := r.pos()
3156 typ0 := r.typ()
3157
3158 typ := typ0
3159 if typ.IsPtr() {
3160 typ = typ.Elem()
3161 }
3162 if typ.Kind() == types.TFORW {
3163 base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
3164 }
3165 var rtype ir.Node
3166 if typ.IsMap() {
3167 rtype = r.rtype(pos)
3168 }
3169
3170 var elems []ir.Node
3171 if r.Version().Has(pkgbits.CompactCompLiterals) {
3172 n := r.Int()
3173 elems = make([]ir.Node, max(n, -n) )
3174 switch typ.Kind() {
3175 default:
3176 base.FatalfAt(pos, "unexpected composite literal type: %v", typ)
3177 case types.TARRAY:
3178 r.arrayElems(n >= 0, elems)
3179 case types.TMAP:
3180 r.mapElems(elems)
3181 case types.TSLICE:
3182 r.arrayElems(n >= 0, elems)
3183 case types.TSTRUCT:
3184 r.structElems(typ, n >= 0, elems)
3185 }
3186 } else {
3187 elems = make([]ir.Node, r.Len())
3188 isStruct := typ.Kind() == types.TSTRUCT
3189 for i := range elems {
3190 elemp := &elems[i]
3191 if isStruct {
3192 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.Len()), nil)
3193 *elemp, elemp = sk, &sk.Value
3194 } else if r.Bool() {
3195 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3196 *elemp, elemp = kv, &kv.Value
3197 }
3198 *elemp = r.expr()
3199 }
3200 }
3201
3202 lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems))
3203 if rtype != nil {
3204 lit := lit.(*ir.CompLitExpr)
3205 lit.RType = rtype
3206 }
3207 if typ0.IsPtr() {
3208 lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit))
3209 lit.SetType(typ0)
3210 }
3211 return lit
3212 }
3213
3214 func (r *reader) arrayElems(valuesOnly bool, elems []ir.Node) {
3215 if valuesOnly {
3216 for i := range elems {
3217 elems[i] = r.expr()
3218 }
3219 return
3220 }
3221
3222 for i := range elems {
3223 if r.Bool() {
3224 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3225 kv.Value = r.expr()
3226 elems[i] = kv
3227 } else {
3228 elems[i] = r.expr()
3229 }
3230 }
3231 }
3232
3233 func (r *reader) mapElems(elems []ir.Node) {
3234
3235 for i := range elems {
3236 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3237 kv.Value = r.expr()
3238 elems[i] = kv
3239 }
3240 }
3241
3242 func (r *reader) structElems(typ *types.Type, valuesOnly bool, elems []ir.Node) {
3243 if valuesOnly {
3244 for i := range elems {
3245 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(i), nil)
3246 sk.Value = r.expr()
3247 elems[i] = sk
3248 }
3249 return
3250 }
3251
3252
3253 for i := range elems {
3254 pos := r.pos()
3255 var fld *types.Field
3256 if n := r.Int(); n < 0 {
3257
3258 typ := typ
3259 for range -n {
3260 fld = typ.Field(r.Int())
3261 typ = fld.Type
3262 }
3263 } else {
3264 fld = typ.Field(n)
3265 }
3266 sk := ir.NewStructKeyExpr(pos, fld, nil)
3267 sk.Value = r.expr()
3268 elems[i] = sk
3269 }
3270 }
3271
3272 func (r *reader) funcLit() ir.Node {
3273 r.Sync(pkgbits.SyncFuncLit)
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291 r.suppressInlPos++
3292 origPos := r.pos()
3293 sig := r.signature(nil)
3294 r.suppressInlPos--
3295 why := ir.OCLOSURE
3296 if r.Bool() {
3297 why = ir.ORANGE
3298 }
3299
3300 fn := r.inlClosureFunc(origPos, sig, why)
3301
3302 fn.ClosureVars = make([]*ir.Name, 0, r.Len())
3303 for len(fn.ClosureVars) < cap(fn.ClosureVars) {
3304
3305
3306 ir.NewClosureVar(r.pos(), fn, r.useLocal())
3307 }
3308 if param := r.dictParam; param != nil {
3309
3310
3311 ir.NewClosureVar(param.Pos(), fn, param)
3312 }
3313
3314 r.addBody(fn, nil)
3315
3316 return fn.OClosure
3317 }
3318
3319
3320
3321 func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type, why ir.Op) *ir.Func {
3322 curfn := r.inlCaller
3323 if curfn == nil {
3324 curfn = r.curfn
3325 }
3326
3327 var gen int
3328 if why == ir.ORANGE {
3329 r.rangeLitGen++
3330 gen = r.rangeLitGen
3331 } else {
3332 r.funcLitGen++
3333 gen = r.funcLitGen
3334 }
3335
3336
3337 return ir.NewClosureFunc(origPos, r.inlPos(origPos), why, sig, curfn, typecheck.Target, gen)
3338 }
3339
3340 func (r *reader) exprList() []ir.Node {
3341 r.Sync(pkgbits.SyncExprList)
3342 return r.exprs()
3343 }
3344
3345 func (r *reader) exprs() []ir.Node {
3346 r.Sync(pkgbits.SyncExprs)
3347 nodes := make([]ir.Node, r.Len())
3348 if len(nodes) == 0 {
3349 return nil
3350 }
3351 for i := range nodes {
3352 nodes[i] = r.expr()
3353 }
3354 return nodes
3355 }
3356
3357
3358
3359 func (r *reader) dictWord(pos src.XPos, idx int) ir.Node {
3360 base.AssertfAt(r.dictParam != nil, pos, "expected dictParam in %v", r.curfn)
3361 return typecheck.Expr(ir.NewIndexExpr(pos, r.dictParam, ir.NewInt(pos, int64(idx))))
3362 }
3363
3364
3365
3366 func (r *reader) rttiWord(pos src.XPos, idx int) ir.Node {
3367 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TUINT8]), r.dictWord(pos, idx)))
3368 }
3369
3370
3371
3372
3373 func (r *reader) rtype(pos src.XPos) ir.Node {
3374 _, rtype := r.rtype0(pos)
3375 return rtype
3376 }
3377
3378 func (r *reader) rtype0(pos src.XPos) (typ *types.Type, rtype ir.Node) {
3379 r.Sync(pkgbits.SyncRType)
3380 if r.Bool() {
3381 idx := r.Len()
3382 info := r.dict.rtypes[idx]
3383 typ = r.p.typIdx(info, r.dict, true)
3384 rtype = r.rttiWord(pos, r.dict.rtypesOffset()+idx)
3385 return
3386 }
3387
3388 typ = r.typ()
3389 rtype = reflectdata.TypePtrAt(pos, typ)
3390 return
3391 }
3392
3393
3394 func (r *reader) varDictIndex(name *ir.Name) {
3395 if r.Bool() {
3396 idx := 1 + r.dict.rtypesOffset() + r.Len()
3397 if int(uint16(idx)) != idx {
3398 base.FatalfAt(name.Pos(), "DictIndex overflow for %v: %v", name, idx)
3399 }
3400 name.DictIndex = uint16(idx)
3401 }
3402 }
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412 func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) {
3413 typ, typRType = r.rtype0(pos)
3414 iface, ifaceRType = r.rtype0(pos)
3415
3416 idx := -1
3417 if r.Bool() {
3418 idx = r.Len()
3419 }
3420
3421 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
3422 if idx >= 0 {
3423 itab = r.rttiWord(pos, r.dict.itabsOffset()+idx)
3424 } else {
3425 base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ)
3426 base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface)
3427
3428 lsym := reflectdata.ITabLsym(typ, iface)
3429 itab = typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
3430 }
3431 }
3432
3433 return
3434 }
3435
3436
3437
3438 func (r *reader) convRTTI(pos src.XPos) (typeWord, srcRType ir.Node) {
3439 r.Sync(pkgbits.SyncConvRTTI)
3440 src, srcRType0, dst, dstRType, itab := r.itab(pos)
3441 if !dst.IsInterface() {
3442 return
3443 }
3444
3445
3446 switch {
3447 case dst.IsEmptyInterface():
3448 if !src.IsInterface() {
3449 typeWord = srcRType0
3450 }
3451 case !src.IsInterface():
3452 typeWord = itab
3453 default:
3454 typeWord = dstRType
3455 }
3456
3457
3458 if !src.IsInterface() {
3459 srcRType = srcRType0
3460 }
3461
3462 return
3463 }
3464
3465 func (r *reader) exprType() ir.Node {
3466 r.Sync(pkgbits.SyncExprType)
3467 pos := r.pos()
3468
3469 var typ *types.Type
3470 var rtype, itab ir.Node
3471
3472 if r.Bool() {
3473
3474 typ, rtype, _, _, itab = r.itab(pos)
3475 if !typ.IsInterface() {
3476 rtype = nil
3477 }
3478 } else {
3479 typ, rtype = r.rtype0(pos)
3480
3481 if !r.Bool() {
3482 return ir.TypeNode(typ)
3483 }
3484 }
3485
3486 dt := ir.NewDynamicType(pos, rtype)
3487 dt.ITab = itab
3488 dt = typed(typ, dt).(*ir.DynamicType)
3489 if st := dt.ToStatic(); st != nil {
3490 return st
3491 }
3492 return dt
3493 }
3494
3495 func (r *reader) op() ir.Op {
3496 r.Sync(pkgbits.SyncOp)
3497 return ir.Op(r.Len())
3498 }
3499
3500
3501
3502 func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) {
3503 cgoPragmas := make([][]string, r.Len())
3504 for i := range cgoPragmas {
3505 cgoPragmas[i] = r.Strings()
3506 }
3507 target.CgoPragmas = cgoPragmas
3508
3509 r.pkgInitOrder(target)
3510
3511 r.pkgDecls(target)
3512
3513 r.Sync(pkgbits.SyncEOF)
3514 }
3515
3516
3517
3518 func (r *reader) pkgInitOrder(target *ir.Package) {
3519 initOrder := make([]ir.Node, r.Len())
3520 if len(initOrder) == 0 {
3521 return
3522 }
3523
3524
3525 pos := base.AutogeneratedPos
3526 base.Pos = pos
3527
3528 fn := ir.NewFunc(pos, pos, typecheck.Lookup("init"), types.NewSignature(nil, nil, nil))
3529 fn.SetIsPackageInit(true)
3530 fn.SetInlinabilityChecked(true)
3531
3532 typecheck.DeclFunc(fn)
3533 r.curfn = fn
3534
3535 for i := range initOrder {
3536 lhs := make([]ir.Node, r.Len())
3537 for j := range lhs {
3538 lhs[j] = r.obj()
3539 }
3540 rhs := r.expr()
3541 pos := lhs[0].Pos()
3542
3543 var as ir.Node
3544 if len(lhs) == 1 {
3545 as = typecheck.Stmt(ir.NewAssignStmt(pos, lhs[0], rhs))
3546 } else {
3547 as = typecheck.Stmt(ir.NewAssignListStmt(pos, ir.OAS2, lhs, []ir.Node{rhs}))
3548 }
3549
3550 for _, v := range lhs {
3551 v.(*ir.Name).Defn = as
3552 }
3553
3554 initOrder[i] = as
3555 }
3556
3557 fn.Body = initOrder
3558
3559 typecheck.FinishFuncBody()
3560 r.curfn = nil
3561 r.locals = nil
3562
3563
3564 staticinit.OutlineMapInits(fn)
3565
3566
3567 staticinit.SplitLargeInit(fn)
3568
3569 target.Inits = append(target.Inits, fn)
3570 }
3571
3572 func (r *reader) pkgDecls(target *ir.Package) {
3573 r.Sync(pkgbits.SyncDecls)
3574 for {
3575 switch code := codeDecl(r.Code(pkgbits.SyncDecl)); code {
3576 default:
3577 panic(fmt.Sprintf("unhandled decl: %v", code))
3578
3579 case declEnd:
3580 return
3581
3582 case declFunc:
3583 names := r.pkgObjs(target)
3584 assert(len(names) == 1)
3585 target.Funcs = append(target.Funcs, names[0].Func)
3586
3587 case declMethod:
3588 typ := r.typ()
3589 sym := r.selector()
3590
3591 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
3592 target.Funcs = append(target.Funcs, method.Nname.(*ir.Name).Func)
3593
3594 case declVar:
3595 names := r.pkgObjs(target)
3596
3597 if n := r.Len(); n > 0 {
3598 assert(len(names) == 1)
3599 embeds := make([]ir.Embed, n)
3600 for i := range embeds {
3601 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.Strings()}
3602 }
3603 names[0].Embed = &embeds
3604 target.Embeds = append(target.Embeds, names[0])
3605 }
3606
3607 case declOther:
3608 r.pkgObjs(target)
3609 }
3610 }
3611 }
3612
3613 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
3614 r.Sync(pkgbits.SyncDeclNames)
3615 nodes := make([]*ir.Name, r.Len())
3616 for i := range nodes {
3617 r.Sync(pkgbits.SyncDeclName)
3618
3619 name := r.obj().(*ir.Name)
3620 nodes[i] = name
3621
3622 sym := name.Sym()
3623 if sym.IsBlank() {
3624 continue
3625 }
3626
3627 switch name.Class {
3628 default:
3629 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
3630
3631 case ir.PEXTERN:
3632 target.Externs = append(target.Externs, name)
3633
3634 case ir.PFUNC:
3635 assert(name.Type().Recv() == nil)
3636
3637
3638 if strings.HasPrefix(sym.Name, "init.") {
3639 target.Inits = append(target.Inits, name.Func)
3640 }
3641 }
3642
3643 if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME {
3644 assert(!sym.OnExportList())
3645 target.PluginExports = append(target.PluginExports, name)
3646 sym.SetOnExportList(true)
3647 }
3648
3649 if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) {
3650 assert(!sym.Asm())
3651 target.AsmHdrDecls = append(target.AsmHdrDecls, name)
3652 sym.SetAsm(true)
3653 }
3654 }
3655
3656 return nodes
3657 }
3658
3659
3660
3661
3662
3663 func unifiedHaveInlineBody(fn *ir.Func) bool {
3664 if fn.Inl == nil {
3665 return false
3666 }
3667
3668 _, ok := bodyReaderFor(fn)
3669 return ok
3670 }
3671
3672 var inlgen = 0
3673
3674
3675
3676 func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
3677 pri, ok := bodyReaderFor(fn)
3678 if !ok {
3679 base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
3680 }
3681
3682 if !fn.Inl.HaveDcl {
3683 expandInline(fn, pri)
3684 }
3685
3686 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3687
3688 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type())
3689
3690 r.curfn = tmpfn
3691
3692 r.inlCaller = callerfn
3693 r.inlCall = call
3694 r.inlFunc = fn
3695 r.inlTreeIndex = inlIndex
3696 r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
3697 r.funarghack = true
3698
3699 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
3700 for i, cv := range r.inlFunc.ClosureVars {
3701
3702
3703 if cv.Outer.Curfn != callerfn {
3704 base.FatalfAt(call.Pos(), "inlining closure call across frames")
3705 }
3706 r.closureVars[i] = cv.Outer
3707 }
3708 if len(r.closureVars) != 0 && r.hasTypeParams() {
3709 r.dictParam = r.closureVars[len(r.closureVars)-1]
3710 }
3711
3712 r.declareParams()
3713
3714 var inlvars, retvars []*ir.Name
3715 {
3716 sig := r.curfn.Type()
3717 endParams := sig.NumRecvs() + sig.NumParams()
3718 endResults := endParams + sig.NumResults()
3719
3720 inlvars = r.curfn.Dcl[:endParams]
3721 retvars = r.curfn.Dcl[endParams:endResults]
3722 }
3723
3724 r.delayResults = fn.Inl.CanDelayResults
3725
3726 r.retlabel = typecheck.AutoLabel(".i")
3727 inlgen++
3728
3729 init := ir.TakeInit(call)
3730
3731
3732
3733
3734 if call.Op() == ir.OCALLFUNC {
3735 inline.CalleeEffects(&init, call.Fun)
3736 }
3737
3738 var args ir.Nodes
3739 if call.Op() == ir.OCALLMETH {
3740 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
3741 }
3742 args.Append(call.Args...)
3743
3744
3745 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, ir.ToNodes(inlvars), args)
3746 as2.Def = true
3747 var as2init ir.Nodes
3748 for _, name := range inlvars {
3749 if ir.IsBlank(name) {
3750 continue
3751 }
3752
3753 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3754 name.Defn = as2
3755 }
3756 as2.SetInit(as2init)
3757 init.Append(typecheck.Stmt(as2))
3758
3759 if !r.delayResults {
3760
3761
3762 for _, name := range retvars {
3763
3764 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3765 ras := ir.NewAssignStmt(call.Pos(), name, nil)
3766 init.Append(typecheck.Stmt(ras))
3767 }
3768 }
3769
3770
3771
3772
3773
3774
3775 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
3776
3777 ir.WithFunc(r.curfn, func() {
3778 if !r.syntheticBody(call.Pos()) {
3779 assert(r.Bool())
3780
3781 r.curfn.Body = r.stmts()
3782 r.curfn.Endlineno = r.pos()
3783 }
3784
3785
3786
3787
3788
3789
3790 readBodies(typecheck.Target, true)
3791
3792
3793 var edit func(ir.Node) ir.Node
3794 edit = func(n ir.Node) ir.Node {
3795 if ret, ok := n.(*ir.ReturnStmt); ok {
3796 n = typecheck.Stmt(r.inlReturn(ret, retvars))
3797 }
3798 ir.EditChildren(n, edit)
3799 return n
3800 }
3801 edit(r.curfn)
3802 })
3803
3804 body := r.curfn.Body
3805
3806
3807 for _, name := range r.curfn.Dcl {
3808 name.Curfn = callerfn
3809
3810 if name.Class != ir.PAUTO {
3811 name.SetPos(r.inlPos(name.Pos()))
3812 name.SetInlFormal(true)
3813 name.Class = ir.PAUTO
3814 } else {
3815 name.SetInlLocal(true)
3816 }
3817 }
3818 callerfn.Dcl = append(callerfn.Dcl, r.curfn.Dcl...)
3819
3820 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
3821
3822 res := ir.NewInlinedCallExpr(call.Pos(), body, ir.ToNodes(retvars))
3823 res.SetInit(init)
3824 res.SetType(call.Type())
3825 res.SetTypecheck(1)
3826 res.Reshape = call.Reshape
3827
3828
3829 assert(len(todoBodies) == 0)
3830
3831 return res
3832 }
3833
3834
3835
3836 func (r *reader) inlReturn(ret *ir.ReturnStmt, retvars []*ir.Name) *ir.BlockStmt {
3837 pos := r.inlCall.Pos()
3838
3839 block := ir.TakeInit(ret)
3840
3841 if results := ret.Results; len(results) != 0 {
3842 assert(len(retvars) == len(results))
3843
3844 as2 := ir.NewAssignListStmt(pos, ir.OAS2, ir.ToNodes(retvars), ret.Results)
3845
3846 if r.delayResults {
3847 for _, name := range retvars {
3848
3849 block.Append(ir.NewDecl(pos, ir.ODCL, name))
3850 name.Defn = as2
3851 }
3852 }
3853
3854 block.Append(as2)
3855 }
3856
3857 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
3858 return ir.NewBlockStmt(pos, block)
3859 }
3860
3861
3862
3863 func expandInline(fn *ir.Func, pri pkgReaderIndex) {
3864
3865
3866
3867
3868
3869 fndcls := len(fn.Dcl)
3870 topdcls := len(typecheck.Target.Funcs)
3871
3872 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type())
3873 tmpfn.ClosureVars = fn.ClosureVars
3874
3875 {
3876 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3877
3878
3879 r.funarghack = true
3880
3881 r.funcBody(tmpfn)
3882 }
3883
3884
3885 for _, name := range tmpfn.Dcl {
3886 name.Curfn = fn
3887 }
3888 fn.Inl.Dcl = tmpfn.Dcl
3889 fn.Inl.HaveDcl = true
3890
3891
3892 assert(fndcls == len(fn.Dcl))
3893
3894
3895
3896
3897 typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
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
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955 var needWrapperTypes []*types.Type
3956
3957
3958
3959 var haveWrapperTypes []*types.Type
3960
3961
3962
3963 var needMethodValueWrappers []methodValueWrapper
3964
3965
3966
3967
3968 var haveMethodValueWrappers []methodValueWrapper
3969
3970 type methodValueWrapper struct {
3971 rcvr *types.Type
3972 method *types.Field
3973 }
3974
3975
3976
3977 func (r *reader) needWrapper(typ *types.Type) {
3978 if typ.IsPtr() || typ.IsKind(types.TFORW) {
3979 return
3980 }
3981
3982
3983 forceNeed := typ == types.ErrorType && base.Ctxt.Pkgpath == "runtime"
3984
3985
3986
3987
3988 if r.importedDef() && !forceNeed {
3989 haveWrapperTypes = append(haveWrapperTypes, typ)
3990 } else {
3991 needWrapperTypes = append(needWrapperTypes, typ)
3992 }
3993 }
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009 func (r *reader) importedDef() bool {
4010 return r.p != localPkgReader && !r.hasTypeParams()
4011 }
4012
4013
4014
4015 func MakeWrappers(target *ir.Package) {
4016
4017 needWrapperTypes = append(needWrapperTypes, types.ErrorType)
4018
4019 seen := make(map[string]*types.Type)
4020
4021 for _, typ := range haveWrapperTypes {
4022 wrapType(typ, target, seen, false)
4023 }
4024 haveWrapperTypes = nil
4025
4026 for _, typ := range needWrapperTypes {
4027 wrapType(typ, target, seen, true)
4028 }
4029 needWrapperTypes = nil
4030
4031 for _, wrapper := range haveMethodValueWrappers {
4032 wrapMethodValue(wrapper.rcvr, wrapper.method, target, false)
4033 }
4034 haveMethodValueWrappers = nil
4035
4036 for _, wrapper := range needMethodValueWrappers {
4037 wrapMethodValue(wrapper.rcvr, wrapper.method, target, true)
4038 }
4039 needMethodValueWrappers = nil
4040 }
4041
4042 func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) {
4043 key := typ.LinkString()
4044 if prev := seen[key]; prev != nil {
4045 if !types.Identical(typ, prev) {
4046 base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key)
4047 }
4048 return
4049 }
4050 seen[key] = typ
4051
4052 if !needed {
4053
4054 return
4055 }
4056
4057 if !typ.IsInterface() {
4058 typecheck.CalcMethods(typ)
4059 }
4060 for _, meth := range typ.AllMethods() {
4061 if meth.Sym.IsBlank() || !meth.IsMethod() {
4062 base.FatalfAt(meth.Pos, "invalid method: %v", meth)
4063 }
4064
4065 methodWrapper(0, typ, meth, target)
4066
4067
4068 if !typ.IsInterface() {
4069 methodWrapper(1, typ, meth, target)
4070
4071
4072
4073 if typ.NotInHeap() {
4074 methodWrapper(2, typ, meth, target)
4075 }
4076 }
4077 }
4078 }
4079
4080 func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) {
4081 wrapper := tbase
4082 for i := 0; i < derefs; i++ {
4083 wrapper = types.NewPtr(wrapper)
4084 }
4085
4086 sym := ir.MethodSym(wrapper, method.Sym)
4087 base.Assertf(!sym.Siggen(), "already generated wrapper %v", sym)
4088 sym.SetSiggen(true)
4089
4090 wrappee := method.Type.Recv().Type
4091 if types.Identical(wrapper, wrappee) ||
4092 !types.IsMethodApplicable(wrapper, method) ||
4093 !reflectdata.NeedEmit(tbase) {
4094 return
4095 }
4096
4097
4098 pos := base.AutogeneratedPos
4099
4100 fn := newWrapperFunc(pos, sym, wrapper, method)
4101
4102 var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
4103
4104
4105
4106 if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) {
4107 cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node))
4108 then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)}
4109 fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil))
4110 }
4111
4112
4113
4114 for i := 1; i < derefs; i++ {
4115 recv = Implicit(ir.NewStarExpr(pos, recv))
4116 }
4117
4118 addTailCall(pos, fn, recv, method)
4119
4120 finishWrapperFunc(fn, target)
4121 }
4122
4123 func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) {
4124 sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm")
4125 if sym.Uniq() {
4126 return
4127 }
4128 sym.SetUniq(true)
4129
4130
4131 pos := base.AutogeneratedPos
4132
4133 fn := newWrapperFunc(pos, sym, nil, method)
4134 sym.Def = fn.Nname
4135
4136
4137 recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
4138
4139 if !needed {
4140 return
4141 }
4142
4143 addTailCall(pos, fn, recv, method)
4144
4145 finishWrapperFunc(fn, target)
4146 }
4147
4148 func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
4149 sig := newWrapperType(wrapper, method)
4150 fn := ir.NewFunc(pos, pos, sym, sig)
4151 fn.DeclareParams(true)
4152 fn.SetDupok(true)
4153
4154 return fn
4155 }
4156
4157 func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
4158 ir.WithFunc(fn, func() {
4159 typecheck.Stmts(fn.Body)
4160 })
4161
4162
4163
4164
4165 interleaved.DevirtualizeAndInlineFunc(fn, nil)
4166
4167
4168
4169
4170
4171
4172
4173
4174 ir.VisitFuncAndClosures(fn, func(n ir.Node) {
4175 if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
4176 wrapMethodValue(n.X.Type(), n.Selection, target, true)
4177 }
4178 })
4179
4180 fn.Nname.Defn = fn
4181 target.Funcs = append(target.Funcs, fn)
4182 }
4183
4184
4185
4186
4187
4188 func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
4189 clone := func(params []*types.Field) []*types.Field {
4190 res := make([]*types.Field, len(params))
4191 for i, param := range params {
4192 res[i] = types.NewField(param.Pos, param.Sym, param.Type)
4193 res[i].SetIsDDD(param.IsDDD())
4194 }
4195 return res
4196 }
4197
4198 sig := method.Type
4199
4200 var recv *types.Field
4201 if recvType != nil {
4202 recv = types.NewField(sig.Recv().Pos, sig.Recv().Sym, recvType)
4203 }
4204 params := clone(sig.Params())
4205 results := clone(sig.Results())
4206
4207 return types.NewSignature(recv, params, results)
4208 }
4209
4210 func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) {
4211 sig := fn.Nname.Type()
4212 args := make([]ir.Node, sig.NumParams())
4213 for i, param := range sig.Params() {
4214 args[i] = param.Nname.(*ir.Name)
4215 }
4216
4217 dot := typecheck.XDotMethod(pos, recv, method.Sym, true)
4218 call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr)
4219
4220 if recv.Type() != nil && recv.Type().IsPtr() && method.Type.Recv().Type.IsPtr() &&
4221 method.Embedded != 0 &&
4222 (types.IsInterfaceMethod(method.Type) && base.Ctxt.Arch.Name != "wasm" ||
4223 !types.IsInterfaceMethod(method.Type) && !unifiedHaveInlineBody(ir.MethodExprName(dot).Func)) &&
4224
4225
4226 !((base.Ctxt.Arch.Name == "ppc64le" || base.Ctxt.Arch.Name == "ppc64") && base.Ctxt.Flag_dynlink) {
4227 if base.Debug.TailCall != 0 {
4228 base.WarnfAt(fn.Nname.Type().Recv().Type.Elem().Pos(), "tail call emitted for the method %v wrapper", method.Nname)
4229 }
4230
4231 fn.Body.Append(ir.NewTailCallStmt(pos, call))
4232 return
4233 }
4234
4235 fn.SetWrapper(true)
4236
4237 if method.Type.NumResults() == 0 {
4238 fn.Body.Append(call)
4239 return
4240 }
4241
4242 ret := ir.NewReturnStmt(pos, nil)
4243 ret.Results = []ir.Node{call}
4244 fn.Body.Append(ret)
4245 }
4246
4247 func setBasePos(pos src.XPos) {
4248
4249 base.Pos = pos
4250 }
4251
4252
4253
4254
4255
4256
4257 const dictParamName = typecheck.LocalDictName
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267 func shapeSig(fn *ir.Func, dict *readerDict) *types.Type {
4268 sig := fn.Nname.Type()
4269 oldRecv := sig.Recv()
4270
4271 var recv *types.Field
4272 if oldRecv != nil {
4273 recv = types.NewField(oldRecv.Pos, oldRecv.Sym, oldRecv.Type)
4274 }
4275
4276 params := make([]*types.Field, 1+sig.NumParams())
4277 params[0] = types.NewField(fn.Pos(), fn.Sym().Pkg.Lookup(dictParamName), types.NewPtr(dict.varType()))
4278 for i, param := range sig.Params() {
4279 d := types.NewField(param.Pos, param.Sym, param.Type)
4280 d.SetIsDDD(param.IsDDD())
4281 params[1+i] = d
4282 }
4283
4284 results := make([]*types.Field, sig.NumResults())
4285 for i, result := range sig.Results() {
4286 results[i] = types.NewField(result.Pos, result.Sym, result.Type)
4287 }
4288
4289 typ := types.NewSignature(recv, params, results)
4290 typ.SetHasShape(true)
4291 return typ
4292 }
4293
View as plain text