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