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