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