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