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