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