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