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