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