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 if !ok {
784 base.Fatalf("%v not in pw.typDecls", obj.(*types2.TypeName))
785 }
786 dict.implicits = decl.implicits
787 }
788
789 if isGenericMethod(obj.Type()) {
790 dict.receivers = asTypeParamSlice(obj.Type().(*types2.Signature).RecvTypeParams())
791 }
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816 w := pw.newWriter(pkgbits.SectionObj, pkgbits.SyncObject1)
817 wext := pw.newWriter(pkgbits.SectionObjExt, pkgbits.SyncObject1)
818 wname := pw.newWriter(pkgbits.SectionName, pkgbits.SyncObject1)
819 wdict := pw.newWriter(pkgbits.SectionObjDict, pkgbits.SyncObject1)
820
821 pw.objsIdx[obj] = w.Idx
822 assert(wext.Idx == w.Idx)
823 assert(wname.Idx == w.Idx)
824 assert(wdict.Idx == w.Idx)
825
826 w.dict = dict
827 wext.dict = dict
828
829 code := w.doObj(wext, obj)
830 w.Flush()
831 wext.Flush()
832
833 wname.qualifiedIdent(obj)
834 wname.Code(code)
835 wname.Flush()
836
837 wdict.objDict(obj, w.dict)
838 wdict.Flush()
839
840 return w.Idx
841 }
842
843
844
845 func (w *writer) doObj(wext *writer, obj types2.Object) pkgbits.CodeObj {
846 if obj.Pkg() != w.p.curpkg {
847 return pkgbits.ObjStub
848 }
849
850 switch obj := obj.(type) {
851 default:
852 w.p.unexpected("object", obj)
853 panic("unreachable")
854
855 case *types2.Const:
856 w.pos(obj)
857 w.typ(obj.Type())
858 w.Value(obj.Val())
859 return pkgbits.ObjConst
860
861 case *types2.Func:
862 if base.Flag.LowerH > 0 {
863
864 defer func() {
865 if p := recover(); p != nil {
866 fmt.Printf("Intercepted unified IR writer panic for function %s, repanicking", obj.FullName())
867 panic(p)
868 }
869 }()
870 }
871 decl, ok := w.p.funDecls[obj]
872 assert(ok)
873 sig := obj.Type().(*types2.Signature)
874
875 w.pos(obj)
876 if isGenericMethod(sig) {
877 w.Bool(true)
878
879 w.selector(obj)
880 w.typeParamNames(sig.RecvTypeParams())
881 w.param(sig.Recv())
882 } else {
883 if w.Version().Has(pkgbits.GenericMethods) {
884 w.Bool(false)
885 }
886 }
887 w.typeParamNames(sig.TypeParams())
888 w.signature(sig)
889 w.pos(decl)
890 wext.funcExt(obj)
891 return pkgbits.ObjFunc
892
893 case *types2.TypeName:
894 if obj.IsAlias() {
895 w.pos(obj)
896 rhs := obj.Type()
897 var tparams *types2.TypeParamList
898 if alias, ok := rhs.(*types2.Alias); ok {
899 assert(alias.TypeArgs() == nil)
900 tparams = alias.TypeParams()
901 rhs = alias.Rhs()
902 }
903 if w.Version().Has(pkgbits.AliasTypeParamNames) {
904 w.typeParamNames(tparams)
905 }
906 assert(w.Version().Has(pkgbits.AliasTypeParamNames) || tparams.Len() == 0)
907 w.typ(rhs)
908 return pkgbits.ObjAlias
909 }
910
911 named := obj.Type().(*types2.Named)
912 assert(named.TypeArgs() == nil)
913
914 w.pos(obj)
915 w.typeParamNames(named.TypeParams())
916 wext.typeExt(obj)
917 w.typ(named.Underlying())
918
919
920 var methods, gmethods []*types2.Func
921 for i := range named.NumMethods() {
922 m := named.Method(i)
923 if isGenericMethod(m.Type()) {
924 gmethods = append(gmethods, m)
925 } else {
926 methods = append(methods, m)
927 }
928 }
929
930 w.Len(len(methods))
931 for _, m := range methods {
932 w.method(wext, m)
933 }
934 if len(gmethods) > 0 {
935 assert(w.Version().Has(pkgbits.GenericMethods))
936 }
937
938 if w.Version().Has(pkgbits.GenericMethods) {
939 w.Len(len(gmethods))
940 for _, m := range gmethods {
941 w.Reloc(pkgbits.SectionObj, w.p.objIdx(m))
942 }
943 }
944
945 return pkgbits.ObjType
946
947 case *types2.Var:
948 w.pos(obj)
949 w.typ(obj.Type())
950 wext.varExt(obj)
951 return pkgbits.ObjVar
952 }
953 }
954
955
956 func (w *writer) objDict(obj types2.Object, dict *writerDict) {
957
958
959
960
961 w.dict = dict
962 w.Len(len(dict.implicits))
963
964 rtparams := objRecvTypeParams(obj)
965 tparams := objTypeParams(obj)
966
967 if w.Version().Has(pkgbits.GenericMethods) {
968 w.Len(len(rtparams))
969 } else {
970 assert(len(rtparams) == 0)
971 }
972 w.Len(len(tparams))
973
974 for _, rtparam := range rtparams {
975 w.typ(rtparam.Constraint())
976 }
977 for _, tparam := range tparams {
978 w.typ(tparam.Constraint())
979 }
980
981 nderived := len(dict.derived)
982 w.Len(nderived)
983 for _, typ := range dict.derived {
984 w.Reloc(pkgbits.SectionType, typ.idx)
985 if w.Version().Has(pkgbits.DerivedInfoNeeded) {
986 w.Bool(false)
987 }
988 }
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005 for _, implicit := range dict.implicits {
1006 w.Bool(implicit.Underlying().(*types2.Interface).IsMethodSet())
1007 }
1008 for _, rtparam := range rtparams {
1009 w.Bool(rtparam.Underlying().(*types2.Interface).IsMethodSet())
1010 }
1011 for _, tparam := range tparams {
1012 w.Bool(tparam.Underlying().(*types2.Interface).IsMethodSet())
1013 }
1014
1015 w.Len(len(dict.typeParamMethodExprs))
1016 for _, info := range dict.typeParamMethodExprs {
1017 w.Len(info.typeParamIdx)
1018 w.selectorInfo(info.methodInfo)
1019 }
1020
1021 w.Len(len(dict.subdicts))
1022 for _, info := range dict.subdicts {
1023 w.objInfo(info)
1024 }
1025
1026 w.Len(len(dict.rtypes))
1027 for _, info := range dict.rtypes {
1028 w.typInfo(info)
1029 }
1030
1031 w.Len(len(dict.itabs))
1032 for _, info := range dict.itabs {
1033 w.typInfo(info.typ)
1034 w.typInfo(info.iface)
1035 }
1036
1037 assert(len(dict.derived) == nderived)
1038 }
1039
1040 func (w *writer) typeParamNames(tparams *types2.TypeParamList) {
1041 w.Sync(pkgbits.SyncTypeParamNames)
1042
1043 ntparams := tparams.Len()
1044 for i := 0; i < ntparams; i++ {
1045 tparam := tparams.At(i).Obj()
1046 w.pos(tparam)
1047 w.localIdent(tparam)
1048 }
1049 }
1050
1051 func (w *writer) method(wext *writer, meth *types2.Func) {
1052 decl, ok := w.p.funDecls[meth]
1053 assert(ok)
1054 sig := meth.Type().(*types2.Signature)
1055
1056 w.Sync(pkgbits.SyncMethod)
1057 w.pos(meth)
1058 w.selector(meth)
1059 w.typeParamNames(sig.RecvTypeParams())
1060 w.param(sig.Recv())
1061 w.signature(sig)
1062
1063 w.pos(decl)
1064 wext.funcExt(meth)
1065 }
1066
1067
1068
1069 func (w *writer) qualifiedIdent(obj types2.Object) {
1070 w.Sync(pkgbits.SyncSym)
1071
1072 name := obj.Name()
1073 if isDefinedType(obj) && obj.Pkg() == w.p.curpkg {
1074 decl, ok := w.p.typDecls[obj.(*types2.TypeName)]
1075 assert(ok)
1076 if decl.gen != 0 {
1077
1078
1079
1080
1081
1082 name = fmt.Sprintf("%s·%v", name, decl.gen)
1083 }
1084 }
1085
1086
1087
1088 if isGenericMethod(obj.Type()) {
1089 recv := obj.Type().(*types2.Signature).Recv().Type()
1090 fstr := "%s.%s"
1091 if _, ok := types2.Unalias(recv).(*types2.Pointer); ok {
1092 fstr = "(*%s).%s"
1093 }
1094 name = fmt.Sprintf(fstr, types2.Unalias(deref2(recv)).(*types2.Named).Obj().Name(), name)
1095 }
1096
1097 w.pkg(obj.Pkg())
1098 w.String(name)
1099 }
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109 func (w *writer) localIdent(obj types2.Object) {
1110 assert(!isGlobal(obj))
1111 w.Sync(pkgbits.SyncLocalIdent)
1112 w.pkg(obj.Pkg())
1113 w.String(obj.Name())
1114 }
1115
1116
1117
1118 func (w *writer) selector(obj types2.Object) {
1119 w.selectorInfo(w.p.selectorIdx(obj))
1120 }
1121
1122 func (w *writer) selectorInfo(info selectorInfo) {
1123 w.Sync(pkgbits.SyncSelector)
1124 w.pkgRef(info.pkgIdx)
1125 w.StringRef(info.nameIdx)
1126 }
1127
1128 func (pw *pkgWriter) selectorIdx(obj types2.Object) selectorInfo {
1129 pkgIdx := pw.pkgIdx(obj.Pkg())
1130 nameIdx := pw.StringIdx(obj.Name())
1131 return selectorInfo{pkgIdx: pkgIdx, nameIdx: nameIdx}
1132 }
1133
1134
1135
1136 func (w *writer) funcExt(obj *types2.Func) {
1137 decl, ok := w.p.funDecls[obj]
1138 assert(ok)
1139
1140
1141
1142
1143
1144 pragma := asPragmaFlag(decl.Pragma)
1145 if pragma&ir.Systemstack != 0 && pragma&ir.Nosplit != 0 {
1146 w.p.errorf(decl, "go:nosplit and go:systemstack cannot be combined")
1147 }
1148 wi := asWasmImport(decl.Pragma)
1149 we := asWasmExport(decl.Pragma)
1150
1151 if decl.Body != nil {
1152 if pragma&ir.Noescape != 0 {
1153 w.p.errorf(decl, "can only use //go:noescape with external func implementations")
1154 }
1155 if wi != nil {
1156 w.p.errorf(decl, "can only use //go:wasmimport with external func implementations")
1157 }
1158 if (pragma&ir.UintptrKeepAlive != 0 && pragma&ir.UintptrEscapes == 0) && pragma&ir.Nosplit == 0 {
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172 w.p.errorf(decl, "go:uintptrkeepalive requires go:nosplit")
1173 }
1174 } else {
1175 if base.Flag.Complete || decl.Name.Value == "init" {
1176
1177
1178
1179 if _, ok := w.p.linknames[obj]; !ok && wi == nil {
1180 w.p.errorf(decl, "missing function body")
1181 }
1182 }
1183 }
1184
1185 sig, block := obj.Type().(*types2.Signature), decl.Body
1186 body, closureVars := w.p.bodyIdx(sig, block, w.dict)
1187 if len(closureVars) > 0 {
1188 fmt.Fprintln(os.Stderr, "CLOSURE", closureVars)
1189 }
1190 assert(len(closureVars) == 0)
1191
1192 w.Sync(pkgbits.SyncFuncExt)
1193 w.pragmaFlag(pragma)
1194 w.linkname(obj)
1195
1196 if buildcfg.GOARCH == "wasm" {
1197 if wi != nil {
1198 w.String(wi.Module)
1199 w.String(wi.Name)
1200 } else {
1201 w.String("")
1202 w.String("")
1203 }
1204 if we != nil {
1205 w.String(we.Name)
1206 } else {
1207 w.String("")
1208 }
1209 }
1210
1211 w.Bool(false)
1212 w.Reloc(pkgbits.SectionBody, body)
1213 w.Sync(pkgbits.SyncEOF)
1214 }
1215
1216 func (w *writer) typeExt(obj *types2.TypeName) {
1217 decl, ok := w.p.typDecls[obj]
1218 assert(ok)
1219
1220 w.Sync(pkgbits.SyncTypeExt)
1221
1222 w.pragmaFlag(asPragmaFlag(decl.Pragma))
1223
1224
1225 w.Int64(-1)
1226 w.Int64(-1)
1227 }
1228
1229 func (w *writer) varExt(obj *types2.Var) {
1230 w.Sync(pkgbits.SyncVarExt)
1231 w.linkname(obj)
1232 }
1233
1234 func (w *writer) linkname(obj types2.Object) {
1235 w.Sync(pkgbits.SyncLinkname)
1236 w.Int64(-1)
1237 info := w.p.linknames[obj]
1238 w.String(info.remote)
1239 w.Bool(info.std)
1240 }
1241
1242 func (w *writer) pragmaFlag(p ir.PragmaFlag) {
1243 w.Sync(pkgbits.SyncPragma)
1244 w.Int(int(p))
1245 }
1246
1247
1248
1249
1250
1251 func (pw *pkgWriter) bodyIdx(sig *types2.Signature, block *syntax.BlockStmt, dict *writerDict) (idx index, closureVars []posVar) {
1252 w := pw.newWriter(pkgbits.SectionBody, pkgbits.SyncFuncBody)
1253 w.sig = sig
1254 w.dict = dict
1255
1256 w.declareParams(sig)
1257 if w.Bool(block != nil) {
1258 w.stmts(block.List)
1259 w.pos(block.Rbrace)
1260 }
1261
1262 return w.Flush(), w.closureVars
1263 }
1264
1265 func (w *writer) declareParams(sig *types2.Signature) {
1266 addLocals := func(params *types2.Tuple) {
1267 for i := 0; i < params.Len(); i++ {
1268 w.addLocal(params.At(i))
1269 }
1270 }
1271
1272 if recv := sig.Recv(); recv != nil {
1273 w.addLocal(recv)
1274 }
1275 addLocals(sig.Params())
1276 addLocals(sig.Results())
1277 }
1278
1279
1280 func (w *writer) addLocal(obj *types2.Var) {
1281 idx := len(w.localsIdx)
1282
1283 w.Sync(pkgbits.SyncAddLocal)
1284 if w.p.SyncMarkers() {
1285 w.Int(idx)
1286 }
1287 w.varDictIndex(obj)
1288
1289 if w.localsIdx == nil {
1290 w.localsIdx = make(map[*types2.Var]int)
1291 }
1292 w.localsIdx[obj] = idx
1293 }
1294
1295
1296
1297 func (w *writer) useLocal(pos syntax.Pos, obj *types2.Var) {
1298 w.Sync(pkgbits.SyncUseObjLocal)
1299
1300 if idx, ok := w.localsIdx[obj]; w.Bool(ok) {
1301 w.Len(idx)
1302 return
1303 }
1304
1305 idx, ok := w.closureVarsIdx[obj]
1306 if !ok {
1307 if w.closureVarsIdx == nil {
1308 w.closureVarsIdx = make(map[*types2.Var]int)
1309 }
1310 idx = len(w.closureVars)
1311 w.closureVars = append(w.closureVars, posVar{pos, obj})
1312 w.closureVarsIdx[obj] = idx
1313 }
1314 w.Len(idx)
1315 }
1316
1317 func (w *writer) openScope(pos syntax.Pos) {
1318 w.Sync(pkgbits.SyncOpenScope)
1319 w.pos(pos)
1320 }
1321
1322 func (w *writer) closeScope(pos syntax.Pos) {
1323 w.Sync(pkgbits.SyncCloseScope)
1324 w.pos(pos)
1325 w.closeAnotherScope()
1326 }
1327
1328 func (w *writer) closeAnotherScope() {
1329 w.Sync(pkgbits.SyncCloseAnotherScope)
1330 }
1331
1332
1333
1334
1335 func (w *writer) stmt(stmt syntax.Stmt) {
1336 var stmts []syntax.Stmt
1337 if stmt != nil {
1338 stmts = []syntax.Stmt{stmt}
1339 }
1340 w.stmts(stmts)
1341 }
1342
1343 func (w *writer) stmts(stmts []syntax.Stmt) {
1344 dead := false
1345 w.Sync(pkgbits.SyncStmts)
1346 var lastLabel = -1
1347 for i, stmt := range stmts {
1348 if _, ok := stmt.(*syntax.LabeledStmt); ok {
1349 lastLabel = i
1350 }
1351 }
1352 for i, stmt := range stmts {
1353 if dead && i > lastLabel {
1354
1355
1356
1357 if _, ok := stmt.(*syntax.LabeledStmt); !ok {
1358 continue
1359 }
1360 }
1361 w.stmt1(stmt)
1362 dead = w.p.terminates(stmt)
1363 }
1364 w.Code(stmtEnd)
1365 w.Sync(pkgbits.SyncStmtsEnd)
1366 }
1367
1368 func (w *writer) stmt1(stmt syntax.Stmt) {
1369 switch stmt := stmt.(type) {
1370 default:
1371 w.p.unexpected("statement", stmt)
1372
1373 case nil, *syntax.EmptyStmt:
1374 return
1375
1376 case *syntax.AssignStmt:
1377 switch {
1378 case stmt.Rhs == nil:
1379 w.Code(stmtIncDec)
1380 w.op(binOps[stmt.Op])
1381 w.expr(stmt.Lhs)
1382 w.pos(stmt)
1383
1384 case stmt.Op != 0 && stmt.Op != syntax.Def:
1385 w.Code(stmtAssignOp)
1386 w.op(binOps[stmt.Op])
1387 w.expr(stmt.Lhs)
1388 w.pos(stmt)
1389
1390 var typ types2.Type
1391 if stmt.Op != syntax.Shl && stmt.Op != syntax.Shr {
1392 typ = w.p.typeOf(stmt.Lhs)
1393 }
1394 w.implicitConvExpr(typ, stmt.Rhs)
1395
1396 default:
1397 w.assignStmt(stmt, stmt.Lhs, stmt.Rhs)
1398 }
1399
1400 case *syntax.BlockStmt:
1401 w.Code(stmtBlock)
1402 w.blockStmt(stmt)
1403
1404 case *syntax.BranchStmt:
1405 w.Code(stmtBranch)
1406 w.pos(stmt)
1407 var op ir.Op
1408 switch stmt.Tok {
1409 case syntax.Break:
1410 op = ir.OBREAK
1411 case syntax.Continue:
1412 op = ir.OCONTINUE
1413 case syntax.Fallthrough:
1414 op = ir.OFALL
1415 case syntax.Goto:
1416 op = ir.OGOTO
1417 }
1418 w.op(op)
1419 w.optLabel(stmt.Label)
1420
1421 case *syntax.CallStmt:
1422 w.Code(stmtCall)
1423 w.pos(stmt)
1424 var op ir.Op
1425 switch stmt.Tok {
1426 case syntax.Defer:
1427 op = ir.ODEFER
1428 case syntax.Go:
1429 op = ir.OGO
1430 }
1431 w.op(op)
1432 w.expr(stmt.Call)
1433 if stmt.Tok == syntax.Defer {
1434 w.optExpr(stmt.DeferAt)
1435 }
1436
1437 case *syntax.DeclStmt:
1438 for _, decl := range stmt.DeclList {
1439 w.declStmt(decl)
1440 }
1441
1442 case *syntax.ExprStmt:
1443 w.Code(stmtExpr)
1444 w.expr(stmt.X)
1445
1446 case *syntax.ForStmt:
1447 w.Code(stmtFor)
1448 w.forStmt(stmt)
1449
1450 case *syntax.IfStmt:
1451 w.Code(stmtIf)
1452 w.ifStmt(stmt)
1453
1454 case *syntax.LabeledStmt:
1455 w.Code(stmtLabel)
1456 w.pos(stmt)
1457 w.label(stmt.Label)
1458 w.stmt1(stmt.Stmt)
1459
1460 case *syntax.ReturnStmt:
1461 w.Code(stmtReturn)
1462 w.pos(stmt)
1463
1464 resultTypes := w.sig.Results()
1465 dstType := func(i int) types2.Type {
1466 return resultTypes.At(i).Type()
1467 }
1468 w.multiExpr(stmt, dstType, syntax.UnpackListExpr(stmt.Results))
1469
1470 case *syntax.SelectStmt:
1471 w.Code(stmtSelect)
1472 w.selectStmt(stmt)
1473
1474 case *syntax.SendStmt:
1475 chanType := types2.CoreType(w.p.typeOf(stmt.Chan)).(*types2.Chan)
1476
1477 w.Code(stmtSend)
1478 w.pos(stmt)
1479 w.expr(stmt.Chan)
1480 w.implicitConvExpr(chanType.Elem(), stmt.Value)
1481
1482 case *syntax.SwitchStmt:
1483 w.Code(stmtSwitch)
1484 w.switchStmt(stmt)
1485 }
1486 }
1487
1488 func (w *writer) assignList(expr syntax.Expr) {
1489 exprs := syntax.UnpackListExpr(expr)
1490 w.Len(len(exprs))
1491
1492 for _, expr := range exprs {
1493 w.assign(expr)
1494 }
1495 }
1496
1497 func (w *writer) assign(expr syntax.Expr) {
1498 expr = syntax.Unparen(expr)
1499
1500 if name, ok := expr.(*syntax.Name); ok {
1501 if name.Value == "_" {
1502 w.Code(assignBlank)
1503 return
1504 }
1505
1506 if obj, ok := w.p.info.Defs[name]; ok {
1507 obj := obj.(*types2.Var)
1508
1509 w.Code(assignDef)
1510 w.pos(obj)
1511 w.localIdent(obj)
1512 w.typ(obj.Type())
1513
1514
1515
1516 w.addLocal(obj)
1517 return
1518 }
1519 }
1520
1521 w.Code(assignExpr)
1522 w.expr(expr)
1523 }
1524
1525 func (w *writer) declStmt(decl syntax.Decl) {
1526 switch decl := decl.(type) {
1527 default:
1528 w.p.unexpected("declaration", decl)
1529
1530 case *syntax.ConstDecl, *syntax.TypeDecl:
1531
1532 case *syntax.VarDecl:
1533 w.assignStmt(decl, namesAsExpr(decl.NameList), decl.Values)
1534 }
1535 }
1536
1537
1538 func (w *writer) assignStmt(pos poser, lhs0, rhs0 syntax.Expr) {
1539 lhs := syntax.UnpackListExpr(lhs0)
1540 rhs := syntax.UnpackListExpr(rhs0)
1541
1542 w.Code(stmtAssign)
1543 w.pos(pos)
1544
1545
1546 w.Len(len(lhs))
1547 for _, expr := range lhs {
1548 w.assign(expr)
1549 }
1550
1551 dstType := func(i int) types2.Type {
1552 dst := lhs[i]
1553
1554
1555
1556
1557 if name, ok := syntax.Unparen(dst).(*syntax.Name); ok {
1558 if name.Value == "_" {
1559 return nil
1560 } else if def, ok := w.p.info.Defs[name].(*types2.Var); ok {
1561 return def.Type()
1562 } else if use, ok := w.p.info.Uses[name].(*types2.Var); ok {
1563 return use.Type()
1564 } else {
1565 w.p.fatalf(dst, "cannot find type of destination object: %v", dst)
1566 }
1567 }
1568
1569 return w.p.typeOf(dst)
1570 }
1571
1572 w.multiExpr(pos, dstType, rhs)
1573 }
1574
1575 func (w *writer) blockStmt(stmt *syntax.BlockStmt) {
1576 w.Sync(pkgbits.SyncBlockStmt)
1577 w.openScope(stmt.Pos())
1578 w.stmts(stmt.List)
1579 w.closeScope(stmt.Rbrace)
1580 }
1581
1582 func (w *writer) forStmt(stmt *syntax.ForStmt) {
1583 w.Sync(pkgbits.SyncForStmt)
1584 w.openScope(stmt.Pos())
1585
1586 if rang, ok := stmt.Init.(*syntax.RangeClause); w.Bool(ok) {
1587 w.pos(rang)
1588 w.assignList(rang.Lhs)
1589 w.expr(rang.X)
1590
1591 xtyp := w.p.typeOf(rang.X)
1592 if _, isMap := types2.CoreType(xtyp).(*types2.Map); isMap {
1593 w.rtype(xtyp)
1594 }
1595 {
1596 lhs := syntax.UnpackListExpr(rang.Lhs)
1597 assign := func(i int, src types2.Type) {
1598 if i >= len(lhs) {
1599 return
1600 }
1601 dst := syntax.Unparen(lhs[i])
1602 if name, ok := dst.(*syntax.Name); ok && name.Value == "_" {
1603 return
1604 }
1605
1606 var dstType types2.Type
1607 if rang.Def {
1608
1609
1610 dstType = w.p.info.Defs[dst.(*syntax.Name)].(*types2.Var).Type()
1611 } else {
1612 dstType = w.p.typeOf(dst)
1613 }
1614
1615 w.convRTTI(src, dstType)
1616 }
1617
1618 keyType, valueType := types2.RangeKeyVal(w.p.typeOf(rang.X))
1619 assign(0, keyType)
1620 assign(1, valueType)
1621 }
1622
1623 } else {
1624 if stmt.Cond != nil && w.p.staticBool(&stmt.Cond) < 0 {
1625 stmt.Post = nil
1626 stmt.Body.List = nil
1627 }
1628
1629 w.pos(stmt)
1630 w.stmt(stmt.Init)
1631 w.optExpr(stmt.Cond)
1632 w.stmt(stmt.Post)
1633 }
1634
1635 w.blockStmt(stmt.Body)
1636 w.Bool(w.distinctVars(stmt))
1637 w.closeAnotherScope()
1638 }
1639
1640 func (w *writer) distinctVars(stmt *syntax.ForStmt) bool {
1641 lv := base.Debug.LoopVar
1642 fileVersion := w.p.info.FileVersions[stmt.Pos().FileBase()]
1643 is122 := fileVersion == "" || version.Compare(fileVersion, "go1.22") >= 0
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656 return is122 || lv > 0 && lv != 3
1657 }
1658
1659 func (w *writer) ifStmt(stmt *syntax.IfStmt) {
1660 cond := w.p.staticBool(&stmt.Cond)
1661
1662 w.Sync(pkgbits.SyncIfStmt)
1663 w.openScope(stmt.Pos())
1664 w.pos(stmt)
1665 w.stmt(stmt.Init)
1666 w.expr(stmt.Cond)
1667 w.Int(cond)
1668 if cond >= 0 {
1669 w.blockStmt(stmt.Then)
1670 } else {
1671 w.pos(stmt.Then.Rbrace)
1672 }
1673 if cond <= 0 {
1674 w.stmt(stmt.Else)
1675 }
1676 w.closeAnotherScope()
1677 }
1678
1679 func (w *writer) selectStmt(stmt *syntax.SelectStmt) {
1680 w.Sync(pkgbits.SyncSelectStmt)
1681
1682 w.pos(stmt)
1683 w.Len(len(stmt.Body))
1684 for i, clause := range stmt.Body {
1685 if i > 0 {
1686 w.closeScope(clause.Pos())
1687 }
1688 w.openScope(clause.Pos())
1689
1690 w.pos(clause)
1691 w.stmt(clause.Comm)
1692 w.stmts(clause.Body)
1693 }
1694 if len(stmt.Body) > 0 {
1695 w.closeScope(stmt.Rbrace)
1696 }
1697 }
1698
1699 func (w *writer) switchStmt(stmt *syntax.SwitchStmt) {
1700 w.Sync(pkgbits.SyncSwitchStmt)
1701
1702 w.openScope(stmt.Pos())
1703 w.pos(stmt)
1704 w.stmt(stmt.Init)
1705
1706 var iface, tagType types2.Type
1707 var tagTypeIsChan bool
1708 if guard, ok := stmt.Tag.(*syntax.TypeSwitchGuard); w.Bool(ok) {
1709 iface = w.p.typeOf(guard.X)
1710
1711 w.pos(guard)
1712 if tag := guard.Lhs; w.Bool(tag != nil) {
1713 w.pos(tag)
1714
1715
1716 w.Sync(pkgbits.SyncLocalIdent)
1717 w.pkg(w.p.curpkg)
1718 w.String(tag.Value)
1719 }
1720 w.expr(guard.X)
1721 } else {
1722 tag := stmt.Tag
1723
1724 var tagValue constant.Value
1725 if tag != nil {
1726 tv := w.p.typeAndValue(tag)
1727 tagType = tv.Type
1728 tagValue = tv.Value
1729 _, tagTypeIsChan = tagType.Underlying().(*types2.Chan)
1730 } else {
1731 tagType = types2.Typ[types2.Bool]
1732 tagValue = constant.MakeBool(true)
1733 }
1734
1735 if tagValue != nil {
1736
1737
1738 func() {
1739 var target *syntax.CaseClause
1740 Outer:
1741 for _, clause := range stmt.Body {
1742 if clause.Cases == nil {
1743 target = clause
1744 }
1745 for _, cas := range syntax.UnpackListExpr(clause.Cases) {
1746 tv := w.p.typeAndValue(cas)
1747 if tv.Value == nil {
1748 return
1749 }
1750 if constant.Compare(tagValue, token.EQL, tv.Value) {
1751 target = clause
1752 break Outer
1753 }
1754 }
1755 }
1756
1757
1758 if target != nil {
1759 if hasFallthrough(target.Body) {
1760 return
1761 }
1762
1763
1764 target.Cases = nil
1765 stmt.Body = []*syntax.CaseClause{target}
1766 } else {
1767 stmt.Body = nil
1768 }
1769
1770
1771 tag = nil
1772 stmt.Tag = nil
1773 tagType = types2.Typ[types2.Bool]
1774 }()
1775 }
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786 if !tagTypeIsChan {
1787 Outer:
1788 for _, clause := range stmt.Body {
1789 for _, cas := range syntax.UnpackListExpr(clause.Cases) {
1790 if casType := w.p.typeOf(cas); !types2.AssignableTo(casType, tagType) && (types2.IsInterface(casType) || types2.IsInterface(tagType)) {
1791 tagType = types2.NewInterfaceType(nil, nil)
1792 break Outer
1793 }
1794 }
1795 }
1796 }
1797
1798 if w.Bool(tag != nil) {
1799 w.implicitConvExpr(tagType, tag)
1800 }
1801 }
1802
1803 w.Len(len(stmt.Body))
1804 for i, clause := range stmt.Body {
1805 if i > 0 {
1806 w.closeScope(clause.Pos())
1807 }
1808 w.openScope(clause.Pos())
1809
1810 w.pos(clause)
1811
1812 cases := syntax.UnpackListExpr(clause.Cases)
1813 if iface != nil {
1814 w.Len(len(cases))
1815 for _, cas := range cases {
1816 if w.Bool(isNil(w.p, cas)) {
1817 continue
1818 }
1819 w.exprType(iface, cas)
1820 }
1821 } else {
1822
1823
1824
1825 w.Sync(pkgbits.SyncExprList)
1826 w.Sync(pkgbits.SyncExprs)
1827 w.Len(len(cases))
1828 for _, cas := range cases {
1829 typ := tagType
1830 if tagTypeIsChan {
1831 typ = nil
1832 }
1833 w.implicitConvExpr(typ, cas)
1834 }
1835 }
1836
1837 if obj, ok := w.p.info.Implicits[clause]; ok {
1838
1839
1840
1841
1842
1843 pos := clause.Pos()
1844 if typs := syntax.UnpackListExpr(clause.Cases); len(typs) != 0 {
1845 pos = typeExprEndPos(typs[len(typs)-1])
1846 }
1847 w.pos(pos)
1848
1849 obj := obj.(*types2.Var)
1850 w.typ(obj.Type())
1851 w.addLocal(obj)
1852 }
1853
1854 w.stmts(clause.Body)
1855 }
1856 if len(stmt.Body) > 0 {
1857 w.closeScope(stmt.Rbrace)
1858 }
1859
1860 w.closeScope(stmt.Rbrace)
1861 }
1862
1863 func (w *writer) label(label *syntax.Name) {
1864 w.Sync(pkgbits.SyncLabel)
1865
1866
1867 w.String(label.Value)
1868 }
1869
1870 func (w *writer) optLabel(label *syntax.Name) {
1871 w.Sync(pkgbits.SyncOptLabel)
1872 if w.Bool(label != nil) {
1873 w.label(label)
1874 }
1875 }
1876
1877
1878
1879
1880 func (w *writer) expr(expr syntax.Expr) {
1881 base.Assertf(expr != nil, "missing expression")
1882
1883 expr = syntax.Unparen(expr)
1884
1885 obj, inst := lookupObj(w.p, expr)
1886 targs := asTypeSlice(inst.TypeArgs)
1887
1888 if tv, ok := w.p.maybeTypeAndValue(expr); ok {
1889 if tv.IsRuntimeHelper() {
1890 if pkg := obj.Pkg(); pkg != nil && pkg.Name() == "runtime" {
1891 objName := obj.Name()
1892 w.Code(exprRuntimeBuiltin)
1893 w.String(objName)
1894 return
1895 }
1896 }
1897
1898 if tv.IsType() {
1899 w.p.fatalf(expr, "unexpected type expression %v", syntax.String(expr))
1900 }
1901
1902 if tv.Value != nil {
1903 w.Code(exprConst)
1904 w.pos(expr)
1905 typ := idealType(tv)
1906 assert(typ != nil)
1907 w.typ(typ)
1908 w.Value(tv.Value)
1909 return
1910 }
1911
1912 if _, isNil := obj.(*types2.Nil); isNil {
1913 w.Code(exprZero)
1914 w.pos(expr)
1915 w.typ(tv.Type)
1916 return
1917 }
1918
1919
1920
1921
1922
1923 if typ := tv.Type; !tv.IsBuiltin() && !isTuple(typ) && !isUntyped(typ) {
1924 w.Code(exprReshape)
1925 w.typ(typ)
1926
1927 }
1928 }
1929
1930 if obj != nil {
1931 if len(targs) != 0 {
1932 obj := obj.(*types2.Func)
1933
1934 w.Code(exprFuncInst)
1935 w.pos(expr)
1936 w.funcInst(obj, targs)
1937 return
1938 }
1939
1940 if isGlobal(obj) {
1941 w.Code(exprGlobal)
1942 w.obj(obj, nil)
1943 return
1944 }
1945
1946 obj := obj.(*types2.Var)
1947 assert(!obj.IsField())
1948
1949 w.Code(exprLocal)
1950 w.useLocal(expr.Pos(), obj)
1951 return
1952 }
1953
1954 switch expr := expr.(type) {
1955 default:
1956 w.p.unexpected("expression", expr)
1957
1958 case *syntax.CompositeLit:
1959 w.Code(exprCompLit)
1960 w.compLit(expr)
1961
1962 case *syntax.FuncLit:
1963 w.Code(exprFuncLit)
1964 w.funcLit(expr)
1965
1966 case *syntax.SelectorExpr:
1967 sel, ok := w.p.info.Selections[expr]
1968 assert(ok)
1969
1970 switch sel.Kind() {
1971 default:
1972 w.p.fatalf(expr, "unexpected selection kind: %v", sel.Kind())
1973
1974 case types2.FieldVal:
1975 w.Code(exprFieldVal)
1976 w.expr(expr.X)
1977 w.pos(expr)
1978 w.selector(sel.Obj())
1979
1980 case types2.MethodVal:
1981 w.methVal(expr, sel)
1982
1983 case types2.MethodExpr:
1984 w.methExpr(expr, sel)
1985 }
1986
1987 case *syntax.IndexExpr:
1988
1989 if selector, ok := expr.X.(*syntax.SelectorExpr); ok {
1990 if sel, ok := w.p.info.Selections[selector]; ok {
1991 switch sel.Kind() {
1992 default:
1993 w.p.fatalf(selector, "unexpected selection kind: %v", sel.Kind())
1994 case types2.FieldVal:
1995
1996 case types2.MethodVal:
1997 w.methVal(selector, sel)
1998 return
1999 case types2.MethodExpr:
2000 w.methExpr(selector, sel)
2001 return
2002 }
2003 }
2004 }
2005 _ = w.p.typeOf(expr.Index)
2006
2007 xtyp := w.p.typeOf(expr.X)
2008
2009 var keyType types2.Type
2010 if mapType, ok := types2.CoreType(xtyp).(*types2.Map); ok {
2011 keyType = mapType.Key()
2012 }
2013
2014 w.Code(exprIndex)
2015 w.expr(expr.X)
2016 w.pos(expr)
2017 w.implicitConvExpr(keyType, expr.Index)
2018 if keyType != nil {
2019 w.rtype(xtyp)
2020 }
2021
2022 case *syntax.SliceExpr:
2023 w.Code(exprSlice)
2024 w.expr(expr.X)
2025 w.pos(expr)
2026 for _, n := range &expr.Index {
2027 w.optExpr(n)
2028 }
2029
2030 case *syntax.AssertExpr:
2031 iface := w.p.typeOf(expr.X)
2032
2033 w.Code(exprAssert)
2034 w.expr(expr.X)
2035 w.pos(expr)
2036 w.exprType(iface, expr.Type)
2037 w.rtype(iface)
2038
2039 case *syntax.Operation:
2040 if expr.Y == nil {
2041 w.Code(exprUnaryOp)
2042 w.op(unOps[expr.Op])
2043 w.pos(expr)
2044 w.expr(expr.X)
2045 break
2046 }
2047
2048 var commonType types2.Type
2049 switch expr.Op {
2050 case syntax.Shl, syntax.Shr:
2051
2052 default:
2053 xtyp := w.p.typeOf(expr.X)
2054 ytyp := w.p.typeOf(expr.Y)
2055 switch {
2056 case types2.AssignableTo(xtyp, ytyp):
2057 commonType = ytyp
2058 case types2.AssignableTo(ytyp, xtyp):
2059 commonType = xtyp
2060 default:
2061 w.p.fatalf(expr, "failed to find common type between %v and %v", xtyp, ytyp)
2062 }
2063 }
2064
2065 w.Code(exprBinaryOp)
2066 w.op(binOps[expr.Op])
2067 w.implicitConvExpr(commonType, expr.X)
2068 w.pos(expr)
2069 w.implicitConvExpr(commonType, expr.Y)
2070
2071 case *syntax.CallExpr:
2072 tv := w.p.typeAndValue(expr.Fun)
2073 if tv.IsType() {
2074 assert(len(expr.ArgList) == 1)
2075 assert(!expr.HasDots)
2076 w.convertExpr(tv.Type, expr.ArgList[0], false)
2077 break
2078 }
2079
2080 var rtype types2.Type
2081 if tv.IsBuiltin() {
2082 switch obj, _ := lookupObj(w.p, syntax.Unparen(expr.Fun)); obj.Name() {
2083 case "make":
2084 assert(len(expr.ArgList) >= 1)
2085 assert(!expr.HasDots)
2086
2087 w.Code(exprMake)
2088 w.pos(expr)
2089 w.exprType(nil, expr.ArgList[0])
2090 w.exprs(expr.ArgList[1:])
2091
2092 typ := w.p.typeOf(expr)
2093 switch coreType := types2.CoreType(typ).(type) {
2094 default:
2095 w.p.fatalf(expr, "unexpected core type: %v", coreType)
2096 case *types2.Chan:
2097 w.rtype(typ)
2098 case *types2.Map:
2099 w.rtype(typ)
2100 case *types2.Slice:
2101 w.rtype(sliceElem(typ))
2102 }
2103
2104 return
2105
2106 case "new":
2107 assert(len(expr.ArgList) == 1)
2108 assert(!expr.HasDots)
2109 arg := expr.ArgList[0]
2110
2111 w.Code(exprNew)
2112 w.pos(expr)
2113 tv := w.p.typeAndValue(arg)
2114 if w.Bool(!tv.IsType()) {
2115 w.expr(arg)
2116 } else {
2117 w.exprType(nil, arg)
2118 }
2119 return
2120
2121 case "Sizeof":
2122 assert(len(expr.ArgList) == 1)
2123 assert(!expr.HasDots)
2124
2125 w.Code(exprSizeof)
2126 w.pos(expr)
2127 w.typ(w.p.typeOf(expr.ArgList[0]))
2128 return
2129
2130 case "Alignof":
2131 assert(len(expr.ArgList) == 1)
2132 assert(!expr.HasDots)
2133
2134 w.Code(exprAlignof)
2135 w.pos(expr)
2136 w.typ(w.p.typeOf(expr.ArgList[0]))
2137 return
2138
2139 case "Offsetof":
2140 assert(len(expr.ArgList) == 1)
2141 assert(!expr.HasDots)
2142 selector := syntax.Unparen(expr.ArgList[0]).(*syntax.SelectorExpr)
2143 index := w.p.info.Selections[selector].Index()
2144
2145 w.Code(exprOffsetof)
2146 w.pos(expr)
2147 w.typ(deref2(w.p.typeOf(selector.X)))
2148 w.Len(len(index) - 1)
2149 for _, idx := range index {
2150 w.Len(idx)
2151 }
2152 return
2153
2154 case "append":
2155 rtype = sliceElem(w.p.typeOf(expr))
2156 case "copy":
2157 typ := w.p.typeOf(expr.ArgList[0])
2158 if tuple, ok := typ.(*types2.Tuple); ok {
2159 typ = tuple.At(0).Type()
2160 }
2161 rtype = sliceElem(typ)
2162 case "delete":
2163 typ := w.p.typeOf(expr.ArgList[0])
2164 if tuple, ok := typ.(*types2.Tuple); ok {
2165 typ = tuple.At(0).Type()
2166 }
2167 rtype = typ
2168 case "Slice":
2169 rtype = sliceElem(w.p.typeOf(expr))
2170 }
2171 }
2172
2173 writeFunExpr := func() {
2174 fun := syntax.Unparen(expr.Fun)
2175
2176 expr := fun
2177 if idx, ok := expr.(*syntax.IndexExpr); ok {
2178 expr = idx.X
2179 }
2180 if selector, ok := expr.(*syntax.SelectorExpr); ok {
2181 if sel, ok := w.p.info.Selections[selector]; ok && sel.Kind() == types2.MethodVal {
2182 w.Bool(true)
2183 typ := w.recvExpr(selector, sel)
2184 w.methodExpr(selector, typ, sel)
2185 return
2186 }
2187 }
2188
2189 w.Bool(false)
2190
2191 if obj, inst := lookupObj(w.p, fun); w.Bool(obj != nil && inst.TypeArgs.Len() != 0) {
2192 obj := obj.(*types2.Func)
2193
2194 w.pos(fun)
2195 w.funcInst(obj, asTypeSlice(inst.TypeArgs))
2196 return
2197 }
2198
2199 w.expr(fun)
2200 }
2201
2202 sigType := types2.CoreType(tv.Type).(*types2.Signature)
2203 paramTypes := sigType.Params()
2204
2205 w.Code(exprCall)
2206 writeFunExpr()
2207 w.pos(expr)
2208
2209 paramType := func(i int) types2.Type {
2210 if sigType.Variadic() && !expr.HasDots && i >= paramTypes.Len()-1 {
2211 return paramTypes.At(paramTypes.Len() - 1).Type().(*types2.Slice).Elem()
2212 }
2213 return paramTypes.At(i).Type()
2214 }
2215
2216 w.multiExpr(expr, paramType, expr.ArgList)
2217 w.Bool(expr.HasDots)
2218 if rtype != nil {
2219 w.rtype(rtype)
2220 }
2221 }
2222 }
2223
2224 func sliceElem(typ types2.Type) types2.Type {
2225 return types2.CoreType(typ).(*types2.Slice).Elem()
2226 }
2227
2228 func (w *writer) optExpr(expr syntax.Expr) {
2229 if w.Bool(expr != nil) {
2230 w.expr(expr)
2231 }
2232 }
2233
2234 func (w *writer) methVal(expr *syntax.SelectorExpr, sel *types2.Selection) {
2235 w.Code(exprMethodVal)
2236 typ := w.recvExpr(expr, sel)
2237 w.pos(expr)
2238 w.methodExpr(expr, typ, sel)
2239 }
2240
2241 func (w *writer) methExpr(expr *syntax.SelectorExpr, sel *types2.Selection) {
2242 w.Code(exprMethodExpr)
2243
2244 tv := w.p.typeAndValue(expr.X)
2245 assert(tv.IsType())
2246
2247 index := sel.Index()
2248 implicits := index[:len(index)-1]
2249
2250 typ := tv.Type
2251 w.typ(typ)
2252
2253 w.Len(len(implicits))
2254 for _, ix := range implicits {
2255 w.Len(ix)
2256 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
2257 }
2258
2259 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
2260 if w.Bool(isPtrTo(typ, recv)) {
2261 typ = recv
2262 } else if w.Bool(isPtrTo(recv, typ)) {
2263 typ = recv
2264 }
2265
2266 w.pos(expr)
2267 w.methodExpr(expr, typ, sel)
2268 }
2269
2270
2271
2272
2273 func (w *writer) recvExpr(expr *syntax.SelectorExpr, sel *types2.Selection) types2.Type {
2274 index := sel.Index()
2275 implicits := index[:len(index)-1]
2276
2277 w.Code(exprRecv)
2278 w.expr(expr.X)
2279 w.pos(expr)
2280 w.Len(len(implicits))
2281
2282 typ := w.p.typeOf(expr.X)
2283 for _, ix := range implicits {
2284 typ = deref2(typ).Underlying().(*types2.Struct).Field(ix).Type()
2285 w.Len(ix)
2286 }
2287
2288 recv := sel.Obj().(*types2.Func).Type().(*types2.Signature).Recv().Type()
2289 if w.Bool(isPtrTo(typ, recv)) {
2290 typ = recv
2291 } else if w.Bool(isPtrTo(recv, typ)) {
2292 typ = recv
2293 }
2294
2295 return typ
2296 }
2297
2298
2299 func (w *writer) funcInst(obj *types2.Func, targs []types2.Type) {
2300 info := w.p.objInstIdx(obj, targs, w.dict)
2301
2302
2303
2304
2305 if w.Bool(info.anyDerived()) {
2306 w.Len(w.dict.subdictIdx(info))
2307 return
2308 }
2309
2310
2311
2312
2313 w.objInfo(info)
2314 }
2315
2316
2317
2318
2319
2320
2321
2322 func (w *writer) methodExpr(expr *syntax.SelectorExpr, recv types2.Type, sel *types2.Selection) {
2323 fun := sel.Obj().(*types2.Func)
2324 sig := fun.Type().(*types2.Signature)
2325
2326 w.typ(recv)
2327
2328
2329 if isGenericMethod(sig) {
2330 assert(w.Version().Has(pkgbits.GenericMethods))
2331 w.Bool(true)
2332 } else {
2333 if w.Version().Has(pkgbits.GenericMethods) {
2334 w.Bool(false)
2335 }
2336 w.typ(sig)
2337 }
2338
2339 w.pos(expr)
2340 w.selector(fun)
2341
2342
2343
2344 if typeParam, ok := types2.Unalias(recv).(*types2.TypeParam); w.Bool(ok) {
2345 typeParamIdx := w.dict.typeParamIndex(typeParam)
2346 methodInfo := w.p.selectorIdx(fun)
2347
2348 w.Len(w.dict.typeParamMethodExprIdx(typeParamIdx, methodInfo))
2349 return
2350 }
2351
2352 if isInterface(recv) != isInterface(sig.Recv().Type()) {
2353 w.p.fatalf(expr, "isInterface inconsistency: %v and %v", recv, sig.Recv().Type())
2354 }
2355
2356 if isConcreteMethod(sig) {
2357 tname, tExplicits := splitNamed(types2.Unalias(deref2(recv)).(*types2.Named))
2358 var info objInfo
2359 if isGenericMethod(sig) {
2360
2361 mExplicits := asTypeSlice(w.p.info.Instances[expr.Sel].TypeArgs)
2362 info = w.p.objInstIdx(fun.Origin(), slices.Concat(tExplicits, mExplicits), w.dict)
2363 } else {
2364
2365
2366 info = w.p.objInstIdx(tname, tExplicits, w.dict)
2367 }
2368
2369
2370
2371
2372 if info.anyDerived() {
2373 w.Bool(true)
2374 w.Len(w.dict.subdictIdx(info))
2375 return
2376 }
2377
2378
2379
2380 if len(info.explicits) > 0 {
2381 w.Bool(false)
2382 w.Bool(true)
2383 w.objInfo(info)
2384 return
2385 }
2386
2387 }
2388
2389 w.Bool(false)
2390 w.Bool(false)
2391 }
2392
2393
2394
2395
2396
2397 func (w *writer) multiExpr(pos poser, dstType func(int) types2.Type, exprs []syntax.Expr) {
2398 w.Sync(pkgbits.SyncMultiExpr)
2399
2400 if len(exprs) == 1 {
2401 expr := exprs[0]
2402 if tuple, ok := w.p.typeOf(expr).(*types2.Tuple); ok {
2403 assert(tuple.Len() > 1)
2404 w.Bool(true)
2405 w.pos(pos)
2406 w.expr(expr)
2407
2408 w.Len(tuple.Len())
2409 for i := 0; i < tuple.Len(); i++ {
2410 src := tuple.At(i).Type()
2411
2412
2413 w.typ(src)
2414 if dst := dstType(i); w.Bool(dst != nil && !types2.Identical(src, dst)) {
2415 if src == nil || dst == nil {
2416 w.p.fatalf(pos, "src is %v, dst is %v", src, dst)
2417 }
2418 if !types2.AssignableTo(src, dst) {
2419 w.p.fatalf(pos, "%v is not assignable to %v", src, dst)
2420 }
2421 w.typ(dst)
2422 w.convRTTI(src, dst)
2423 }
2424 }
2425 return
2426 }
2427 }
2428
2429 w.Bool(false)
2430 w.Len(len(exprs))
2431 for i, expr := range exprs {
2432 w.implicitConvExpr(dstType(i), expr)
2433 }
2434 }
2435
2436
2437
2438
2439 func (w *writer) implicitConvExpr(dst types2.Type, expr syntax.Expr) {
2440 w.convertExpr(dst, expr, true)
2441 }
2442
2443 func (w *writer) convertExpr(dst types2.Type, expr syntax.Expr, implicit bool) {
2444 src := w.p.typeOf(expr)
2445
2446
2447 identical := dst == nil || types2.Identical(src, dst)
2448 if implicit && identical {
2449 w.expr(expr)
2450 return
2451 }
2452
2453 if implicit && !types2.AssignableTo(src, dst) {
2454 w.p.fatalf(expr, "%v is not assignable to %v", src, dst)
2455 }
2456
2457 w.Code(exprConvert)
2458 w.Bool(implicit)
2459 w.typ(dst)
2460 w.pos(expr)
2461 w.convRTTI(src, dst)
2462 w.Bool(isTypeParam(dst))
2463 w.Bool(identical)
2464 w.expr(expr)
2465 }
2466
2467 func (w *writer) compLit(lit *syntax.CompositeLit) {
2468 typ := w.p.typeOf(lit)
2469
2470 w.Sync(pkgbits.SyncCompLit)
2471 w.pos(lit)
2472 w.typ(typ)
2473
2474 if ptr, ok := types2.CoreType(typ).(*types2.Pointer); ok {
2475 typ = ptr.Elem()
2476 }
2477
2478 if w.Version().Has(pkgbits.CompactCompLiterals) {
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 w.arrayElems(typ.Elem(), lit.ElemList)
2484 case *types2.Map:
2485 w.rtype(typ0)
2486 w.mapElems(typ.Key(), typ.Elem(), lit.ElemList)
2487 case *types2.Slice:
2488 w.arrayElems(typ.Elem(), lit.ElemList)
2489 case *types2.Struct:
2490 w.structElems(typ, lit.NKeys == 0, lit.ElemList)
2491 }
2492 return
2493 }
2494
2495
2496 var keyType, elemType types2.Type
2497 var structType *types2.Struct
2498 switch typ0 := typ; typ := types2.CoreType(typ).(type) {
2499 default:
2500 w.p.fatalf(lit, "unexpected composite literal type: %v", typ)
2501 case *types2.Array:
2502 elemType = typ.Elem()
2503 case *types2.Map:
2504 w.rtype(typ0)
2505 keyType, elemType = typ.Key(), typ.Elem()
2506 case *types2.Slice:
2507 elemType = typ.Elem()
2508 case *types2.Struct:
2509 structType = typ
2510 }
2511
2512 w.Len(len(lit.ElemList))
2513 for i, elem := range lit.ElemList {
2514 elemType := elemType
2515 if structType != nil {
2516 if kv, ok := elem.(*syntax.KeyValueExpr); ok {
2517
2518 w.pos(kv.Key)
2519 i = fieldIndex(w.p.info, structType, kv.Key.(*syntax.Name))
2520 elem = kv.Value
2521 } else {
2522 w.pos(elem)
2523 }
2524 elemType = structType.Field(i).Type()
2525 w.Len(i)
2526 } else {
2527 if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
2528
2529 w.pos(kv.Key)
2530 w.implicitConvExpr(keyType, kv.Key)
2531 elem = kv.Value
2532 }
2533 }
2534 w.implicitConvExpr(elemType, elem)
2535 }
2536 }
2537
2538 func (w *writer) arrayElems(elemType types2.Type, elems []syntax.Expr) {
2539 valuesOnly := true
2540 for _, elem := range elems {
2541 if _, ok := elem.(*syntax.KeyValueExpr); ok {
2542 valuesOnly = false
2543 break
2544 }
2545 }
2546
2547 if valuesOnly {
2548 w.Int(len(elems))
2549 for _, elem := range elems {
2550 w.implicitConvExpr(elemType, elem)
2551 }
2552 return
2553 }
2554
2555 w.Int(-len(elems))
2556 for _, elem := range elems {
2557 if kv, ok := elem.(*syntax.KeyValueExpr); w.Bool(ok) {
2558 w.pos(kv.Key)
2559 w.implicitConvExpr(nil, kv.Key)
2560 elem = kv.Value
2561 }
2562 w.implicitConvExpr(elemType, elem)
2563 }
2564 }
2565
2566 func (w *writer) mapElems(keyType, valueType types2.Type, elems []syntax.Expr) {
2567
2568 w.Int(-len(elems))
2569 for _, elem := range elems {
2570 kv := elem.(*syntax.KeyValueExpr)
2571 w.pos(kv.Key)
2572 w.implicitConvExpr(keyType, kv.Key)
2573 w.implicitConvExpr(valueType, kv.Value)
2574 }
2575 }
2576
2577 func (w *writer) structElems(typ *types2.Struct, valuesOnly bool, elems []syntax.Expr) {
2578 n := len(elems)
2579 if valuesOnly {
2580
2581 w.Int(n)
2582 for i, elem := range elems {
2583 w.pos(elem)
2584 w.implicitConvExpr(typ.Field(i).Type(), elem)
2585 }
2586 return
2587 }
2588
2589 w.Int(-n)
2590 for _, elem := range elems {
2591 kv := elem.(*syntax.KeyValueExpr)
2592 w.pos(kv.Key)
2593
2594 fld, index, _ := types2.LookupFieldOrMethod(typ, false, w.p.curpkg, kv.Key.(*syntax.Name).Value)
2595 if n := len(index); n > 1 {
2596
2597 w.Int(-n)
2598 for _, i := range index {
2599 w.Int(i)
2600 }
2601 } else {
2602 w.Int(index[0])
2603 }
2604 w.implicitConvExpr(fld.Type(), kv.Value)
2605 }
2606 }
2607
2608 func (w *writer) funcLit(expr *syntax.FuncLit) {
2609 sig := w.p.typeOf(expr).(*types2.Signature)
2610
2611 body, closureVars := w.p.bodyIdx(sig, expr.Body, w.dict)
2612
2613 w.Sync(pkgbits.SyncFuncLit)
2614 w.pos(expr)
2615 w.signature(sig)
2616 w.Bool(w.p.rangeFuncBodyClosures[expr])
2617
2618 w.Len(len(closureVars))
2619 for _, cv := range closureVars {
2620 w.pos(cv.pos)
2621 w.useLocal(cv.pos, cv.var_)
2622 }
2623
2624 w.Reloc(pkgbits.SectionBody, body)
2625 }
2626
2627 type posVar struct {
2628 pos syntax.Pos
2629 var_ *types2.Var
2630 }
2631
2632 func (p posVar) String() string {
2633 return p.pos.String() + ":" + p.var_.String()
2634 }
2635
2636 func (w *writer) exprs(exprs []syntax.Expr) {
2637 w.Sync(pkgbits.SyncExprs)
2638 w.Len(len(exprs))
2639 for _, expr := range exprs {
2640 w.expr(expr)
2641 }
2642 }
2643
2644
2645
2646 func (w *writer) rtype(typ types2.Type) {
2647 typ = types2.Default(typ)
2648
2649 info := w.p.typIdx(typ, w.dict)
2650 w.rtypeInfo(info)
2651 }
2652
2653 func (w *writer) rtypeInfo(info typeInfo) {
2654 w.Sync(pkgbits.SyncRType)
2655
2656 if w.Bool(info.derived) {
2657 w.Len(w.dict.rtypeIdx(info))
2658 } else {
2659 w.typInfo(info)
2660 }
2661 }
2662
2663
2664
2665 func (w *writer) varDictIndex(obj *types2.Var) {
2666 info := w.p.typIdx(obj.Type(), w.dict)
2667 if w.Bool(info.derived) {
2668 w.Len(w.dict.rtypeIdx(info))
2669 }
2670 }
2671
2672
2673 func isUntyped(typ types2.Type) bool {
2674
2675 basic, ok := typ.(*types2.Basic)
2676 return ok && basic.Info()&types2.IsUntyped != 0
2677 }
2678
2679
2680 func isTuple(typ types2.Type) bool {
2681
2682 _, ok := typ.(*types2.Tuple)
2683 return ok
2684 }
2685
2686 func (w *writer) itab(typ, iface types2.Type) {
2687 typ = types2.Default(typ)
2688 iface = types2.Default(iface)
2689
2690 typInfo := w.p.typIdx(typ, w.dict)
2691 ifaceInfo := w.p.typIdx(iface, w.dict)
2692
2693 w.rtypeInfo(typInfo)
2694 w.rtypeInfo(ifaceInfo)
2695 if w.Bool(typInfo.derived || ifaceInfo.derived) {
2696 w.Len(w.dict.itabIdx(typInfo, ifaceInfo))
2697 }
2698 }
2699
2700
2701
2702 func (w *writer) convRTTI(src, dst types2.Type) {
2703 w.Sync(pkgbits.SyncConvRTTI)
2704 w.itab(src, dst)
2705 }
2706
2707 func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
2708 base.Assertf(iface == nil || isInterface(iface), "%v must be nil or an interface type", iface)
2709
2710 tv := w.p.typeAndValue(typ)
2711 assert(tv.IsType())
2712
2713 w.Sync(pkgbits.SyncExprType)
2714 w.pos(typ)
2715
2716 if w.Bool(iface != nil && !iface.Underlying().(*types2.Interface).Empty()) {
2717 w.itab(tv.Type, iface)
2718 } else {
2719 w.rtype(tv.Type)
2720
2721 info := w.p.typIdx(tv.Type, w.dict)
2722 w.Bool(info.derived)
2723 }
2724 }
2725
2726
2727
2728
2729 func isInterface(typ types2.Type) bool {
2730 if _, ok := types2.Unalias(typ).(*types2.TypeParam); ok {
2731
2732
2733
2734 base.Fatalf("%v is a type parameter", typ)
2735 }
2736
2737 _, ok := typ.Underlying().(*types2.Interface)
2738 return ok
2739 }
2740
2741
2742
2743 func isConcreteMethod(typ types2.Type) bool {
2744 sig, ok := typ.(*types2.Signature)
2745 return ok && sig.Recv() != nil && !isInterface(sig.Recv().Type())
2746 }
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756 func isGenericMethod(typ types2.Type) bool {
2757 sig, ok := typ.(*types2.Signature)
2758 return ok && sig.Recv() != nil && sig.TypeParams().Len() > 0
2759 }
2760
2761
2762 func (w *writer) op(op ir.Op) {
2763
2764
2765
2766 assert(op != 0)
2767 w.Sync(pkgbits.SyncOp)
2768 w.Len(int(op))
2769 }
2770
2771
2772
2773
2774
2775
2776 type typeDeclGen struct {
2777 *syntax.TypeDecl
2778 gen int
2779
2780
2781 implicits []*types2.TypeParam
2782 }
2783
2784 type fileImports struct {
2785 importedEmbed, importedUnsafe bool
2786 }
2787
2788
2789
2790
2791
2792
2793
2794 type declCollector struct {
2795 pw *pkgWriter
2796 typegen *int
2797 file *fileImports
2798 withinFunc bool
2799 implicits []*types2.TypeParam
2800 }
2801
2802 func (c *declCollector) withTParams(obj types2.Object) *declCollector {
2803 tparams := slices.Concat(objRecvTypeParams(obj), objTypeParams(obj))
2804 if len(tparams) == 0 {
2805 return c
2806 }
2807
2808 copy := *c
2809 copy.implicits = copy.implicits[:len(copy.implicits):len(copy.implicits)]
2810 for _, tparam := range tparams {
2811 copy.implicits = append(copy.implicits, tparam)
2812 }
2813 return ©
2814 }
2815
2816 func (c *declCollector) Visit(n syntax.Node) syntax.Visitor {
2817 pw := c.pw
2818
2819 switch n := n.(type) {
2820 case *syntax.File:
2821 pw.checkPragmas(n.Pragma, ir.GoBuildPragma, false)
2822
2823 case *syntax.ImportDecl:
2824 pw.checkPragmas(n.Pragma, 0, false)
2825
2826 switch pw.info.PkgNameOf(n).Imported().Path() {
2827 case "embed":
2828 c.file.importedEmbed = true
2829 case "unsafe":
2830 c.file.importedUnsafe = true
2831 }
2832
2833 case *syntax.ConstDecl:
2834 pw.checkPragmas(n.Pragma, 0, false)
2835
2836 case *syntax.FuncDecl:
2837 pw.checkPragmas(n.Pragma, funcPragmas, false)
2838
2839 obj := pw.info.Defs[n.Name].(*types2.Func)
2840 pw.funDecls[obj] = n
2841
2842 return c.withTParams(obj)
2843
2844 case *syntax.TypeDecl:
2845 obj := pw.info.Defs[n.Name].(*types2.TypeName)
2846 d := typeDeclGen{TypeDecl: n, implicits: c.implicits}
2847
2848 if n.Alias {
2849 pw.checkPragmas(n.Pragma, 0, false)
2850 } else {
2851 pw.checkPragmas(n.Pragma, 0, false)
2852
2853
2854 if c.withinFunc {
2855 *c.typegen++
2856 d.gen = *c.typegen
2857 }
2858 }
2859
2860 pw.typDecls[obj] = d
2861
2862
2863
2864
2865
2866 return c.withTParams(obj)
2867
2868 case *syntax.VarDecl:
2869 pw.checkPragmas(n.Pragma, 0, true)
2870
2871 if p, ok := n.Pragma.(*pragmas); ok && len(p.Embeds) > 0 {
2872 if err := checkEmbed(n, c.file.importedEmbed, c.withinFunc); err != nil {
2873 pw.errorf(p.Embeds[0].Pos, "%s", err)
2874 }
2875 }
2876
2877 case *syntax.BlockStmt:
2878 if !c.withinFunc {
2879 copy := *c
2880 copy.withinFunc = true
2881 return ©
2882 }
2883 }
2884
2885 return c
2886 }
2887
2888 func (pw *pkgWriter) collectDecls(noders []*noder) {
2889 var typegen int
2890 for _, p := range noders {
2891 var file fileImports
2892
2893 syntax.Walk(p.file, &declCollector{
2894 pw: pw,
2895 typegen: &typegen,
2896 file: &file,
2897 })
2898
2899 pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
2900
2901 for _, l := range p.linknames {
2902 directive := "go:linkname"
2903 if l.std {
2904 directive = "go:linknamestd"
2905 }
2906 if !file.importedUnsafe {
2907 pw.errorf(l.pos, "//%s only allowed in Go files that import \"unsafe\"", directive)
2908 continue
2909 }
2910 if strings.Contains(l.remote, "[") && strings.Contains(l.remote, "]") {
2911 pw.errorf(l.pos, "//%s reference of an instantiation is not allowed", directive)
2912 continue
2913 }
2914
2915 switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
2916 case *types2.Func, *types2.Var:
2917 if _, ok := pw.linknames[obj]; !ok {
2918 pw.linknames[obj] = struct {
2919 remote string
2920 std bool
2921 }{l.remote, l.std}
2922 } else {
2923 pw.errorf(l.pos, "duplicate //%s for %s", directive, l.local)
2924 }
2925
2926 default:
2927 if types.AllowsGoVersion(1, 18) {
2928 pw.errorf(l.pos, "//%s must refer to declared function or variable", directive)
2929 }
2930 }
2931 }
2932 }
2933 }
2934
2935 func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedOK bool) {
2936 if p == nil {
2937 return
2938 }
2939 pragma := p.(*pragmas)
2940
2941 for _, pos := range pragma.Pos {
2942 if pos.Flag&^allowed != 0 {
2943 pw.errorf(pos.Pos, "misplaced compiler directive")
2944 }
2945 }
2946
2947 if !embedOK {
2948 for _, e := range pragma.Embeds {
2949 pw.errorf(e.Pos, "misplaced go:embed directive")
2950 }
2951 }
2952 }
2953
2954 func (w *writer) pkgInit(noders []*noder) {
2955 w.Len(len(w.p.cgoPragmas))
2956 for _, cgoPragma := range w.p.cgoPragmas {
2957 w.Strings(cgoPragma)
2958 }
2959
2960 w.pkgInitOrder()
2961
2962 w.Sync(pkgbits.SyncDecls)
2963 for _, p := range noders {
2964 for _, decl := range p.file.DeclList {
2965 w.pkgDecl(decl)
2966 }
2967 }
2968 w.Code(declEnd)
2969
2970 w.Sync(pkgbits.SyncEOF)
2971 }
2972
2973 func (w *writer) pkgInitOrder() {
2974
2975 w.Len(len(w.p.info.InitOrder))
2976 for _, init := range w.p.info.InitOrder {
2977 w.Len(len(init.Lhs))
2978 for _, v := range init.Lhs {
2979 w.obj(v, nil)
2980 }
2981 w.expr(init.Rhs)
2982 }
2983 }
2984
2985 func (w *writer) pkgDecl(decl syntax.Decl) {
2986 switch decl := decl.(type) {
2987 default:
2988 w.p.unexpected("declaration", decl)
2989
2990 case *syntax.ImportDecl:
2991
2992 case *syntax.ConstDecl:
2993 w.Code(declOther)
2994 w.pkgObjs(decl.NameList...)
2995
2996 case *syntax.FuncDecl:
2997 if decl.Name.Value == "_" {
2998 break
2999 }
3000
3001 obj := w.p.info.Defs[decl.Name].(*types2.Func)
3002 sig := obj.Type().(*types2.Signature)
3003
3004 if sig.RecvTypeParams() != nil || sig.TypeParams() != nil {
3005 break
3006 }
3007
3008 if recv := sig.Recv(); recv != nil {
3009 w.Code(declMethod)
3010 w.typ(recvBase(recv))
3011 w.selector(obj)
3012 break
3013 }
3014
3015 w.Code(declFunc)
3016 w.pkgObjs(decl.Name)
3017
3018 case *syntax.TypeDecl:
3019 if len(decl.TParamList) != 0 {
3020 break
3021 }
3022
3023 if decl.Name.Value == "_" {
3024 break
3025 }
3026
3027 name := w.p.info.Defs[decl.Name].(*types2.TypeName)
3028
3029
3030 if iface, ok := name.Type().Underlying().(*types2.Interface); ok && !iface.IsMethodSet() {
3031 break
3032 }
3033
3034 w.Code(declOther)
3035 w.pkgObjs(decl.Name)
3036
3037 case *syntax.VarDecl:
3038 w.Code(declVar)
3039 w.pkgObjs(decl.NameList...)
3040
3041 var embeds []pragmaEmbed
3042 if p, ok := decl.Pragma.(*pragmas); ok {
3043 embeds = p.Embeds
3044 }
3045 w.Len(len(embeds))
3046 for _, embed := range embeds {
3047 w.pos(embed.Pos)
3048 w.Strings(embed.Patterns)
3049 }
3050 }
3051 }
3052
3053 func (w *writer) pkgObjs(names ...*syntax.Name) {
3054 w.Sync(pkgbits.SyncDeclNames)
3055 w.Len(len(names))
3056
3057 for _, name := range names {
3058 obj, ok := w.p.info.Defs[name]
3059 assert(ok)
3060
3061 w.Sync(pkgbits.SyncDeclName)
3062 w.obj(obj, nil)
3063 }
3064 }
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074 func (pw *pkgWriter) staticBool(ep *syntax.Expr) int {
3075 if val := pw.typeAndValue(*ep).Value; val != nil {
3076 if constant.BoolVal(val) {
3077 return +1
3078 } else {
3079 return -1
3080 }
3081 }
3082
3083 if e, ok := (*ep).(*syntax.Operation); ok {
3084 switch e.Op {
3085 case syntax.Not:
3086 return pw.staticBool(&e.X)
3087
3088 case syntax.AndAnd:
3089 x := pw.staticBool(&e.X)
3090 if x < 0 {
3091 *ep = e.X
3092 return x
3093 }
3094
3095 y := pw.staticBool(&e.Y)
3096 if x > 0 || y < 0 {
3097 if pw.typeAndValue(e.X).Value != nil {
3098 *ep = e.Y
3099 }
3100 return y
3101 }
3102
3103 case syntax.OrOr:
3104 x := pw.staticBool(&e.X)
3105 if x > 0 {
3106 *ep = e.X
3107 return x
3108 }
3109
3110 y := pw.staticBool(&e.Y)
3111 if x < 0 || y > 0 {
3112 if pw.typeAndValue(e.X).Value != nil {
3113 *ep = e.Y
3114 }
3115 return y
3116 }
3117 }
3118 }
3119
3120 return 0
3121 }
3122
3123
3124
3125
3126 func (pw *pkgWriter) hasImplicitTypeParams(obj *types2.TypeName) bool {
3127 if obj.Pkg() == pw.curpkg {
3128 decl, ok := pw.typDecls[obj]
3129 assert(ok)
3130 if len(decl.implicits) != 0 {
3131 return true
3132 }
3133 }
3134 return false
3135 }
3136
3137
3138 func isDefinedType(obj types2.Object) bool {
3139 if obj, ok := obj.(*types2.TypeName); ok {
3140 return !obj.IsAlias()
3141 }
3142 return false
3143 }
3144
3145
3146
3147
3148 func isGlobal(obj types2.Object) bool {
3149 return obj.Parent() == obj.Pkg().Scope()
3150 }
3151
3152
3153
3154
3155 func lookupObj(p *pkgWriter, expr syntax.Expr) (obj types2.Object, inst types2.Instance) {
3156 if index, ok := expr.(*syntax.IndexExpr); ok {
3157 args := syntax.UnpackListExpr(index.Index)
3158 if len(args) == 1 {
3159 tv := p.typeAndValue(args[0])
3160 if tv.IsValue() {
3161 return
3162 }
3163 }
3164
3165 expr = index.X
3166 }
3167
3168
3169 if sel, ok := expr.(*syntax.SelectorExpr); ok {
3170 if !isPkgQual(p.info, sel) {
3171 return
3172 }
3173 expr = sel.Sel
3174 }
3175
3176 if name, ok := expr.(*syntax.Name); ok {
3177 obj = p.info.Uses[name]
3178 inst = p.info.Instances[name]
3179 }
3180 return
3181 }
3182
3183
3184
3185 func isPkgQual(info *types2.Info, sel *syntax.SelectorExpr) bool {
3186 if name, ok := sel.X.(*syntax.Name); ok {
3187 _, isPkgName := info.Uses[name].(*types2.PkgName)
3188 return isPkgName
3189 }
3190 return false
3191 }
3192
3193
3194
3195 func isNil(p *pkgWriter, expr syntax.Expr) bool {
3196 tv := p.typeAndValue(expr)
3197 return tv.IsNil()
3198 }
3199
3200
3201
3202 func (pw *pkgWriter) isBuiltin(expr syntax.Expr, builtin string) bool {
3203 if name, ok := syntax.Unparen(expr).(*syntax.Name); ok && name.Value == builtin {
3204 return pw.typeAndValue(name).IsBuiltin()
3205 }
3206 return false
3207 }
3208
3209
3210 func recvBase(recv *types2.Var) *types2.Named {
3211 typ := types2.Unalias(recv.Type())
3212 if ptr, ok := typ.(*types2.Pointer); ok {
3213 typ = types2.Unalias(ptr.Elem())
3214 }
3215 return typ.(*types2.Named)
3216 }
3217
3218
3219 func namesAsExpr(names []*syntax.Name) syntax.Expr {
3220 if len(names) == 1 {
3221 return names[0]
3222 }
3223
3224 exprs := make([]syntax.Expr, len(names))
3225 for i, name := range names {
3226 exprs[i] = name
3227 }
3228 return &syntax.ListExpr{ElemList: exprs}
3229 }
3230
3231
3232 func fieldIndex(info *types2.Info, str *types2.Struct, key *syntax.Name) int {
3233 field := info.Uses[key].(*types2.Var)
3234
3235 for i := 0; i < str.NumFields(); i++ {
3236 if str.Field(i) == field {
3237 return i
3238 }
3239 }
3240
3241 panic(fmt.Sprintf("%s: %v is not a field of %v", key.Pos(), field, str))
3242 }
3243
3244
3245 func objRecvTypeParams(obj types2.Object) []*types2.TypeParam {
3246 if f, ok := obj.(*types2.Func); ok {
3247 return asTypeParamSlice(f.Signature().RecvTypeParams())
3248 }
3249 return nil
3250 }
3251
3252
3253 func objTypeParams(obj types2.Object) []*types2.TypeParam {
3254 switch t := obj.(type) {
3255 case *types2.Func:
3256 return asTypeParamSlice(t.Signature().TypeParams())
3257 case *types2.TypeName:
3258 switch t := obj.Type().(type) {
3259 case *types2.Named:
3260 return asTypeParamSlice(t.TypeParams())
3261 case *types2.Alias:
3262 return asTypeParamSlice(t.TypeParams())
3263 }
3264 }
3265 return nil
3266 }
3267
3268
3269 func asTypeParamSlice(l *types2.TypeParamList) []*types2.TypeParam {
3270 if l.Len() == 0 {
3271 return nil
3272 }
3273 s := make([]*types2.TypeParam, l.Len())
3274 for i := range l.Len() {
3275 s[i] = l.At(i)
3276 }
3277 return s
3278 }
3279
3280
3281
3282 func splitNamed(typ *types2.Named) (*types2.TypeName, []types2.Type) {
3283 base.Assertf(typ.TypeParams().Len() == typ.TypeArgs().Len(), "use of uninstantiated type: %v", typ)
3284
3285 orig := typ.Origin()
3286 base.Assertf(orig.TypeArgs() == nil, "origin %v of %v has type arguments", orig, typ)
3287 base.Assertf(typ.Obj() == orig.Obj(), "%v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())
3288
3289 return typ.Obj(), asTypeSlice(typ.TypeArgs())
3290 }
3291
3292
3293 func splitAlias(typ *types2.Alias) (*types2.TypeName, []types2.Type) {
3294 orig := typ.Origin()
3295 base.Assertf(typ.Obj() == orig.Obj(), "alias type %v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj())
3296
3297 return typ.Obj(), asTypeSlice(typ.TypeArgs())
3298 }
3299
3300
3301 func asTypeSlice(l *types2.TypeList) []types2.Type {
3302 if l.Len() == 0 {
3303 return nil
3304 }
3305 s := make([]types2.Type, l.Len())
3306 for i := range l.Len() {
3307 s[i] = l.At(i)
3308 }
3309 return s
3310 }
3311
3312 func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag {
3313 if p == nil {
3314 return 0
3315 }
3316 return p.(*pragmas).Flag
3317 }
3318
3319 func asWasmImport(p syntax.Pragma) *WasmImport {
3320 if p == nil {
3321 return nil
3322 }
3323 return p.(*pragmas).WasmImport
3324 }
3325
3326 func asWasmExport(p syntax.Pragma) *WasmExport {
3327 if p == nil {
3328 return nil
3329 }
3330 return p.(*pragmas).WasmExport
3331 }
3332
3333
3334 func isPtrTo(from, to types2.Type) bool {
3335 ptr, ok := types2.Unalias(from).(*types2.Pointer)
3336 return ok && types2.Identical(ptr.Elem(), to)
3337 }
3338
3339
3340
3341 func hasFallthrough(stmts []syntax.Stmt) bool {
3342
3343
3344 stmt := lastNonEmptyStmt(stmts)
3345 for {
3346 ls, ok := stmt.(*syntax.LabeledStmt)
3347 if !ok {
3348 break
3349 }
3350 stmt = ls.Stmt
3351 }
3352 last, ok := stmt.(*syntax.BranchStmt)
3353 return ok && last.Tok == syntax.Fallthrough
3354 }
3355
3356
3357
3358 func lastNonEmptyStmt(stmts []syntax.Stmt) syntax.Stmt {
3359 for i := len(stmts) - 1; i >= 0; i-- {
3360 stmt := stmts[i]
3361 if _, ok := stmt.(*syntax.EmptyStmt); !ok {
3362 return stmt
3363 }
3364 }
3365 return nil
3366 }
3367
3368
3369
3370 func (pw *pkgWriter) terminates(stmt syntax.Stmt) bool {
3371 switch stmt := stmt.(type) {
3372 case *syntax.BranchStmt:
3373 if stmt.Tok == syntax.Goto {
3374 return true
3375 }
3376 case *syntax.ReturnStmt:
3377 return true
3378 case *syntax.ExprStmt:
3379 if call, ok := syntax.Unparen(stmt.X).(*syntax.CallExpr); ok {
3380 if pw.isBuiltin(call.Fun, "panic") {
3381 return true
3382 }
3383 }
3384
3385
3386
3387
3388
3389
3390
3391
3392 case *syntax.IfStmt:
3393 cond := pw.staticBool(&stmt.Cond)
3394 return (cond < 0 || pw.terminates(stmt.Then)) && (cond > 0 || pw.terminates(stmt.Else))
3395 case *syntax.BlockStmt:
3396 return pw.terminates(lastNonEmptyStmt(stmt.List))
3397 }
3398
3399 return false
3400 }
3401
View as plain text