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
3346 staticinit.SplitLargeInit(fn)
3347
3348 target.Inits = append(target.Inits, fn)
3349 }
3350
3351 func (r *reader) pkgDecls(target *ir.Package) {
3352 r.Sync(pkgbits.SyncDecls)
3353 for {
3354 switch code := codeDecl(r.Code(pkgbits.SyncDecl)); code {
3355 default:
3356 panic(fmt.Sprintf("unhandled decl: %v", code))
3357
3358 case declEnd:
3359 return
3360
3361 case declFunc:
3362 names := r.pkgObjs(target)
3363 assert(len(names) == 1)
3364 target.Funcs = append(target.Funcs, names[0].Func)
3365
3366 case declMethod:
3367 typ := r.typ()
3368 sym := r.selector()
3369
3370 method := typecheck.Lookdot1(nil, sym, typ, typ.Methods(), 0)
3371 target.Funcs = append(target.Funcs, method.Nname.(*ir.Name).Func)
3372
3373 case declVar:
3374 names := r.pkgObjs(target)
3375
3376 if n := r.Len(); n > 0 {
3377 assert(len(names) == 1)
3378 embeds := make([]ir.Embed, n)
3379 for i := range embeds {
3380 embeds[i] = ir.Embed{Pos: r.pos(), Patterns: r.Strings()}
3381 }
3382 names[0].Embed = &embeds
3383 target.Embeds = append(target.Embeds, names[0])
3384 }
3385
3386 case declOther:
3387 r.pkgObjs(target)
3388 }
3389 }
3390 }
3391
3392 func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
3393 r.Sync(pkgbits.SyncDeclNames)
3394 nodes := make([]*ir.Name, r.Len())
3395 for i := range nodes {
3396 r.Sync(pkgbits.SyncDeclName)
3397
3398 name := r.obj().(*ir.Name)
3399 nodes[i] = name
3400
3401 sym := name.Sym()
3402 if sym.IsBlank() {
3403 continue
3404 }
3405
3406 switch name.Class {
3407 default:
3408 base.FatalfAt(name.Pos(), "unexpected class: %v", name.Class)
3409
3410 case ir.PEXTERN:
3411 target.Externs = append(target.Externs, name)
3412
3413 case ir.PFUNC:
3414 assert(name.Type().Recv() == nil)
3415
3416
3417 if strings.HasPrefix(sym.Name, "init.") {
3418 target.Inits = append(target.Inits, name.Func)
3419 }
3420 }
3421
3422 if base.Ctxt.Flag_dynlink && types.LocalPkg.Name == "main" && types.IsExported(sym.Name) && name.Op() == ir.ONAME {
3423 assert(!sym.OnExportList())
3424 target.PluginExports = append(target.PluginExports, name)
3425 sym.SetOnExportList(true)
3426 }
3427
3428 if base.Flag.AsmHdr != "" && (name.Op() == ir.OLITERAL || name.Op() == ir.OTYPE) {
3429 assert(!sym.Asm())
3430 target.AsmHdrDecls = append(target.AsmHdrDecls, name)
3431 sym.SetAsm(true)
3432 }
3433 }
3434
3435 return nodes
3436 }
3437
3438
3439
3440
3441
3442 func unifiedHaveInlineBody(fn *ir.Func) bool {
3443 if fn.Inl == nil {
3444 return false
3445 }
3446
3447 _, ok := bodyReaderFor(fn)
3448 return ok
3449 }
3450
3451 var inlgen = 0
3452
3453
3454
3455 func unifiedInlineCall(callerfn *ir.Func, call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
3456 pri, ok := bodyReaderFor(fn)
3457 if !ok {
3458 base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
3459 }
3460
3461 if !fn.Inl.HaveDcl {
3462 expandInline(fn, pri)
3463 }
3464
3465 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3466
3467 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), callerfn.Sym(), fn.Type())
3468
3469 r.curfn = tmpfn
3470
3471 r.inlCaller = callerfn
3472 r.inlCall = call
3473 r.inlFunc = fn
3474 r.inlTreeIndex = inlIndex
3475 r.inlPosBases = make(map[*src.PosBase]*src.PosBase)
3476 r.funarghack = true
3477
3478 r.closureVars = make([]*ir.Name, len(r.inlFunc.ClosureVars))
3479 for i, cv := range r.inlFunc.ClosureVars {
3480
3481
3482 if cv.Outer.Curfn != callerfn {
3483 base.FatalfAt(call.Pos(), "inlining closure call across frames")
3484 }
3485 r.closureVars[i] = cv.Outer
3486 }
3487 if len(r.closureVars) != 0 && r.hasTypeParams() {
3488 r.dictParam = r.closureVars[len(r.closureVars)-1]
3489 }
3490
3491 r.declareParams()
3492
3493 var inlvars, retvars []*ir.Name
3494 {
3495 sig := r.curfn.Type()
3496 endParams := sig.NumRecvs() + sig.NumParams()
3497 endResults := endParams + sig.NumResults()
3498
3499 inlvars = r.curfn.Dcl[:endParams]
3500 retvars = r.curfn.Dcl[endParams:endResults]
3501 }
3502
3503 r.delayResults = fn.Inl.CanDelayResults
3504
3505 r.retlabel = typecheck.AutoLabel(".i")
3506 inlgen++
3507
3508 init := ir.TakeInit(call)
3509
3510
3511
3512
3513 if call.Op() == ir.OCALLFUNC {
3514 inline.CalleeEffects(&init, call.Fun)
3515 }
3516
3517 var args ir.Nodes
3518 if call.Op() == ir.OCALLMETH {
3519 base.FatalfAt(call.Pos(), "OCALLMETH missed by typecheck")
3520 }
3521 args.Append(call.Args...)
3522
3523
3524 as2 := ir.NewAssignListStmt(call.Pos(), ir.OAS2, ir.ToNodes(inlvars), args)
3525 as2.Def = true
3526 var as2init ir.Nodes
3527 for _, name := range inlvars {
3528 if ir.IsBlank(name) {
3529 continue
3530 }
3531
3532 as2init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3533 name.Defn = as2
3534 }
3535 as2.SetInit(as2init)
3536 init.Append(typecheck.Stmt(as2))
3537
3538 if !r.delayResults {
3539
3540
3541 for _, name := range retvars {
3542
3543 init.Append(ir.NewDecl(call.Pos(), ir.ODCL, name))
3544 ras := ir.NewAssignStmt(call.Pos(), name, nil)
3545 init.Append(typecheck.Stmt(ras))
3546 }
3547 }
3548
3549
3550
3551
3552
3553
3554 init.Append(ir.NewInlineMarkStmt(call.Pos().WithIsStmt(), int64(r.inlTreeIndex)))
3555
3556 ir.WithFunc(r.curfn, func() {
3557 if !r.syntheticBody(call.Pos()) {
3558 assert(r.Bool())
3559
3560 r.curfn.Body = r.stmts()
3561 r.curfn.Endlineno = r.pos()
3562 }
3563
3564
3565
3566
3567
3568
3569 readBodies(typecheck.Target, true)
3570
3571
3572 var edit func(ir.Node) ir.Node
3573 edit = func(n ir.Node) ir.Node {
3574 if ret, ok := n.(*ir.ReturnStmt); ok {
3575 n = typecheck.Stmt(r.inlReturn(ret, retvars))
3576 }
3577 ir.EditChildren(n, edit)
3578 return n
3579 }
3580 edit(r.curfn)
3581 })
3582
3583 body := r.curfn.Body
3584
3585
3586 for _, name := range r.curfn.Dcl {
3587 name.Curfn = callerfn
3588
3589 if name.Class != ir.PAUTO {
3590 name.SetPos(r.inlPos(name.Pos()))
3591 name.SetInlFormal(true)
3592 name.Class = ir.PAUTO
3593 } else {
3594 name.SetInlLocal(true)
3595 }
3596 }
3597 callerfn.Dcl = append(callerfn.Dcl, r.curfn.Dcl...)
3598
3599 body.Append(ir.NewLabelStmt(call.Pos(), r.retlabel))
3600
3601 res := ir.NewInlinedCallExpr(call.Pos(), body, ir.ToNodes(retvars))
3602 res.SetInit(init)
3603 res.SetType(call.Type())
3604 res.SetTypecheck(1)
3605
3606
3607 assert(len(todoBodies) == 0)
3608
3609 return res
3610 }
3611
3612
3613
3614 func (r *reader) inlReturn(ret *ir.ReturnStmt, retvars []*ir.Name) *ir.BlockStmt {
3615 pos := r.inlCall.Pos()
3616
3617 block := ir.TakeInit(ret)
3618
3619 if results := ret.Results; len(results) != 0 {
3620 assert(len(retvars) == len(results))
3621
3622 as2 := ir.NewAssignListStmt(pos, ir.OAS2, ir.ToNodes(retvars), ret.Results)
3623
3624 if r.delayResults {
3625 for _, name := range retvars {
3626
3627 block.Append(ir.NewDecl(pos, ir.ODCL, name))
3628 name.Defn = as2
3629 }
3630 }
3631
3632 block.Append(as2)
3633 }
3634
3635 block.Append(ir.NewBranchStmt(pos, ir.OGOTO, r.retlabel))
3636 return ir.NewBlockStmt(pos, block)
3637 }
3638
3639
3640
3641 func expandInline(fn *ir.Func, pri pkgReaderIndex) {
3642
3643
3644
3645
3646
3647 fndcls := len(fn.Dcl)
3648 topdcls := len(typecheck.Target.Funcs)
3649
3650 tmpfn := ir.NewFunc(fn.Pos(), fn.Nname.Pos(), fn.Sym(), fn.Type())
3651 tmpfn.ClosureVars = fn.ClosureVars
3652
3653 {
3654 r := pri.asReader(pkgbits.SectionBody, pkgbits.SyncFuncBody)
3655
3656
3657 r.funarghack = true
3658
3659 r.funcBody(tmpfn)
3660 }
3661
3662
3663 for _, name := range tmpfn.Dcl {
3664 name.Curfn = fn
3665 }
3666 fn.Inl.Dcl = tmpfn.Dcl
3667 fn.Inl.HaveDcl = true
3668
3669
3670 assert(fndcls == len(fn.Dcl))
3671
3672
3673
3674
3675 typecheck.Target.Funcs = typecheck.Target.Funcs[:topdcls]
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
3731
3732
3733 var needWrapperTypes []*types.Type
3734
3735
3736
3737 var haveWrapperTypes []*types.Type
3738
3739
3740
3741 var needMethodValueWrappers []methodValueWrapper
3742
3743
3744
3745
3746 var haveMethodValueWrappers []methodValueWrapper
3747
3748 type methodValueWrapper struct {
3749 rcvr *types.Type
3750 method *types.Field
3751 }
3752
3753
3754
3755 func (r *reader) needWrapper(typ *types.Type) {
3756 if typ.IsPtr() {
3757 return
3758 }
3759
3760
3761 forceNeed := typ == types.ErrorType && base.Ctxt.Pkgpath == "runtime"
3762
3763
3764
3765
3766 if r.importedDef() && !forceNeed {
3767 haveWrapperTypes = append(haveWrapperTypes, typ)
3768 } else {
3769 needWrapperTypes = append(needWrapperTypes, typ)
3770 }
3771 }
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787 func (r *reader) importedDef() bool {
3788 return r.p != localPkgReader && !r.hasTypeParams()
3789 }
3790
3791
3792
3793 func MakeWrappers(target *ir.Package) {
3794
3795 needWrapperTypes = append(needWrapperTypes, types.ErrorType)
3796
3797 seen := make(map[string]*types.Type)
3798
3799 for _, typ := range haveWrapperTypes {
3800 wrapType(typ, target, seen, false)
3801 }
3802 haveWrapperTypes = nil
3803
3804 for _, typ := range needWrapperTypes {
3805 wrapType(typ, target, seen, true)
3806 }
3807 needWrapperTypes = nil
3808
3809 for _, wrapper := range haveMethodValueWrappers {
3810 wrapMethodValue(wrapper.rcvr, wrapper.method, target, false)
3811 }
3812 haveMethodValueWrappers = nil
3813
3814 for _, wrapper := range needMethodValueWrappers {
3815 wrapMethodValue(wrapper.rcvr, wrapper.method, target, true)
3816 }
3817 needMethodValueWrappers = nil
3818 }
3819
3820 func wrapType(typ *types.Type, target *ir.Package, seen map[string]*types.Type, needed bool) {
3821 key := typ.LinkString()
3822 if prev := seen[key]; prev != nil {
3823 if !types.Identical(typ, prev) {
3824 base.Fatalf("collision: types %v and %v have link string %q", typ, prev, key)
3825 }
3826 return
3827 }
3828 seen[key] = typ
3829
3830 if !needed {
3831
3832 return
3833 }
3834
3835 if !typ.IsInterface() {
3836 typecheck.CalcMethods(typ)
3837 }
3838 for _, meth := range typ.AllMethods() {
3839 if meth.Sym.IsBlank() || !meth.IsMethod() {
3840 base.FatalfAt(meth.Pos, "invalid method: %v", meth)
3841 }
3842
3843 methodWrapper(0, typ, meth, target)
3844
3845
3846 if !typ.IsInterface() {
3847 methodWrapper(1, typ, meth, target)
3848
3849
3850
3851 if typ.NotInHeap() {
3852 methodWrapper(2, typ, meth, target)
3853 }
3854 }
3855 }
3856 }
3857
3858 func methodWrapper(derefs int, tbase *types.Type, method *types.Field, target *ir.Package) {
3859 wrapper := tbase
3860 for i := 0; i < derefs; i++ {
3861 wrapper = types.NewPtr(wrapper)
3862 }
3863
3864 sym := ir.MethodSym(wrapper, method.Sym)
3865 base.Assertf(!sym.Siggen(), "already generated wrapper %v", sym)
3866 sym.SetSiggen(true)
3867
3868 wrappee := method.Type.Recv().Type
3869 if types.Identical(wrapper, wrappee) ||
3870 !types.IsMethodApplicable(wrapper, method) ||
3871 !reflectdata.NeedEmit(tbase) {
3872 return
3873 }
3874
3875
3876 pos := base.AutogeneratedPos
3877
3878 fn := newWrapperFunc(pos, sym, wrapper, method)
3879
3880 var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
3881
3882
3883
3884 if wrapper.IsPtr() && types.Identical(wrapper.Elem(), wrappee) {
3885 cond := ir.NewBinaryExpr(pos, ir.OEQ, recv, types.BuiltinPkg.Lookup("nil").Def.(ir.Node))
3886 then := []ir.Node{ir.NewCallExpr(pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)}
3887 fn.Body.Append(ir.NewIfStmt(pos, cond, then, nil))
3888 }
3889
3890
3891
3892 for i := 1; i < derefs; i++ {
3893 recv = Implicit(ir.NewStarExpr(pos, recv))
3894 }
3895
3896 addTailCall(pos, fn, recv, method)
3897
3898 finishWrapperFunc(fn, target)
3899 }
3900
3901 func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Package, needed bool) {
3902 sym := ir.MethodSymSuffix(recvType, method.Sym, "-fm")
3903 if sym.Uniq() {
3904 return
3905 }
3906 sym.SetUniq(true)
3907
3908
3909 pos := base.AutogeneratedPos
3910
3911 fn := newWrapperFunc(pos, sym, nil, method)
3912 sym.Def = fn.Nname
3913
3914
3915 recv := ir.NewHiddenParam(pos, fn, typecheck.Lookup(".this"), recvType)
3916
3917 if !needed {
3918 return
3919 }
3920
3921 addTailCall(pos, fn, recv, method)
3922
3923 finishWrapperFunc(fn, target)
3924 }
3925
3926 func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
3927 sig := newWrapperType(wrapper, method)
3928 fn := ir.NewFunc(pos, pos, sym, sig)
3929 fn.DeclareParams(true)
3930 fn.SetDupok(true)
3931
3932 return fn
3933 }
3934
3935 func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
3936 ir.WithFunc(fn, func() {
3937 typecheck.Stmts(fn.Body)
3938 })
3939
3940
3941
3942
3943 interleaved.DevirtualizeAndInlineFunc(fn, nil)
3944
3945
3946
3947
3948
3949
3950
3951
3952 ir.VisitFuncAndClosures(fn, func(n ir.Node) {
3953 if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
3954 wrapMethodValue(n.X.Type(), n.Selection, target, true)
3955 }
3956 })
3957
3958 fn.Nname.Defn = fn
3959 target.Funcs = append(target.Funcs, fn)
3960 }
3961
3962
3963
3964
3965
3966 func newWrapperType(recvType *types.Type, method *types.Field) *types.Type {
3967 clone := func(params []*types.Field) []*types.Field {
3968 res := make([]*types.Field, len(params))
3969 for i, param := range params {
3970 res[i] = types.NewField(param.Pos, param.Sym, param.Type)
3971 res[i].SetIsDDD(param.IsDDD())
3972 }
3973 return res
3974 }
3975
3976 sig := method.Type
3977
3978 var recv *types.Field
3979 if recvType != nil {
3980 recv = types.NewField(sig.Recv().Pos, sig.Recv().Sym, recvType)
3981 }
3982 params := clone(sig.Params())
3983 results := clone(sig.Results())
3984
3985 return types.NewSignature(recv, params, results)
3986 }
3987
3988 func addTailCall(pos src.XPos, fn *ir.Func, recv ir.Node, method *types.Field) {
3989 sig := fn.Nname.Type()
3990 args := make([]ir.Node, sig.NumParams())
3991 for i, param := range sig.Params() {
3992 args[i] = param.Nname.(*ir.Name)
3993 }
3994
3995 dot := typecheck.XDotMethod(pos, recv, method.Sym, true)
3996 call := typecheck.Call(pos, dot, args, method.Type.IsVariadic()).(*ir.CallExpr)
3997
3998 if recv.Type() != nil && recv.Type().IsPtr() && method.Type.Recv().Type.IsPtr() &&
3999 method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) &&
4000 !unifiedHaveInlineBody(ir.MethodExprName(dot).Func) &&
4001 !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) {
4002 if base.Debug.TailCall != 0 {
4003 base.WarnfAt(fn.Nname.Type().Recv().Type.Elem().Pos(), "tail call emitted for the method %v wrapper", method.Nname)
4004 }
4005
4006 fn.Body.Append(ir.NewTailCallStmt(pos, call))
4007 return
4008 }
4009
4010 fn.SetWrapper(true)
4011
4012 if method.Type.NumResults() == 0 {
4013 fn.Body.Append(call)
4014 return
4015 }
4016
4017 ret := ir.NewReturnStmt(pos, nil)
4018 ret.Results = []ir.Node{call}
4019 fn.Body.Append(ret)
4020 }
4021
4022 func setBasePos(pos src.XPos) {
4023
4024 base.Pos = pos
4025 }
4026
4027
4028
4029
4030
4031
4032 const dictParamName = typecheck.LocalDictName
4033
4034
4035
4036
4037
4038
4039
4040 func shapeSig(fn *ir.Func, dict *readerDict) *types.Type {
4041 sig := fn.Nname.Type()
4042 oldRecv := sig.Recv()
4043
4044 var recv *types.Field
4045 if oldRecv != nil {
4046 recv = types.NewField(oldRecv.Pos, oldRecv.Sym, oldRecv.Type)
4047 }
4048
4049 params := make([]*types.Field, 1+sig.NumParams())
4050 params[0] = types.NewField(fn.Pos(), fn.Sym().Pkg.Lookup(dictParamName), types.NewPtr(dict.varType()))
4051 for i, param := range sig.Params() {
4052 d := types.NewField(param.Pos, param.Sym, param.Type)
4053 d.SetIsDDD(param.IsDDD())
4054 params[1+i] = d
4055 }
4056
4057 results := make([]*types.Field, sig.NumResults())
4058 for i, result := range sig.Results() {
4059 results[i] = types.NewField(result.Pos, result.Sym, result.Type)
4060 }
4061
4062 return types.NewSignature(recv, params, results)
4063 }
4064
View as plain text