1
2
3
4
5 package reflectdata
6
7 import (
8 "encoding/binary"
9 "fmt"
10 "internal/abi"
11 "internal/buildcfg"
12 "os"
13 "slices"
14 "sort"
15 "strings"
16 "sync"
17
18 "cmd/compile/internal/base"
19 "cmd/compile/internal/bitvec"
20 "cmd/compile/internal/compare"
21 "cmd/compile/internal/ir"
22 "cmd/compile/internal/objw"
23 "cmd/compile/internal/rttype"
24 "cmd/compile/internal/staticdata"
25 "cmd/compile/internal/typebits"
26 "cmd/compile/internal/typecheck"
27 "cmd/compile/internal/types"
28 "cmd/internal/gcprog"
29 "cmd/internal/obj"
30 "cmd/internal/objabi"
31 "cmd/internal/src"
32 )
33
34 type ptabEntry struct {
35 s *types.Sym
36 t *types.Type
37 }
38
39
40 var (
41
42 signatmu sync.Mutex
43
44 signatset = make(map[*types.Type]struct{})
45
46 signatslice []typeAndStr
47
48 gcsymmu sync.Mutex
49 gcsymset = make(map[*types.Type]struct{})
50 )
51
52 type typeSig struct {
53 name *types.Sym
54 isym *obj.LSym
55 tsym *obj.LSym
56 type_ *types.Type
57 mtype *types.Type
58 }
59
60 func commonSize() int { return int(rttype.Type.Size()) }
61
62 func uncommonSize(t *types.Type) int {
63 if t.Sym() == nil && len(methods(t)) == 0 {
64 return 0
65 }
66 return int(rttype.UncommonType.Size())
67 }
68
69 func makefield(name string, t *types.Type) *types.Field {
70 sym := (*types.Pkg)(nil).Lookup(name)
71 return types.NewField(src.NoXPos, sym, t)
72 }
73
74
75
76 func methods(t *types.Type) []*typeSig {
77 if t.HasShape() {
78
79 return nil
80 }
81
82 mt := types.ReceiverBaseType(t)
83
84 if mt == nil {
85 return nil
86 }
87 typecheck.CalcMethods(mt)
88
89
90
91 var ms []*typeSig
92 for _, f := range mt.AllMethods() {
93 if f.Sym == nil {
94 base.Fatalf("method with no sym on %v", mt)
95 }
96 if !f.IsMethod() {
97 base.Fatalf("non-method on %v method %v %v", mt, f.Sym, f)
98 }
99 if f.Type.Recv() == nil {
100 base.Fatalf("receiver with no type on %v method %v %v", mt, f.Sym, f)
101 }
102 if f.Nointerface() && !t.IsFullyInstantiated() {
103
104
105
106
107 continue
108 }
109
110
111
112
113
114 if !types.IsMethodApplicable(t, f) {
115 continue
116 }
117
118 sig := &typeSig{
119 name: f.Sym,
120 isym: methodWrapper(t, f, true),
121 tsym: methodWrapper(t, f, false),
122 type_: typecheck.NewMethodType(f.Type, t),
123 mtype: typecheck.NewMethodType(f.Type, nil),
124 }
125 if f.Nointerface() {
126
127
128 continue
129 }
130 ms = append(ms, sig)
131 }
132
133 return ms
134 }
135
136
137 func imethods(t *types.Type) []*typeSig {
138 var methods []*typeSig
139 for _, f := range t.AllMethods() {
140 if f.Type.Kind() != types.TFUNC || f.Sym == nil {
141 continue
142 }
143 if f.Sym.IsBlank() {
144 base.Fatalf("unexpected blank symbol in interface method set")
145 }
146 if n := len(methods); n > 0 {
147 last := methods[n-1]
148 if !last.name.Less(f.Sym) {
149 base.Fatalf("sigcmp vs sortinter %v %v", last.name, f.Sym)
150 }
151 }
152
153 sig := &typeSig{
154 name: f.Sym,
155 mtype: f.Type,
156 type_: typecheck.NewMethodType(f.Type, nil),
157 }
158 methods = append(methods, sig)
159
160
161
162
163
164 methodWrapper(t, f, false)
165 }
166
167 return methods
168 }
169
170 func dimportpath(p *types.Pkg) {
171 if p.Pathsym != nil {
172 return
173 }
174
175 if p == types.LocalPkg && base.Ctxt.Pkgpath == "" {
176 panic("missing pkgpath")
177 }
178
179
180
181
182 if base.Ctxt.Pkgpath == "runtime" && p == ir.Pkgs.Runtime {
183 return
184 }
185
186 s := base.Ctxt.Lookup("type:.importpath." + p.Prefix + ".")
187 ot := dnameData(s, 0, p.Path, "", nil, false, false)
188 objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
189 s.Set(obj.AttrContentAddressable, true)
190 p.Pathsym = s
191 }
192
193 func dgopkgpath(c rttype.Cursor, pkg *types.Pkg) {
194 c = c.Field("Bytes")
195 if pkg == nil {
196 c.WritePtr(nil)
197 return
198 }
199
200 dimportpath(pkg)
201 c.WritePtr(pkg.Pathsym)
202 }
203
204
205 func dgopkgpathOff(c rttype.Cursor, pkg *types.Pkg) {
206 if pkg == nil {
207 c.WriteInt32(0)
208 return
209 }
210
211 dimportpath(pkg)
212 c.WriteSymPtrOff(pkg.Pathsym, false)
213 }
214
215
216 func dnameField(c rttype.Cursor, spkg *types.Pkg, ft *types.Field) {
217 if !types.IsExported(ft.Sym.Name) && ft.Sym.Pkg != spkg {
218 base.Fatalf("package mismatch for %v", ft.Sym)
219 }
220 nsym := dname(ft.Sym.Name, ft.Note, nil, types.IsExported(ft.Sym.Name), ft.Embedded != 0)
221 c.Field("Bytes").WritePtr(nsym)
222 }
223
224
225 func dnameData(s *obj.LSym, ot int, name, tag string, pkg *types.Pkg, exported, embedded bool) int {
226 if len(name) >= 1<<29 {
227 base.Fatalf("name too long: %d %s...", len(name), name[:1024])
228 }
229 if len(tag) >= 1<<29 {
230 base.Fatalf("tag too long: %d %s...", len(tag), tag[:1024])
231 }
232 var nameLen [binary.MaxVarintLen64]byte
233 nameLenLen := binary.PutUvarint(nameLen[:], uint64(len(name)))
234 var tagLen [binary.MaxVarintLen64]byte
235 tagLenLen := binary.PutUvarint(tagLen[:], uint64(len(tag)))
236
237
238 var bits byte
239 l := 1 + nameLenLen + len(name)
240 if exported {
241 bits |= 1 << 0
242 }
243 if len(tag) > 0 {
244 l += tagLenLen + len(tag)
245 bits |= 1 << 1
246 }
247 if pkg != nil {
248 bits |= 1 << 2
249 }
250 if embedded {
251 bits |= 1 << 3
252 }
253 b := make([]byte, l)
254 b[0] = bits
255 copy(b[1:], nameLen[:nameLenLen])
256 copy(b[1+nameLenLen:], name)
257 if len(tag) > 0 {
258 tb := b[1+nameLenLen+len(name):]
259 copy(tb, tagLen[:tagLenLen])
260 copy(tb[tagLenLen:], tag)
261 }
262
263 ot = int(s.WriteBytes(base.Ctxt, int64(ot), b))
264
265 if pkg != nil {
266 c := rttype.NewCursor(s, int64(ot), types.Types[types.TUINT32])
267 dgopkgpathOff(c, pkg)
268 ot += 4
269 }
270
271 return ot
272 }
273
274 var dnameCount int
275
276
277 func dname(name, tag string, pkg *types.Pkg, exported, embedded bool) *obj.LSym {
278
279
280
281
282 sname := "type:.namedata."
283 if pkg == nil {
284
285 if name == "" {
286 if exported {
287 sname += "-noname-exported." + tag
288 } else {
289 sname += "-noname-unexported." + tag
290 }
291 } else {
292 if exported {
293 sname += name + "." + tag
294 } else {
295 sname += name + "-" + tag
296 }
297 }
298 } else {
299
300
301 sname = fmt.Sprintf("%s%s.%d", sname, types.LocalPkg.Prefix, dnameCount)
302 dnameCount++
303 }
304 if embedded {
305 sname += ".embedded"
306 }
307 s := base.Ctxt.Lookup(sname)
308 if len(s.P) > 0 {
309 return s
310 }
311 ot := dnameData(s, 0, name, tag, pkg, exported, embedded)
312 objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
313 s.Set(obj.AttrContentAddressable, true)
314 return s
315 }
316
317
318
319
320 func dextratype(lsym *obj.LSym, off int64, t *types.Type, dataAdd int) {
321 m := methods(t)
322 if t.Sym() == nil && len(m) == 0 {
323 base.Fatalf("extra requested of type with no extra info %v", t)
324 }
325 noff := types.RoundUp(off, int64(types.PtrSize))
326 if noff != off {
327 base.Fatalf("unexpected alignment in dextratype for %v", t)
328 }
329
330 for _, a := range m {
331 writeType(a.type_)
332 }
333
334 c := rttype.NewCursor(lsym, off, rttype.UncommonType)
335 dgopkgpathOff(c.Field("PkgPath"), typePkg(t))
336
337 dataAdd += uncommonSize(t)
338 mcount := len(m)
339 if mcount != int(uint16(mcount)) {
340 base.Fatalf("too many methods on %v: %d", t, mcount)
341 }
342 xcount := sort.Search(mcount, func(i int) bool { return !types.IsExported(m[i].name.Name) })
343 if dataAdd != int(uint32(dataAdd)) {
344 base.Fatalf("methods are too far away on %v: %d", t, dataAdd)
345 }
346
347 c.Field("Mcount").WriteUint16(uint16(mcount))
348 c.Field("Xcount").WriteUint16(uint16(xcount))
349 c.Field("Moff").WriteUint32(uint32(dataAdd))
350
351
352
353 array := rttype.NewArrayCursor(lsym, off+int64(dataAdd), rttype.Method, mcount)
354 for i, a := range m {
355 exported := types.IsExported(a.name.Name)
356 var pkg *types.Pkg
357 if !exported && a.name.Pkg != typePkg(t) {
358 pkg = a.name.Pkg
359 }
360 nsym := dname(a.name.Name, "", pkg, exported, false)
361
362 e := array.Elem(i)
363 e.Field("Name").WriteSymPtrOff(nsym, false)
364 dmethodptrOff(e.Field("Mtyp"), writeType(a.mtype))
365 dmethodptrOff(e.Field("Ifn"), a.isym)
366 dmethodptrOff(e.Field("Tfn"), a.tsym)
367 }
368 }
369
370 func typePkg(t *types.Type) *types.Pkg {
371 tsym := t.Sym()
372 if tsym == nil {
373 switch t.Kind() {
374 case types.TARRAY, types.TSLICE, types.TPTR, types.TCHAN:
375 if t.Elem() != nil {
376 tsym = t.Elem().Sym()
377 }
378 }
379 }
380 if tsym != nil && tsym.Pkg != types.BuiltinPkg {
381 return tsym.Pkg
382 }
383 return nil
384 }
385
386 func dmethodptrOff(c rttype.Cursor, x *obj.LSym) {
387 c.WriteInt32(0)
388 c.Reloc(obj.Reloc{Type: objabi.R_METHODOFF, Sym: x})
389 }
390
391 var kinds = []abi.Kind{
392 types.TINT: abi.Int,
393 types.TUINT: abi.Uint,
394 types.TINT8: abi.Int8,
395 types.TUINT8: abi.Uint8,
396 types.TINT16: abi.Int16,
397 types.TUINT16: abi.Uint16,
398 types.TINT32: abi.Int32,
399 types.TUINT32: abi.Uint32,
400 types.TINT64: abi.Int64,
401 types.TUINT64: abi.Uint64,
402 types.TUINTPTR: abi.Uintptr,
403 types.TFLOAT32: abi.Float32,
404 types.TFLOAT64: abi.Float64,
405 types.TBOOL: abi.Bool,
406 types.TSTRING: abi.String,
407 types.TPTR: abi.Pointer,
408 types.TSTRUCT: abi.Struct,
409 types.TINTER: abi.Interface,
410 types.TCHAN: abi.Chan,
411 types.TMAP: abi.Map,
412 types.TARRAY: abi.Array,
413 types.TSLICE: abi.Slice,
414 types.TFUNC: abi.Func,
415 types.TCOMPLEX64: abi.Complex64,
416 types.TCOMPLEX128: abi.Complex128,
417 types.TUNSAFEPTR: abi.UnsafePointer,
418 }
419
420 var (
421 memhashvarlen *obj.LSym
422 memequalvarlen *obj.LSym
423 )
424
425
426 func dcommontype(c rttype.Cursor, t *types.Type) {
427 types.CalcSize(t)
428 eqfunc := geneq(t)
429
430 sptrWeak := true
431 var sptr *obj.LSym
432 if !t.IsPtr() || t.IsPtrElem() {
433 tptr := types.NewPtr(t)
434 if t.Sym() != nil || methods(tptr) != nil {
435 sptrWeak = false
436 }
437 sptr = writeType(tptr)
438 }
439
440 gcsym, useGCProg, ptrdata := dgcsym(t, true)
441 delete(gcsymset, t)
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458 c.Field("Size_").WriteUintptr(uint64(t.Size()))
459 c.Field("PtrBytes").WriteUintptr(uint64(ptrdata))
460 c.Field("Hash").WriteUint32(types.TypeHash(t))
461
462 var tflag abi.TFlag
463 if uncommonSize(t) != 0 {
464 tflag |= abi.TFlagUncommon
465 }
466 if t.Sym() != nil && t.Sym().Name != "" {
467 tflag |= abi.TFlagNamed
468 }
469 if compare.IsRegularMemory(t) {
470 tflag |= abi.TFlagRegularMemory
471 }
472
473 exported := false
474 p := t.NameString()
475
476
477
478
479
480 if !strings.HasPrefix(p, "*") {
481 p = "*" + p
482 tflag |= abi.TFlagExtraStar
483 if t.Sym() != nil {
484 exported = types.IsExported(t.Sym().Name)
485 }
486 } else {
487 if t.Elem() != nil && t.Elem().Sym() != nil {
488 exported = types.IsExported(t.Elem().Sym().Name)
489 }
490 }
491
492 if tflag != abi.TFlag(uint8(tflag)) {
493
494 panic("Unexpected change in size of abi.TFlag")
495 }
496 c.Field("TFlag").WriteUint8(uint8(tflag))
497
498
499 i := int(uint8(t.Alignment()))
500
501 if i == 0 {
502 i = 1
503 }
504 if i&(i-1) != 0 {
505 base.Fatalf("invalid alignment %d for %v", uint8(t.Alignment()), t)
506 }
507 c.Field("Align_").WriteUint8(uint8(t.Alignment()))
508 c.Field("FieldAlign_").WriteUint8(uint8(t.Alignment()))
509
510 kind := kinds[t.Kind()]
511 if types.IsDirectIface(t) {
512 kind |= abi.KindDirectIface
513 }
514 if useGCProg {
515 kind |= abi.KindGCProg
516 }
517 c.Field("Kind_").WriteUint8(uint8(kind))
518
519 c.Field("Equal").WritePtr(eqfunc)
520 c.Field("GCData").WritePtr(gcsym)
521
522 nsym := dname(p, "", nil, exported, false)
523 c.Field("Str").WriteSymPtrOff(nsym, false)
524 c.Field("PtrToThis").WriteSymPtrOff(sptr, sptrWeak)
525 }
526
527
528
529 func TrackSym(t *types.Type, f *types.Field) *obj.LSym {
530 return base.PkgLinksym("go:track", t.LinkString()+"."+f.Sym.Name, obj.ABI0)
531 }
532
533 func TypeSymPrefix(prefix string, t *types.Type) *types.Sym {
534 p := prefix + "." + t.LinkString()
535 s := types.TypeSymLookup(p)
536
537
538
539 signatmu.Lock()
540 NeedRuntimeType(t)
541 signatmu.Unlock()
542
543
544
545 return s
546 }
547
548 func TypeSym(t *types.Type) *types.Sym {
549 if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
550 base.Fatalf("TypeSym %v", t)
551 }
552 if t.Kind() == types.TFUNC && t.Recv() != nil {
553 base.Fatalf("misuse of method type: %v", t)
554 }
555 s := types.TypeSym(t)
556 signatmu.Lock()
557 NeedRuntimeType(t)
558 signatmu.Unlock()
559 return s
560 }
561
562 func TypeLinksymPrefix(prefix string, t *types.Type) *obj.LSym {
563 return TypeSymPrefix(prefix, t).Linksym()
564 }
565
566 func TypeLinksymLookup(name string) *obj.LSym {
567 return types.TypeSymLookup(name).Linksym()
568 }
569
570 func TypeLinksym(t *types.Type) *obj.LSym {
571 lsym := TypeSym(t).Linksym()
572 signatmu.Lock()
573 if lsym.Extra == nil {
574 ti := lsym.NewTypeInfo()
575 ti.Type = t
576 }
577 signatmu.Unlock()
578 return lsym
579 }
580
581
582
583 func TypePtrAt(pos src.XPos, t *types.Type) *ir.AddrExpr {
584 return typecheck.LinksymAddr(pos, TypeLinksym(t), types.Types[types.TUINT8])
585 }
586
587
588
589
590
591
592
593
594 func ITabLsym(typ, iface *types.Type) *obj.LSym {
595 s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString())
596 lsym := s.Linksym()
597
598 if !existed {
599 writeITab(lsym, typ, iface, true)
600 }
601 return lsym
602 }
603
604
605
606
607 func ITabAddrAt(pos src.XPos, typ, iface *types.Type) *ir.AddrExpr {
608 s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString())
609 lsym := s.Linksym()
610
611 if !existed {
612 writeITab(lsym, typ, iface, false)
613 }
614
615 return typecheck.LinksymAddr(pos, lsym, types.Types[types.TUINT8])
616 }
617
618
619
620 func needkeyupdate(t *types.Type) bool {
621 switch t.Kind() {
622 case types.TBOOL, types.TINT, types.TUINT, types.TINT8, types.TUINT8, types.TINT16, types.TUINT16, types.TINT32, types.TUINT32,
623 types.TINT64, types.TUINT64, types.TUINTPTR, types.TPTR, types.TUNSAFEPTR, types.TCHAN:
624 return false
625
626 case types.TFLOAT32, types.TFLOAT64, types.TCOMPLEX64, types.TCOMPLEX128,
627 types.TINTER,
628 types.TSTRING:
629 return true
630
631 case types.TARRAY:
632 return needkeyupdate(t.Elem())
633
634 case types.TSTRUCT:
635 for _, t1 := range t.Fields() {
636 if needkeyupdate(t1.Type) {
637 return true
638 }
639 }
640 return false
641
642 default:
643 base.Fatalf("bad type for map key: %v", t)
644 return true
645 }
646 }
647
648
649 func hashMightPanic(t *types.Type) bool {
650 switch t.Kind() {
651 case types.TINTER:
652 return true
653
654 case types.TARRAY:
655 return hashMightPanic(t.Elem())
656
657 case types.TSTRUCT:
658 for _, t1 := range t.Fields() {
659 if hashMightPanic(t1.Type) {
660 return true
661 }
662 }
663 return false
664
665 default:
666 return false
667 }
668 }
669
670
671
672
673 func formalType(t *types.Type) *types.Type {
674 switch t {
675 case types.AnyType, types.ByteType, types.RuneType:
676 return types.Types[t.Kind()]
677 }
678 return t
679 }
680
681 func writeType(t *types.Type) *obj.LSym {
682 t = formalType(t)
683 if t.IsUntyped() {
684 base.Fatalf("writeType %v", t)
685 }
686
687 s := types.TypeSym(t)
688 lsym := s.Linksym()
689
690
691
692
693 tbase := t
694 if t.IsPtr() && t.Sym() == nil && t.Elem().Sym() != nil {
695 tbase = t.Elem()
696 }
697 if tbase.Kind() == types.TFORW {
698 base.Fatalf("unresolved defined type: %v", tbase)
699 }
700
701
702
703
704
705 if sym := tbase.Sym(); sym != nil && sym.Pkg == ir.Pkgs.Runtime {
706 return lsym
707 }
708
709 if s.Siggen() {
710 return lsym
711 }
712 s.SetSiggen(true)
713
714 if !NeedEmit(tbase) {
715 if i := typecheck.BaseTypeIndex(t); i >= 0 {
716 lsym.Pkg = tbase.Sym().Pkg.Prefix
717 lsym.SymIdx = int32(i)
718 lsym.Set(obj.AttrIndexed, true)
719 }
720
721
722
723
724
725 return lsym
726 }
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750 extra := t.Sym() != nil || len(methods(t)) != 0
751
752
753
754 var rt *types.Type
755 dataAdd := 0
756 switch t.Kind() {
757 default:
758 rt = rttype.Type
759 case types.TARRAY:
760 rt = rttype.ArrayType
761 case types.TSLICE:
762 rt = rttype.SliceType
763 case types.TCHAN:
764 rt = rttype.ChanType
765 case types.TFUNC:
766 rt = rttype.FuncType
767 dataAdd = (t.NumRecvs() + t.NumParams() + t.NumResults()) * types.PtrSize
768 case types.TINTER:
769 rt = rttype.InterfaceType
770 dataAdd = len(imethods(t)) * int(rttype.IMethod.Size())
771 case types.TMAP:
772 if buildcfg.Experiment.SwissMap {
773 rt = rttype.SwissMapType
774 } else {
775 rt = rttype.OldMapType
776 }
777 case types.TPTR:
778 rt = rttype.PtrType
779
780 case types.TSTRUCT:
781 rt = rttype.StructType
782 dataAdd = t.NumFields() * int(rttype.StructField.Size())
783 }
784
785
786 B := rt.Size()
787 C := B
788 if extra {
789 C = B + rttype.UncommonType.Size()
790 }
791 D := C + int64(dataAdd)
792 E := D + int64(len(methods(t)))*rttype.Method.Size()
793
794
795 c := rttype.NewCursor(lsym, 0, rt)
796 if rt == rttype.Type {
797 dcommontype(c, t)
798 } else {
799 dcommontype(c.Field("Type"), t)
800 }
801
802
803
804 switch t.Kind() {
805 case types.TARRAY:
806
807 s1 := writeType(t.Elem())
808 t2 := types.NewSlice(t.Elem())
809 s2 := writeType(t2)
810 c.Field("Elem").WritePtr(s1)
811 c.Field("Slice").WritePtr(s2)
812 c.Field("Len").WriteUintptr(uint64(t.NumElem()))
813
814 case types.TSLICE:
815
816 s1 := writeType(t.Elem())
817 c.Field("Elem").WritePtr(s1)
818
819 case types.TCHAN:
820
821 s1 := writeType(t.Elem())
822 c.Field("Elem").WritePtr(s1)
823 c.Field("Dir").WriteInt(int64(t.ChanDir()))
824
825 case types.TFUNC:
826
827 for _, t1 := range t.RecvParamsResults() {
828 writeType(t1.Type)
829 }
830 inCount := t.NumRecvs() + t.NumParams()
831 outCount := t.NumResults()
832 if t.IsVariadic() {
833 outCount |= 1 << 15
834 }
835
836 c.Field("InCount").WriteUint16(uint16(inCount))
837 c.Field("OutCount").WriteUint16(uint16(outCount))
838
839
840 typs := t.RecvParamsResults()
841 array := rttype.NewArrayCursor(lsym, C, types.Types[types.TUNSAFEPTR], len(typs))
842 for i, t1 := range typs {
843 array.Elem(i).WritePtr(writeType(t1.Type))
844 }
845
846 case types.TINTER:
847
848 m := imethods(t)
849 n := len(m)
850 for _, a := range m {
851 writeType(a.type_)
852 }
853
854 var tpkg *types.Pkg
855 if t.Sym() != nil && t != types.Types[t.Kind()] && t != types.ErrorType {
856 tpkg = t.Sym().Pkg
857 }
858 dgopkgpath(c.Field("PkgPath"), tpkg)
859 c.Field("Methods").WriteSlice(lsym, C, int64(n), int64(n))
860
861 array := rttype.NewArrayCursor(lsym, C, rttype.IMethod, n)
862 for i, a := range m {
863 exported := types.IsExported(a.name.Name)
864 var pkg *types.Pkg
865 if !exported && a.name.Pkg != tpkg {
866 pkg = a.name.Pkg
867 }
868 nsym := dname(a.name.Name, "", pkg, exported, false)
869
870 e := array.Elem(i)
871 e.Field("Name").WriteSymPtrOff(nsym, false)
872 e.Field("Typ").WriteSymPtrOff(writeType(a.type_), false)
873 }
874
875 case types.TMAP:
876 if buildcfg.Experiment.SwissMap {
877 writeSwissMapType(t, lsym, c)
878 } else {
879 writeOldMapType(t, lsym, c)
880 }
881
882 case types.TPTR:
883
884 if t.Elem().Kind() == types.TANY {
885 base.Fatalf("bad pointer base type")
886 }
887
888 s1 := writeType(t.Elem())
889 c.Field("Elem").WritePtr(s1)
890
891 case types.TSTRUCT:
892
893 fields := t.Fields()
894 for _, t1 := range fields {
895 writeType(t1.Type)
896 }
897
898
899
900
901
902
903 var spkg *types.Pkg
904 for _, f := range fields {
905 if !types.IsExported(f.Sym.Name) {
906 spkg = f.Sym.Pkg
907 break
908 }
909 }
910
911 dgopkgpath(c.Field("PkgPath"), spkg)
912 c.Field("Fields").WriteSlice(lsym, C, int64(len(fields)), int64(len(fields)))
913
914 array := rttype.NewArrayCursor(lsym, C, rttype.StructField, len(fields))
915 for i, f := range fields {
916 e := array.Elem(i)
917 dnameField(e.Field("Name"), spkg, f)
918 e.Field("Typ").WritePtr(writeType(f.Type))
919 e.Field("Offset").WriteUintptr(uint64(f.Offset))
920 }
921 }
922
923
924 if extra {
925 dextratype(lsym, B, t, dataAdd)
926 }
927
928
929
930
931
932 dupok := 0
933 if tbase.Sym() == nil || tbase.IsFullyInstantiated() || tbase.HasShape() {
934 dupok = obj.DUPOK
935 }
936
937 objw.Global(lsym, int32(E), int16(dupok|obj.RODATA))
938
939
940
941
942
943
944 keep := base.Ctxt.Flag_dynlink
945 if !keep && t.Sym() == nil {
946
947
948
949
950
951 switch t.Kind() {
952 case types.TPTR, types.TARRAY, types.TCHAN, types.TFUNC, types.TMAP, types.TSLICE, types.TSTRUCT:
953 keep = true
954 }
955 }
956
957 if types.TypeHasNoAlg(t) {
958 keep = false
959 }
960 lsym.Set(obj.AttrMakeTypelink, keep)
961
962 return lsym
963 }
964
965
966
967 func InterfaceMethodOffset(ityp *types.Type, i int64) int64 {
968
969
970
971
972
973
974
975
976 return int64(commonSize()+4*types.PtrSize+uncommonSize(ityp)) + i*8
977 }
978
979
980 func NeedRuntimeType(t *types.Type) {
981 if _, ok := signatset[t]; !ok {
982 signatset[t] = struct{}{}
983 signatslice = append(signatslice, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()})
984 }
985 }
986
987 func WriteRuntimeTypes() {
988
989
990 for len(signatslice) > 0 {
991 signats := signatslice
992
993 slices.SortFunc(signats, typesStrCmp)
994 for _, ts := range signats {
995 t := ts.t
996 writeType(t)
997 if t.Sym() != nil {
998 writeType(types.NewPtr(t))
999 }
1000 }
1001 signatslice = signatslice[len(signats):]
1002 }
1003 }
1004
1005 func WriteGCSymbols() {
1006
1007 gcsyms := make([]typeAndStr, 0, len(gcsymset))
1008 for t := range gcsymset {
1009 gcsyms = append(gcsyms, typeAndStr{t: t, short: types.TypeSymName(t), regular: t.String()})
1010 }
1011 slices.SortFunc(gcsyms, typesStrCmp)
1012 for _, ts := range gcsyms {
1013 dgcsym(ts.t, true)
1014 }
1015 }
1016
1017
1018
1019
1020 func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) {
1021
1022
1023 oldpos, oldfn := base.Pos, ir.CurFunc
1024 defer func() { base.Pos, ir.CurFunc = oldpos, oldfn }()
1025
1026 if typ == nil || (typ.IsPtr() && typ.Elem() == nil) || typ.IsUntyped() || iface == nil || !iface.IsInterface() || iface.IsEmptyInterface() {
1027 base.Fatalf("writeITab(%v, %v)", typ, iface)
1028 }
1029
1030 sigs := iface.AllMethods()
1031 entries := make([]*obj.LSym, 0, len(sigs))
1032
1033
1034
1035 for _, m := range methods(typ) {
1036 if m.name == sigs[0].Sym {
1037 entries = append(entries, m.isym)
1038 if m.isym == nil {
1039 panic("NO ISYM")
1040 }
1041 sigs = sigs[1:]
1042 if len(sigs) == 0 {
1043 break
1044 }
1045 }
1046 }
1047 completeItab := len(sigs) == 0
1048 if !allowNonImplement && !completeItab {
1049 base.Fatalf("incomplete itab")
1050 }
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060 c := rttype.NewCursor(lsym, 0, rttype.ITab)
1061 c.Field("Inter").WritePtr(writeType(iface))
1062 c.Field("Type").WritePtr(writeType(typ))
1063 c.Field("Hash").WriteUint32(types.TypeHash(typ))
1064
1065 var delta int64
1066 c = c.Field("Fun")
1067 if !completeItab {
1068
1069 c.Elem(0).WriteUintptr(0)
1070 } else {
1071 var a rttype.ArrayCursor
1072 a, delta = c.ModifyArray(len(entries))
1073 for i, fn := range entries {
1074 a.Elem(i).WritePtrWeak(fn)
1075 }
1076 }
1077
1078 objw.Global(lsym, int32(rttype.ITab.Size()+delta), int16(obj.DUPOK|obj.RODATA))
1079 lsym.Set(obj.AttrContentAddressable, true)
1080 }
1081
1082 func WritePluginTable() {
1083 ptabs := typecheck.Target.PluginExports
1084 if len(ptabs) == 0 {
1085 return
1086 }
1087
1088 lsym := base.Ctxt.Lookup("go:plugin.tabs")
1089 ot := 0
1090 for _, p := range ptabs {
1091
1092
1093
1094
1095
1096
1097 nsym := dname(p.Sym().Name, "", nil, true, false)
1098 t := p.Type()
1099 if p.Class != ir.PFUNC {
1100 t = types.NewPtr(t)
1101 }
1102 tsym := writeType(t)
1103 ot = objw.SymPtrOff(lsym, ot, nsym)
1104 ot = objw.SymPtrOff(lsym, ot, tsym)
1105
1106
1107 tsym.Set(obj.AttrUsedInIface, true)
1108 }
1109 objw.Global(lsym, int32(ot), int16(obj.RODATA))
1110
1111 lsym = base.Ctxt.Lookup("go:plugin.exports")
1112 ot = 0
1113 for _, p := range ptabs {
1114 ot = objw.SymPtr(lsym, ot, p.Linksym(), 0)
1115 }
1116 objw.Global(lsym, int32(ot), int16(obj.RODATA))
1117 }
1118
1119
1120
1121 func writtenByWriteBasicTypes(typ *types.Type) bool {
1122 if typ.Sym() == nil && typ.Kind() == types.TFUNC {
1123
1124 if typ.NumRecvs() == 0 &&
1125 typ.NumParams() == 1 && typ.NumResults() == 1 &&
1126 typ.Param(0).Type == types.ErrorType &&
1127 typ.Result(0).Type == types.Types[types.TSTRING] {
1128 return true
1129 }
1130 }
1131
1132
1133
1134 if typ.Sym() == nil && typ.IsSlice() {
1135 typ = typ.Elem()
1136 }
1137
1138
1139 sym := typ.Sym()
1140 if sym != nil && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg) {
1141 return true
1142 }
1143
1144 return (sym == nil && typ.IsEmptyInterface()) || typ == types.ErrorType
1145 }
1146
1147 func WriteBasicTypes() {
1148
1149
1150
1151
1152
1153
1154
1155 if base.Ctxt.Pkgpath != "runtime" {
1156 return
1157 }
1158
1159
1160 var list []*types.Type
1161 for i := types.Kind(1); i <= types.TBOOL; i++ {
1162 list = append(list, types.Types[i])
1163 }
1164 list = append(list,
1165 types.Types[types.TSTRING],
1166 types.Types[types.TUNSAFEPTR],
1167 types.AnyType,
1168 types.ErrorType)
1169 for _, t := range list {
1170 writeType(types.NewPtr(t))
1171 writeType(types.NewPtr(types.NewSlice(t)))
1172 }
1173
1174
1175
1176 writeType(types.NewPtr(types.NewSignature(nil, []*types.Field{
1177 types.NewField(base.Pos, nil, types.ErrorType),
1178 }, []*types.Field{
1179 types.NewField(base.Pos, nil, types.Types[types.TSTRING]),
1180 })))
1181 }
1182
1183 type typeAndStr struct {
1184 t *types.Type
1185 short string
1186 regular string
1187 }
1188
1189 func typesStrCmp(a, b typeAndStr) int {
1190
1191 if a.t.Sym() != nil && b.t.Sym() == nil {
1192 return -1
1193 }
1194 if a.t.Sym() == nil && b.t.Sym() != nil {
1195 return +1
1196 }
1197
1198 if r := strings.Compare(a.short, b.short); r != 0 {
1199 return r
1200 }
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210 if r := strings.Compare(a.regular, b.regular); r != 0 {
1211 return r
1212 }
1213
1214
1215
1216
1217 if a.t.Kind() == types.TINTER && len(a.t.AllMethods()) > 0 {
1218 if a.t.AllMethods()[0].Pos.Before(b.t.AllMethods()[0].Pos) {
1219 return -1
1220 }
1221 return +1
1222 }
1223 return 0
1224 }
1225
1226
1227
1228
1229
1230
1231 func GCSym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
1232
1233 gcsymmu.Lock()
1234 if _, ok := gcsymset[t]; !ok {
1235 gcsymset[t] = struct{}{}
1236 }
1237 gcsymmu.Unlock()
1238
1239 return dgcsym(t, false)
1240 }
1241
1242
1243
1244
1245
1246 func dgcsym(t *types.Type, write bool) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
1247 ptrdata = types.PtrDataSize(t)
1248 if ptrdata/int64(types.PtrSize) <= abi.MaxPtrmaskBytes*8 {
1249 lsym = dgcptrmask(t, write)
1250 return
1251 }
1252
1253 useGCProg = true
1254 lsym, ptrdata = dgcprog(t, write)
1255 return
1256 }
1257
1258
1259 func dgcptrmask(t *types.Type, write bool) *obj.LSym {
1260
1261 n := (types.PtrDataSize(t)/int64(types.PtrSize) + 7) / 8
1262
1263 n = (n + int64(types.PtrSize) - 1) &^ (int64(types.PtrSize) - 1)
1264 ptrmask := make([]byte, n)
1265 fillptrmask(t, ptrmask)
1266 p := fmt.Sprintf("runtime.gcbits.%x", ptrmask)
1267
1268 lsym := base.Ctxt.Lookup(p)
1269 if write && !lsym.OnList() {
1270 for i, x := range ptrmask {
1271 objw.Uint8(lsym, i, x)
1272 }
1273 objw.Global(lsym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
1274 lsym.Set(obj.AttrContentAddressable, true)
1275 }
1276 return lsym
1277 }
1278
1279
1280
1281
1282 func fillptrmask(t *types.Type, ptrmask []byte) {
1283 for i := range ptrmask {
1284 ptrmask[i] = 0
1285 }
1286 if !t.HasPointers() {
1287 return
1288 }
1289
1290 vec := bitvec.New(8 * int32(len(ptrmask)))
1291 typebits.Set(t, 0, vec)
1292
1293 nptr := types.PtrDataSize(t) / int64(types.PtrSize)
1294 for i := int64(0); i < nptr; i++ {
1295 if vec.Get(int32(i)) {
1296 ptrmask[i/8] |= 1 << (uint(i) % 8)
1297 }
1298 }
1299 }
1300
1301
1302
1303
1304
1305
1306 func dgcprog(t *types.Type, write bool) (*obj.LSym, int64) {
1307 types.CalcSize(t)
1308 if t.Size() == types.BADWIDTH {
1309 base.Fatalf("dgcprog: %v badwidth", t)
1310 }
1311 lsym := TypeLinksymPrefix(".gcprog", t)
1312 var p gcProg
1313 p.init(lsym, write)
1314 p.emit(t, 0)
1315 offset := p.w.BitIndex() * int64(types.PtrSize)
1316 p.end()
1317 if ptrdata := types.PtrDataSize(t); offset < ptrdata || offset > t.Size() {
1318 base.Fatalf("dgcprog: %v: offset=%d but ptrdata=%d size=%d", t, offset, ptrdata, t.Size())
1319 }
1320 return lsym, offset
1321 }
1322
1323 type gcProg struct {
1324 lsym *obj.LSym
1325 symoff int
1326 w gcprog.Writer
1327 write bool
1328 }
1329
1330 func (p *gcProg) init(lsym *obj.LSym, write bool) {
1331 p.lsym = lsym
1332 p.write = write && !lsym.OnList()
1333 p.symoff = 4
1334 if !write {
1335 p.w.Init(func(byte) {})
1336 return
1337 }
1338 p.w.Init(p.writeByte)
1339 if base.Debug.GCProg > 0 {
1340 fmt.Fprintf(os.Stderr, "compile: start GCProg for %v\n", lsym)
1341 p.w.Debug(os.Stderr)
1342 }
1343 }
1344
1345 func (p *gcProg) writeByte(x byte) {
1346 p.symoff = objw.Uint8(p.lsym, p.symoff, x)
1347 }
1348
1349 func (p *gcProg) end() {
1350 p.w.End()
1351 if !p.write {
1352 return
1353 }
1354 objw.Uint32(p.lsym, 0, uint32(p.symoff-4))
1355 objw.Global(p.lsym, int32(p.symoff), obj.DUPOK|obj.RODATA|obj.LOCAL)
1356 p.lsym.Set(obj.AttrContentAddressable, true)
1357 if base.Debug.GCProg > 0 {
1358 fmt.Fprintf(os.Stderr, "compile: end GCProg for %v\n", p.lsym)
1359 }
1360 }
1361
1362 func (p *gcProg) emit(t *types.Type, offset int64) {
1363 types.CalcSize(t)
1364 if !t.HasPointers() {
1365 return
1366 }
1367 if t.Size() == int64(types.PtrSize) {
1368 p.w.Ptr(offset / int64(types.PtrSize))
1369 return
1370 }
1371 switch t.Kind() {
1372 default:
1373 base.Fatalf("gcProg.emit: unexpected type %v", t)
1374
1375 case types.TSTRING:
1376 p.w.Ptr(offset / int64(types.PtrSize))
1377
1378 case types.TINTER:
1379
1380 p.w.Ptr(offset/int64(types.PtrSize) + 1)
1381
1382 case types.TSLICE:
1383 p.w.Ptr(offset / int64(types.PtrSize))
1384
1385 case types.TARRAY:
1386 if t.NumElem() == 0 {
1387
1388 base.Fatalf("gcProg.emit: empty array")
1389 }
1390
1391
1392 count := t.NumElem()
1393 elem := t.Elem()
1394 for elem.IsArray() {
1395 count *= elem.NumElem()
1396 elem = elem.Elem()
1397 }
1398
1399 if !p.w.ShouldRepeat(elem.Size()/int64(types.PtrSize), count) {
1400
1401 for i := int64(0); i < count; i++ {
1402 p.emit(elem, offset+i*elem.Size())
1403 }
1404 return
1405 }
1406 p.emit(elem, offset)
1407 p.w.ZeroUntil((offset + elem.Size()) / int64(types.PtrSize))
1408 p.w.Repeat(elem.Size()/int64(types.PtrSize), count-1)
1409
1410 case types.TSTRUCT:
1411 for _, t1 := range t.Fields() {
1412 p.emit(t1.Type, offset+t1.Offset)
1413 }
1414 }
1415 }
1416
1417
1418
1419 func ZeroAddr(size int64) ir.Node {
1420 if size >= 1<<31 {
1421 base.Fatalf("map elem too big %d", size)
1422 }
1423 if ZeroSize < size {
1424 ZeroSize = size
1425 }
1426 lsym := base.PkgLinksym("go:map", "zero", obj.ABI0)
1427 x := ir.NewLinksymExpr(base.Pos, lsym, types.Types[types.TUINT8])
1428 return typecheck.Expr(typecheck.NodAddr(x))
1429 }
1430
1431
1432
1433 func NeedEmit(typ *types.Type) bool {
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443 switch sym := typ.Sym(); {
1444 case writtenByWriteBasicTypes(typ):
1445 return base.Ctxt.Pkgpath == "runtime"
1446
1447 case sym == nil:
1448
1449
1450 return true
1451
1452 case sym.Pkg == types.LocalPkg:
1453
1454 return true
1455
1456 case typ.IsFullyInstantiated():
1457
1458
1459 return true
1460
1461 case typ.HasShape():
1462
1463
1464 return true
1465
1466 default:
1467
1468 return false
1469 }
1470 }
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508 func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym {
1509 if forItab && !types.IsDirectIface(rcvr) {
1510 rcvr = rcvr.PtrTo()
1511 }
1512
1513 newnam := ir.MethodSym(rcvr, method.Sym)
1514 lsym := newnam.Linksym()
1515
1516
1517 return lsym
1518 }
1519
1520 var ZeroSize int64
1521
1522
1523
1524 func MarkTypeUsedInInterface(t *types.Type, from *obj.LSym) {
1525 if t.HasShape() {
1526
1527 base.Fatalf("shape types have no methods %+v", t)
1528 }
1529 MarkTypeSymUsedInInterface(TypeLinksym(t), from)
1530 }
1531 func MarkTypeSymUsedInInterface(tsym *obj.LSym, from *obj.LSym) {
1532
1533
1534 from.AddRel(base.Ctxt, obj.Reloc{Type: objabi.R_USEIFACE, Sym: tsym})
1535 }
1536
1537
1538
1539 func MarkUsedIfaceMethod(n *ir.CallExpr) {
1540
1541 if ir.CurFunc.LSym == nil {
1542 return
1543 }
1544 dot := n.Fun.(*ir.SelectorExpr)
1545 ityp := dot.X.Type()
1546 if ityp.HasShape() {
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566 ir.CurFunc.LSym.AddRel(base.Ctxt, obj.Reloc{
1567 Type: objabi.R_USENAMEDMETHOD,
1568 Sym: staticdata.StringSymNoCommon(dot.Sel.Name),
1569 })
1570 return
1571 }
1572
1573
1574 midx := dot.Offset() / int64(types.PtrSize)
1575 ir.CurFunc.LSym.AddRel(base.Ctxt, obj.Reloc{
1576 Type: objabi.R_USEIFACEMETHOD,
1577 Sym: TypeLinksym(ityp),
1578 Add: InterfaceMethodOffset(ityp, midx),
1579 })
1580 }
1581
1582 func deref(t *types.Type) *types.Type {
1583 if t.IsPtr() {
1584 return t.Elem()
1585 }
1586 return t
1587 }
1588
View as plain text