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