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