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 if r.Bool() {
2435
2436 x := r.expr()
2437 x = typecheck.DefaultLit(x, nil)
2438 var init ir.Nodes
2439 addr := ir.NewAddrExpr(pos, r.tempCopy(pos, x, &init))
2440 addr.SetInit(init)
2441 return typecheck.Expr(addr)
2442 }
2443
2444 return typecheck.Expr(ir.NewUnaryExpr(pos, ir.ONEW, r.exprType()))
2445
2446 case exprSizeof:
2447 return ir.NewUintptr(r.pos(), r.typ().Size())
2448
2449 case exprAlignof:
2450 return ir.NewUintptr(r.pos(), r.typ().Alignment())
2451
2452 case exprOffsetof:
2453 pos := r.pos()
2454 typ := r.typ()
2455 types.CalcSize(typ)
2456
2457 var offset int64
2458 for i := r.Len(); i >= 0; i-- {
2459 field := typ.Field(r.Len())
2460 offset += field.Offset
2461 typ = field.Type
2462 }
2463
2464 return ir.NewUintptr(pos, offset)
2465
2466 case exprReshape:
2467 typ := r.typ()
2468 x := r.expr()
2469
2470 if types.IdenticalStrict(x.Type(), typ) {
2471 return x
2472 }
2473
2474
2475
2476
2477
2478
2479 if x.Type() == types.UntypedBool && typ.IsBoolean() {
2480 return x
2481 }
2482
2483 base.AssertfAt(x.Type().HasShape() || typ.HasShape(), x.Pos(), "%L and %v are not shape types", x, typ)
2484 base.AssertfAt(types.Identical(x.Type(), typ), x.Pos(), "%L is not shape-identical to %v", x, typ)
2485
2486
2487
2488
2489
2490
2491
2492 base.AssertfAt(ir.HasUniquePos(x), x.Pos(), "cannot call SetType(%v) on %L", typ, x)
2493
2494 if base.Debug.Reshape != 0 {
2495 base.WarnfAt(x.Pos(), "reshaping %L to %v", x, typ)
2496 }
2497
2498 x.SetType(typ)
2499 return x
2500
2501 case exprConvert:
2502 implicit := r.Bool()
2503 typ := r.typ()
2504 pos := r.pos()
2505 typeWord, srcRType := r.convRTTI(pos)
2506 dstTypeParam := r.Bool()
2507 identical := r.Bool()
2508 x := r.expr()
2509
2510
2511 x = typecheck.DefaultLit(x, typ)
2512
2513 ce := ir.NewConvExpr(pos, ir.OCONV, typ, x)
2514 ce.TypeWord, ce.SrcRType = typeWord, srcRType
2515 if implicit {
2516 ce.SetImplicit(true)
2517 }
2518 n := typecheck.Expr(ce)
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536 if !identical {
2537 if n, ok := n.(*ir.ConvExpr); ok && n.Op() == ir.OCONVNOP && n.Type().IsInterface() && !n.Type().IsEmptyInterface() && (n.Type().HasShape() || n.X.Type().HasShape()) {
2538 n.SetOp(ir.OCONVIFACE)
2539 }
2540 }
2541
2542
2543
2544 if dstTypeParam && ir.IsConstNode(n) {
2545
2546 n = Implicit(ir.NewConvExpr(pos, ir.OCONVNOP, n.Type(), n))
2547 n.SetTypecheck(1)
2548 }
2549 return n
2550
2551 case exprRuntimeBuiltin:
2552 builtin := typecheck.LookupRuntime(r.String())
2553 return builtin
2554 }
2555 }
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579 func (r *reader) funcInst(pos src.XPos) (wrapperFn, baseFn, dictPtr ir.Node) {
2580
2581 var implicits []*types.Type
2582 if r.dict != nil {
2583 implicits = r.dict.targs
2584 }
2585
2586 if r.Bool() {
2587 idx := r.Len()
2588 info := r.dict.subdicts[idx]
2589 explicits := r.p.typListIdx(info.explicits, r.dict)
2590
2591 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2592
2593
2594
2595 dictPtrType := baseFn.Type().Param(0).Type
2596 dictPtr = typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2597
2598 return
2599 }
2600
2601 info := r.objInfo()
2602 explicits := r.p.typListIdx(info.explicits, r.dict)
2603
2604 wrapperFn = r.p.objIdx(info.idx, implicits, explicits, false).(*ir.Name)
2605 baseFn = r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2606
2607 dictName := r.p.objDictName(info.idx, implicits, explicits)
2608 dictPtr = typecheck.Expr(ir.NewAddrExpr(pos, dictName))
2609
2610 return
2611 }
2612
2613 func (pr *pkgReader) objDictName(idx index, implicits, explicits []*types.Type) *ir.Name {
2614 rname := pr.newReader(pkgbits.SectionName, idx, pkgbits.SyncObject1)
2615 _, sym := rname.qualifiedIdent()
2616 tag := pkgbits.CodeObj(rname.Code(pkgbits.SyncCodeObj))
2617
2618 if tag == pkgbits.ObjStub {
2619 assert(!sym.IsBlank())
2620 if pri, ok := objReader[sym]; ok {
2621 return pri.pr.objDictName(pri.idx, nil, explicits)
2622 }
2623 base.Fatalf("unresolved stub: %v", sym)
2624 }
2625
2626 dict, err := pr.objDictIdx(sym, idx, implicits, explicits, false)
2627 if err != nil {
2628 base.Fatalf("%v", err)
2629 }
2630
2631 return pr.dictNameOf(dict)
2632 }
2633
2634
2635
2636
2637
2638
2639
2640
2641 func (r *reader) curry(origPos src.XPos, ifaceHack bool, fun ir.Node, arg0, arg1 ir.Node) ir.Node {
2642 var captured ir.Nodes
2643 captured.Append(fun, arg0)
2644 if arg1 != nil {
2645 captured.Append(arg1)
2646 }
2647
2648 params, results := syntheticSig(fun.Type())
2649 params = params[len(captured)-1:]
2650 typ := types.NewSignature(nil, params, results)
2651
2652 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2653 fun := captured[0]
2654
2655 var args ir.Nodes
2656 args.Append(captured[1:]...)
2657 args.Append(r.syntheticArgs()...)
2658
2659 r.syntheticTailCall(pos, fun, args)
2660 }
2661
2662 return r.syntheticClosure(origPos, typ, ifaceHack, captured, addBody)
2663 }
2664
2665
2666
2667
2668 func (r *reader) methodExprWrap(origPos src.XPos, recv *types.Type, implicits []int, deref, addr bool, method, dictPtr ir.Node) ir.Node {
2669 var captured ir.Nodes
2670 captured.Append(method)
2671
2672 params, results := syntheticSig(method.Type())
2673
2674
2675 params[0].Type = recv
2676
2677
2678
2679
2680 if dictPtr != nil {
2681 captured.Append(dictPtr)
2682 params = append(params[:1], params[2:]...)
2683 }
2684
2685 typ := types.NewSignature(nil, params, results)
2686
2687 addBody := func(pos src.XPos, r *reader, captured []ir.Node) {
2688 fn := captured[0]
2689 args := r.syntheticArgs()
2690
2691
2692 {
2693 arg := args[0]
2694 for _, ix := range implicits {
2695 arg = Implicit(typecheck.DotField(pos, arg, ix))
2696 }
2697 if deref {
2698 arg = Implicit(Deref(pos, arg.Type().Elem(), arg))
2699 } else if addr {
2700 arg = Implicit(Addr(pos, arg))
2701 }
2702 args[0] = arg
2703 }
2704
2705
2706 if dictPtr != nil {
2707 newArgs := make([]ir.Node, len(args)+1)
2708 newArgs[0] = args[0]
2709 newArgs[1] = captured[1]
2710 copy(newArgs[2:], args[1:])
2711 args = newArgs
2712 }
2713
2714 r.syntheticTailCall(pos, fn, args)
2715 }
2716
2717 return r.syntheticClosure(origPos, typ, false, captured, addBody)
2718 }
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734 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 {
2735
2736
2737
2738
2739
2740 isSafe := func(n ir.Node) bool {
2741 if n.Op() == ir.ONAME && n.(*ir.Name).Class == ir.PFUNC {
2742 return true
2743 }
2744 if n.Op() == ir.OMETHEXPR {
2745 return true
2746 }
2747
2748 return false
2749 }
2750
2751 fn := r.inlClosureFunc(origPos, typ, ir.OCLOSURE)
2752 fn.SetWrapper(true)
2753
2754 clo := fn.OClosure
2755 inlPos := clo.Pos()
2756
2757 var init ir.Nodes
2758 for i, n := range captures {
2759 if isSafe(n) {
2760 continue
2761 }
2762
2763 tmp := r.tempCopy(inlPos, n, &init)
2764 ir.NewClosureVar(origPos, fn, tmp)
2765
2766
2767
2768 if ifaceHack && i == 1 && n.Type().IsInterface() {
2769 check := ir.NewUnaryExpr(inlPos, ir.OCHECKNIL, ir.NewUnaryExpr(inlPos, ir.OITAB, tmp))
2770 init.Append(typecheck.Stmt(check))
2771 }
2772 }
2773
2774 pri := pkgReaderIndex{synthetic: func(pos src.XPos, r *reader) {
2775 captured := make([]ir.Node, len(captures))
2776 next := 0
2777 for i, n := range captures {
2778 if isSafe(n) {
2779 captured[i] = n
2780 } else {
2781 captured[i] = r.closureVars[next]
2782 next++
2783 }
2784 }
2785 assert(next == len(r.closureVars))
2786
2787 addBody(origPos, r, captured)
2788 }}
2789 bodyReader[fn] = pri
2790 pri.funcBody(fn)
2791
2792 return ir.InitExpr(init, clo)
2793 }
2794
2795
2796
2797
2798 func syntheticSig(sig *types.Type) (params, results []*types.Field) {
2799 clone := func(params []*types.Field) []*types.Field {
2800 res := make([]*types.Field, len(params))
2801 for i, param := range params {
2802
2803
2804
2805
2806
2807
2808 res[i] = types.NewField(base.AutogeneratedPos, param.Sym, param.Type)
2809 res[i].SetIsDDD(param.IsDDD())
2810 }
2811 return res
2812 }
2813
2814 return clone(sig.Params()), clone(sig.Results())
2815 }
2816
2817 func (r *reader) optExpr() ir.Node {
2818 if r.Bool() {
2819 return r.expr()
2820 }
2821 return nil
2822 }
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847 func (r *reader) methodExpr() (wrapperFn, baseFn, dictPtr ir.Node) {
2848 recv := r.typ()
2849 sig0 := r.typ()
2850 pos := r.pos()
2851 sym := r.selector()
2852
2853
2854
2855 sig := typecheck.NewMethodType(sig0, recv)
2856
2857 if r.Bool() {
2858 idx := r.Len()
2859 word := r.dictWord(pos, r.dict.typeParamMethodExprsOffset()+idx)
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870 fn := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, sig, ir.NewAddrExpr(pos, word)))
2871 return fn, fn, nil
2872 }
2873
2874
2875
2876
2877 var implicits []*types.Type
2878 if r.dict != nil {
2879 implicits = r.dict.targs
2880 }
2881
2882 if r.Bool() {
2883 idx := r.Len()
2884 info := r.dict.subdicts[idx]
2885 explicits := r.p.typListIdx(info.explicits, r.dict)
2886
2887 shapedObj := r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2888 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
2889
2890
2891
2892 dictPtrType := shapedFn.Type().Param(1).Type
2893 dictPtr := typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, dictPtrType, r.dictWord(pos, r.dict.subdictsOffset()+idx)))
2894
2895 return nil, shapedFn, dictPtr
2896 }
2897
2898 if r.Bool() {
2899 info := r.objInfo()
2900 explicits := r.p.typListIdx(info.explicits, r.dict)
2901
2902 shapedObj := r.p.objIdx(info.idx, implicits, explicits, true).(*ir.Name)
2903 shapedFn := shapedMethodExpr(pos, shapedObj, sym)
2904
2905 dict := r.p.objDictName(info.idx, implicits, explicits)
2906 dictPtr := typecheck.Expr(ir.NewAddrExpr(pos, dict))
2907
2908
2909 if !types.Identical(dictPtr.Type(), shapedFn.Type().Param(1).Type) {
2910 base.FatalfAt(pos, "dict %L, but shaped method %L", dict, shapedFn)
2911 }
2912
2913
2914
2915 base.AssertfAt(!recv.HasShape(), pos, "shaped receiver %v", recv)
2916 wrapperFn := typecheck.NewMethodExpr(pos, recv, sym)
2917 base.AssertfAt(types.Identical(sig, wrapperFn.Type()), pos, "wrapper %L does not have type %v", wrapperFn, sig)
2918
2919 return wrapperFn, shapedFn, dictPtr
2920 }
2921
2922
2923 base.AssertfAt(!recv.HasShape() || recv.IsInterface(), pos, "shaped receiver %v", recv)
2924 fn := typecheck.NewMethodExpr(pos, recv, sym)
2925 return fn, fn, nil
2926 }
2927
2928
2929
2930 func shapedMethodExpr(pos src.XPos, obj *ir.Name, sym *types.Sym) *ir.SelectorExpr {
2931 assert(obj.Op() == ir.OTYPE)
2932
2933 typ := obj.Type()
2934 assert(typ.HasShape())
2935
2936 method := func() *types.Field {
2937 for _, method := range typ.Methods() {
2938 if method.Sym == sym {
2939 return method
2940 }
2941 }
2942
2943 base.FatalfAt(pos, "failed to find method %v in shaped type %v", sym, typ)
2944 panic("unreachable")
2945 }()
2946
2947
2948 recv := method.Type.Recv().Type
2949 return typecheck.NewMethodExpr(pos, recv, sym)
2950 }
2951
2952 func (r *reader) multiExpr() []ir.Node {
2953 r.Sync(pkgbits.SyncMultiExpr)
2954
2955 if r.Bool() {
2956 pos := r.pos()
2957 expr := r.expr()
2958
2959 results := make([]ir.Node, r.Len())
2960 as := ir.NewAssignListStmt(pos, ir.OAS2, nil, []ir.Node{expr})
2961 as.Def = true
2962 for i := range results {
2963 tmp := r.temp(pos, r.typ())
2964 tmp.Defn = as
2965 as.PtrInit().Append(ir.NewDecl(pos, ir.ODCL, tmp))
2966 as.Lhs.Append(tmp)
2967
2968 res := ir.Node(tmp)
2969 if r.Bool() {
2970 n := ir.NewConvExpr(pos, ir.OCONV, r.typ(), res)
2971 n.TypeWord, n.SrcRType = r.convRTTI(pos)
2972 n.SetImplicit(true)
2973 res = typecheck.Expr(n)
2974 }
2975 results[i] = res
2976 }
2977
2978
2979 results[0] = ir.InitExpr([]ir.Node{typecheck.Stmt(as)}, results[0])
2980 return results
2981 }
2982
2983
2984 exprs := make([]ir.Node, r.Len())
2985 if len(exprs) == 0 {
2986 return nil
2987 }
2988 for i := range exprs {
2989 exprs[i] = r.expr()
2990 }
2991 return exprs
2992 }
2993
2994
2995 func (r *reader) temp(pos src.XPos, typ *types.Type) *ir.Name {
2996 return typecheck.TempAt(pos, r.curfn, typ)
2997 }
2998
2999
3000
3001 func (r *reader) tempCopy(pos src.XPos, expr ir.Node, init *ir.Nodes) *ir.Name {
3002 tmp := r.temp(pos, expr.Type())
3003
3004 init.Append(typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)))
3005
3006 assign := ir.NewAssignStmt(pos, tmp, expr)
3007 assign.Def = true
3008 init.Append(typecheck.Stmt(ir.NewAssignStmt(pos, tmp, expr)))
3009
3010 tmp.Defn = assign
3011
3012 return tmp
3013 }
3014
3015 func (r *reader) compLit() ir.Node {
3016 r.Sync(pkgbits.SyncCompLit)
3017 pos := r.pos()
3018 typ0 := r.typ()
3019
3020 typ := typ0
3021 if typ.IsPtr() {
3022 typ = typ.Elem()
3023 }
3024 if typ.Kind() == types.TFORW {
3025 base.FatalfAt(pos, "unresolved composite literal type: %v", typ)
3026 }
3027 var rtype ir.Node
3028 if typ.IsMap() {
3029 rtype = r.rtype(pos)
3030 }
3031 isStruct := typ.Kind() == types.TSTRUCT
3032
3033 elems := make([]ir.Node, r.Len())
3034 for i := range elems {
3035 elemp := &elems[i]
3036
3037 if isStruct {
3038 sk := ir.NewStructKeyExpr(r.pos(), typ.Field(r.Len()), nil)
3039 *elemp, elemp = sk, &sk.Value
3040 } else if r.Bool() {
3041 kv := ir.NewKeyExpr(r.pos(), r.expr(), nil)
3042 *elemp, elemp = kv, &kv.Value
3043 }
3044
3045 *elemp = r.expr()
3046 }
3047
3048 lit := typecheck.Expr(ir.NewCompLitExpr(pos, ir.OCOMPLIT, typ, elems))
3049 if rtype != nil {
3050 lit := lit.(*ir.CompLitExpr)
3051 lit.RType = rtype
3052 }
3053 if typ0.IsPtr() {
3054 lit = typecheck.Expr(typecheck.NodAddrAt(pos, lit))
3055 lit.SetType(typ0)
3056 }
3057 return lit
3058 }
3059
3060 func (r *reader) funcLit() ir.Node {
3061 r.Sync(pkgbits.SyncFuncLit)
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079 r.suppressInlPos++
3080 origPos := r.pos()
3081 sig := r.signature(nil)
3082 r.suppressInlPos--
3083 why := ir.OCLOSURE
3084 if r.Bool() {
3085 why = ir.ORANGE
3086 }
3087
3088 fn := r.inlClosureFunc(origPos, sig, why)
3089
3090 fn.ClosureVars = make([]*ir.Name, 0, r.Len())
3091 for len(fn.ClosureVars) < cap(fn.ClosureVars) {
3092
3093
3094 ir.NewClosureVar(r.pos(), fn, r.useLocal())
3095 }
3096 if param := r.dictParam; param != nil {
3097
3098
3099 ir.NewClosureVar(param.Pos(), fn, param)
3100 }
3101
3102 r.addBody(fn, nil)
3103
3104 return fn.OClosure
3105 }
3106
3107
3108
3109 func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type, why ir.Op) *ir.Func {
3110 curfn := r.inlCaller
3111 if curfn == nil {
3112 curfn = r.curfn
3113 }
3114
3115
3116 return ir.NewClosureFunc(origPos, r.inlPos(origPos), why, sig, curfn, typecheck.Target)
3117 }
3118
3119 func (r *reader) exprList() []ir.Node {
3120 r.Sync(pkgbits.SyncExprList)
3121 return r.exprs()
3122 }
3123
3124 func (r *reader) exprs() []ir.Node {
3125 r.Sync(pkgbits.SyncExprs)
3126 nodes := make([]ir.Node, r.Len())
3127 if len(nodes) == 0 {
3128 return nil
3129 }
3130 for i := range nodes {
3131 nodes[i] = r.expr()
3132 }
3133 return nodes
3134 }
3135
3136
3137
3138 func (r *reader) dictWord(pos src.XPos, idx int) ir.Node {
3139 base.AssertfAt(r.dictParam != nil, pos, "expected dictParam in %v", r.curfn)
3140 return typecheck.Expr(ir.NewIndexExpr(pos, r.dictParam, ir.NewInt(pos, int64(idx))))
3141 }
3142
3143
3144
3145 func (r *reader) rttiWord(pos src.XPos, idx int) ir.Node {
3146 return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TUINT8]), r.dictWord(pos, idx)))
3147 }
3148
3149
3150
3151
3152 func (r *reader) rtype(pos src.XPos) ir.Node {
3153 _, rtype := r.rtype0(pos)
3154 return rtype
3155 }
3156
3157 func (r *reader) rtype0(pos src.XPos) (typ *types.Type, rtype ir.Node) {
3158 r.Sync(pkgbits.SyncRType)
3159 if r.Bool() {
3160 idx := r.Len()
3161 info := r.dict.rtypes[idx]
3162 typ = r.p.typIdx(info, r.dict, true)
3163 rtype = r.rttiWord(pos, r.dict.rtypesOffset()+idx)
3164 return
3165 }
3166
3167 typ = r.typ()
3168 rtype = reflectdata.TypePtrAt(pos, typ)
3169 return
3170 }
3171
3172
3173 func (r *reader) varDictIndex(name *ir.Name) {
3174 if r.Bool() {
3175 idx := 1 + r.dict.rtypesOffset() + r.Len()
3176 if int(uint16(idx)) != idx {
3177 base.FatalfAt(name.Pos(), "DictIndex overflow for %v: %v", name, idx)
3178 }
3179 name.DictIndex = uint16(idx)
3180 }
3181 }
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191 func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) {
3192 typ, typRType = r.rtype0(pos)
3193 iface, ifaceRType = r.rtype0(pos)
3194
3195 idx := -1
3196 if r.Bool() {
3197 idx = r.Len()
3198 }
3199
3200 if !typ.IsInterface() && iface.IsInterface() && !iface.IsEmptyInterface() {
3201 if idx >= 0 {
3202 itab = r.rttiWord(pos, r.dict.itabsOffset()+idx)
3203 } else {
3204 base.AssertfAt(!typ.HasShape(), pos, "%v is a shape type", typ)
3205 base.AssertfAt(!iface.HasShape(), pos, "%v is a shape type", iface)
3206
3207 lsym := reflectdata.ITabLsym(typ, iface)
3208 itab = typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
3209 }
3210 }
3211
3212 return
3213 }
3214
3215
3216
3217 func (r *reader) convRTTI(pos src.XPos) (typeWord, srcRType ir.Node) {
3218 r.Sync(pkgbits.SyncConvRTTI)
3219 src, srcRType0, dst, dstRType, itab := r.itab(pos)
3220 if !dst.IsInterface() {
3221 return
3222 }
3223
3224
3225 switch {
3226 case dst.IsEmptyInterface():
3227 if !src.IsInterface() {
3228 typeWord = srcRType0
3229 }
3230 case !src.IsInterface():
3231 typeWord = itab
3232 default:
3233 typeWord = dstRType
3234 }
3235
3236
3237 if !src.IsInterface() {
3238 srcRType = srcRType0
3239 }
3240
3241 return
3242 }
3243
3244 func (r *reader) exprType() ir.Node {
3245 r.Sync(pkgbits.SyncExprType)
3246 pos := r.pos()
3247
3248 var typ *types.Type
3249 var rtype, itab ir.Node
3250
3251 if r.Bool() {
3252
3253 typ, rtype, _, _, itab = r.itab(pos)
3254 if !typ.IsInterface() {
3255 rtype = nil
3256 }
3257 } else {
3258 typ, rtype = r.rtype0(pos)
3259
3260 if !r.Bool() {
3261 return ir.TypeNode(typ)
3262 }
3263 }
3264
3265 dt := ir.NewDynamicType(pos, rtype)
3266 dt.ITab = itab
3267 dt = typed(typ, dt).(*ir.DynamicType)
3268 if st := dt.ToStatic(); st != nil {
3269 return st
3270 }
3271 return dt
3272 }
3273
3274 func (r *reader) op() ir.Op {
3275 r.Sync(pkgbits.SyncOp)
3276 return ir.Op(r.Len())
3277 }
3278
3279
3280
3281 func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) {
3282 cgoPragmas := make([][]string, r.Len())
3283 for i := range cgoPragmas {
3284 cgoPragmas[i] = r.Strings()
3285 }
3286 target.CgoPragmas = cgoPragmas
3287
3288 r.pkgInitOrder(target)
3289
3290 r.pkgDecls(target)
3291
3292 r.Sync(pkgbits.SyncEOF)
3293 }
3294
3295
3296
3297 func (r *reader) pkgInitOrder(target *ir.Package) {
3298 initOrder := make([]ir.Node, r.Len())
3299 if len(initOrder) == 0 {
3300 return
3301 }
3302
3303
3304 pos := base.AutogeneratedPos
3305 base.Pos = pos
3306
3307 fn := ir.NewFunc(pos, pos, typecheck.Lookup("init"), types.NewSignature(nil, nil, nil))
3308 fn.SetIsPackageInit(true)
3309 fn.SetInlinabilityChecked(true)
3310
3311 typecheck.DeclFunc(fn)
3312 r.curfn = fn
3313
3314 for i := range initOrder {
3315 lhs := make([]ir.Node, r.Len())
3316 for j := range lhs {
3317 lhs[j] = r.obj()
3318 }
3319 rhs := r.expr()
3320 pos := lhs[0].Pos()
3321
3322 var as ir.Node
3323 if len(lhs) == 1 {
3324 as = typecheck.Stmt(ir.NewAssignStmt(pos, lhs[0], rhs))
3325 } else {
3326 as = typecheck.Stmt(ir.NewAssignListStmt(pos, ir.OAS2, lhs, []ir.Node{rhs}))
3327 }
3328
3329 for _, v := range lhs {
3330 v.(*ir.Name).Defn = as
3331 }
3332
3333 initOrder[i] = as
3334 }
3335
3336 fn.Body = initOrder
3337
3338 typecheck.FinishFuncBody()
3339 r.curfn = nil
3340 r.locals = nil
3341
3342
3343 staticinit.OutlineMapInits(fn)
3344
3345 target.Inits = append(target.Inits, fn)
3346 }
3347
3348 func (r *reader) pkgDecls(target *ir.Package) {
3349 r.Sync(pkgbits.SyncDecls)
3350 for {
3351 switch code := codeDecl(r.Code(pkgbits.SyncDecl)); code {
3352 default:
3353 panic(fmt.Sprintf("unhandled decl: %v", code))
3354
3355 case declEnd:
3356 return
3357
3358 case declFunc:
3359 names := r.pkgObjs(target)
3360 assert(len(names) == 1)
3361 target.Funcs = append(target.Funcs, names[0].Func)
3362
3363 case declMethod:
3364 typ := r.typ()
3365 sym := r.selector()
3366
3367 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
3368 target.Funcs = append(target.Funcs, method.Nname.(*ir.Name).Func)
3369
3370 case declVar:
3371 names := r.pkgObjs(target)
3372
3373 if n := r.Len(); n > 0 {
3374 assert(len(names) == 1)
3375 embeds := make([]ir.Embed, n)
3376 for i := range embeds {
3377 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.Strings()}
3378 }
3379 names[0].Embed = &embeds
3380 target.Embeds = append(target.Embeds, names[0])
3381 }
3382
3383 case declOther:
3384 r.pkgObjs(target)
3385 }
3386 }
3387 }
3388
3389 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
3390 r.Sync(pkgbits.SyncDeclNames)
3391 nodes := make([]*ir.Name, r.Len())
3392 for i := range nodes {
3393 r.Sync(pkgbits.SyncDeclName)
3394
3395 name := r.obj().(*ir.Name)
3396 nodes[i] = name
3397
3398 sym := name.Sym()
3399 if sym.IsBlank() {
3400 continue
3401 }
3402
3403 switch name.Class {
3404 default:
3405 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
3406
3407 case ir.PEXTERN:
3408 target.Externs = append(target.Externs, name)
3409
3410 case ir.PFUNC:
3411 assert(name.Type().Recv() == nil)
3412
3413
3414 if strings.HasPrefix(sym.Name, "init.") {
3415 target.Inits = append(target.Inits, name.Func)
3416 }
3417 }
3418
3419 if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME {
3420 assert(!sym.OnExportList())
3421 target.PluginExports = append(target.PluginExports, name)
3422 sym.SetOnExportList(true)
3423 }
3424
3425 if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) {
3426 assert(!sym.Asm())
3427 target.AsmHdrDecls = append(target.AsmHdrDecls, name)
3428 sym.SetAsm(true)
3429 }
3430 }
3431
3432 return nodes
3433 }
3434
3435
3436
3437
3438
3439 func unifiedHaveInlineBody(fn *ir.Func) bool {
3440 if fn.Inl == nil {
3441 return false
3442 }
3443
3444 _, ok := bodyReaderFor(fn)
3445 return ok
3446 }
3447
3448 var inlgen = 0
3449
3450
3451
3452 func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
3453 pri, ok := bodyReaderFor(fn)
3454 if !ok {
3455 base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
3456 }
3457
3458 if !fn.Inl.HaveDcl {
3459 expandInline(fn, pri)
3460 }
3461
3462 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3463
3464 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type())
3465
3466 r.curfn = tmpfn
3467
3468 r.inlCaller = callerfn
3469 r.inlCall = call
3470 r.inlFunc = fn
3471 r.inlTreeIndex = inlIndex
3472 r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
3473 r.funarghack = true
3474
3475 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
3476 for i, cv := range r.inlFunc.ClosureVars {
3477
3478
3479 if cv.Outer.Curfn != callerfn {
3480 base.FatalfAt(call.Pos(), "inlining closure call across frames")
3481 }
3482 r.closureVars[i] = cv.Outer
3483 }
3484 if len(r.closureVars) != 0 && r.hasTypeParams() {
3485 r.dictParam = r.closureVars[len(r.closureVars)-1]
3486 }
3487
3488 r.declareParams()
3489
3490 var inlvars, retvars []*ir.Name
3491 {
3492 sig := r.curfn.Type()
3493 endParams := sig.NumRecvs() + sig.NumParams()
3494 endResults := endParams + sig.NumResults()
3495
3496 inlvars = r.curfn.Dcl[:endParams]
3497 retvars = r.curfn.Dcl[endParams:endResults]
3498 }
3499
3500 r.delayResults = fn.Inl.CanDelayResults
3501
3502 r.retlabel = typecheck.AutoLabel(".i")
3503 inlgen++
3504
3505 init := ir.TakeInit(call)
3506
3507
3508
3509
3510 if call.Op() == ir.OCALLFUNC {
3511 inline.CalleeEffects(&init, call.Fun)
3512 }
3513
3514 var args ir.Nodes
3515 if call.Op() == ir.OCALLMETH {
3516 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
3517 }
3518 args.Append(call.Args...)
3519
3520
3521 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, ir.ToNodes(inlvars), args)
3522 as2.Def = true
3523 var as2init ir.Nodes
3524 for _, name := range inlvars {
3525 if ir.IsBlank(name) {
3526 continue
3527 }
3528
3529 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3530 name.Defn = as2
3531 }
3532 as2.SetInit(as2init)
3533 init.Append(typecheck.Stmt(as2))
3534
3535 if !r.delayResults {
3536
3537
3538 for _, name := range retvars {
3539
3540 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3541 ras := ir.NewAssignStmt(call.Pos(), name, nil)
3542 init.Append(typecheck.Stmt(ras))
3543 }
3544 }
3545
3546
3547
3548
3549
3550
3551 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
3552
3553 ir.WithFunc(r.curfn, func() {
3554 if !r.syntheticBody(call.Pos()) {
3555 assert(r.Bool())
3556
3557 r.curfn.Body = r.stmts()
3558 r.curfn.Endlineno = r.pos()
3559 }
3560
3561
3562
3563
3564
3565
3566 readBodies(typecheck.Target, true)
3567
3568
3569 var edit func(ir.Node) ir.Node
3570 edit = func(n ir.Node) ir.Node {
3571 if ret, ok := n.(*ir.ReturnStmt); ok {
3572 n = typecheck.Stmt(r.inlReturn(ret, retvars))
3573 }
3574 ir.EditChildren(n, edit)
3575 return n
3576 }
3577 edit(r.curfn)
3578 })
3579
3580 body := ir.Nodes(r.curfn.Body)
3581
3582
3583 for _, name := range r.curfn.Dcl {
3584 name.Curfn = callerfn
3585
3586 if name.Class != ir.PAUTO {
3587 name.SetPos(r.inlPos(name.Pos()))
3588 name.SetInlFormal(true)
3589 name.Class = ir.PAUTO
3590 } else {
3591 name.SetInlLocal(true)
3592 }
3593 }
3594 callerfn.Dcl = append(callerfn.Dcl, r.curfn.Dcl...)
3595
3596 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
3597
3598 res := ir.NewInlinedCallExpr(call.Pos(), body, ir.ToNodes(retvars))
3599 res.SetInit(init)
3600 res.SetType(call.Type())
3601 res.SetTypecheck(1)
3602
3603
3604 assert(len(todoBodies) == 0)
3605
3606 return res
3607 }
3608
3609
3610
3611 func (r *reader) inlReturn(ret *ir.ReturnStmt, retvars []*ir.Name) *ir.BlockStmt {
3612 pos := r.inlCall.Pos()
3613
3614 block := ir.TakeInit(ret)
3615
3616 if results := ret.Results; len(results) != 0 {
3617 assert(len(retvars) == len(results))
3618
3619 as2 := ir.NewAssignListStmt(pos, ir.OAS2, ir.ToNodes(retvars), ret.Results)
3620
3621 if r.delayResults {
3622 for _, name := range retvars {
3623
3624 block.Append(ir.NewDecl(pos, ir.ODCL, name))
3625 name.Defn = as2
3626 }
3627 }
3628
3629 block.Append(as2)
3630 }
3631
3632 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
3633 return ir.NewBlockStmt(pos, block)
3634 }
3635
3636
3637
3638 func expandInline(fn *ir.Func, pri pkgReaderIndex) {
3639
3640
3641
3642
3643
3644 fndcls := len(fn.Dcl)
3645 topdcls := len(typecheck.Target.Funcs)
3646
3647 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type())
3648 tmpfn.ClosureVars = fn.ClosureVars
3649
3650 {
3651 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3652
3653
3654 r.funarghack = true
3655
3656 r.funcBody(tmpfn)
3657 }
3658
3659
3660 for _, name := range tmpfn.Dcl {
3661 name.Curfn = fn
3662 }
3663 fn.Inl.Dcl = tmpfn.Dcl
3664 fn.Inl.HaveDcl = true
3665
3666
3667 assert(fndcls == len(fn.Dcl))
3668
3669
3670
3671
3672 typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
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