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