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