1
2
3
4
5 package noder
6
7 import (
8 "fmt"
9 "go/constant"
10 "go/token"
11 "go/version"
12 "internal/buildcfg"
13 "internal/pkgbits"
14 "os"
15 "slices"
16 "strings"
17
18 "cmd/compile/internal/base"
19 "cmd/compile/internal/ir"
20 "cmd/compile/internal/syntax"
21 "cmd/compile/internal/types"
22 "cmd/compile/internal/types2"
23 )
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 type index = pkgbits.Index
63
64 func assert(p bool) { base.Assert(p) }
65
66
67
68 type pkgWriter struct {
69 pkgbits.PkgEncoder
70
71 m posMap
72 curpkg *types2.Package
73 info *types2.Info
74 rangeFuncBodyClosures map[*syntax.FuncLit]bool
75
76
77
78 posBasesIdx map[*syntax.PosBase]index
79 pkgsIdx map[*types2.Package]index
80 typsIdx map[types2.Type]index
81 objsIdx map[types2.Object]index
82
83
84
85 funDecls map[*types2.Func]*syntax.FuncDecl
86 typDecls map[*types2.TypeName]typeDeclGen
87
88
89
90 linknames map[types2.Object]struct {
91 remote string
92 std bool
93 }
94
95
96
97 cgoPragmas [][]string
98 }
99
100
101
102 func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
103 return &pkgWriter{
104 PkgEncoder: pkgbits.NewPkgEncoder(uirVersion, base.Debug.SyncFrames),
105
106 m: m,
107 curpkg: pkg,
108 info: info,
109 rangeFuncBodyClosures: otherInfo,
110
111 pkgsIdx: make(map[*types2.Package]index),
112 objsIdx: make(map[types2.Object]index),
113 typsIdx: make(map[types2.Type]index),
114
115 posBasesIdx: make(map[*syntax.PosBase]index),
116
117 funDecls: make(map[*types2.Func]*syntax.FuncDecl),
118 typDecls: make(map[*types2.TypeName]typeDeclGen),
119
120 linknames: make(map[types2.Object]struct {
121 remote string
122 std bool
123 }),
124 }
125 }
126
127
128 func (pw *pkgWriter) errorf(p poser, msg string, args ...any) {
129 base.ErrorfAt(pw.m.pos(p), 0, msg, args...)
130 }
131
132
133 func (pw *pkgWriter) fatalf(p poser, msg string, args ...any) {
134 base.FatalfAt(pw.m.pos(p), msg, args...)
135 }
136
137
138
139 func (pw *pkgWriter) unexpected(what string, p poser) {
140 pw.fatalf(p, "unexpected %s: %v (%T)", what, p, p)
141 }
142
143 func (pw *pkgWriter) typeAndValue(x syntax.Expr) syntax.TypeAndValue {
144 tv, ok := pw.maybeTypeAndValue(x)
145 if !ok {
146 pw.fatalf(x, "missing Types entry: %v", syntax.String(x))
147 }
148 return tv
149 }
150
151 func (pw *pkgWriter) maybeTypeAndValue(x syntax.Expr) (syntax.TypeAndValue, bool) {
152 tv := x.GetTypeInfo()
153
154
155
156
157 if name, ok := x.(*syntax.Name); ok {
158 if inst, ok := pw.info.Instances[name]; ok {
159 tv.Type = inst.Type
160 }
161 }
162
163 return tv, tv.Type != nil
164 }
165
166
167 func (pw *pkgWriter) typeOf(expr syntax.Expr) types2.Type {
168 tv := pw.typeAndValue(expr)
169 if !tv.IsValue() {
170 pw.fatalf(expr, "expected value: %v", syntax.String(expr))
171 }
172 return tv.Type
173 }
174
175
176 type writer struct {
177 p *pkgWriter
178
179 *pkgbits.Encoder
180
181
182 sig *types2.Signature
183
184
185
186
187
188
189
190 localsIdx map[*types2.Var]int
191
192
193
194 closureVars []posVar
195 closureVarsIdx map[*types2.Var]int
196
197 dict *writerDict
198
199
200
201 derived bool
202 }
203
204
205 type writerDict struct {
206
207 implicits []*types2.TypeParam
208
209 receivers []*types2.TypeParam
210
211
212
213 derived []derivedInfo
214
215
216
217 derivedIdx map[types2.Type]index
218
219
220 typeParamMethodExprs []writerMethodExprInfo
221 subdicts []objInfo
222 rtypes []typeInfo
223 itabs []itabInfo
224 }
225
226 type itabInfo struct {
227 typ typeInfo
228 iface typeInfo
229 }
230
231
232
233
234 func (dict *writerDict) typeParamIndex(typ *types2.TypeParam) int {
235 for idx, implicit := range dict.implicits {
236 if implicit == typ {
237 return idx
238 }
239 }
240
241 for idx, receiver := range dict.receivers {
242 if receiver == typ {
243 return len(dict.implicits) + idx
244 }
245 }
246
247 return len(dict.implicits) + len(dict.receivers) + typ.Index()
248 }
249
250
251 type derivedInfo struct {
252 idx index
253 }
254
255
256
257
258
259
260
261
262
263 type typeInfo struct {
264 idx index
265 derived bool
266 }
267
268
269
270 type objInfo struct {
271 idx index
272 explicits []typeInfo
273 }
274
275
276
277
278 type selectorInfo struct {
279 pkgIdx index
280 nameIdx index
281 }
282
283
284
285 func (info objInfo) anyDerived() bool {
286 for _, explicit := range info.explicits {
287 if explicit.derived {
288 return true
289 }
290 }
291 return false
292 }
293
294
295
296 func (info objInfo) equals(other objInfo) bool {
297 if info.idx != other.idx {
298 return false
299 }
300 assert(len(info.explicits) == len(other.explicits))
301 for i, targ := range info.explicits {
302 if targ != other.explicits[i] {
303 return false
304 }
305 }
306 return true
307 }
308
309 type writerMethodExprInfo struct {
310 typeParamIdx int
311 methodInfo selectorInfo
312 }
313
314
315
316
317 func (dict *writerDict) typeParamMethodExprIdx(typeParamIdx int, methodInfo selectorInfo) int {
318 newInfo := writerMethodExprInfo{typeParamIdx, methodInfo}
319
320 for idx, oldInfo := range dict.typeParamMethodExprs {
321 if oldInfo == newInfo {
322 return idx
323 }
324 }
325
326 idx := len(dict.typeParamMethodExprs)
327 dict.typeParamMethodExprs = append(dict.typeParamMethodExprs, newInfo)
328 return idx
329 }
330
331
332
333
334 func (dict *writerDict) subdictIdx(newInfo objInfo) int {
335 for idx, oldInfo := range dict.subdicts {
336 if oldInfo.equals(newInfo) {
337 return idx
338 }
339 }
340
341 idx := len(dict.subdicts)
342 dict.subdicts = append(dict.subdicts, newInfo)
343 return idx
344 }
345
346
347
348
349 func (dict *writerDict) rtypeIdx(newInfo typeInfo) int {
350 for idx, oldInfo := range dict.rtypes {
351 if oldInfo == newInfo {
352 return idx
353 }
354 }
355
356 idx := len(dict.rtypes)
357 dict.rtypes = append(dict.rtypes, newInfo)
358 return idx
359 }
360
361
362
363
364 func (dict *writerDict) itabIdx(typInfo, ifaceInfo typeInfo) int {
365 newInfo := itabInfo{typInfo, ifaceInfo}
366
367 for idx, oldInfo := range dict.itabs {
368 if oldInfo == newInfo {
369 return idx
370 }
371 }
372
373 idx := len(dict.itabs)
374 dict.itabs = append(dict.itabs, newInfo)
375 return idx
376 }
377
378 func (pw *pkgWriter) newWriter(k pkgbits.SectionKind, marker pkgbits.SyncMarker) *writer {
379 return &writer{
380 Encoder: pw.NewEncoder(k, marker),
381 p: pw,
382 }
383 }
384
385
386
387
388 func (w *writer) pos(p poser) {
389 w.Sync(pkgbits.SyncPos)
390 pos := p.Pos()
391
392
393 if !w.Bool(pos.IsKnown()) {
394 return
395 }
396
397
398 w.posBase(pos.Base())
399 w.Uint(pos.Line())
400 w.Uint(pos.Col())
401 }
402
403
404
405 func (w *writer) posBase(b *syntax.PosBase) {
406 w.Reloc(pkgbits.SectionPosBase, w.p.posBaseIdx(b))
407 }
408
409
410 func (pw *pkgWriter) posBaseIdx(b *syntax.PosBase) index {
411 if idx, ok := pw.posBasesIdx[b]; ok {
412 return idx
413 }
414
415 w := pw.newWriter(pkgbits.SectionPosBase, pkgbits.SyncPosBase)
416 w.p.posBasesIdx[b] = w.Idx
417
418 w.String(trimFilename(b))
419
420 if !w.Bool(b.IsFileBase()) {
421 w.pos(b)
422 w.Uint(b.Line())
423 w.Uint(b.Col())
424 }
425
426 return w.Flush()
427 }
428
429
430
431
432 func (w *writer) pkg(pkg *types2.Package) {
433 w.pkgRef(w.p.pkgIdx(pkg))
434 }
435
436 func (w *writer) pkgRef(idx index) {
437 w.Sync(pkgbits.SyncPkg)
438 w.Reloc(pkgbits.SectionPkg, idx)
439 }
440
441
442
443 func (pw *pkgWriter) pkgIdx(pkg *types2.Package) index {
444 if idx, ok := pw.pkgsIdx[pkg]; ok {
445 return idx
446 }
447
448 w := pw.newWriter(pkgbits.SectionPkg, pkgbits.SyncPkgDef)
449 pw.pkgsIdx[pkg] = w.Idx
450
451
452
453
454
455 switch pkg {
456 case nil:
457 w.String("builtin")
458 case types2.Unsafe:
459 w.String("unsafe")
460 default:
461
462 var path string
463 if pkg != w.p.curpkg {
464 path = pkg.Path()
465 }
466 base.Assertf(path != "builtin" && path != "unsafe", "unexpected path for user-defined package: %q", path)
467 w.String(path)
468 w.String(pkg.Name())
469
470 w.Len(len(pkg.Imports()))
471 for _, imp := range pkg.Imports() {
472 w.pkg(imp)
473 }
474 }
475
476 return w.Flush()
477 }
478
479
480
481 var (
482 anyTypeName = types2.Universe.Lookup("any").(*types2.TypeName)
483 comparableTypeName = types2.Universe.Lookup("comparable").(*types2.TypeName)
484 runeTypeName = types2.Universe.Lookup("rune").(*types2.TypeName)
485 )
486
487
488 func (w *writer) typ(typ types2.Type) {
489 w.typInfo(w.p.typIdx(typ, w.dict))
490 }
491
492
493
494 func (w *writer) typInfo(info typeInfo) {
495 w.Sync(pkgbits.SyncType)
496 if w.Bool(info.derived) {
497 w.Len(int(info.idx))
498 w.derived = true
499 } else {
500 w.Reloc(pkgbits.SectionType, info.idx)
501 }
502 }
503
504
505
506
507
508
509 func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
510
511
512
513
514 for {
515 if alias, ok := typ.(*types2.Alias); ok && !isGlobal(alias.Obj()) {
516 typ = alias.Rhs()
517 } else {
518 break
519 }
520 }
521
522 if idx, ok := pw.typsIdx[typ]; ok {
523 return typeInfo{idx: idx, derived: false}
524 }
525 if dict != nil {
526 if idx, ok := dict.derivedIdx[typ]; ok {
527 return typeInfo{idx: idx, derived: true}
528 }
529 }
530
531 w := pw.newWriter(pkgbits.SectionType, pkgbits.SyncTypeIdx)
532 w.dict = dict
533
534 switch typ := typ.(type) {
535 default:
536 base.Fatalf("unexpected type: %v (%T)", typ, typ)
537
538 case *types2.Basic:
539 switch kind := typ.Kind(); {
540 case kind == types2.Invalid:
541 base.Fatalf("unexpected types2.Invalid")
542
543 case types2.Typ[kind] == typ:
544 w.Code(pkgbits.TypeBasic)
545 w.Len(int(kind))
546
547 default:
548
549 obj := types2.Universe.Lookup(typ.Name()).(*types2.TypeName)
550 assert(obj.Type() == typ)
551
552 w.Code(pkgbits.TypeNamed)
553 w.namedType(obj, nil)
554 }
555
556 case *types2.Named:
557 w.Code(pkgbits.TypeNamed)
558 w.namedType(splitNamed(typ))
559
560 case *types2.Alias:
561 w.Code(pkgbits.TypeNamed)
562 w.namedType(splitAlias(typ))
563
564 case *types2.TypeParam:
565 w.derived = true
566 w.Code(pkgbits.TypeTypeParam)
567 w.Len(w.dict.typeParamIndex(typ))
568
569 case *types2.Array:
570 w.Code(pkgbits.TypeArray)
571 w.Uint64(uint64(typ.Len()))
572 w.typ(typ.Elem())
573
574 case *types2.Chan:
575 w.Code(pkgbits.TypeChan)
576 w.Len(int(typ.Dir()))
577 w.typ(typ.Elem())
578
579 case *types2.Map:
580 w.Code(pkgbits.TypeMap)
581 w.typ(typ.Key())
582 w.typ(typ.Elem())
583
584 case *types2.Pointer:
585 w.Code(pkgbits.TypePointer)
586 w.typ(typ.Elem())
587
588 case *types2.Signature:
589 base.Assertf(typ.TypeParams() == nil, "unexpected type params: %v", typ)
590 w.Code(pkgbits.TypeSignature)
591 w.signature(typ)
592
593 case *types2.Slice:
594 w.Code(pkgbits.TypeSlice)
595 w.typ(typ.Elem())
596
597 case *types2.Struct:
598 w.Code(pkgbits.TypeStruct)
599 w.structType(typ)
600
601 case *types2.Interface:
602
603
604
605
606 if types2.Unalias(typ) == types2.Unalias(anyTypeName.Type()) {
607 w.Code(pkgbits.TypeNamed)
608 w.obj(anyTypeName, nil)
609 break
610 }
611
612 w.Code(pkgbits.TypeInterface)
613 w.interfaceType(typ)
614
615 case *types2.Union:
616 w.Code(pkgbits.TypeUnion)
617 w.unionType(typ)
618 }
619
620 if w.derived {
621 idx := index(len(dict.derived))
622 dict.derived = append(dict.derived, derivedInfo{idx: w.Flush()})
623 dict.derivedIdx[typ] = idx
624 return typeInfo{idx: idx, derived: true}
625 }
626
627 pw.typsIdx[typ] = w.Idx
628 return typeInfo{idx: w.Flush(), derived: false}
629 }
630
631
632 func (w *writer) namedType(obj *types2.TypeName, targs []types2.Type) {
633
634
635 if w.p.hasImplicitTypeParams(obj) {
636 w.derived = true
637 }
638
639 w.obj(obj, targs)
640 }
641
642 func (w *writer) structType(typ *types2.Struct) {
643 w.Len(typ.NumFields())
644 for i := 0; i < typ.NumFields(); i++ {
645 f := typ.Field(i)
646 w.pos(f)
647 w.selector(f)
648 w.typ(f.Type())
649 w.String(typ.Tag(i))
650 w.Bool(f.Embedded())
651 }
652 }
653
654 func (w *writer) unionType(typ *types2.Union) {
655 w.Len(typ.Len())
656 for i := 0; i < typ.Len(); i++ {
657 t := typ.Term(i)
658 w.Bool(t.Tilde())
659 w.typ(t.Type())
660 }
661 }
662
663 func (w *writer) interfaceType(typ *types2.Interface) {
664
665
666
667 if typ.NumEmbeddeds() == 0 && !typ.IsMethodSet() {
668
669
670
671 assert(typ == comparableTypeName.Type().(*types2.Named).Underlying())
672
673
674 w.Len(0)
675 w.Len(1)
676 w.Bool(false)
677 w.typ(comparableTypeName.Type())
678 return
679 }
680
681 w.Len(typ.NumExplicitMethods())
682 w.Len(typ.NumEmbeddeds())
683
684 if typ.NumExplicitMethods() == 0 && typ.NumEmbeddeds() == 1 {
685 w.Bool(typ.IsImplicit())
686 } else {
687
688
689
690 assert(!typ.IsImplicit())
691 }
692
693 for i := 0; i < typ.NumExplicitMethods(); i++ {
694 m := typ.ExplicitMethod(i)
695 sig := m.Type().(*types2.Signature)
696 assert(sig.TypeParams() == nil)
697
698 w.pos(m)
699 w.selector(m)
700 w.signature(sig)
701 }
702
703 for i := 0; i < typ.NumEmbeddeds(); i++ {
704 w.typ(typ.EmbeddedType(i))
705 }
706 }
707
708 func (w *writer) signature(sig *types2.Signature) {
709 w.Sync(pkgbits.SyncSignature)
710 w.params(sig.Params())
711 w.params(sig.Results())
712 w.Bool(sig.Variadic())
713 }
714
715 func (w *writer) params(typ *types2.Tuple) {
716 w.Sync(pkgbits.SyncParams)
717 w.Len(typ.Len())
718 for i := 0; i < typ.Len(); i++ {
719 w.param(typ.At(i))
720 }
721 }
722
723 func (w *writer) param(param *types2.Var) {
724 w.Sync(pkgbits.SyncParam)
725 w.pos(param)
726 w.localIdent(param)
727 w.typ(param.Type())
728 }
729
730
731
732
733
734
735
736
737 func (w *writer) obj(obj types2.Object, explicits []types2.Type) {
738 w.objInfo(w.p.objInstIdx(obj, explicits, w.dict))
739 }
740
741
742
743 func (w *writer) objInfo(info objInfo) {
744 w.Sync(pkgbits.SyncObject)
745 if w.Version().Has(pkgbits.DerivedFuncInstance) {
746 w.Bool(false)
747 }
748 w.Reloc(pkgbits.SectionObj, info.idx)
749
750 w.Len(len(info.explicits))
751 for _, info := range info.explicits {
752 w.typInfo(info)
753 }
754 }
755
756
757
758
759 func (pw *pkgWriter) objInstIdx(obj types2.Object, explicits []types2.Type, dict *writerDict) objInfo {
760 explicitInfos := make([]typeInfo, len(explicits))
761 for i := range explicitInfos {
762 explicitInfos[i] = pw.typIdx(explicits[i], dict)
763 }
764 return objInfo{idx: pw.objIdx(obj), explicits: explicitInfos}
765 }
766
767
768
769 func (pw *pkgWriter) objIdx(obj types2.Object) index {
770
771
772
773 if idx, ok := pw.objsIdx[obj]; ok {
774 return idx
775 }
776
777 dict := &writerDict{
778 derivedIdx: make(map[types2.Type]index),
779 }
780
781 if isDefinedType(obj) && obj.Pkg() == pw.curpkg {
782 decl, ok := pw.typDecls[obj.(*types2.TypeName)]
783 assert(ok)
784 dict.implicits = decl.implicits
785 }
786
787 if isGenericMethod(obj.Type()) {
788 dict.receivers = asTypeParamSlice(obj.Type().(*types2.Signature).RecvTypeParams())
789 }
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814 w := pw.newWriter(pkgbits.SectionObj, pkgbits.SyncObject1)
815 wext := pw.newWriter(pkgbits.SectionObjExt, pkgbits.SyncObject1)
816 wname := pw.newWriter(pkgbits.SectionName, pkgbits.SyncObject1)
817 wdict := pw.newWriter(pkgbits.SectionObjDict, pkgbits.SyncObject1)
818
819 pw.objsIdx[obj] = w.Idx
820 assert(wext.Idx == w.Idx)
821 assert(wname.Idx == w.Idx)
822 assert(wdict.Idx == w.Idx)
823
824 w.dict = dict
825 wext.dict = dict
826
827 code := w.doObj(wext, obj)
828 w.Flush()
829 wext.Flush()
830
831 wname.qualifiedIdent(obj)
832 wname.Code(code)
833 wname.Flush()
834
835 wdict.objDict(obj, w.dict)
836 wdict.Flush()
837
838 return w.Idx
839 }
840
841
842
843 func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
844 if obj.Pkg() != w.p.curpkg {
845 return pkgbits.ObjStub
846 }
847
848 switch obj := obj.(type) {
849 default:
850 w.p.unexpected("object", obj)
851 panic("unreachable")
852
853 case *types2.Const:
854 w.pos(obj)
855 w.typ(obj.Type())
856 w.Value(obj.Val())
857 return pkgbits.ObjConst
858
859 case *types2.Func:
860 decl, ok := w.p.funDecls[obj]
861 assert(ok)
862 sig := obj.Type().(*types2.Signature)
863
864 w.pos(obj)
865 if isGenericMethod(sig) {
866
867 assert(w.Version().Has(pkgbits.GenericMethods))
868 w.Bool(true)
869
870 w.selector(obj)
871 w.typeParamNames(sig.RecvTypeParams())
872 w.param(sig.Recv())
873 } else {
874 if w.Version().Has(pkgbits.GenericMethods) {
875 w.Bool(false)
876 }
877 }
878 w.typeParamNames(sig.TypeParams())
879 w.signature(sig)
880 w.pos(decl)
881 wext.funcExt(obj)
882 return pkgbits.ObjFunc
883
884 case *types2.TypeName:
885 if obj.IsAlias() {
886 w.pos(obj)
887 rhs := obj.Type()
888 var tparams *types2.TypeParamList
889 if alias, ok := rhs.(*types2.Alias); ok {
890 assert(alias.TypeArgs() == nil)
891 tparams = alias.TypeParams()
892 rhs = alias.Rhs()
893 }
894 if w.Version().Has(pkgbits.AliasTypeParamNames) {
895 w.typeParamNames(tparams)
896 }
897 assert(w.Version().Has(pkgbits.AliasTypeParamNames) || tparams.Len() == 0)
898 w.typ(rhs)
899 return pkgbits.ObjAlias
900 }
901
902 named := obj.Type().(*types2.Named)
903 assert(named.TypeArgs() == nil)
904
905 w.pos(obj)
906 w.typeParamNames(named.TypeParams())
907 wext.typeExt(obj)
908 w.typ(named.Underlying())
909
910
911 var methods, gmethods []*types2.Func
912 for i := range named.NumMethods() {
913 m := named.Method(i)
914 if isGenericMethod(m.Type()) {
915 gmethods = append(gmethods, m)
916 } else {
917 methods = append(methods, m)
918 }
919 }
920
921 w.Len(len(methods))
922 for _, m := range methods {
923 w.method(wext, m)
924 }
925
926 for _, m := range gmethods {
927 w.p.objIdx(m)
928 }
929
930 return pkgbits.ObjType
931
932 case *types2.Var:
933 w.pos(obj)
934 w.typ(obj.Type())
935 wext.varExt(obj)
936 return pkgbits.ObjVar
937 }
938 }
939
940
941 func (w *writer) objDict(obj types2.Object, dict *writerDict) {
942
943
944
945
946 w.dict = dict
947 w.Len(len(dict.implicits))
948
949 rtparams := objRecvTypeParams(obj)
950 tparams := objTypeParams(obj)
951
952 if w.Version().Has(pkgbits.GenericMethods) {
953 w.Len(len(rtparams))
954 } else {
955 assert(len(rtparams) == 0)
956 }
957 w.Len(len(tparams))
958
959 for _, rtparam := range rtparams {
960 w.typ(rtparam.Constraint())
961 }
962 for _, tparam := range tparams {
963 w.typ(tparam.Constraint())
964 }
965
966 nderived := len(dict.derived)
967 w.Len(nderived)
968 for _, typ := range dict.derived {
969 w.Reloc(pkgbits.SectionType, typ.idx)
970 if w.Version().Has(pkgbits.DerivedInfoNeeded) {
971 w.Bool(false)
972 }
973 }
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990 for _, implicit := range dict.implicits {
991 w.Bool(implicit.Underlying().(*types2.Interface).IsMethodSet())
992 }
993 for _, rtparam := range rtparams {
994 w.Bool(rtparam.Underlying().(*types2.Interface).IsMethodSet())
995 }
996 for _, tparam := range tparams {
997 w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet())
998 }
999
1000 w.Len(len(dict.typeParamMethodExprs))
1001 for _, info := range dict.typeParamMethodExprs {
1002 w.Len(info.typeParamIdx)
1003 w.selectorInfo(info.methodInfo)
1004 }
1005
1006 w.Len(len(dict.subdicts))
1007 for _, info := range dict.subdicts {
1008 w.objInfo(info)
1009 }
1010
1011 w.Len(len(dict.rtypes))
1012 for _, info := range dict.rtypes {
1013 w.typInfo(info)
1014 }
1015
1016 w.Len(len(dict.itabs))
1017 for _, info := range dict.itabs {
1018 w.typInfo(info.typ)
1019 w.typInfo(info.iface)
1020 }
1021
1022 assert(len(dict.derived) == nderived)
1023 }
1024
1025 func (w *writer) typeParamNames(tparams *types2.TypeParamList) {
1026 w.Sync(pkgbits.SyncTypeParamNames)
1027
1028 ntparams := tparams.Len()
1029 for i := 0; i < ntparams; i++ {
1030 tparam := tparams.At(i).Obj()
1031 w.pos(tparam)
1032 w.localIdent(tparam)
1033 }
1034 }
1035
1036 func (w *writer) method(wext *writer, meth *types2.Func) {
1037 decl, ok := w.p.funDecls[meth]
1038 assert(ok)
1039 sig := meth.Type().(*types2.Signature)
1040
1041 w.Sync(pkgbits.SyncMethod)
1042 w.pos(meth)
1043 w.selector(meth)
1044 w.typeParamNames(sig.RecvTypeParams())
1045 w.param(sig.Recv())
1046 w.signature(sig)
1047
1048 w.pos(decl)
1049 wext.funcExt(meth)
1050 }
1051
1052
1053
1054 func (w *writer) qualifiedIdent(obj types2.Object) {
1055 w.Sync(pkgbits.SyncSym)
1056
1057 name := obj.Name()
1058 if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
1059 decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
1060 assert(ok)
1061 if decl.gen != 0 {
1062
1063
1064
1065
1066
1067 name = fmt.Sprintf("%s·%v", name, decl.gen)
1068 }
1069 }
1070
1071
1072
1073 if isGenericMethod(obj.Type()) {
1074 recv := types2.Unalias(deref2(obj.Type().(*types2.Signature).Recv().Type()))
1075 name = fmt.Sprintf("%s.%s", recv.(*types2.Named).Obj().Name(), name)
1076 }
1077
1078 w.pkg(obj.Pkg())
1079 w.String(name)
1080 }
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090 func (w *writer) localIdent(obj types2.Object) {
1091 assert(!isGlobal(obj))
1092 w.Sync(pkgbits.SyncLocalIdent)
1093 w.pkg(obj.Pkg())
1094 w.String(obj.Name())
1095 }
1096
1097
1098
1099 func (w *writer) selector(obj types2.Object) {
1100 w.selectorInfo(w.p.selectorIdx(obj))
1101 }
1102
1103 func (w *writer) selectorInfo(info selectorInfo) {
1104 w.Sync(pkgbits.SyncSelector)
1105 w.pkgRef(info.pkgIdx)
1106 w.StringRef(info.nameIdx)
1107 }
1108
1109 func (pw *pkgWriter) selectorIdx(obj types2.Object) selectorInfo {
1110 pkgIdx := pw.pkgIdx(obj.Pkg())
1111 nameIdx := pw.StringIdx(obj.Name())
1112 return selectorInfo{pkgIdx: pkgIdx, nameIdx: nameIdx}
1113 }
1114
1115
1116
1117 func (w *writer) funcExt(obj *types2.Func) {
1118 decl, ok := w.p.funDecls[obj]
1119 assert(ok)
1120
1121
1122
1123
1124
1125 pragma := asPragmaFlag(decl.Pragma)
1126 if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 {
1127 w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined")
1128 }
1129 wi := asWasmImport(decl.Pragma)
1130 we := asWasmExport(decl.Pragma)
1131
1132 if decl.Body != nil {
1133 if pragma&ir.Noescape != 0 {
1134 w.p.errorf(decl, "can only use //go:noescape with external func implementations")
1135 }
1136 if wi != nil {
1137 w.p.errorf(decl, "can only use //go:wasmimport with external func implementations")
1138 }
1139 if (pragma&ir.UintptrKeepAlive != 0 && pragma&ir.UintptrEscapes == 0) && pragma&ir.Nosplit == 0 {
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit")
1154 }
1155 } else {
1156 if base.Flag.Complete || decl.Name.Value == "init" {
1157
1158
1159
1160 if _, ok := w.p.linknames[obj]; !ok && wi == nil {
1161 w.p.errorf(decl, "missing function body")
1162 }
1163 }
1164 }
1165
1166 sig, block := obj.Type().(*types2.Signature), decl.Body
1167 body, closureVars := w.p.bodyIdx(sig, block, w.dict)
1168 if len(closureVars) > 0 {
1169 fmt.Fprintln(os.Stderr, "CLOSURE", closureVars)
1170 }
1171 assert(len(closureVars) == 0)
1172
1173 w.Sync(pkgbits.SyncFuncExt)
1174 w.pragmaFlag(pragma)
1175 w.linkname(obj)
1176
1177 if buildcfg.GOARCH == "wasm" {
1178 if wi != nil {
1179 w.String(wi.Module)
1180 w.String(wi.Name)
1181 } else {
1182 w.String("")
1183 w.String("")
1184 }
1185 if we != nil {
1186 w.String(we.Name)
1187 } else {
1188 w.String("")
1189 }
1190 }
1191
1192 w.Bool(false)
1193 w.Reloc(pkgbits.SectionBody, body)
1194 w.Sync(pkgbits.SyncEOF)
1195 }
1196
1197 func (w *writer) typeExt(obj *types2.TypeName) {
1198 decl, ok := w.p.typDecls[obj]
1199 assert(ok)
1200
1201 w.Sync(pkgbits.SyncTypeExt)
1202
1203 w.pragmaFlag(asPragmaFlag(decl.Pragma))
1204
1205
1206 w.Int64(-1)
1207 w.Int64(-1)
1208 }
1209
1210 func (w *writer) varExt(obj *types2.Var) {
1211 w.Sync(pkgbits.SyncVarExt)
1212 w.linkname(obj)
1213 }
1214
1215 func (w *writer) linkname(obj types2.Object) {
1216 w.Sync(pkgbits.SyncLinkname)
1217 w.Int64(-1)
1218 info := w.p.linknames[obj]
1219 w.String(info.remote)
1220 w.Bool(info.std)
1221 }
1222
1223 func (w *writer) pragmaFlag(p ir.PragmaFlag) {
1224 w.Sync(pkgbits.SyncPragma)
1225 w.Int(int(p))
1226 }
1227
1228
1229
1230
1231
1232 func (pw *pkgWriter) bodyIdx(sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx index, closureVars []posVar) {
1233 w := pw.newWriter(pkgbits.SectionBody, pkgbits.SyncFuncBody)
1234 w.sig = sig
1235 w.dict = dict
1236
1237 w.declareParams(sig)
1238 if w.Bool(block != nil) {
1239 w.stmts(block.List)
1240 w.pos(block.Rbrace)
1241 }
1242
1243 return w.Flush(), w.closureVars
1244 }
1245
1246 func (w *writer) declareParams(sig *types2.Signature) {
1247 addLocals := func(params *types2.Tuple) {
1248 for i := 0; i < params.Len(); i++ {
1249 w.addLocal(params.At(i))
1250 }
1251 }
1252
1253 if recv := sig.Recv(); recv != nil {
1254 w.addLocal(recv)
1255 }
1256 addLocals(sig.Params())
1257 addLocals(sig.Results())
1258 }
1259
1260
1261 func (w *writer) addLocal(obj *types2.Var) {
1262 idx := len(w.localsIdx)
1263
1264 w.Sync(pkgbits.SyncAddLocal)
1265 if w.p.SyncMarkers() {
1266 w.Int(idx)
1267 }
1268 w.varDictIndex(obj)
1269
1270 if w.localsIdx == nil {
1271 w.localsIdx = make(map[*types2.Var]int)
1272 }
1273 w.localsIdx[obj] = idx
1274 }
1275
1276
1277
1278 func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) {
1279 w.Sync(pkgbits.SyncUseObjLocal)
1280
1281 if idx, ok := w.localsIdx[obj]; w.Bool(ok) {
1282 w.Len(idx)
1283 return
1284 }
1285
1286 idx, ok := w.closureVarsIdx[obj]
1287 if !ok {
1288 if w.closureVarsIdx == nil {
1289 w.closureVarsIdx = make(map[*types2.Var]int)
1290 }
1291 idx = len(w.closureVars)
1292 w.closureVars = append(w.closureVars, posVar{pos, obj})
1293 w.closureVarsIdx[obj] = idx
1294 }
1295 w.Len(idx)
1296 }
1297
1298 func (w *writer) openScope(pos syntax.Pos) {
1299 w.Sync(pkgbits.SyncOpenScope)
1300 w.pos(pos)
1301 }
1302
1303 func (w *writer) closeScope(pos syntax.Pos) {
1304 w.Sync(pkgbits.SyncCloseScope)
1305 w.pos(pos)
1306 w.closeAnotherScope()
1307 }
1308
1309 func (w *writer) closeAnotherScope() {
1310 w.Sync(pkgbits.SyncCloseAnotherScope)
1311 }
1312
1313
1314
1315
1316 func (w *writer) stmt(stmt syntax.Stmt) {
1317 var stmts []syntax.Stmt
1318 if stmt != nil {
1319 stmts = []syntax.Stmt{stmt}
1320 }
1321 w.stmts(stmts)
1322 }
1323
1324 func (w *writer) stmts(stmts []syntax.Stmt) {
1325 dead := false
1326 w.Sync(pkgbits.SyncStmts)
1327 var lastLabel = -1
1328 for i, stmt := range stmts {
1329 if _, ok := stmt.(*syntax.LabeledStmt); ok {
1330 lastLabel = i
1331 }
1332 }
1333 for i, stmt := range stmts {
1334 if dead && i > lastLabel {
1335
1336
1337
1338 if _, ok := stmt.(*syntax.LabeledStmt); !ok {
1339 continue
1340 }
1341 }
1342 w.stmt1(stmt)
1343 dead = w.p.terminates(stmt)
1344 }
1345 w.Code(stmtEnd)
1346 w.Sync(pkgbits.SyncStmtsEnd)
1347 }
1348
1349 func (w *writer) stmt1(stmt syntax.Stmt) {
1350 switch stmt := stmt.(type) {
1351 default:
1352 w.p.unexpected("statement", stmt)
1353
1354 case nil, *syntax.EmptyStmt:
1355 return
1356
1357 case *syntax.AssignStmt:
1358 switch {
1359 case stmt.Rhs == nil:
1360 w.Code(stmtIncDec)
1361 w.op(binOps[stmt.Op])
1362 w.expr(stmt.Lhs)
1363 w.pos(stmt)
1364
1365 case stmt.Op != 0 && stmt.Op != syntax.Def:
1366 w.Code(stmtAssignOp)
1367 w.op(binOps[stmt.Op])
1368 w.expr(stmt.Lhs)
1369 w.pos(stmt)
1370
1371 var typ types2.Type
1372 if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr {
1373 typ = w.p.typeOf(stmt.Lhs)
1374 }
1375 w.implicitConvExpr(typ, stmt.Rhs)
1376
1377 default:
1378 w.assignStmt(stmt, stmt.Lhs, stmt.Rhs)
1379 }
1380
1381 case *syntax.BlockStmt:
1382 w.Code(stmtBlock)
1383 w.blockStmt(stmt)
1384
1385 case *syntax.BranchStmt:
1386 w.Code(stmtBranch)
1387 w.pos(stmt)
1388 var op ir.Op
1389 switch stmt.Tok {
1390 case syntax.Break:
1391 op = ir.OBREAK
1392 case syntax.Continue:
1393 op = ir.OCONTINUE
1394 case syntax.Fallthrough:
1395 op = ir.OFALL
1396 case syntax.Goto:
1397 op = ir.OGOTO
1398 }
1399 w.op(op)
1400 w.optLabel(stmt.Label)
1401
1402 case *syntax.CallStmt:
1403 w.Code(stmtCall)
1404 w.pos(stmt)
1405 var op ir.Op
1406 switch stmt.Tok {
1407 case syntax.Defer:
1408 op = ir.ODEFER
1409 case syntax.Go:
1410 op = ir.OGO
1411 }
1412 w.op(op)
1413 w.expr(stmt.Call)
1414 if stmt.Tok == syntax.Defer {
1415 w.optExpr(stmt.DeferAt)
1416 }
1417
1418 case *syntax.DeclStmt:
1419 for _, decl := range stmt.DeclList {
1420 w.declStmt(decl)
1421 }
1422
1423 case *syntax.ExprStmt:
1424 w.Code(stmtExpr)
1425 w.expr(stmt.X)
1426
1427 case *syntax.ForStmt:
1428 w.Code(stmtFor)
1429 w.forStmt(stmt)
1430
1431 case *syntax.IfStmt:
1432 w.Code(stmtIf)
1433 w.ifStmt(stmt)
1434
1435 case *syntax.LabeledStmt:
1436 w.Code(stmtLabel)
1437 w.pos(stmt)
1438 w.label(stmt.Label)
1439 w.stmt1(stmt.Stmt)
1440
1441 case *syntax.ReturnStmt:
1442 w.Code(stmtReturn)
1443 w.pos(stmt)
1444
1445 resultTypes := w.sig.Results()
1446 dstType := func(i int) types2.Type {
1447 return resultTypes.At(i).Type()
1448 }
1449 w.multiExpr(stmt, dstType, syntax.UnpackListExpr(stmt.Results))
1450
1451 case *syntax.SelectStmt:
1452 w.Code(stmtSelect)
1453 w.selectStmt(stmt)
1454
1455 case *syntax.SendStmt:
1456 chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan)
1457
1458 w.Code(stmtSend)
1459 w.pos(stmt)
1460 w.expr(stmt.Chan)
1461 w.implicitConvExpr(chanType.Elem(), stmt.Value)
1462
1463 case *syntax.SwitchStmt:
1464 w.Code(stmtSwitch)
1465 w.switchStmt(stmt)
1466 }
1467 }
1468
1469 func (w *writer) assignList(expr syntax.Expr) {
1470 exprs := syntax.UnpackListExpr(expr)
1471 w.Len(len(exprs))
1472
1473 for _, expr := range exprs {
1474 w.assign(expr)
1475 }
1476 }
1477
1478 func (w *writer) assign(expr syntax.Expr) {
1479 expr = syntax.Unparen(expr)
1480
1481 if name, ok := expr.(*syntax.Name); ok {
1482 if name.Value == "_" {
1483 w.Code(assignBlank)
1484 return
1485 }
1486
1487 if obj, ok := w.p.info.Defs[name]; ok {
1488 obj := obj.(*types2.Var)
1489
1490 w.Code(assignDef)
1491 w.pos(obj)
1492 w.localIdent(obj)
1493 w.typ(obj.Type())
1494
1495
1496
1497 w.addLocal(obj)
1498 return
1499 }
1500 }
1501
1502 w.Code(assignExpr)
1503 w.expr(expr)
1504 }
1505
1506 func (w *writer) declStmt(decl syntax.Decl) {
1507 switch decl := decl.(type) {
1508 default:
1509 w.p.unexpected("declaration", decl)
1510
1511 case *syntax.ConstDecl, *syntax.TypeDecl:
1512
1513 case *syntax.VarDecl:
1514 w.assignStmt(decl, namesAsExpr(decl.NameList), decl.Values)
1515 }
1516 }
1517
1518
1519 func (w *writer) assignStmt(pos poser, lhs0, rhs0 syntax.Expr) {
1520 lhs := syntax.UnpackListExpr(lhs0)
1521 rhs := syntax.UnpackListExpr(rhs0)
1522
1523 w.Code(stmtAssign)
1524 w.pos(pos)
1525
1526
1527 w.Len(len(lhs))
1528 for _, expr := range lhs {
1529 w.assign(expr)
1530 }
1531
1532 dstType := func(i int) types2.Type {
1533 dst := lhs[i]
1534
1535
1536
1537
1538 if name, ok := syntax.Unparen(dst).(*syntax.Name); ok {
1539 if name.Value == "_" {
1540 return nil
1541 } else if def, ok := w.p.info.Defs[name].(*types2.Var); ok {
1542 return def.Type()
1543 } else if use, ok := w.p.info.Uses[name].(*types2.Var); ok {
1544 return use.Type()
1545 } else {
1546 w.p.fatalf(dst, "cannot find type of destination object: %v", dst)
1547 }
1548 }
1549
1550 return w.p.typeOf(dst)
1551 }
1552
1553 w.multiExpr(pos, dstType, rhs)
1554 }
1555
1556 func (w *writer) blockStmt(stmt *syntax.BlockStmt) {
1557 w.Sync(pkgbits.SyncBlockStmt)
1558 w.openScope(stmt.Pos())
1559 w.stmts(stmt.List)
1560 w.closeScope(stmt.Rbrace)
1561 }
1562
1563 func (w *writer) forStmt(stmt *syntax.ForStmt) {
1564 w.Sync(pkgbits.SyncForStmt)
1565 w.openScope(stmt.Pos())
1566
1567 if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
1568 w.pos(rang)
1569 w.assignList(rang.Lhs)
1570 w.expr(rang.X)
1571
1572 xtyp := w.p.typeOf(rang.X)
1573 if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap {
1574 w.rtype(xtyp)
1575 }
1576 {
1577 lhs := syntax.UnpackListExpr(rang.Lhs)
1578 assign := func(i int, src types2.Type) {
1579 if i >= len(lhs) {
1580 return
1581 }
1582 dst := syntax.Unparen(lhs[i])
1583 if name, ok := dst.(*syntax.Name); ok && name.Value == "_" {
1584 return
1585 }
1586
1587 var dstType types2.Type
1588 if rang.Def {
1589
1590
1591 dstType = w.p.info.Defs[dst.(*syntax.Name)].(*types2.Var).Type()
1592 } else {
1593 dstType = w.p.typeOf(dst)
1594 }
1595
1596 w.convRTTI(src, dstType)
1597 }
1598
1599 keyType, valueType := types2.RangeKeyVal(w.p.typeOf(rang.X))
1600 assign(0, keyType)
1601 assign(1, valueType)
1602 }
1603
1604 } else {
1605 if stmt.Cond != nil && w.p.staticBool(&stmt.Cond) < 0 {
1606 stmt.Post = nil
1607 stmt.Body.List = nil
1608 }
1609
1610 w.pos(stmt)
1611 w.stmt(stmt.Init)
1612 w.optExpr(stmt.Cond)
1613 w.stmt(stmt.Post)
1614 }
1615
1616 w.blockStmt(stmt.Body)
1617 w.Bool(w.distinctVars(stmt))
1618 w.closeAnotherScope()
1619 }
1620
1621 func (w *writer) distinctVars(stmt *syntax.ForStmt) bool {
1622 lv := base.Debug.LoopVar
1623 fileVersion := w.p.info.FileVersions[stmt.Pos().FileBase()]
1624 is122 := fileVersion == "" || version.Compare(fileVersion, "go1.22") >= 0
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637 return is122 || lv > 0 && lv != 3
1638 }
1639
1640 func (w *writer) ifStmt(stmt *syntax.IfStmt) {
1641 cond := w.p.staticBool(&stmt.Cond)
1642
1643 w.Sync(pkgbits.SyncIfStmt)
1644 w.openScope(stmt.Pos())
1645 w.pos(stmt)
1646 w.stmt(stmt.Init)
1647 w.expr(stmt.Cond)
1648 w.Int(cond)
1649 if cond >= 0 {
1650 w.blockStmt(stmt.Then)
1651 } else {
1652 w.pos(stmt.Then.Rbrace)
1653 }
1654 if cond <= 0 {
1655 w.stmt(stmt.Else)
1656 }
1657 w.closeAnotherScope()
1658 }
1659
1660 func (w *writer) selectStmt(stmt *syntax.SelectStmt) {
1661 w.Sync(pkgbits.SyncSelectStmt)
1662
1663 w.pos(stmt)
1664 w.Len(len(stmt.Body))
1665 for i, clause := range stmt.Body {
1666 if i > 0 {
1667 w.closeScope(clause.Pos())
1668 }
1669 w.openScope(clause.Pos())
1670
1671 w.pos(clause)
1672 w.stmt(clause.Comm)
1673 w.stmts(clause.Body)
1674 }
1675 if len(stmt.Body) > 0 {
1676 w.closeScope(stmt.Rbrace)
1677 }
1678 }
1679
1680 func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
1681 w.Sync(pkgbits.SyncSwitchStmt)
1682
1683 w.openScope(stmt.Pos())
1684 w.pos(stmt)
1685 w.stmt(stmt.Init)
1686
1687 var iface, tagType types2.Type
1688 var tagTypeIsChan bool
1689 if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) {
1690 iface = w.p.typeOf(guard.X)
1691
1692 w.pos(guard)
1693 if tag := guard.Lhs; w.Bool(tag != nil) {
1694 w.pos(tag)
1695
1696
1697 w.Sync(pkgbits.SyncLocalIdent)
1698 w.pkg(w.p.curpkg)
1699 w.String(tag.Value)
1700 }
1701 w.expr(guard.X)
1702 } else {
1703 tag := stmt.Tag
1704
1705 var tagValue constant.Value
1706 if tag != nil {
1707 tv := w.p.typeAndValue(tag)
1708 tagType = tv.Type
1709 tagValue = tv.Value
1710 _, tagTypeIsChan = tagType.Underlying().(*types2.Chan)
1711 } else {
1712 tagType = types2.Typ[types2.Bool]
1713 tagValue = constant.MakeBool(true)
1714 }
1715
1716 if tagValue != nil {
1717
1718
1719 func() {
1720 var target *syntax.CaseClause
1721 Outer:
1722 for _, clause := range stmt.Body {
1723 if clause.Cases == nil {
1724 target = clause
1725 }
1726 for _, cas := range syntax.UnpackListExpr(clause.Cases) {
1727 tv := w.p.typeAndValue(cas)
1728 if tv.Value == nil {
1729 return
1730 }
1731 if constant.Compare(tagValue, token.EQL, tv.Value) {
1732 target = clause
1733 break Outer
1734 }
1735 }
1736 }
1737
1738
1739 if target != nil {
1740 if hasFallthrough(target.Body) {
1741 return
1742 }
1743
1744
1745 target.Cases = nil
1746 stmt.Body = []*syntax.CaseClause{target}
1747 } else {
1748 stmt.Body = nil
1749 }
1750
1751
1752 tag = nil
1753 stmt.Tag = nil
1754 tagType = types2.Typ[types2.Bool]
1755 }()
1756 }
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767 if !tagTypeIsChan {
1768 Outer:
1769 for _, clause := range stmt.Body {
1770 for _, cas := range syntax.UnpackListExpr(clause.Cases) {
1771 if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) && (types2.IsInterface(casType) || types2.IsInterface(tagType)) {
1772 tagType = types2.NewInterfaceType(nil, nil)
1773 break Outer
1774 }
1775 }
1776 }
1777 }
1778
1779 if w.Bool(tag != nil) {
1780 w.implicitConvExpr(tagType, tag)
1781 }
1782 }
1783
1784 w.Len(len(stmt.Body))
1785 for i, clause := range stmt.Body {
1786 if i > 0 {
1787 w.closeScope(clause.Pos())
1788 }
1789 w.openScope(clause.Pos())
1790
1791 w.pos(clause)
1792
1793 cases := syntax.UnpackListExpr(clause.Cases)
1794 if iface != nil {
1795 w.Len(len(cases))
1796 for _, cas := range cases {
1797 if w.Bool(isNil(w.p, cas)) {
1798 continue
1799 }
1800 w.exprType(iface, cas)
1801 }
1802 } else {
1803
1804
1805
1806 w.Sync(pkgbits.SyncExprList)
1807 w.Sync(pkgbits.SyncExprs)
1808 w.Len(len(cases))
1809 for _, cas := range cases {
1810 typ := tagType
1811 if tagTypeIsChan {
1812 typ = nil
1813 }
1814 w.implicitConvExpr(typ, cas)
1815 }
1816 }
1817
1818 if obj, ok := w.p.info.Implicits[clause]; ok {
1819
1820
1821
1822
1823
1824 pos := clause.Pos()
1825 if typs := syntax.UnpackListExpr(clause.Cases); len(typs) != 0 {
1826 pos = typeExprEndPos(typs[len(typs)-1])
1827 }
1828 w.pos(pos)
1829
1830 obj := obj.(*types2.Var)
1831 w.typ(obj.Type())
1832 w.addLocal(obj)
1833 }
1834
1835 w.stmts(clause.Body)
1836 }
1837 if len(stmt.Body) > 0 {
1838 w.closeScope(stmt.Rbrace)
1839 }
1840
1841 w.closeScope(stmt.Rbrace)
1842 }
1843
1844 func (w *writer) label(label *syntax.Name) {
1845 w.Sync(pkgbits.SyncLabel)
1846
1847
1848 w.String(label.Value)
1849 }
1850
1851 func (w *writer) optLabel(label *syntax.Name) {
1852 w.Sync(pkgbits.SyncOptLabel)
1853 if w.Bool(label != nil) {
1854 w.label(label)
1855 }
1856 }
1857
1858
1859
1860
1861 func (w *writer) expr(expr syntax.Expr) {
1862 base.Assertf(expr != nil, "missing expression")
1863
1864 expr = syntax.Unparen(expr)
1865
1866 obj, inst := lookupObj(w.p, expr)
1867 targs := asTypeSlice(inst.TypeArgs)
1868
1869 if tv, ok := w.p.maybeTypeAndValue(expr); ok {
1870 if tv.IsRuntimeHelper() {
1871 if pkg := obj.Pkg(); pkg != nil && pkg.Name() == "runtime" {
1872 objName := obj.Name()
1873 w.Code(exprRuntimeBuiltin)
1874 w.String(objName)
1875 return
1876 }
1877 }
1878
1879 if tv.IsType() {
1880 w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
1881 }
1882
1883 if tv.Value != nil {
1884 w.Code(exprConst)
1885 w.pos(expr)
1886 typ := idealType(tv)
1887 assert(typ != nil)
1888 w.typ(typ)
1889 w.Value(tv.Value)
1890 return
1891 }
1892
1893 if _, isNil := obj.(*types2.Nil); isNil {
1894 w.Code(exprZero)
1895 w.pos(expr)
1896 w.typ(tv.Type)
1897 return
1898 }
1899
1900
1901
1902
1903
1904 if typ := tv.Type; !tv.IsBuiltin() && !isTuple(typ) && !isUntyped(typ) {
1905 w.Code(exprReshape)
1906 w.typ(typ)
1907
1908 }
1909 }
1910
1911 if obj != nil {
1912 if len(targs) != 0 {
1913 obj := obj.(*types2.Func)
1914
1915 w.Code(exprFuncInst)
1916 w.pos(expr)
1917 w.funcInst(obj, targs)
1918 return
1919 }
1920
1921 if isGlobal(obj) {
1922 w.Code(exprGlobal)
1923 w.obj(obj, nil)
1924 return
1925 }
1926
1927 obj := obj.(*types2.Var)
1928 assert(!obj.IsField())
1929
1930 w.Code(exprLocal)
1931 w.useLocal(expr.Pos(), obj)
1932 return
1933 }
1934
1935 switch expr := expr.(type) {
1936 default:
1937 w.p.unexpected("expression", expr)
1938
1939 case *syntax.CompositeLit:
1940 w.Code(exprCompLit)
1941 w.compLit(expr)
1942
1943 case *syntax.FuncLit:
1944 w.Code(exprFuncLit)
1945 w.funcLit(expr)
1946
1947 case *syntax.SelectorExpr:
1948 sel, ok := w.p.info.Selections[expr]
1949 assert(ok)
1950
1951 switch sel.Kind() {
1952 default:
1953 w.p.fatalf(expr, "unexpected selection kind: %v", sel.Kind())
1954
1955 case types2.FieldVal:
1956 w.Code(exprFieldVal)
1957 w.expr(expr.X)
1958 w.pos(expr)
1959 w.selector(sel.Obj())
1960
1961 case types2.MethodVal:
1962 w.methVal(expr, sel)
1963
1964 case types2.MethodExpr:
1965 w.methExpr(expr, sel)
1966 }
1967
1968 case *syntax.IndexExpr:
1969
1970 if selector, ok := expr.X.(*syntax.SelectorExpr); ok {
1971 if sel, ok := w.p.info.Selections[selector]; ok {
1972 switch sel.Kind() {
1973 default:
1974 w.p.fatalf(selector, "unexpected selection kind: %v", sel.Kind())
1975 case types2.FieldVal:
1976
1977 case types2.MethodVal:
1978 w.methVal(selector, sel)
1979 return
1980 case types2.MethodExpr:
1981 w.methExpr(selector, sel)
1982 return
1983 }
1984 }
1985 }
1986 _ = w.p.typeOf(expr.Index)
1987
1988 xtyp := w.p.typeOf(expr.X)
1989
1990 var keyType types2.Type
1991 if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok {
1992 keyType = mapType.Key()
1993 }
1994
1995 w.Code(exprIndex)
1996 w.expr(expr.X)
1997 w.pos(expr)
1998 w.implicitConvExpr(keyType, expr.Index)
1999 if keyType != nil {
2000 w.rtype(xtyp)
2001 }
2002
2003 case *syntax.SliceExpr:
2004 w.Code(exprSlice)
2005 w.expr(expr.X)
2006 w.pos(expr)
2007 for _, n := range &expr.Index {
2008 w.optExpr(n)
2009 }
2010
2011 case *syntax.AssertExpr:
2012 iface := w.p.typeOf(expr.X)
2013
2014 w.Code(exprAssert)
2015 w.expr(expr.X)
2016 w.pos(expr)
2017 w.exprType(iface, expr.Type)
2018 w.rtype(iface)
2019
2020 case *syntax.Operation:
2021 if expr.Y == nil {
2022 w.Code(exprUnaryOp)
2023 w.op(unOps[expr.Op])
2024 w.pos(expr)
2025 w.expr(expr.X)
2026 break
2027 }
2028
2029 var commonType types2.Type
2030 switch expr.Op {
2031 case syntax.Shl, syntax.Shr:
2032
2033 default:
2034 xtyp := w.p.typeOf(expr.X)
2035 ytyp := w.p.typeOf(expr.Y)
2036 switch {
2037 case types2.AssignableTo(xtyp, ytyp):
2038 commonType = ytyp
2039 case types2.AssignableTo(ytyp, xtyp):
2040 commonType = xtyp
2041 default:
2042 w.p.fatalf(expr, "failed to find common type between %v and %v", xtyp, ytyp)
2043 }
2044 }
2045
2046 w.Code(exprBinaryOp)
2047 w.op(binOps[expr.Op])
2048 w.implicitConvExpr(commonType, expr.X)
2049 w.pos(expr)
2050 w.implicitConvExpr(commonType, expr.Y)
2051
2052 case *syntax.CallExpr:
2053 tv := w.p.typeAndValue(expr.Fun)
2054 if tv.IsType() {
2055 assert(len(expr.ArgList) == 1)
2056 assert(!expr.HasDots)
2057 w.convertExpr(tv.Type, expr.ArgList[0], false)
2058 break
2059 }
2060
2061 var rtype types2.Type
2062 if tv.IsBuiltin() {
2063 switch obj, _ := lookupObj(w.p, syntax.Unparen(expr.Fun)); obj.Name() {
2064 case "make":
2065 assert(len(expr.ArgList) >= 1)
2066 assert(!expr.HasDots)
2067
2068 w.Code(exprMake)
2069 w.pos(expr)
2070 w.exprType(nil, expr.ArgList[0])
2071 w.exprs(expr.ArgList[1:])
2072
2073 typ := w.p.typeOf(expr)
2074 switch coreType := types2.CoreType(typ).(type) {
2075 default:
2076 w.p.fatalf(expr, "unexpected core type: %v", coreType)
2077 case *types2.Chan:
2078 w.rtype(typ)
2079 case *types2.Map:
2080 w.rtype(typ)
2081 case *types2.Slice:
2082 w.rtype(sliceElem(typ))
2083 }
2084
2085 return
2086
2087 case "new":
2088 assert(len(expr.ArgList) == 1)
2089 assert(!expr.HasDots)
2090 arg := expr.ArgList[0]
2091
2092 w.Code(exprNew)
2093 w.pos(expr)
2094 tv := w.p.typeAndValue(arg)
2095 if w.Bool(!tv.IsType()) {
2096 w.expr(arg)
2097 } else {
2098 w.exprType(nil, arg)
2099 }
2100 return
2101
2102 case "Sizeof":
2103 assert(len(expr.ArgList) == 1)
2104 assert(!expr.HasDots)
2105
2106 w.Code(exprSizeof)
2107 w.pos(expr)
2108 w.typ(w.p.typeOf(expr.ArgList[0]))
2109 return
2110
2111 case "Alignof":
2112 assert(len(expr.ArgList) == 1)
2113 assert(!expr.HasDots)
2114
2115 w.Code(exprAlignof)
2116 w.pos(expr)
2117 w.typ(w.p.typeOf(expr.ArgList[0]))
2118 return
2119
2120 case "Offsetof":
2121 assert(len(expr.ArgList) == 1)
2122 assert(!expr.HasDots)
2123 selector := syntax.Unparen(expr.ArgList[0]).(*syntax.SelectorExpr)
2124 index := w.p.info.Selections[selector].Index()
2125
2126 w.Code(exprOffsetof)
2127 w.pos(expr)
2128 w.typ(deref2(w.p.typeOf(selector.X)))
2129 w.Len(len(index) - 1)
2130 for _, idx := range index {
2131 w.Len(idx)
2132 }
2133 return
2134
2135 case "append":
2136 rtype = sliceElem(w.p.typeOf(expr))
2137 case "copy":
2138 typ := w.p.typeOf(expr.ArgList[0])
2139 if tuple, ok := typ.(*types2.Tuple); ok {
2140 typ = tuple.At(0).Type()
2141 }
2142 rtype = sliceElem(typ)
2143 case "delete":
2144 typ := w.p.typeOf(expr.ArgList[0])
2145 if tuple, ok := typ.(*types2.Tuple); ok {
2146 typ = tuple.At(0).Type()
2147 }
2148 rtype = typ
2149 case "Slice":
2150 rtype = sliceElem(w.p.typeOf(expr))
2151 }
2152 }
2153
2154 writeFunExpr := func() {
2155 fun := syntax.Unparen(expr.Fun)
2156
2157 expr := fun
2158 if idx, ok := expr.(*syntax.IndexExpr); ok {
2159 expr = idx.X
2160 }
2161 if selector, ok := expr.(*syntax.SelectorExpr); ok {
2162 if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
2163 w.Bool(true)
2164 typ := w.recvExpr(selector, sel)
2165 w.methodExpr(selector, typ, sel)
2166 return
2167 }
2168 }
2169
2170 w.Bool(false)
2171
2172 if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
2173 obj := obj.(*types2.Func)
2174
2175 w.pos(fun)
2176 w.funcInst(obj, asTypeSlice(inst.TypeArgs))
2177 return
2178 }
2179
2180 w.expr(fun)
2181 }
2182
2183 sigType := types2.CoreType(tv.Type).(*types2.Signature)
2184 paramTypes := sigType.Params()
2185
2186 w.Code(exprCall)
2187 writeFunExpr()
2188 w.pos(expr)
2189
2190 paramType := func(i int) types2.Type {
2191 if sigType.Variadic() && !expr.HasDots && i >= paramTypes.Len()-1 {
2192 return paramTypes.At(paramTypes.Len() - 1).Type().(*types2.Slice).Elem()
2193 }
2194 return paramTypes.At(i).Type()
2195 }
2196
2197 w.multiExpr(expr, paramType, expr.ArgList)
2198 w.Bool(expr.HasDots)
2199 if rtype != nil {
2200 w.rtype(rtype)
2201 }
2202 }
2203 }
2204
2205 func sliceElem(typ types2.Type) types2.Type {
2206 return types2.CoreType(typ).(*types2.Slice).Elem()
2207 }
2208
2209 func (w *writer) optExpr(expr syntax.Expr) {
2210 if w.Bool(expr != nil) {
2211 w.expr(expr)
2212 }
2213 }
2214
2215 func (w *writer) methVal(expr *syntax.SelectorExpr, sel *types2.Selection) {
2216 w.Code(exprMethodVal)
2217 typ := w.recvExpr(expr, sel)
2218 w.pos(expr)
2219 w.methodExpr(expr, typ, sel)
2220 }
2221
2222 func (w *writer) methExpr(expr *syntax.SelectorExpr, sel *types2.Selection) {
2223 w.Code(exprMethodExpr)
2224
2225 tv := w.p.typeAndValue(expr.X)
2226 assert(tv.IsType())
2227
2228 index := sel.Index()
2229 implicits := index[:len(index)-1]
2230
2231 typ := tv.Type
2232 w.typ(typ)
2233
2234 w.Len(len(implicits))
2235 for _, ix := range implicits {
2236 w.Len(ix)
2237 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
2238 }
2239
2240 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
2241 if w.Bool(isPtrTo(typ, recv)) {
2242 typ = recv
2243 } else if w.Bool(isPtrTo(recv, typ)) {
2244 typ = recv
2245 }
2246
2247 w.pos(expr)
2248 w.methodExpr(expr, typ, sel)
2249 }
2250
2251
2252
2253
2254 func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type {
2255 index := sel.Index()
2256 implicits := index[:len(index)-1]
2257
2258 w.Code(exprRecv)
2259 w.expr(expr.X)
2260 w.pos(expr)
2261 w.Len(len(implicits))
2262
2263 typ := w.p.typeOf(expr.X)
2264 for _, ix := range implicits {
2265 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
2266 w.Len(ix)
2267 }
2268
2269 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
2270 if w.Bool(isPtrTo(typ, recv)) {
2271 typ = recv
2272 } else if w.Bool(isPtrTo(recv, typ)) {
2273 typ = recv
2274 }
2275
2276 return typ
2277 }
2278
2279
2280 func (w *writer) funcInst(obj *types2.Func, targs []types2.Type) {
2281 info := w.p.objInstIdx(obj, targs, w.dict)
2282
2283
2284
2285
2286 if w.Bool(info.anyDerived()) {
2287 w.Len(w.dict.subdictIdx(info))
2288 return
2289 }
2290
2291
2292
2293
2294 w.objInfo(info)
2295 }
2296
2297
2298
2299
2300
2301
2302
2303 func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *types2.Selection) {
2304 fun := sel.Obj().(*types2.Func)
2305 sig := fun.Type().(*types2.Signature)
2306
2307 w.typ(recv)
2308
2309
2310 if isGenericMethod(sig) {
2311 assert(w.Version().Has(pkgbits.GenericMethods))
2312 w.Bool(true)
2313 } else {
2314 if w.Version().Has(pkgbits.GenericMethods) {
2315 w.Bool(false)
2316 }
2317 w.typ(sig)
2318 }
2319
2320 w.pos(expr)
2321 w.selector(fun)
2322
2323
2324
2325 if typeParam, ok := types2.Unalias(recv).(*types2.TypeParam); w.Bool(ok) {
2326 typeParamIdx := w.dict.typeParamIndex(typeParam)
2327 methodInfo := w.p.selectorIdx(fun)
2328
2329 w.Len(w.dict.typeParamMethodExprIdx(typeParamIdx, methodInfo))
2330 return
2331 }
2332
2333 if isInterface(recv) != isInterface(sig.Recv().Type()) {
2334 w.p.fatalf(expr, "isInterface inconsistency: %v and %v", recv, sig.Recv().Type())
2335 }
2336
2337 if isConcreteMethod(sig) {
2338 tname, tExplicits := splitNamed(types2.Unalias(deref2(recv)).(*types2.Named))
2339 var info objInfo
2340 if isGenericMethod(sig) {
2341
2342 mExplicits := asTypeSlice(w.p.info.Instances[expr.Sel].TypeArgs)
2343 info = w.p.objInstIdx(fun.Origin(), slices.Concat(tExplicits, mExplicits), w.dict)
2344 } else {
2345
2346
2347 info = w.p.objInstIdx(tname, tExplicits, w.dict)
2348 }
2349
2350
2351
2352
2353 if info.anyDerived() {
2354 w.Bool(true)
2355 w.Len(w.dict.subdictIdx(info))
2356 return
2357 }
2358
2359
2360
2361 if len(info.explicits) > 0 {
2362 w.Bool(false)
2363 w.Bool(true)
2364 w.objInfo(info)
2365 return
2366 }
2367
2368 }
2369
2370 w.Bool(false)
2371 w.Bool(false)
2372 }
2373
2374
2375
2376
2377
2378 func (w *writer) multiExpr(pos poser, dstType func(int) types2.Type, exprs []syntax.Expr) {
2379 w.Sync(pkgbits.SyncMultiExpr)
2380
2381 if len(exprs) == 1 {
2382 expr := exprs[0]
2383 if tuple, ok := w.p.typeOf(expr).(*types2.Tuple); ok {
2384 assert(tuple.Len() > 1)
2385 w.Bool(true)
2386 w.pos(pos)
2387 w.expr(expr)
2388
2389 w.Len(tuple.Len())
2390 for i := 0; i < tuple.Len(); i++ {
2391 src := tuple.At(i).Type()
2392
2393
2394 w.typ(src)
2395 if dst := dstType(i); w.Bool(dst != nil && !types2.Identical(src, dst)) {
2396 if src == nil || dst == nil {
2397 w.p.fatalf(pos, "src is %v, dst is %v", src, dst)
2398 }
2399 if !types2.AssignableTo(src, dst) {
2400 w.p.fatalf(pos, "%v is not assignable to %v", src, dst)
2401 }
2402 w.typ(dst)
2403 w.convRTTI(src, dst)
2404 }
2405 }
2406 return
2407 }
2408 }
2409
2410 w.Bool(false)
2411 w.Len(len(exprs))
2412 for i, expr := range exprs {
2413 w.implicitConvExpr(dstType(i), expr)
2414 }
2415 }
2416
2417
2418
2419
2420 func (w *writer) implicitConvExpr(dst types2.Type, expr syntax.Expr) {
2421 w.convertExpr(dst, expr, true)
2422 }
2423
2424 func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) {
2425 src := w.p.typeOf(expr)
2426
2427
2428 identical := dst == nil || types2.Identical(src, dst)
2429 if implicit && identical {
2430 w.expr(expr)
2431 return
2432 }
2433
2434 if implicit && !types2.AssignableTo(src, dst) {
2435 w.p.fatalf(expr, "%v is not assignable to %v", src, dst)
2436 }
2437
2438 w.Code(exprConvert)
2439 w.Bool(implicit)
2440 w.typ(dst)
2441 w.pos(expr)
2442 w.convRTTI(src, dst)
2443 w.Bool(isTypeParam(dst))
2444 w.Bool(identical)
2445 w.expr(expr)
2446 }
2447
2448 func (w *writer) compLit(lit *syntax.CompositeLit) {
2449 typ := w.p.typeOf(lit)
2450
2451 w.Sync(pkgbits.SyncCompLit)
2452 w.pos(lit)
2453 w.typ(typ)
2454
2455 if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
2456 typ = ptr.Elem()
2457 }
2458
2459 if w.Version().Has(pkgbits.CompactCompLiterals) {
2460 switch typ0 := typ; typ := types2.CoreType(typ).(type) {
2461 default:
2462 w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
2463 case *types2.Array:
2464 w.arrayElems(typ.Elem(), lit.ElemList)
2465 case *types2.Map:
2466 w.rtype(typ0)
2467 w.mapElems(typ.Key(), typ.Elem(), lit.ElemList)
2468 case *types2.Slice:
2469 w.arrayElems(typ.Elem(), lit.ElemList)
2470 case *types2.Struct:
2471 w.structElems(typ, lit.NKeys == 0, lit.ElemList)
2472 }
2473 return
2474 }
2475
2476
2477 var keyType, elemType types2.Type
2478 var structType *types2.Struct
2479 switch typ0 := typ; typ := types2.CoreType(typ).(type) {
2480 default:
2481 w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
2482 case *types2.Array:
2483 elemType = typ.Elem()
2484 case *types2.Map:
2485 w.rtype(typ0)
2486 keyType, elemType = typ.Key(), typ.Elem()
2487 case *types2.Slice:
2488 elemType = typ.Elem()
2489 case *types2.Struct:
2490 structType = typ
2491 }
2492
2493 w.Len(len(lit.ElemList))
2494 for i, elem := range lit.ElemList {
2495 elemType := elemType
2496 if structType != nil {
2497 if kv, ok := elem.(*syntax.KeyValueExpr); ok {
2498
2499 w.pos(kv.Key)
2500 i = fieldIndex(w.p.info, structType, kv.Key.(*syntax.Name))
2501 elem = kv.Value
2502 } else {
2503 w.pos(elem)
2504 }
2505 elemType = structType.Field(i).Type()
2506 w.Len(i)
2507 } else {
2508 if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
2509
2510 w.pos(kv.Key)
2511 w.implicitConvExpr(keyType, kv.Key)
2512 elem = kv.Value
2513 }
2514 }
2515 w.implicitConvExpr(elemType, elem)
2516 }
2517 }
2518
2519 func (w *writer) arrayElems(elemType types2.Type, elems []syntax.Expr) {
2520 valuesOnly := true
2521 for _, elem := range elems {
2522 if _, ok := elem.(*syntax.KeyValueExpr); ok {
2523 valuesOnly = false
2524 break
2525 }
2526 }
2527
2528 if valuesOnly {
2529 w.Int(len(elems))
2530 for _, elem := range elems {
2531 w.implicitConvExpr(elemType, elem)
2532 }
2533 return
2534 }
2535
2536 w.Int(-len(elems))
2537 for _, elem := range elems {
2538 if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
2539 w.pos(kv.Key)
2540 w.implicitConvExpr(nil, kv.Key)
2541 elem = kv.Value
2542 }
2543 w.implicitConvExpr(elemType, elem)
2544 }
2545 }
2546
2547 func (w *writer) mapElems(keyType, valueType types2.Type, elems []syntax.Expr) {
2548
2549 w.Int(-len(elems))
2550 for _, elem := range elems {
2551 kv := elem.(*syntax.KeyValueExpr)
2552 w.pos(kv.Key)
2553 w.implicitConvExpr(keyType, kv.Key)
2554 w.implicitConvExpr(valueType, kv.Value)
2555 }
2556 }
2557
2558 func (w *writer) structElems(typ *types2.Struct, valuesOnly bool, elems []syntax.Expr) {
2559 n := len(elems)
2560 if valuesOnly {
2561
2562 w.Int(n)
2563 for i, elem := range elems {
2564 w.pos(elem)
2565 w.implicitConvExpr(typ.Field(i).Type(), elem)
2566 }
2567 return
2568 }
2569
2570 w.Int(-n)
2571 for _, elem := range elems {
2572 kv := elem.(*syntax.KeyValueExpr)
2573 w.pos(kv.Key)
2574
2575 fld, index, _ := types2.LookupFieldOrMethod(typ, false, w.p.curpkg, kv.Key.(*syntax.Name).Value)
2576 if n := len(index); n > 1 {
2577
2578 w.Int(-n)
2579 for _, i := range index {
2580 w.Int(i)
2581 }
2582 } else {
2583 w.Int(index[0])
2584 }
2585 w.implicitConvExpr(fld.Type(), kv.Value)
2586 }
2587 }
2588
2589 func (w *writer) funcLit(expr *syntax.FuncLit) {
2590 sig := w.p.typeOf(expr).(*types2.Signature)
2591
2592 body, closureVars := w.p.bodyIdx(sig, expr.Body, w.dict)
2593
2594 w.Sync(pkgbits.SyncFuncLit)
2595 w.pos(expr)
2596 w.signature(sig)
2597 w.Bool(w.p.rangeFuncBodyClosures[expr])
2598
2599 w.Len(len(closureVars))
2600 for _, cv := range closureVars {
2601 w.pos(cv.pos)
2602 w.useLocal(cv.pos, cv.var_)
2603 }
2604
2605 w.Reloc(pkgbits.SectionBody, body)
2606 }
2607
2608 type posVar struct {
2609 pos syntax.Pos
2610 var_ *types2.Var
2611 }
2612
2613 func (p posVar) String() string {
2614 return p.pos.String() + ":" + p.var_.String()
2615 }
2616
2617 func (w *writer) exprs(exprs []syntax.Expr) {
2618 w.Sync(pkgbits.SyncExprs)
2619 w.Len(len(exprs))
2620 for _, expr := range exprs {
2621 w.expr(expr)
2622 }
2623 }
2624
2625
2626
2627 func (w *writer) rtype(typ types2.Type) {
2628 typ = types2.Default(typ)
2629
2630 info := w.p.typIdx(typ, w.dict)
2631 w.rtypeInfo(info)
2632 }
2633
2634 func (w *writer) rtypeInfo(info typeInfo) {
2635 w.Sync(pkgbits.SyncRType)
2636
2637 if w.Bool(info.derived) {
2638 w.Len(w.dict.rtypeIdx(info))
2639 } else {
2640 w.typInfo(info)
2641 }
2642 }
2643
2644
2645
2646 func (w *writer) varDictIndex(obj *types2.Var) {
2647 info := w.p.typIdx(obj.Type(), w.dict)
2648 if w.Bool(info.derived) {
2649 w.Len(w.dict.rtypeIdx(info))
2650 }
2651 }
2652
2653
2654 func isUntyped(typ types2.Type) bool {
2655
2656 basic, ok := typ.(*types2.Basic)
2657 return ok && basic.Info()&types2.IsUntyped != 0
2658 }
2659
2660
2661 func isTuple(typ types2.Type) bool {
2662
2663 _, ok := typ.(*types2.Tuple)
2664 return ok
2665 }
2666
2667 func (w *writer) itab(typ, iface types2.Type) {
2668 typ = types2.Default(typ)
2669 iface = types2.Default(iface)
2670
2671 typInfo := w.p.typIdx(typ, w.dict)
2672 ifaceInfo := w.p.typIdx(iface, w.dict)
2673
2674 w.rtypeInfo(typInfo)
2675 w.rtypeInfo(ifaceInfo)
2676 if w.Bool(typInfo.derived || ifaceInfo.derived) {
2677 w.Len(w.dict.itabIdx(typInfo, ifaceInfo))
2678 }
2679 }
2680
2681
2682
2683 func (w *writer) convRTTI(src, dst types2.Type) {
2684 w.Sync(pkgbits.SyncConvRTTI)
2685 w.itab(src, dst)
2686 }
2687
2688 func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
2689 base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)
2690
2691 tv := w.p.typeAndValue(typ)
2692 assert(tv.IsType())
2693
2694 w.Sync(pkgbits.SyncExprType)
2695 w.pos(typ)
2696
2697 if w.Bool(iface != nil && !iface.Underlying().(*types2.Interface).Empty()) {
2698 w.itab(tv.Type, iface)
2699 } else {
2700 w.rtype(tv.Type)
2701
2702 info := w.p.typIdx(tv.Type, w.dict)
2703 w.Bool(info.derived)
2704 }
2705 }
2706
2707
2708
2709
2710 func isInterface(typ types2.Type) bool {
2711 if _, ok := types2.Unalias(typ).(*types2.TypeParam); ok {
2712
2713
2714
2715 base.Fatalf("%v is a type parameter", typ)
2716 }
2717
2718 _, ok := typ.Underlying().(*types2.Interface)
2719 return ok
2720 }
2721
2722
2723
2724 func isConcreteMethod(typ types2.Type) bool {
2725 sig, ok := typ.(*types2.Signature)
2726 return ok && sig.Recv() != nil && !isInterface(sig.Recv().Type())
2727 }
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737 func isGenericMethod(typ types2.Type) bool {
2738 sig, ok := typ.(*types2.Signature)
2739 return ok && sig.Recv() != nil && sig.TypeParams().Len() > 0
2740 }
2741
2742
2743 func (w *writer) op(op ir.Op) {
2744
2745
2746
2747 assert(op != 0)
2748 w.Sync(pkgbits.SyncOp)
2749 w.Len(int(op))
2750 }
2751
2752
2753
2754
2755
2756
2757 type typeDeclGen struct {
2758 *syntax.TypeDecl
2759 gen int
2760
2761
2762 implicits []*types2.TypeParam
2763 }
2764
2765 type fileImports struct {
2766 importedEmbed, importedUnsafe bool
2767 }
2768
2769
2770
2771
2772
2773
2774
2775 type declCollector struct {
2776 pw *pkgWriter
2777 typegen *int
2778 file *fileImports
2779 withinFunc bool
2780 implicits []*types2.TypeParam
2781 }
2782
2783 func (c *declCollector) withTParams(obj types2.Object) *declCollector {
2784 tparams := slices.Concat(objRecvTypeParams(obj), objTypeParams(obj))
2785 if len(tparams) == 0 {
2786 return c
2787 }
2788
2789 copy := *c
2790 copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
2791 for _, tparam := range tparams {
2792 copy.implicits = append(copy.implicits, tparam)
2793 }
2794 return ©
2795 }
2796
2797 func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
2798 pw := c.pw
2799
2800 switch n := n.(type) {
2801 case *syntax.File:
2802 pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)
2803
2804 case *syntax.ImportDecl:
2805 pw.checkPragmas(n.Pragma, 0, false)
2806
2807 switch pw.info.PkgNameOf(n).Imported().Path() {
2808 case "embed":
2809 c.file.importedEmbed = true
2810 case "unsafe":
2811 c.file.importedUnsafe = true
2812 }
2813
2814 case *syntax.ConstDecl:
2815 pw.checkPragmas(n.Pragma, 0, false)
2816
2817 case *syntax.FuncDecl:
2818 pw.checkPragmas(n.Pragma, funcPragmas, false)
2819
2820 obj := pw.info.Defs[n.Name].(*types2.Func)
2821 pw.funDecls[obj] = n
2822
2823 return c.withTParams(obj)
2824
2825 case *syntax.TypeDecl:
2826 obj := pw.info.Defs[n.Name].(*types2.TypeName)
2827 d := typeDeclGen{TypeDecl: n, implicits: c.implicits}
2828
2829 if n.Alias {
2830 pw.checkPragmas(n.Pragma, 0, false)
2831 } else {
2832 pw.checkPragmas(n.Pragma, 0, false)
2833
2834
2835 if c.withinFunc {
2836 *c.typegen++
2837 d.gen = *c.typegen
2838 }
2839 }
2840
2841 pw.typDecls[obj] = d
2842
2843
2844
2845
2846
2847 return c.withTParams(obj)
2848
2849 case *syntax.VarDecl:
2850 pw.checkPragmas(n.Pragma, 0, true)
2851
2852 if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 {
2853 if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil {
2854 pw.errorf(p.Embeds[0].Pos, "%s", err)
2855 }
2856 }
2857
2858 case *syntax.BlockStmt:
2859 if !c.withinFunc {
2860 copy := *c
2861 copy.withinFunc = true
2862 return ©
2863 }
2864 }
2865
2866 return c
2867 }
2868
2869 func (pw *pkgWriter) collectDecls(noders []*noder) {
2870 var typegen int
2871 for _, p := range noders {
2872 var file fileImports
2873
2874 syntax.Walk(p.file, &declCollector{
2875 pw: pw,
2876 typegen: &typegen,
2877 file: &file,
2878 })
2879
2880 pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
2881
2882 for _, l := range p.linknames {
2883 directive := "go:linkname"
2884 if l.std {
2885 directive = "go:linknamestd"
2886 }
2887 if !file.importedUnsafe {
2888 pw.errorf(l.pos, "//%s only allowed in Go files that import \"unsafe\"", directive)
2889 continue
2890 }
2891 if strings.Contains(l.remote, "[") && strings.Contains(l.remote, "]") {
2892 pw.errorf(l.pos, "//%s reference of an instantiation is not allowed", directive)
2893 continue
2894 }
2895
2896 switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
2897 case *types2.Func, *types2.Var:
2898 if _, ok := pw.linknames[obj]; !ok {
2899 pw.linknames[obj] = struct {
2900 remote string
2901 std bool
2902 }{l.remote, l.std}
2903 } else {
2904 pw.errorf(l.pos, "duplicate //%s for %s", directive, l.local)
2905 }
2906
2907 default:
2908 if types.AllowsGoVersion(1, 18) {
2909 pw.errorf(l.pos, "//%s must refer to declared function or variable", directive)
2910 }
2911 }
2912 }
2913 }
2914 }
2915
2916 func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
2917 if p == nil {
2918 return
2919 }
2920 pragma := p.(*pragmas)
2921
2922 for _, pos := range pragma.Pos {
2923 if pos.Flag&^allowed != 0 {
2924 pw.errorf(pos.Pos, "misplaced compiler directive")
2925 }
2926 }
2927
2928 if !embedOK {
2929 for _, e := range pragma.Embeds {
2930 pw.errorf(e.Pos, "misplaced go:embed directive")
2931 }
2932 }
2933 }
2934
2935 func (w *writer) pkgInit(noders []*noder) {
2936 w.Len(len(w.p.cgoPragmas))
2937 for _, cgoPragma := range w.p.cgoPragmas {
2938 w.Strings(cgoPragma)
2939 }
2940
2941 w.pkgInitOrder()
2942
2943 w.Sync(pkgbits.SyncDecls)
2944 for _, p := range noders {
2945 for _, decl := range p.file.DeclList {
2946 w.pkgDecl(decl)
2947 }
2948 }
2949 w.Code(declEnd)
2950
2951 w.Sync(pkgbits.SyncEOF)
2952 }
2953
2954 func (w *writer) pkgInitOrder() {
2955
2956 w.Len(len(w.p.info.InitOrder))
2957 for _, init := range w.p.info.InitOrder {
2958 w.Len(len(init.Lhs))
2959 for _, v := range init.Lhs {
2960 w.obj(v, nil)
2961 }
2962 w.expr(init.Rhs)
2963 }
2964 }
2965
2966 func (w *writer) pkgDecl(decl syntax.Decl) {
2967 switch decl := decl.(type) {
2968 default:
2969 w.p.unexpected("declaration", decl)
2970
2971 case *syntax.ImportDecl:
2972
2973 case *syntax.ConstDecl:
2974 w.Code(declOther)
2975 w.pkgObjs(decl.NameList...)
2976
2977 case *syntax.FuncDecl:
2978 if decl.Name.Value == "_" {
2979 break
2980 }
2981
2982 obj := w.p.info.Defs[decl.Name].(*types2.Func)
2983 sig := obj.Type().(*types2.Signature)
2984
2985 if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
2986 break
2987 }
2988
2989 if recv := sig.Recv(); recv != nil {
2990 w.Code(declMethod)
2991 w.typ(recvBase(recv))
2992 w.selector(obj)
2993 break
2994 }
2995
2996 w.Code(declFunc)
2997 w.pkgObjs(decl.Name)
2998
2999 case *syntax.TypeDecl:
3000 if len(decl.TParamList) != 0 {
3001 break
3002 }
3003
3004 if decl.Name.Value == "_" {
3005 break
3006 }
3007
3008 name := w.p.info.Defs[decl.Name].(*types2.TypeName)
3009
3010
3011 if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() {
3012 break
3013 }
3014
3015 w.Code(declOther)
3016 w.pkgObjs(decl.Name)
3017
3018 case *syntax.VarDecl:
3019 w.Code(declVar)
3020 w.pkgObjs(decl.NameList...)
3021
3022 var embeds []pragmaEmbed
3023 if p, ok := decl.Pragma.(*pragmas); ok {
3024 embeds = p.Embeds
3025 }
3026 w.Len(len(embeds))
3027 for _, embed := range embeds {
3028 w.pos(embed.Pos)
3029 w.Strings(embed.Patterns)
3030 }
3031 }
3032 }
3033
3034 func (w *writer) pkgObjs(names ...*syntax.Name) {
3035 w.Sync(pkgbits.SyncDeclNames)
3036 w.Len(len(names))
3037
3038 for _, name := range names {
3039 obj, ok := w.p.info.Defs[name]
3040 assert(ok)
3041
3042 w.Sync(pkgbits.SyncDeclName)
3043 w.obj(obj, nil)
3044 }
3045 }
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055 func (pw *pkgWriter) staticBool(ep *syntax.Expr) int {
3056 if val := pw.typeAndValue(*ep).Value; val != nil {
3057 if constant.BoolVal(val) {
3058 return +1
3059 } else {
3060 return -1
3061 }
3062 }
3063
3064 if e, ok := (*ep).(*syntax.Operation); ok {
3065 switch e.Op {
3066 case syntax.Not:
3067 return pw.staticBool(&e.X)
3068
3069 case syntax.AndAnd:
3070 x := pw.staticBool(&e.X)
3071 if x < 0 {
3072 *ep = e.X
3073 return x
3074 }
3075
3076 y := pw.staticBool(&e.Y)
3077 if x > 0 || y < 0 {
3078 if pw.typeAndValue(e.X).Value != nil {
3079 *ep = e.Y
3080 }
3081 return y
3082 }
3083
3084 case syntax.OrOr:
3085 x := pw.staticBool(&e.X)
3086 if x > 0 {
3087 *ep = e.X
3088 return x
3089 }
3090
3091 y := pw.staticBool(&e.Y)
3092 if x < 0 || y > 0 {
3093 if pw.typeAndValue(e.X).Value != nil {
3094 *ep = e.Y
3095 }
3096 return y
3097 }
3098 }
3099 }
3100
3101 return 0
3102 }
3103
3104
3105
3106
3107 func (pw *pkgWriter) hasImplicitTypeParams(obj *types2.TypeName) bool {
3108 if obj.Pkg() == pw.curpkg {
3109 decl, ok := pw.typDecls[obj]
3110 assert(ok)
3111 if len(decl.implicits) != 0 {
3112 return true
3113 }
3114 }
3115 return false
3116 }
3117
3118
3119 func isDefinedType(obj types2.Object) bool {
3120 if obj, ok := obj.(*types2.TypeName); ok {
3121 return !obj.IsAlias()
3122 }
3123 return false
3124 }
3125
3126
3127
3128
3129 func isGlobal(obj types2.Object) bool {
3130 return obj.Parent() == obj.Pkg().Scope()
3131 }
3132
3133
3134
3135
3136 func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
3137 if index, ok := expr.(*syntax.IndexExpr); ok {
3138 args := syntax.UnpackListExpr(index.Index)
3139 if len(args) == 1 {
3140 tv := p.typeAndValue(args[0])
3141 if tv.IsValue() {
3142 return
3143 }
3144 }
3145
3146 expr = index.X
3147 }
3148
3149
3150 if sel, ok := expr.(*syntax.SelectorExpr); ok {
3151 if !isPkgQual(p.info, sel) {
3152 return
3153 }
3154 expr = sel.Sel
3155 }
3156
3157 if name, ok := expr.(*syntax.Name); ok {
3158 obj = p.info.Uses[name]
3159 inst = p.info.Instances[name]
3160 }
3161 return
3162 }
3163
3164
3165
3166 func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
3167 if name, ok := sel.X.(*syntax.Name); ok {
3168 _, isPkgName := info.Uses[name].(*types2.PkgName)
3169 return isPkgName
3170 }
3171 return false
3172 }
3173
3174
3175
3176 func isNil(p *pkgWriter, expr syntax.Expr) bool {
3177 tv := p.typeAndValue(expr)
3178 return tv.IsNil()
3179 }
3180
3181
3182
3183 func (pw *pkgWriter) isBuiltin(expr syntax.Expr, builtin string) bool {
3184 if name, ok := syntax.Unparen(expr).(*syntax.Name); ok && name.Value == builtin {
3185 return pw.typeAndValue(name).IsBuiltin()
3186 }
3187 return false
3188 }
3189
3190
3191 func recvBase(recv *types2.Var) *types2.Named {
3192 typ := types2.Unalias(recv.Type())
3193 if ptr, ok := typ.(*types2.Pointer); ok {
3194 typ = types2.Unalias(ptr.Elem())
3195 }
3196 return typ.(*types2.Named)
3197 }
3198
3199
3200 func namesAsExpr(names []*syntax.Name) syntax.Expr {
3201 if len(names) == 1 {
3202 return names[0]
3203 }
3204
3205 exprs := make([]syntax.Expr, len(names))
3206 for i, name := range names {
3207 exprs[i] = name
3208 }
3209 return &syntax.ListExpr{ElemList: exprs}
3210 }
3211
3212
3213 func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int {
3214 field := info.Uses[key].(*types2.Var)
3215
3216 for i := 0; i < str.NumFields(); i++ {
3217 if str.Field(i) == field {
3218 return i
3219 }
3220 }
3221
3222 panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
3223 }
3224
3225
3226 func objRecvTypeParams(obj types2.Object) []*types2.TypeParam {
3227 if f, ok := obj.(*types2.Func); ok {
3228 return asTypeParamSlice(f.Signature().RecvTypeParams())
3229 }
3230 return nil
3231 }
3232
3233
3234 func objTypeParams(obj types2.Object) []*types2.TypeParam {
3235 switch t := obj.(type) {
3236 case *types2.Func:
3237 return asTypeParamSlice(t.Signature().TypeParams())
3238 case *types2.TypeName:
3239 switch t := obj.Type().(type) {
3240 case *types2.Named:
3241 return asTypeParamSlice(t.TypeParams())
3242 case *types2.Alias:
3243 return asTypeParamSlice(t.TypeParams())
3244 }
3245 }
3246 return nil
3247 }
3248
3249
3250 func asTypeParamSlice(l *types2.TypeParamList) []*types2.TypeParam {
3251 if l.Len() == 0 {
3252 return nil
3253 }
3254 s := make([]*types2.TypeParam, l.Len())
3255 for i := range l.Len() {
3256 s[i] = l.At(i)
3257 }
3258 return s
3259 }
3260
3261
3262
3263 func splitNamed(typ *types2.Named) (*types2.TypeName, []types2.Type) {
3264 base.Assertf(typ.TypeParams().Len() == typ.TypeArgs().Len(), "use of uninstantiated type: %v", typ)
3265
3266 orig := typ.Origin()
3267 base.Assertf(orig.TypeArgs() == nil, "origin %v of %v has type arguments", orig, typ)
3268 base.Assertf(typ.Obj() == orig.Obj(), "%v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())
3269
3270 return typ.Obj(), asTypeSlice(typ.TypeArgs())
3271 }
3272
3273
3274 func splitAlias(typ *types2.Alias) (*types2.TypeName, []types2.Type) {
3275 orig := typ.Origin()
3276 base.Assertf(typ.Obj() == orig.Obj(), "alias type %v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())
3277
3278 return typ.Obj(), asTypeSlice(typ.TypeArgs())
3279 }
3280
3281
3282 func asTypeSlice(l *types2.TypeList) []types2.Type {
3283 if l.Len() == 0 {
3284 return nil
3285 }
3286 s := make([]types2.Type, l.Len())
3287 for i := range l.Len() {
3288 s[i] = l.At(i)
3289 }
3290 return s
3291 }
3292
3293 func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
3294 if p == nil {
3295 return 0
3296 }
3297 return p.(*pragmas).Flag
3298 }
3299
3300 func asWasmImport(p syntax.Pragma) *WasmImport {
3301 if p == nil {
3302 return nil
3303 }
3304 return p.(*pragmas).WasmImport
3305 }
3306
3307 func asWasmExport(p syntax.Pragma) *WasmExport {
3308 if p == nil {
3309 return nil
3310 }
3311 return p.(*pragmas).WasmExport
3312 }
3313
3314
3315 func isPtrTo(from, to types2.Type) bool {
3316 ptr, ok := types2.Unalias(from).(*types2.Pointer)
3317 return ok && types2.Identical(ptr.Elem(), to)
3318 }
3319
3320
3321
3322 func hasFallthrough(stmts []syntax.Stmt) bool {
3323
3324
3325 stmt := lastNonEmptyStmt(stmts)
3326 for {
3327 ls, ok := stmt.(*syntax.LabeledStmt)
3328 if !ok {
3329 break
3330 }
3331 stmt = ls.Stmt
3332 }
3333 last, ok := stmt.(*syntax.BranchStmt)
3334 return ok && last.Tok == syntax.Fallthrough
3335 }
3336
3337
3338
3339 func lastNonEmptyStmt(stmts []syntax.Stmt) syntax.Stmt {
3340 for i := len(stmts) - 1; i >= 0; i-- {
3341 stmt := stmts[i]
3342 if _, ok := stmt.(*syntax.EmptyStmt); !ok {
3343 return stmt
3344 }
3345 }
3346 return nil
3347 }
3348
3349
3350
3351 func (pw *pkgWriter) terminates(stmt syntax.Stmt) bool {
3352 switch stmt := stmt.(type) {
3353 case *syntax.BranchStmt:
3354 if stmt.Tok == syntax.Goto {
3355 return true
3356 }
3357 case *syntax.ReturnStmt:
3358 return true
3359 case *syntax.ExprStmt:
3360 if call, ok := syntax.Unparen(stmt.X).(*syntax.CallExpr); ok {
3361 if pw.isBuiltin(call.Fun, "panic") {
3362 return true
3363 }
3364 }
3365
3366
3367
3368
3369
3370
3371
3372
3373 case *syntax.IfStmt:
3374 cond := pw.staticBool(&stmt.Cond)
3375 return (cond < 0 || pw.terminates(stmt.Then)) && (cond > 0 || pw.terminates(stmt.Else))
3376 case *syntax.BlockStmt:
3377 return pw.terminates(lastNonEmptyStmt(stmt.List))
3378 }
3379
3380 return false
3381 }
3382
View as plain text