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