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