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