Source file
src/reflect/type.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package reflect
17
18 import (
19 "internal/abi"
20 "internal/goarch"
21 "iter"
22 "runtime"
23 "strconv"
24 "sync"
25 "unicode"
26 "unicode/utf8"
27 "unsafe"
28 )
29
30
31
32
33
34
35
36
37
38
39
40
41 type Type interface {
42
43
44
45
46 Align() int
47
48
49
50 FieldAlign() int
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 Method(int) Method
67
68
69
70 Methods() iter.Seq[Method]
71
72
73
74
75
76
77
78
79
80
81
82
83
84 MethodByName(string) (Method, bool)
85
86
87
88
89
90
91 NumMethod() int
92
93
94
95 Name() string
96
97
98
99
100
101
102 PkgPath() string
103
104
105
106 Size() uintptr
107
108
109
110
111
112
113 String() string
114
115
116 Kind() Kind
117
118
119 Implements(u Type) bool
120
121
122 AssignableTo(u Type) bool
123
124
125
126
127
128 ConvertibleTo(u Type) bool
129
130
131
132
133
134 Comparable() bool
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 Bits() int
152
153
154
155 ChanDir() ChanDir
156
157
158
159
160
161
162
163
164
165
166
167
168
169 IsVariadic() bool
170
171
172
173 Elem() Type
174
175
176
177
178 Field(i int) StructField
179
180
181
182
183 Fields() iter.Seq[StructField]
184
185
186
187
188
189 FieldByIndex(index []int) StructField
190
191
192
193
194
195
196 FieldByName(name string) (StructField, bool)
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214 FieldByNameFunc(match func(string) bool) (StructField, bool)
215
216
217
218
219 In(i int) Type
220
221
222
223
224 Ins() iter.Seq[Type]
225
226
227
228 Key() Type
229
230
231
232 Len() int
233
234
235
236 NumField() int
237
238
239
240 NumIn() int
241
242
243
244 NumOut() int
245
246
247
248
249 Out(i int) Type
250
251
252
253
254 Outs() iter.Seq[Type]
255
256
257
258 OverflowComplex(x complex128) bool
259
260
261
262 OverflowFloat(x float64) bool
263
264
265
266 OverflowInt(x int64) bool
267
268
269
270 OverflowUint(x uint64) bool
271
272
273 CanSeq() bool
274
275
276 CanSeq2() bool
277
278 common() *abi.Type
279 uncommon() *uncommonType
280 }
281
282
283
284
285
286
287
288
289
290
295
296
297
298 type Kind uint
299
300 const (
301 Invalid Kind = iota
302 Bool
303 Int
304 Int8
305 Int16
306 Int32
307 Int64
308 Uint
309 Uint8
310 Uint16
311 Uint32
312 Uint64
313 Uintptr
314 Float32
315 Float64
316 Complex64
317 Complex128
318 Array
319 Chan
320 Func
321 Interface
322 Map
323 Pointer
324 Slice
325 String
326 Struct
327 UnsafePointer
328 )
329
330
331
332
333 const Ptr = Pointer
334
335
336
337
338
339
340
341
342 type uncommonType = abi.UncommonType
343
344
345 type common struct {
346 abi.Type
347 }
348
349
350
351 type rtype struct {
352 t abi.Type
353 }
354
355 func (t *rtype) common() *abi.Type {
356 return &t.t
357 }
358
359 func (t *rtype) uncommon() *abi.UncommonType {
360 return t.t.Uncommon()
361 }
362
363 type aNameOff = abi.NameOff
364 type aTypeOff = abi.TypeOff
365 type aTextOff = abi.TextOff
366
367
368 type ChanDir int
369
370 const (
371 RecvDir ChanDir = 1 << iota
372 SendDir
373 BothDir = RecvDir | SendDir
374 )
375
376
377 type arrayType = abi.ArrayType
378
379
380 type chanType = abi.ChanType
381
382
383
384
385
386
387
388
389
390
391
392
393 type funcType = abi.FuncType
394
395
396 type interfaceType struct {
397 abi.InterfaceType
398 }
399
400 func (t *interfaceType) nameOff(off aNameOff) abi.Name {
401 return toRType(&t.Type).nameOff(off)
402 }
403
404 func nameOffFor(t *abi.Type, off aNameOff) abi.Name {
405 return toRType(t).nameOff(off)
406 }
407
408 func typeOffFor(t *abi.Type, off aTypeOff) *abi.Type {
409 return toRType(t).typeOff(off)
410 }
411
412 func (t *interfaceType) typeOff(off aTypeOff) *abi.Type {
413 return toRType(&t.Type).typeOff(off)
414 }
415
416 func (t *interfaceType) common() *abi.Type {
417 return &t.Type
418 }
419
420 func (t *interfaceType) uncommon() *abi.UncommonType {
421 return t.Uncommon()
422 }
423
424
425 type ptrType struct {
426 abi.PtrType
427 }
428
429
430 type sliceType struct {
431 abi.SliceType
432 }
433
434
435 type structField = abi.StructField
436
437
438 type structType struct {
439 abi.StructType
440 }
441
442 func pkgPath(n abi.Name) string {
443 if n.Bytes == nil || *n.DataChecked(0, "name flag field")&(1<<2) == 0 {
444 return ""
445 }
446 i, l := n.ReadVarint(1)
447 off := 1 + i + l
448 if n.HasTag() {
449 i2, l2 := n.ReadVarint(off)
450 off += i2 + l2
451 }
452 var nameOff int32
453
454
455 copy((*[4]byte)(unsafe.Pointer(&nameOff))[:], (*[4]byte)(unsafe.Pointer(n.DataChecked(off, "name offset field")))[:])
456 pkgPathName := abi.Name{Bytes: (*byte)(resolveTypeOff(unsafe.Pointer(n.Bytes), nameOff))}
457 return pkgPathName.Name()
458 }
459
460 func newName(n, tag string, exported, embedded bool) abi.Name {
461 return abi.NewName(n, tag, exported, embedded)
462 }
463
464
468
469
470 type Method struct {
471
472 Name string
473
474
475
476
477
478
479 PkgPath string
480
481 Type Type
482 Func Value
483 Index int
484 }
485
486
487 func (m Method) IsExported() bool {
488 return m.PkgPath == ""
489 }
490
491
492 func (k Kind) String() string {
493 if uint(k) < uint(len(kindNames)) {
494 return kindNames[uint(k)]
495 }
496 return "kind" + strconv.Itoa(int(k))
497 }
498
499 var kindNames = []string{
500 Invalid: "invalid",
501 Bool: "bool",
502 Int: "int",
503 Int8: "int8",
504 Int16: "int16",
505 Int32: "int32",
506 Int64: "int64",
507 Uint: "uint",
508 Uint8: "uint8",
509 Uint16: "uint16",
510 Uint32: "uint32",
511 Uint64: "uint64",
512 Uintptr: "uintptr",
513 Float32: "float32",
514 Float64: "float64",
515 Complex64: "complex64",
516 Complex128: "complex128",
517 Array: "array",
518 Chan: "chan",
519 Func: "func",
520 Interface: "interface",
521 Map: "map",
522 Pointer: "ptr",
523 Slice: "slice",
524 String: "string",
525 Struct: "struct",
526 UnsafePointer: "unsafe.Pointer",
527 }
528
529
530
531
532
533
534 func resolveNameOff(ptrInModule unsafe.Pointer, off int32) unsafe.Pointer
535
536
537
538
539
540
541 func resolveTypeOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
542
543
544
545
546
547
548 func resolveTextOff(rtype unsafe.Pointer, off int32) unsafe.Pointer
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564 func addReflectOff(ptr unsafe.Pointer) int32
565
566
567
568 func resolveReflectName(n abi.Name) aNameOff {
569 return aNameOff(addReflectOff(unsafe.Pointer(n.Bytes)))
570 }
571
572
573
574 func resolveReflectType(t *abi.Type) aTypeOff {
575 return aTypeOff(addReflectOff(unsafe.Pointer(t)))
576 }
577
578
579
580
581 func resolveReflectText(ptr unsafe.Pointer) aTextOff {
582 return aTextOff(addReflectOff(ptr))
583 }
584
585 func (t *rtype) nameOff(off aNameOff) abi.Name {
586 return abi.Name{Bytes: (*byte)(resolveNameOff(unsafe.Pointer(t), int32(off)))}
587 }
588
589 func (t *rtype) typeOff(off aTypeOff) *abi.Type {
590 return (*abi.Type)(resolveTypeOff(unsafe.Pointer(t), int32(off)))
591 }
592
593 func (t *rtype) textOff(off aTextOff) unsafe.Pointer {
594 return resolveTextOff(unsafe.Pointer(t), int32(off))
595 }
596
597 func textOffFor(t *abi.Type, off aTextOff) unsafe.Pointer {
598 return toRType(t).textOff(off)
599 }
600
601 func (t *rtype) String() string {
602 s := t.nameOff(t.t.Str).Name()
603 if t.t.TFlag&abi.TFlagExtraStar != 0 {
604 return s[1:]
605 }
606 return s
607 }
608
609 func (t *rtype) Size() uintptr { return t.t.Size() }
610
611 func (t *rtype) Bits() int {
612 if t == nil {
613 panic("reflect: Bits of nil Type")
614 }
615 k := t.Kind()
616 if k < Int || k > Complex128 {
617 panic("reflect: Bits of non-arithmetic Type " + t.String())
618 }
619 return int(t.t.Size_) * 8
620 }
621
622 func (t *rtype) Align() int { return t.t.Align() }
623
624 func (t *rtype) FieldAlign() int { return t.t.FieldAlign() }
625
626 func (t *rtype) Kind() Kind { return Kind(t.t.Kind()) }
627
628 func (t *rtype) exportedMethods() []abi.Method {
629 ut := t.uncommon()
630 if ut == nil {
631 return nil
632 }
633 return ut.ExportedMethods()
634 }
635
636 func (t *rtype) NumMethod() int {
637 if t.Kind() == Interface {
638 tt := (*interfaceType)(unsafe.Pointer(t))
639 return tt.NumMethod()
640 }
641 return len(t.exportedMethods())
642 }
643
644 func (t *rtype) Method(i int) (m Method) {
645 if t.Kind() == Interface {
646 tt := (*interfaceType)(unsafe.Pointer(t))
647 return tt.Method(i)
648 }
649 methods := t.exportedMethods()
650 if i < 0 || i >= len(methods) {
651 panic("reflect: Method index out of range")
652 }
653 p := methods[i]
654 pname := t.nameOff(p.Name)
655 m.Name = pname.Name()
656 fl := flag(Func)
657 mtyp := t.typeOff(p.Mtyp)
658 ft := (*funcType)(unsafe.Pointer(mtyp))
659 in := make([]Type, 0, 1+ft.NumIn())
660 in = append(in, t)
661 for _, arg := range ft.InSlice() {
662 in = append(in, toRType(arg))
663 }
664 out := make([]Type, 0, ft.NumOut())
665 for _, ret := range ft.OutSlice() {
666 out = append(out, toRType(ret))
667 }
668 mt := FuncOf(in, out, ft.IsVariadic())
669 m.Type = mt
670 tfn := t.textOff(p.Tfn)
671 fn := unsafe.Pointer(&tfn)
672 m.Func = Value{&mt.(*rtype).t, fn, fl}
673
674 m.Index = i
675 return m
676 }
677
678 func (t *rtype) MethodByName(name string) (m Method, ok bool) {
679 if t.Kind() == Interface {
680 tt := (*interfaceType)(unsafe.Pointer(t))
681 return tt.MethodByName(name)
682 }
683 ut := t.uncommon()
684 if ut == nil {
685 return Method{}, false
686 }
687
688 methods := ut.ExportedMethods()
689
690
691
692 i, j := 0, len(methods)
693 for i < j {
694 h := int(uint(i+j) >> 1)
695
696 if !(t.nameOff(methods[h].Name).Name() >= name) {
697 i = h + 1
698 } else {
699 j = h
700 }
701 }
702
703 if i < len(methods) && name == t.nameOff(methods[i].Name).Name() {
704 return t.Method(i), true
705 }
706
707 return Method{}, false
708 }
709
710 func (t *rtype) PkgPath() string {
711 if t.t.TFlag&abi.TFlagNamed == 0 {
712 return ""
713 }
714 ut := t.uncommon()
715 if ut == nil {
716 return ""
717 }
718 return t.nameOff(ut.PkgPath).Name()
719 }
720
721 func pkgPathFor(t *abi.Type) string {
722 return toRType(t).PkgPath()
723 }
724
725 func (t *rtype) Name() string {
726 if !t.t.HasName() {
727 return ""
728 }
729 s := t.String()
730 i := len(s) - 1
731 sqBrackets := 0
732 for i >= 0 && (s[i] != '.' || sqBrackets != 0) {
733 switch s[i] {
734 case ']':
735 sqBrackets++
736 case '[':
737 sqBrackets--
738 }
739 i--
740 }
741 return s[i+1:]
742 }
743
744 func nameFor(t *abi.Type) string {
745 return toRType(t).Name()
746 }
747
748 func (t *rtype) ChanDir() ChanDir {
749 if t.Kind() != Chan {
750 panic("reflect: ChanDir of non-chan type " + t.String())
751 }
752 tt := (*abi.ChanType)(unsafe.Pointer(t))
753 return ChanDir(tt.Dir)
754 }
755
756 func toRType(t *abi.Type) *rtype {
757 return (*rtype)(unsafe.Pointer(t))
758 }
759
760 func elem(t *abi.Type) *abi.Type {
761 et := t.Elem()
762 if et != nil {
763 return et
764 }
765 panic("reflect: Elem of invalid type " + stringFor(t))
766 }
767
768 func (t *rtype) Elem() Type {
769 return toType(elem(t.common()))
770 }
771
772 func (t *rtype) Field(i int) StructField {
773 if t.Kind() != Struct {
774 panic("reflect: Field of non-struct type " + t.String())
775 }
776 tt := (*structType)(unsafe.Pointer(t))
777 return tt.Field(i)
778 }
779
780 func (t *rtype) FieldByIndex(index []int) StructField {
781 if t.Kind() != Struct {
782 panic("reflect: FieldByIndex of non-struct type " + t.String())
783 }
784 tt := (*structType)(unsafe.Pointer(t))
785 return tt.FieldByIndex(index)
786 }
787
788 func (t *rtype) FieldByName(name string) (StructField, bool) {
789 if t.Kind() != Struct {
790 panic("reflect: FieldByName of non-struct type " + t.String())
791 }
792 tt := (*structType)(unsafe.Pointer(t))
793 return tt.FieldByName(name)
794 }
795
796 func (t *rtype) FieldByNameFunc(match func(string) bool) (StructField, bool) {
797 if t.Kind() != Struct {
798 panic("reflect: FieldByNameFunc of non-struct type " + t.String())
799 }
800 tt := (*structType)(unsafe.Pointer(t))
801 return tt.FieldByNameFunc(match)
802 }
803
804 func (t *rtype) Len() int {
805 if t.Kind() != Array {
806 panic("reflect: Len of non-array type " + t.String())
807 }
808 tt := (*arrayType)(unsafe.Pointer(t))
809 return int(tt.Len)
810 }
811
812 func (t *rtype) NumField() int {
813 if t.Kind() != Struct {
814 panic("reflect: NumField of non-struct type " + t.String())
815 }
816 tt := (*structType)(unsafe.Pointer(t))
817 return len(tt.Fields)
818 }
819
820 func (t *rtype) In(i int) Type {
821 if t.Kind() != Func {
822 panic("reflect: In of non-func type " + t.String())
823 }
824 tt := (*abi.FuncType)(unsafe.Pointer(t))
825 return toType(tt.InSlice()[i])
826 }
827
828 func (t *rtype) NumIn() int {
829 if t.Kind() != Func {
830 panic("reflect: NumIn of non-func type " + t.String())
831 }
832 tt := (*abi.FuncType)(unsafe.Pointer(t))
833 return tt.NumIn()
834 }
835
836 func (t *rtype) NumOut() int {
837 if t.Kind() != Func {
838 panic("reflect: NumOut of non-func type " + t.String())
839 }
840 tt := (*abi.FuncType)(unsafe.Pointer(t))
841 return tt.NumOut()
842 }
843
844 func (t *rtype) Out(i int) Type {
845 if t.Kind() != Func {
846 panic("reflect: Out of non-func type " + t.String())
847 }
848 tt := (*abi.FuncType)(unsafe.Pointer(t))
849 return toType(tt.OutSlice()[i])
850 }
851
852 func (t *rtype) IsVariadic() bool {
853 if t.Kind() != Func {
854 panic("reflect: IsVariadic of non-func type " + t.String())
855 }
856 tt := (*abi.FuncType)(unsafe.Pointer(t))
857 return tt.IsVariadic()
858 }
859
860 func (t *rtype) OverflowComplex(x complex128) bool {
861 k := t.Kind()
862 switch k {
863 case Complex64:
864 return overflowFloat32(real(x)) || overflowFloat32(imag(x))
865 case Complex128:
866 return false
867 }
868 panic("reflect: OverflowComplex of non-complex type " + t.String())
869 }
870
871 func (t *rtype) OverflowFloat(x float64) bool {
872 k := t.Kind()
873 switch k {
874 case Float32:
875 return overflowFloat32(x)
876 case Float64:
877 return false
878 }
879 panic("reflect: OverflowFloat of non-float type " + t.String())
880 }
881
882 func (t *rtype) OverflowInt(x int64) bool {
883 k := t.Kind()
884 switch k {
885 case Int, Int8, Int16, Int32, Int64:
886 bitSize := t.Size() * 8
887 trunc := (x << (64 - bitSize)) >> (64 - bitSize)
888 return x != trunc
889 }
890 panic("reflect: OverflowInt of non-int type " + t.String())
891 }
892
893 func (t *rtype) OverflowUint(x uint64) bool {
894 k := t.Kind()
895 switch k {
896 case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
897 bitSize := t.Size() * 8
898 trunc := (x << (64 - bitSize)) >> (64 - bitSize)
899 return x != trunc
900 }
901 panic("reflect: OverflowUint of non-uint type " + t.String())
902 }
903
904 func (t *rtype) CanSeq() bool {
905 switch t.Kind() {
906 case Int8, Int16, Int32, Int64, Int, Uint8, Uint16, Uint32, Uint64, Uint, Uintptr, Array, Slice, Chan, String, Map:
907 return true
908 case Func:
909 return canRangeFunc(&t.t, 1)
910 case Pointer:
911 return t.Elem().Kind() == Array
912 }
913 return false
914 }
915
916 func (t *rtype) CanSeq2() bool {
917 switch t.Kind() {
918 case Array, Slice, String, Map:
919 return true
920 case Func:
921 return canRangeFunc(&t.t, 2)
922 case Pointer:
923 return t.Elem().Kind() == Array
924 }
925 return false
926 }
927
928 func canRangeFunc(t *abi.Type, seq uint16) bool {
929 if t.Kind() != abi.Func {
930 return false
931 }
932 f := t.FuncType()
933 if f.InCount != 1 || f.OutCount != 0 {
934 return false
935 }
936 y := f.In(0)
937 if y.Kind() != abi.Func {
938 return false
939 }
940 yield := y.FuncType()
941 return yield.InCount == seq && yield.OutCount == 1 && yield.Out(0).Kind() == abi.Bool && toRType(yield.Out(0)).PkgPath() == ""
942 }
943
944 func (t *rtype) Fields() iter.Seq[StructField] {
945 if t.Kind() != Struct {
946 panic("reflect: Fields of non-struct type " + t.String())
947 }
948 return func(yield func(StructField) bool) {
949 for i := range t.NumField() {
950 if !yield(t.Field(i)) {
951 return
952 }
953 }
954 }
955 }
956
957 func (t *rtype) Methods() iter.Seq[Method] {
958 return func(yield func(Method) bool) {
959 for i := range t.NumMethod() {
960 if !yield(t.Method(i)) {
961 return
962 }
963 }
964 }
965 }
966
967 func (t *rtype) Ins() iter.Seq[Type] {
968 if t.Kind() != Func {
969 panic("reflect: Ins of non-func type " + t.String())
970 }
971 return func(yield func(Type) bool) {
972 for i := range t.NumIn() {
973 if !yield(t.In(i)) {
974 return
975 }
976 }
977 }
978 }
979
980 func (t *rtype) Outs() iter.Seq[Type] {
981 if t.Kind() != Func {
982 panic("reflect: Outs of non-func type " + t.String())
983 }
984 return func(yield func(Type) bool) {
985 for i := range t.NumOut() {
986 if !yield(t.Out(i)) {
987 return
988 }
989 }
990 }
991 }
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011 func add(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
1012 return unsafe.Pointer(uintptr(p) + x)
1013 }
1014
1015 func (d ChanDir) String() string {
1016 switch d {
1017 case SendDir:
1018 return "chan<-"
1019 case RecvDir:
1020 return "<-chan"
1021 case BothDir:
1022 return "chan"
1023 }
1024 return "ChanDir" + strconv.Itoa(int(d))
1025 }
1026
1027
1028 func (t *interfaceType) Method(i int) (m Method) {
1029 if i < 0 || i >= len(t.Methods) {
1030 return
1031 }
1032 p := &t.Methods[i]
1033 pname := t.nameOff(p.Name)
1034 m.Name = pname.Name()
1035 if !pname.IsExported() {
1036 m.PkgPath = pkgPath(pname)
1037 if m.PkgPath == "" {
1038 m.PkgPath = t.PkgPath.Name()
1039 }
1040 }
1041 m.Type = toType(t.typeOff(p.Typ))
1042 m.Index = i
1043 return
1044 }
1045
1046
1047 func (t *interfaceType) NumMethod() int { return len(t.Methods) }
1048
1049
1050 func (t *interfaceType) MethodByName(name string) (m Method, ok bool) {
1051 if t == nil {
1052 return
1053 }
1054 var p *abi.Imethod
1055 for i := range t.Methods {
1056 p = &t.Methods[i]
1057 if t.nameOff(p.Name).Name() == name {
1058 return t.Method(i), true
1059 }
1060 }
1061 return
1062 }
1063
1064
1065 type StructField struct {
1066
1067 Name string
1068
1069
1070
1071
1072 PkgPath string
1073
1074 Type Type
1075 Tag StructTag
1076 Offset uintptr
1077 Index []int
1078 Anonymous bool
1079 }
1080
1081
1082 func (f StructField) IsExported() bool {
1083 return f.PkgPath == ""
1084 }
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 type StructTag string
1095
1096
1097
1098
1099
1100
1101 func (tag StructTag) Get(key string) string {
1102 v, _ := tag.Lookup(key)
1103 return v
1104 }
1105
1106
1107
1108
1109
1110
1111
1112 func (tag StructTag) Lookup(key string) (value string, ok bool) {
1113
1114
1115
1116 for tag != "" {
1117
1118 i := 0
1119 for i < len(tag) && tag[i] == ' ' {
1120 i++
1121 }
1122 tag = tag[i:]
1123 if tag == "" {
1124 break
1125 }
1126
1127
1128
1129
1130
1131 i = 0
1132 for i < len(tag) && tag[i] > ' ' && tag[i] != ':' && tag[i] != '"' && tag[i] != 0x7f {
1133 i++
1134 }
1135 if i == 0 || i+1 >= len(tag) || tag[i] != ':' || tag[i+1] != '"' {
1136 break
1137 }
1138 name := string(tag[:i])
1139 tag = tag[i+1:]
1140
1141
1142 i = 1
1143 for i < len(tag) && tag[i] != '"' {
1144 if tag[i] == '\\' {
1145 i++
1146 }
1147 i++
1148 }
1149 if i >= len(tag) {
1150 break
1151 }
1152 qvalue := string(tag[:i+1])
1153 tag = tag[i+1:]
1154
1155 if key == name {
1156 value, err := strconv.Unquote(qvalue)
1157 if err != nil {
1158 break
1159 }
1160 return value, true
1161 }
1162 }
1163 return "", false
1164 }
1165
1166
1167 func (t *structType) Field(i int) (f StructField) {
1168 if i < 0 || i >= len(t.Fields) {
1169 panic("reflect: Field index out of bounds")
1170 }
1171 p := &t.Fields[i]
1172 f.Type = toType(p.Typ)
1173 f.Name = p.Name.Name()
1174 f.Anonymous = p.Embedded()
1175 if !p.Name.IsExported() {
1176 f.PkgPath = t.PkgPath.Name()
1177 }
1178 if tag := p.Name.Tag(); tag != "" {
1179 f.Tag = StructTag(tag)
1180 }
1181 f.Offset = p.Offset
1182
1183
1184
1185 if i < 256 && runtime.GOOS != "js" && runtime.GOOS != "wasip1" {
1186 staticuint64s := getStaticuint64s()
1187 p := unsafe.Pointer(&(*staticuint64s)[i])
1188 if unsafe.Sizeof(int(0)) == 4 && goarch.BigEndian {
1189 p = unsafe.Add(p, 4)
1190 }
1191 f.Index = unsafe.Slice((*int)(p), 1)
1192 } else {
1193
1194
1195
1196
1197
1198
1199
1200 f.Index = []int{i}
1201 }
1202 return
1203 }
1204
1205
1206
1207
1208
1209
1210 func getStaticuint64s() *[256]uint64
1211
1212
1213
1214
1215
1216 func (t *structType) FieldByIndex(index []int) (f StructField) {
1217 f.Type = toType(&t.Type)
1218 for i, x := range index {
1219 if i > 0 {
1220 ft := f.Type
1221 if ft.Kind() == Pointer && ft.Elem().Kind() == Struct {
1222 ft = ft.Elem()
1223 }
1224 f.Type = ft
1225 }
1226 f = f.Type.Field(x)
1227 }
1228 return
1229 }
1230
1231
1232 type fieldScan struct {
1233 typ *structType
1234 index []int
1235 }
1236
1237
1238
1239 func (t *structType) FieldByNameFunc(match func(string) bool) (result StructField, ok bool) {
1240
1241
1242
1243
1244
1245
1246
1247
1248 current := []fieldScan{}
1249 next := []fieldScan{{typ: t}}
1250
1251
1252
1253
1254
1255
1256
1257 var nextCount map[*structType]int
1258
1259
1260
1261
1262
1263
1264 visited := map[*structType]bool{}
1265
1266 for len(next) > 0 {
1267 current, next = next, current[:0]
1268 count := nextCount
1269 nextCount = nil
1270
1271
1272
1273
1274
1275 for _, scan := range current {
1276 t := scan.typ
1277 if visited[t] {
1278
1279
1280
1281 continue
1282 }
1283 visited[t] = true
1284 for i := range t.Fields {
1285 f := &t.Fields[i]
1286
1287 fname := f.Name.Name()
1288 var ntyp *abi.Type
1289 if f.Embedded() {
1290
1291 ntyp = f.Typ
1292 if ntyp.Kind() == abi.Pointer {
1293 ntyp = ntyp.Elem()
1294 }
1295 }
1296
1297
1298 if match(fname) {
1299
1300 if count[t] > 1 || ok {
1301
1302 return StructField{}, false
1303 }
1304 result = t.Field(i)
1305 result.Index = nil
1306 result.Index = append(result.Index, scan.index...)
1307 result.Index = append(result.Index, i)
1308 ok = true
1309 continue
1310 }
1311
1312
1313
1314
1315 if ok || ntyp == nil || ntyp.Kind() != abi.Struct {
1316 continue
1317 }
1318 styp := (*structType)(unsafe.Pointer(ntyp))
1319 if nextCount[styp] > 0 {
1320 nextCount[styp] = 2
1321 continue
1322 }
1323 if nextCount == nil {
1324 nextCount = map[*structType]int{}
1325 }
1326 nextCount[styp] = 1
1327 if count[t] > 1 {
1328 nextCount[styp] = 2
1329 }
1330 var index []int
1331 index = append(index, scan.index...)
1332 index = append(index, i)
1333 next = append(next, fieldScan{styp, index})
1334 }
1335 }
1336 if ok {
1337 break
1338 }
1339 }
1340 return
1341 }
1342
1343
1344
1345 func (t *structType) FieldByName(name string) (f StructField, present bool) {
1346
1347 hasEmbeds := false
1348 if name != "" {
1349 for i := range t.Fields {
1350 tf := &t.Fields[i]
1351 if tf.Name.Name() == name {
1352 return t.Field(i), true
1353 }
1354 if tf.Embedded() {
1355 hasEmbeds = true
1356 }
1357 }
1358 }
1359 if !hasEmbeds {
1360 return
1361 }
1362 return t.FieldByNameFunc(func(s string) bool { return s == name })
1363 }
1364
1365
1366
1367 func TypeOf(i any) Type {
1368 return toType(abi.TypeOf(i))
1369 }
1370
1371
1372 func TypeFor[T any]() Type {
1373
1374 return toRType(abi.TypeFor[T]())
1375 }
1376
1377
1378 func rtypeOf(i any) *abi.Type {
1379 return abi.TypeOf(i)
1380 }
1381
1382
1383 var ptrMap sync.Map
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394 func PtrTo(t Type) Type { return PointerTo(t) }
1395
1396
1397
1398 func PointerTo(t Type) Type {
1399 return toRType(t.(*rtype).ptrTo())
1400 }
1401
1402 func (t *rtype) ptrTo() *abi.Type {
1403 at := &t.t
1404 if at.PtrToThis != 0 {
1405 return t.typeOff(at.PtrToThis)
1406 }
1407
1408
1409 if pi, ok := ptrMap.Load(t); ok {
1410 return &pi.(*ptrType).Type
1411 }
1412
1413
1414 s := "*" + t.String()
1415 for _, tt := range typesByString(s) {
1416 p := (*ptrType)(unsafe.Pointer(tt))
1417 if p.Elem != &t.t {
1418 continue
1419 }
1420 pi, _ := ptrMap.LoadOrStore(t, p)
1421 return &pi.(*ptrType).Type
1422 }
1423
1424
1425
1426 var iptr any = (*unsafe.Pointer)(nil)
1427 prototype := *(**ptrType)(unsafe.Pointer(&iptr))
1428 pp := *prototype
1429
1430 pp.Str = resolveReflectName(newName(s, "", false, false))
1431 pp.PtrToThis = 0
1432
1433
1434
1435
1436
1437
1438 pp.Hash = fnv1(t.t.Hash, '*')
1439
1440 pp.Elem = at
1441
1442 pi, _ := ptrMap.LoadOrStore(t, &pp)
1443 return &pi.(*ptrType).Type
1444 }
1445
1446 func ptrTo(t *abi.Type) *abi.Type {
1447 return toRType(t).ptrTo()
1448 }
1449
1450
1451 func fnv1(x uint32, list ...byte) uint32 {
1452 for _, b := range list {
1453 x = x*16777619 ^ uint32(b)
1454 }
1455 return x
1456 }
1457
1458 func (t *rtype) Implements(u Type) bool {
1459 if u == nil {
1460 panic("reflect: nil type passed to Type.Implements")
1461 }
1462 if u.Kind() != Interface {
1463 panic("reflect: non-interface type passed to Type.Implements")
1464 }
1465 return implements(u.common(), t.common())
1466 }
1467
1468 func (t *rtype) AssignableTo(u Type) bool {
1469 if u == nil {
1470 panic("reflect: nil type passed to Type.AssignableTo")
1471 }
1472 uu := u.common()
1473 return directlyAssignable(uu, t.common()) || implements(uu, t.common())
1474 }
1475
1476 func (t *rtype) ConvertibleTo(u Type) bool {
1477 if u == nil {
1478 panic("reflect: nil type passed to Type.ConvertibleTo")
1479 }
1480 return convertOp(u.common(), t.common()) != nil
1481 }
1482
1483 func (t *rtype) Comparable() bool {
1484 return t.t.Equal != nil
1485 }
1486
1487
1488 func implements(T, V *abi.Type) bool {
1489 if T.Kind() != abi.Interface {
1490 return false
1491 }
1492 t := (*interfaceType)(unsafe.Pointer(T))
1493 if len(t.Methods) == 0 {
1494 return true
1495 }
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509 if V.Kind() == abi.Interface {
1510 v := (*interfaceType)(unsafe.Pointer(V))
1511 i := 0
1512 for j := 0; j < len(v.Methods); j++ {
1513 tm := &t.Methods[i]
1514 tmName := t.nameOff(tm.Name)
1515 vm := &v.Methods[j]
1516 vmName := nameOffFor(V, vm.Name)
1517 if vmName.Name() == tmName.Name() && typeOffFor(V, vm.Typ) == t.typeOff(tm.Typ) {
1518 if !tmName.IsExported() {
1519 tmPkgPath := pkgPath(tmName)
1520 if tmPkgPath == "" {
1521 tmPkgPath = t.PkgPath.Name()
1522 }
1523 vmPkgPath := pkgPath(vmName)
1524 if vmPkgPath == "" {
1525 vmPkgPath = v.PkgPath.Name()
1526 }
1527 if tmPkgPath != vmPkgPath {
1528 continue
1529 }
1530 }
1531 if i++; i >= len(t.Methods) {
1532 return true
1533 }
1534 }
1535 }
1536 return false
1537 }
1538
1539 v := V.Uncommon()
1540 if v == nil {
1541 return false
1542 }
1543 i := 0
1544 vmethods := v.Methods()
1545 for j := 0; j < int(v.Mcount); j++ {
1546 tm := &t.Methods[i]
1547 tmName := t.nameOff(tm.Name)
1548 vm := vmethods[j]
1549 vmName := nameOffFor(V, vm.Name)
1550 if vmName.Name() == tmName.Name() && typeOffFor(V, vm.Mtyp) == t.typeOff(tm.Typ) {
1551 if !tmName.IsExported() {
1552 tmPkgPath := pkgPath(tmName)
1553 if tmPkgPath == "" {
1554 tmPkgPath = t.PkgPath.Name()
1555 }
1556 vmPkgPath := pkgPath(vmName)
1557 if vmPkgPath == "" {
1558 vmPkgPath = nameOffFor(V, v.PkgPath).Name()
1559 }
1560 if tmPkgPath != vmPkgPath {
1561 continue
1562 }
1563 }
1564 if i++; i >= len(t.Methods) {
1565 return true
1566 }
1567 }
1568 }
1569 return false
1570 }
1571
1572
1573
1574
1575
1576 func specialChannelAssignability(T, V *abi.Type) bool {
1577
1578
1579
1580
1581 return V.ChanDir() == abi.BothDir && (nameFor(T) == "" || nameFor(V) == "") && haveIdenticalType(T.Elem(), V.Elem(), true)
1582 }
1583
1584
1585
1586
1587
1588
1589 func directlyAssignable(T, V *abi.Type) bool {
1590
1591 if T == V {
1592 return true
1593 }
1594
1595
1596
1597 if T.HasName() && V.HasName() || T.Kind() != V.Kind() {
1598 return false
1599 }
1600
1601 if T.Kind() == abi.Chan && specialChannelAssignability(T, V) {
1602 return true
1603 }
1604
1605
1606 return haveIdenticalUnderlyingType(T, V, true)
1607 }
1608
1609 func haveIdenticalType(T, V *abi.Type, cmpTags bool) bool {
1610 if cmpTags {
1611 return T == V
1612 }
1613
1614 if nameFor(T) != nameFor(V) || T.Kind() != V.Kind() || pkgPathFor(T) != pkgPathFor(V) {
1615 return false
1616 }
1617
1618 return haveIdenticalUnderlyingType(T, V, false)
1619 }
1620
1621 func haveIdenticalUnderlyingType(T, V *abi.Type, cmpTags bool) bool {
1622 if T == V {
1623 return true
1624 }
1625
1626 kind := Kind(T.Kind())
1627 if kind != Kind(V.Kind()) {
1628 return false
1629 }
1630
1631
1632
1633 if Bool <= kind && kind <= Complex128 || kind == String || kind == UnsafePointer {
1634 return true
1635 }
1636
1637
1638 switch kind {
1639 case Array:
1640 return T.Len() == V.Len() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1641
1642 case Chan:
1643 return V.ChanDir() == T.ChanDir() && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1644
1645 case Func:
1646 t := (*funcType)(unsafe.Pointer(T))
1647 v := (*funcType)(unsafe.Pointer(V))
1648 if t.OutCount != v.OutCount || t.InCount != v.InCount {
1649 return false
1650 }
1651 for i := 0; i < t.NumIn(); i++ {
1652 if !haveIdenticalType(t.In(i), v.In(i), cmpTags) {
1653 return false
1654 }
1655 }
1656 for i := 0; i < t.NumOut(); i++ {
1657 if !haveIdenticalType(t.Out(i), v.Out(i), cmpTags) {
1658 return false
1659 }
1660 }
1661 return true
1662
1663 case Interface:
1664 t := (*interfaceType)(unsafe.Pointer(T))
1665 v := (*interfaceType)(unsafe.Pointer(V))
1666 if len(t.Methods) == 0 && len(v.Methods) == 0 {
1667 return true
1668 }
1669
1670
1671 return false
1672
1673 case Map:
1674 return haveIdenticalType(T.Key(), V.Key(), cmpTags) && haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1675
1676 case Pointer, Slice:
1677 return haveIdenticalType(T.Elem(), V.Elem(), cmpTags)
1678
1679 case Struct:
1680 t := (*structType)(unsafe.Pointer(T))
1681 v := (*structType)(unsafe.Pointer(V))
1682 if len(t.Fields) != len(v.Fields) {
1683 return false
1684 }
1685 if t.PkgPath.Name() != v.PkgPath.Name() {
1686 return false
1687 }
1688 for i := range t.Fields {
1689 tf := &t.Fields[i]
1690 vf := &v.Fields[i]
1691 if tf.Name.Name() != vf.Name.Name() {
1692 return false
1693 }
1694 if !haveIdenticalType(tf.Typ, vf.Typ, cmpTags) {
1695 return false
1696 }
1697 if cmpTags && tf.Name.Tag() != vf.Name.Tag() {
1698 return false
1699 }
1700 if tf.Offset != vf.Offset {
1701 return false
1702 }
1703 if tf.Embedded() != vf.Embedded() {
1704 return false
1705 }
1706 }
1707 return true
1708 }
1709
1710 return false
1711 }
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724 func compiledTypelinks() ([]*abi.Type, [][]*abi.Type)
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735 func rtypeOff(section unsafe.Pointer, off int32) *abi.Type {
1736 return (*abi.Type)(add(section, uintptr(off), "sizeof(rtype) > 0"))
1737 }
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754 func typesByString(s string) []*abi.Type {
1755 first, rest := compiledTypelinks()
1756 var ret []*abi.Type
1757
1758 searchTypes := func(types []*abi.Type) {
1759
1760
1761 i, j := 0, len(types)
1762 for i < j {
1763 h := int(uint(i+j) >> 1)
1764
1765 if !(stringFor(types[h]) >= s) {
1766 i = h + 1
1767 } else {
1768 j = h
1769 }
1770 }
1771
1772
1773
1774
1775
1776 for j := i; j < len(types); j++ {
1777 typ := types[j]
1778 if stringFor(typ) != s {
1779 break
1780 }
1781 ret = append(ret, typ)
1782 }
1783 }
1784
1785 searchTypes(first)
1786 for _, r := range rest {
1787 searchTypes(r)
1788 }
1789
1790 return ret
1791 }
1792
1793
1794 var lookupCache sync.Map
1795
1796
1797
1798
1799 type cacheKey struct {
1800 kind Kind
1801 t1 *abi.Type
1802 t2 *abi.Type
1803 extra uintptr
1804 }
1805
1806
1807
1808
1809 var funcLookupCache struct {
1810 sync.Mutex
1811
1812
1813
1814 m sync.Map
1815 }
1816
1817
1818
1819
1820
1821
1822 func ChanOf(dir ChanDir, t Type) Type {
1823 typ := t.common()
1824
1825
1826 ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
1827 if ch, ok := lookupCache.Load(ckey); ok {
1828 return ch.(*rtype)
1829 }
1830
1831
1832 if typ.Size_ >= 1<<16 {
1833 panic("reflect.ChanOf: element size too large")
1834 }
1835
1836
1837 var s string
1838 switch dir {
1839 default:
1840 panic("reflect.ChanOf: invalid dir")
1841 case SendDir:
1842 s = "chan<- " + stringFor(typ)
1843 case RecvDir:
1844 s = "<-chan " + stringFor(typ)
1845 case BothDir:
1846 typeStr := stringFor(typ)
1847 if typeStr[0] == '<' {
1848
1849
1850
1851
1852 s = "chan (" + typeStr + ")"
1853 } else {
1854 s = "chan " + typeStr
1855 }
1856 }
1857 for _, tt := range typesByString(s) {
1858 ch := (*chanType)(unsafe.Pointer(tt))
1859 if ch.Elem == typ && ch.Dir == abi.ChanDir(dir) {
1860 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
1861 return ti.(Type)
1862 }
1863 }
1864
1865
1866 var ichan any = (chan unsafe.Pointer)(nil)
1867 prototype := *(**chanType)(unsafe.Pointer(&ichan))
1868 ch := *prototype
1869 ch.TFlag = abi.TFlagRegularMemory | abi.TFlagDirectIface
1870 ch.Dir = abi.ChanDir(dir)
1871 ch.Str = resolveReflectName(newName(s, "", false, false))
1872 ch.Hash = fnv1(typ.Hash, 'c', byte(dir))
1873 ch.Elem = typ
1874
1875 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&ch.Type))
1876 return ti.(Type)
1877 }
1878
1879 var funcTypes []Type
1880 var funcTypesMutex sync.Mutex
1881
1882 func initFuncTypes(n int) Type {
1883 funcTypesMutex.Lock()
1884 defer funcTypesMutex.Unlock()
1885 if n >= len(funcTypes) {
1886 newFuncTypes := make([]Type, n+1)
1887 copy(newFuncTypes, funcTypes)
1888 funcTypes = newFuncTypes
1889 }
1890 if funcTypes[n] != nil {
1891 return funcTypes[n]
1892 }
1893
1894 funcTypes[n] = StructOf([]StructField{
1895 {
1896 Name: "FuncType",
1897 Type: TypeOf(funcType{}),
1898 },
1899 {
1900 Name: "Args",
1901 Type: ArrayOf(n, TypeOf(&rtype{})),
1902 },
1903 })
1904 return funcTypes[n]
1905 }
1906
1907
1908
1909
1910
1911
1912
1913
1914 func FuncOf(in, out []Type, variadic bool) Type {
1915 if variadic && (len(in) == 0 || in[len(in)-1].Kind() != Slice) {
1916 panic("reflect.FuncOf: last arg of variadic func must be slice")
1917 }
1918
1919
1920 var ifunc any = (func())(nil)
1921 prototype := *(**funcType)(unsafe.Pointer(&ifunc))
1922 n := len(in) + len(out)
1923
1924 if n > 128 {
1925 panic("reflect.FuncOf: too many arguments")
1926 }
1927
1928 o := New(initFuncTypes(n)).Elem()
1929 ft := (*funcType)(unsafe.Pointer(o.Field(0).Addr().Pointer()))
1930 args := unsafe.Slice((**rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
1931 *ft = *prototype
1932
1933
1934 var hash uint32
1935 for _, in := range in {
1936 t := in.(*rtype)
1937 args = append(args, t)
1938 hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
1939 }
1940 if variadic {
1941 hash = fnv1(hash, 'v')
1942 }
1943 hash = fnv1(hash, '.')
1944 for _, out := range out {
1945 t := out.(*rtype)
1946 args = append(args, t)
1947 hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
1948 }
1949
1950 ft.TFlag = abi.TFlagDirectIface
1951 ft.Hash = hash
1952 ft.InCount = uint16(len(in))
1953 ft.OutCount = uint16(len(out))
1954 if variadic {
1955 ft.OutCount |= 1 << 15
1956 }
1957
1958
1959 if ts, ok := funcLookupCache.m.Load(hash); ok {
1960 for _, t := range ts.([]*abi.Type) {
1961 if haveIdenticalUnderlyingType(&ft.Type, t, true) {
1962 return toRType(t)
1963 }
1964 }
1965 }
1966
1967
1968 funcLookupCache.Lock()
1969 defer funcLookupCache.Unlock()
1970 if ts, ok := funcLookupCache.m.Load(hash); ok {
1971 for _, t := range ts.([]*abi.Type) {
1972 if haveIdenticalUnderlyingType(&ft.Type, t, true) {
1973 return toRType(t)
1974 }
1975 }
1976 }
1977
1978 addToCache := func(tt *abi.Type) Type {
1979 var rts []*abi.Type
1980 if rti, ok := funcLookupCache.m.Load(hash); ok {
1981 rts = rti.([]*abi.Type)
1982 }
1983 funcLookupCache.m.Store(hash, append(rts, tt))
1984 return toType(tt)
1985 }
1986
1987
1988 str := funcStr(ft)
1989 for _, tt := range typesByString(str) {
1990 if haveIdenticalUnderlyingType(&ft.Type, tt, true) {
1991 return addToCache(tt)
1992 }
1993 }
1994
1995
1996 ft.Str = resolveReflectName(newName(str, "", false, false))
1997 ft.PtrToThis = 0
1998 return addToCache(&ft.Type)
1999 }
2000 func stringFor(t *abi.Type) string {
2001 return toRType(t).String()
2002 }
2003
2004
2005 func funcStr(ft *funcType) string {
2006 repr := make([]byte, 0, 64)
2007 repr = append(repr, "func("...)
2008 for i, t := range ft.InSlice() {
2009 if i > 0 {
2010 repr = append(repr, ", "...)
2011 }
2012 if ft.IsVariadic() && i == int(ft.InCount)-1 {
2013 repr = append(repr, "..."...)
2014 repr = append(repr, stringFor((*sliceType)(unsafe.Pointer(t)).Elem)...)
2015 } else {
2016 repr = append(repr, stringFor(t)...)
2017 }
2018 }
2019 repr = append(repr, ')')
2020 out := ft.OutSlice()
2021 if len(out) == 1 {
2022 repr = append(repr, ' ')
2023 } else if len(out) > 1 {
2024 repr = append(repr, " ("...)
2025 }
2026 for i, t := range out {
2027 if i > 0 {
2028 repr = append(repr, ", "...)
2029 }
2030 repr = append(repr, stringFor(t)...)
2031 }
2032 if len(out) > 1 {
2033 repr = append(repr, ')')
2034 }
2035 return string(repr)
2036 }
2037
2038
2039
2040 func isReflexive(t *abi.Type) bool {
2041 switch Kind(t.Kind()) {
2042 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, String, UnsafePointer:
2043 return true
2044 case Float32, Float64, Complex64, Complex128, Interface:
2045 return false
2046 case Array:
2047 tt := (*arrayType)(unsafe.Pointer(t))
2048 return isReflexive(tt.Elem)
2049 case Struct:
2050 tt := (*structType)(unsafe.Pointer(t))
2051 for _, f := range tt.Fields {
2052 if !isReflexive(f.Typ) {
2053 return false
2054 }
2055 }
2056 return true
2057 default:
2058
2059 panic("isReflexive called on non-key type " + stringFor(t))
2060 }
2061 }
2062
2063
2064 func needKeyUpdate(t *abi.Type) bool {
2065 switch Kind(t.Kind()) {
2066 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, UnsafePointer:
2067 return false
2068 case Float32, Float64, Complex64, Complex128, Interface, String:
2069
2070
2071
2072 return true
2073 case Array:
2074 tt := (*arrayType)(unsafe.Pointer(t))
2075 return needKeyUpdate(tt.Elem)
2076 case Struct:
2077 tt := (*structType)(unsafe.Pointer(t))
2078 for _, f := range tt.Fields {
2079 if needKeyUpdate(f.Typ) {
2080 return true
2081 }
2082 }
2083 return false
2084 default:
2085
2086 panic("needKeyUpdate called on non-key type " + stringFor(t))
2087 }
2088 }
2089
2090
2091 func hashMightPanic(t *abi.Type) bool {
2092 switch Kind(t.Kind()) {
2093 case Interface:
2094 return true
2095 case Array:
2096 tt := (*arrayType)(unsafe.Pointer(t))
2097 return hashMightPanic(tt.Elem)
2098 case Struct:
2099 tt := (*structType)(unsafe.Pointer(t))
2100 for _, f := range tt.Fields {
2101 if hashMightPanic(f.Typ) {
2102 return true
2103 }
2104 }
2105 return false
2106 default:
2107 return false
2108 }
2109 }
2110
2111
2112
2113 func emitGCMask(out []byte, base uintptr, typ *abi.Type, n uintptr) {
2114 ptrs := typ.PtrBytes / goarch.PtrSize
2115 words := typ.Size_ / goarch.PtrSize
2116 mask := typ.GcSlice(0, (ptrs+7)/8)
2117 for j := uintptr(0); j < ptrs; j++ {
2118 if (mask[j/8]>>(j%8))&1 != 0 {
2119 for i := uintptr(0); i < n; i++ {
2120 k := base + i*words + j
2121 out[k/8] |= 1 << (k % 8)
2122 }
2123 }
2124 }
2125 }
2126
2127
2128
2129 func SliceOf(t Type) Type {
2130 typ := t.common()
2131
2132
2133 ckey := cacheKey{Slice, typ, nil, 0}
2134 if slice, ok := lookupCache.Load(ckey); ok {
2135 return slice.(Type)
2136 }
2137
2138
2139 s := "[]" + stringFor(typ)
2140 for _, tt := range typesByString(s) {
2141 slice := (*sliceType)(unsafe.Pointer(tt))
2142 if slice.Elem == typ {
2143 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
2144 return ti.(Type)
2145 }
2146 }
2147
2148
2149 var islice any = ([]unsafe.Pointer)(nil)
2150 prototype := *(**sliceType)(unsafe.Pointer(&islice))
2151 slice := *prototype
2152 slice.TFlag = 0
2153 slice.Str = resolveReflectName(newName(s, "", false, false))
2154 slice.Hash = fnv1(typ.Hash, '[')
2155 slice.Elem = typ
2156 slice.PtrToThis = 0
2157
2158 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&slice.Type))
2159 return ti.(Type)
2160 }
2161
2162
2163
2164
2165 var structLookupCache struct {
2166 sync.Mutex
2167
2168
2169
2170 m sync.Map
2171 }
2172
2173 type structTypeUncommon struct {
2174 structType
2175 u uncommonType
2176 }
2177
2178
2179 func isLetter(ch rune) bool {
2180 return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
2181 }
2182
2183
2184
2185
2186
2187
2188
2189 func isValidFieldName(fieldName string) bool {
2190 for i, c := range fieldName {
2191 if i == 0 && !isLetter(c) {
2192 return false
2193 }
2194
2195 if !(isLetter(c) || unicode.IsDigit(c)) {
2196 return false
2197 }
2198 }
2199
2200 return len(fieldName) > 0
2201 }
2202
2203
2204 func isRegularMemory(t Type) bool {
2205 switch t.Kind() {
2206 case Array:
2207 elem := t.Elem()
2208 if isRegularMemory(elem) {
2209 return true
2210 }
2211 return elem.Comparable() && t.Len() == 0
2212 case Int8, Int16, Int32, Int64, Int, Uint8, Uint16, Uint32, Uint64, Uint, Uintptr, Chan, Pointer, Bool, UnsafePointer:
2213 return true
2214 case Struct:
2215 num := t.NumField()
2216 switch num {
2217 case 0:
2218 return true
2219 case 1:
2220 field := t.Field(0)
2221 if field.Name == "_" {
2222 return false
2223 }
2224 return isRegularMemory(field.Type)
2225 default:
2226 for i := range num {
2227 field := t.Field(i)
2228 if field.Name == "_" || !isRegularMemory(field.Type) || isPaddedField(t, i) {
2229 return false
2230 }
2231 }
2232 return true
2233 }
2234 }
2235 return false
2236 }
2237
2238
2239
2240 func isPaddedField(t Type, i int) bool {
2241 field := t.Field(i)
2242 if i+1 < t.NumField() {
2243 return field.Offset+field.Type.Size() != t.Field(i+1).Offset
2244 }
2245 return field.Offset+field.Type.Size() != t.Size()
2246 }
2247
2248
2249
2250
2251
2252
2253
2254 func StructOf(fields []StructField) Type {
2255 var (
2256 hash = fnv1(0, []byte("struct {")...)
2257 size uintptr
2258 typalign uint8
2259 comparable = true
2260 methods []abi.Method
2261
2262 fs = make([]structField, len(fields))
2263 repr = make([]byte, 0, 64)
2264 fset = map[string]struct{}{}
2265 )
2266
2267 lastzero := uintptr(0)
2268 repr = append(repr, "struct {"...)
2269 pkgpath := ""
2270 for i, field := range fields {
2271 if field.Name == "" {
2272 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
2273 }
2274 if !isValidFieldName(field.Name) {
2275 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name")
2276 }
2277 if field.Type == nil {
2278 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
2279 }
2280 f, fpkgpath := runtimeStructField(field)
2281 ft := f.Typ
2282 if fpkgpath != "" {
2283 if pkgpath == "" {
2284 pkgpath = fpkgpath
2285 } else if pkgpath != fpkgpath {
2286 panic("reflect.StructOf: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
2287 }
2288 }
2289
2290
2291 name := f.Name.Name()
2292 hash = fnv1(hash, []byte(name)...)
2293 if !f.Embedded() {
2294 repr = append(repr, (" " + name)...)
2295 } else {
2296
2297 if f.Typ.Kind() == abi.Pointer {
2298
2299 elem := ft.Elem()
2300 if k := elem.Kind(); k == abi.Pointer || k == abi.Interface {
2301 panic("reflect.StructOf: illegal embedded field type " + stringFor(ft))
2302 }
2303 }
2304
2305 switch Kind(f.Typ.Kind()) {
2306 case Interface:
2307 ift := (*interfaceType)(unsafe.Pointer(ft))
2308 for _, m := range ift.Methods {
2309 if pkgPath(ift.nameOff(m.Name)) != "" {
2310
2311 panic("reflect: embedded interface with unexported method(s) not implemented")
2312 }
2313
2314 fnStub := resolveReflectText(unsafe.Pointer(abi.FuncPCABIInternal(embeddedIfaceMethStub)))
2315 methods = append(methods, abi.Method{
2316 Name: resolveReflectName(ift.nameOff(m.Name)),
2317 Mtyp: resolveReflectType(ift.typeOff(m.Typ)),
2318 Ifn: fnStub,
2319 Tfn: fnStub,
2320 })
2321 }
2322 case Pointer:
2323 ptr := (*ptrType)(unsafe.Pointer(ft))
2324 if unt := ptr.Uncommon(); unt != nil {
2325 if i > 0 && unt.Mcount > 0 {
2326
2327 panic("reflect: embedded type with methods not implemented if type is not first field")
2328 }
2329 if len(fields) > 1 {
2330 panic("reflect: embedded type with methods not implemented if there is more than one field")
2331 }
2332 for _, m := range unt.Methods() {
2333 mname := nameOffFor(ft, m.Name)
2334 if pkgPath(mname) != "" {
2335
2336
2337 panic("reflect: embedded interface with unexported method(s) not implemented")
2338 }
2339 methods = append(methods, abi.Method{
2340 Name: resolveReflectName(mname),
2341 Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
2342 Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
2343 Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
2344 })
2345 }
2346 }
2347 if unt := ptr.Elem.Uncommon(); unt != nil {
2348 for _, m := range unt.Methods() {
2349 mname := nameOffFor(ft, m.Name)
2350 if pkgPath(mname) != "" {
2351
2352
2353 panic("reflect: embedded interface with unexported method(s) not implemented")
2354 }
2355 methods = append(methods, abi.Method{
2356 Name: resolveReflectName(mname),
2357 Mtyp: resolveReflectType(typeOffFor(ptr.Elem, m.Mtyp)),
2358 Ifn: resolveReflectText(textOffFor(ptr.Elem, m.Ifn)),
2359 Tfn: resolveReflectText(textOffFor(ptr.Elem, m.Tfn)),
2360 })
2361 }
2362 }
2363 default:
2364 if unt := ft.Uncommon(); unt != nil {
2365 if i > 0 && unt.Mcount > 0 {
2366
2367 panic("reflect: embedded type with methods not implemented if type is not first field")
2368 }
2369 if len(fields) > 1 && ft.IsDirectIface() {
2370 panic("reflect: embedded type with methods not implemented for non-pointer type")
2371 }
2372 for _, m := range unt.Methods() {
2373 mname := nameOffFor(ft, m.Name)
2374 if pkgPath(mname) != "" {
2375
2376
2377 panic("reflect: embedded interface with unexported method(s) not implemented")
2378 }
2379 methods = append(methods, abi.Method{
2380 Name: resolveReflectName(mname),
2381 Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
2382 Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
2383 Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
2384 })
2385
2386 }
2387 }
2388 }
2389 }
2390 if _, dup := fset[name]; dup && name != "_" {
2391 panic("reflect.StructOf: duplicate field " + name)
2392 }
2393 fset[name] = struct{}{}
2394
2395 hash = fnv1(hash, byte(ft.Hash>>24), byte(ft.Hash>>16), byte(ft.Hash>>8), byte(ft.Hash))
2396
2397 repr = append(repr, (" " + stringFor(ft))...)
2398 if f.Name.HasTag() {
2399 hash = fnv1(hash, []byte(f.Name.Tag())...)
2400 repr = append(repr, (" " + strconv.Quote(f.Name.Tag()))...)
2401 }
2402 if i < len(fields)-1 {
2403 repr = append(repr, ';')
2404 }
2405
2406 comparable = comparable && (ft.Equal != nil)
2407
2408 offset := align(size, uintptr(ft.Align_))
2409 if offset < size {
2410 panic("reflect.StructOf: struct size would exceed virtual address space")
2411 }
2412 if ft.Align_ > typalign {
2413 typalign = ft.Align_
2414 }
2415 size = offset + ft.Size_
2416 if size < offset {
2417 panic("reflect.StructOf: struct size would exceed virtual address space")
2418 }
2419 f.Offset = offset
2420
2421 if ft.Size_ == 0 {
2422 lastzero = size
2423 }
2424
2425 fs[i] = f
2426 }
2427
2428 if size > 0 && lastzero == size {
2429
2430
2431
2432
2433
2434 size++
2435 if size == 0 {
2436 panic("reflect.StructOf: struct size would exceed virtual address space")
2437 }
2438 }
2439
2440 var typ *structType
2441 var ut *uncommonType
2442
2443 if len(methods) == 0 {
2444 t := new(structTypeUncommon)
2445 typ = &t.structType
2446 ut = &t.u
2447 } else {
2448
2449
2450
2451
2452
2453 tt := New(StructOf([]StructField{
2454 {Name: "S", Type: TypeOf(structType{})},
2455 {Name: "U", Type: TypeOf(uncommonType{})},
2456 {Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))},
2457 }))
2458
2459 typ = (*structType)(tt.Elem().Field(0).Addr().UnsafePointer())
2460 ut = (*uncommonType)(tt.Elem().Field(1).Addr().UnsafePointer())
2461
2462 copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]abi.Method), methods)
2463 }
2464
2465
2466
2467
2468 ut.Mcount = uint16(len(methods))
2469 ut.Xcount = ut.Mcount
2470 ut.Moff = uint32(unsafe.Sizeof(uncommonType{}))
2471
2472 if len(fs) > 0 {
2473 repr = append(repr, ' ')
2474 }
2475 repr = append(repr, '}')
2476 hash = fnv1(hash, '}')
2477 str := string(repr)
2478
2479
2480 s := align(size, uintptr(typalign))
2481 if s < size {
2482 panic("reflect.StructOf: struct size would exceed virtual address space")
2483 }
2484 size = s
2485
2486
2487 var istruct any = struct{}{}
2488 prototype := *(**structType)(unsafe.Pointer(&istruct))
2489 *typ = *prototype
2490 typ.Fields = fs
2491 if pkgpath != "" {
2492 typ.PkgPath = newName(pkgpath, "", false, false)
2493 }
2494
2495
2496 if ts, ok := structLookupCache.m.Load(hash); ok {
2497 for _, st := range ts.([]Type) {
2498 t := st.common()
2499 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2500 return toType(t)
2501 }
2502 }
2503 }
2504
2505
2506 structLookupCache.Lock()
2507 defer structLookupCache.Unlock()
2508 if ts, ok := structLookupCache.m.Load(hash); ok {
2509 for _, st := range ts.([]Type) {
2510 t := st.common()
2511 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2512 return toType(t)
2513 }
2514 }
2515 }
2516
2517 addToCache := func(t Type) Type {
2518 var ts []Type
2519 if ti, ok := structLookupCache.m.Load(hash); ok {
2520 ts = ti.([]Type)
2521 }
2522 structLookupCache.m.Store(hash, append(ts, t))
2523 return t
2524 }
2525
2526
2527 for _, t := range typesByString(str) {
2528 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2529
2530
2531
2532 return addToCache(toType(t))
2533 }
2534 }
2535
2536 typ.Str = resolveReflectName(newName(str, "", false, false))
2537 if isRegularMemory(toType(&typ.Type)) {
2538 typ.TFlag = abi.TFlagRegularMemory
2539 } else {
2540 typ.TFlag = 0
2541 }
2542 typ.Hash = hash
2543 typ.Size_ = size
2544 typ.PtrBytes = typeptrdata(&typ.Type)
2545 typ.Align_ = typalign
2546 typ.FieldAlign_ = typalign
2547 typ.PtrToThis = 0
2548 if len(methods) > 0 {
2549 typ.TFlag |= abi.TFlagUncommon
2550 }
2551
2552 if typ.PtrBytes == 0 {
2553 typ.GCData = nil
2554 } else if typ.PtrBytes <= abi.MaxPtrmaskBytes*8*goarch.PtrSize {
2555 bv := new(bitVector)
2556 addTypeBits(bv, 0, &typ.Type)
2557 typ.GCData = &bv.data[0]
2558 } else {
2559
2560
2561 typ.TFlag |= abi.TFlagGCMaskOnDemand
2562 typ.GCData = (*byte)(unsafe.Pointer(new(uintptr)))
2563 if runtime.GOOS == "aix" {
2564 typ.GCData = adjustAIXGCData(typ.GCData)
2565 }
2566 }
2567
2568 typ.Equal = nil
2569 if comparable {
2570 typ.Equal = func(p, q unsafe.Pointer) bool {
2571 for _, ft := range typ.Fields {
2572 pi := add(p, ft.Offset, "&x.field safe")
2573 qi := add(q, ft.Offset, "&x.field safe")
2574 if !ft.Typ.Equal(pi, qi) {
2575 return false
2576 }
2577 }
2578 return true
2579 }
2580 }
2581
2582 switch {
2583 case typ.Size_ == goarch.PtrSize && typ.PtrBytes == goarch.PtrSize:
2584 typ.TFlag |= abi.TFlagDirectIface
2585 default:
2586 typ.TFlag &^= abi.TFlagDirectIface
2587 }
2588
2589 return addToCache(toType(&typ.Type))
2590 }
2591
2592 func embeddedIfaceMethStub() {
2593 panic("reflect: StructOf does not support methods of embedded interfaces")
2594 }
2595
2596
2597
2598
2599 func runtimeStructField(field StructField) (structField, string) {
2600 if field.Anonymous && field.PkgPath != "" {
2601 panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
2602 }
2603
2604 if field.IsExported() {
2605
2606
2607 c := field.Name[0]
2608 if 'a' <= c && c <= 'z' || c == '_' {
2609 panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
2610 }
2611 }
2612
2613 resolveReflectType(field.Type.common())
2614 f := structField{
2615 Name: newName(field.Name, string(field.Tag), field.IsExported(), field.Anonymous),
2616 Typ: field.Type.common(),
2617 Offset: 0,
2618 }
2619 return f, field.PkgPath
2620 }
2621
2622
2623
2624
2625 func typeptrdata(t *abi.Type) uintptr {
2626 switch t.Kind() {
2627 case abi.Struct:
2628 st := (*structType)(unsafe.Pointer(t))
2629
2630 field := -1
2631 for i := range st.Fields {
2632 ft := st.Fields[i].Typ
2633 if ft.Pointers() {
2634 field = i
2635 }
2636 }
2637 if field == -1 {
2638 return 0
2639 }
2640 f := st.Fields[field]
2641 return f.Offset + f.Typ.PtrBytes
2642
2643 default:
2644 panic("reflect.typeptrdata: unexpected type, " + stringFor(t))
2645 }
2646 }
2647
2648
2649
2650
2651
2652
2653 func ArrayOf(length int, elem Type) Type {
2654 if length < 0 {
2655 panic("reflect: negative length passed to ArrayOf")
2656 }
2657
2658 typ := elem.common()
2659
2660
2661 ckey := cacheKey{Array, typ, nil, uintptr(length)}
2662 if array, ok := lookupCache.Load(ckey); ok {
2663 return array.(Type)
2664 }
2665
2666
2667 s := "[" + strconv.Itoa(length) + "]" + stringFor(typ)
2668 for _, tt := range typesByString(s) {
2669 array := (*arrayType)(unsafe.Pointer(tt))
2670 if array.Elem == typ {
2671 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
2672 return ti.(Type)
2673 }
2674 }
2675
2676
2677 var iarray any = [1]unsafe.Pointer{}
2678 prototype := *(**arrayType)(unsafe.Pointer(&iarray))
2679 array := *prototype
2680 array.TFlag = typ.TFlag & abi.TFlagRegularMemory
2681 array.Str = resolveReflectName(newName(s, "", false, false))
2682 array.Hash = fnv1(typ.Hash, '[')
2683 for n := uint32(length); n > 0; n >>= 8 {
2684 array.Hash = fnv1(array.Hash, byte(n))
2685 }
2686 array.Hash = fnv1(array.Hash, ']')
2687 array.Elem = typ
2688 array.PtrToThis = 0
2689 if typ.Size_ > 0 {
2690 max := ^uintptr(0) / typ.Size_
2691 if uintptr(length) > max {
2692 panic("reflect.ArrayOf: array size would exceed virtual address space")
2693 }
2694 }
2695 array.Size_ = typ.Size_ * uintptr(length)
2696 if length > 0 && typ.Pointers() {
2697 array.PtrBytes = typ.Size_*uintptr(length-1) + typ.PtrBytes
2698 } else {
2699 array.PtrBytes = 0
2700 }
2701 array.Align_ = typ.Align_
2702 array.FieldAlign_ = typ.FieldAlign_
2703 array.Len = uintptr(length)
2704 array.Slice = &(SliceOf(elem).(*rtype).t)
2705
2706 switch {
2707 case array.PtrBytes == 0:
2708
2709 array.GCData = nil
2710
2711 case length == 1:
2712
2713
2714 array.TFlag |= typ.TFlag & abi.TFlagGCMaskOnDemand
2715 array.GCData = typ.GCData
2716
2717 case array.PtrBytes <= abi.MaxPtrmaskBytes*8*goarch.PtrSize:
2718
2719 n := (array.PtrBytes/goarch.PtrSize + 7) / 8
2720
2721 n = (n + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)
2722 mask := make([]byte, n)
2723 emitGCMask(mask, 0, typ, array.Len)
2724 array.GCData = &mask[0]
2725
2726 default:
2727
2728
2729 array.TFlag |= abi.TFlagGCMaskOnDemand
2730 array.GCData = (*byte)(unsafe.Pointer(new(uintptr)))
2731 if runtime.GOOS == "aix" {
2732 array.GCData = adjustAIXGCData(array.GCData)
2733 }
2734 }
2735
2736 etyp := typ
2737 esize := etyp.Size()
2738
2739 array.Equal = nil
2740 if eequal := etyp.Equal; eequal != nil {
2741 array.Equal = func(p, q unsafe.Pointer) bool {
2742 for i := 0; i < length; i++ {
2743 pi := arrayAt(p, i, esize, "i < length")
2744 qi := arrayAt(q, i, esize, "i < length")
2745 if !eequal(pi, qi) {
2746 return false
2747 }
2748
2749 }
2750 return true
2751 }
2752 }
2753
2754 switch {
2755 case array.Size_ == goarch.PtrSize && array.PtrBytes == goarch.PtrSize:
2756 array.TFlag |= abi.TFlagDirectIface
2757 default:
2758 array.TFlag &^= abi.TFlagDirectIface
2759 }
2760
2761 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&array.Type))
2762 return ti.(Type)
2763 }
2764
2765
2766
2767 func adjustAIXGCData(addr *byte) *byte {
2768 adjusted := adjustAIXGCDataForRuntime(addr)
2769 if adjusted != addr {
2770 pinAIXGCDataMu.Lock()
2771 pinAIXGCData = append(pinAIXGCData, addr)
2772 pinAIXGCDataMu.Unlock()
2773 }
2774 return adjusted
2775 }
2776
2777
2778
2779
2780
2781
2782 func adjustAIXGCDataForRuntime(*byte) *byte
2783
2784
2785 var pinAIXGCDataMu sync.Mutex
2786
2787
2788
2789
2790
2791 var pinAIXGCData []*byte
2792
2793 func appendVarint(x []byte, v uintptr) []byte {
2794 for ; v >= 0x80; v >>= 7 {
2795 x = append(x, byte(v|0x80))
2796 }
2797 x = append(x, byte(v))
2798 return x
2799 }
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819 func toType(t *abi.Type) Type {
2820 if t == nil {
2821 return nil
2822 }
2823 return toRType(t)
2824 }
2825
2826 type layoutKey struct {
2827 ftyp *funcType
2828 rcvr *abi.Type
2829 }
2830
2831 type layoutType struct {
2832 t *abi.Type
2833 framePool *sync.Pool
2834 abid abiDesc
2835 }
2836
2837 var layoutCache sync.Map
2838
2839
2840
2841
2842
2843
2844
2845
2846 func funcLayout(t *funcType, rcvr *abi.Type) (frametype *abi.Type, framePool *sync.Pool, abid abiDesc) {
2847 if t.Kind() != abi.Func {
2848 panic("reflect: funcLayout of non-func type " + stringFor(&t.Type))
2849 }
2850 if rcvr != nil && rcvr.Kind() == abi.Interface {
2851 panic("reflect: funcLayout with interface receiver " + stringFor(rcvr))
2852 }
2853 k := layoutKey{t, rcvr}
2854 if lti, ok := layoutCache.Load(k); ok {
2855 lt := lti.(layoutType)
2856 return lt.t, lt.framePool, lt.abid
2857 }
2858
2859
2860 abid = newAbiDesc(t, rcvr)
2861
2862
2863 x := &abi.Type{
2864 Align_: goarch.PtrSize,
2865
2866
2867
2868
2869 Size_: align(abid.retOffset+abid.ret.stackBytes, goarch.PtrSize),
2870 PtrBytes: uintptr(abid.stackPtrs.n) * goarch.PtrSize,
2871 }
2872 if abid.stackPtrs.n > 0 {
2873 x.GCData = &abid.stackPtrs.data[0]
2874 }
2875
2876 var s string
2877 if rcvr != nil {
2878 s = "methodargs(" + stringFor(rcvr) + ")(" + stringFor(&t.Type) + ")"
2879 } else {
2880 s = "funcargs(" + stringFor(&t.Type) + ")"
2881 }
2882 x.Str = resolveReflectName(newName(s, "", false, false))
2883
2884
2885 framePool = &sync.Pool{New: func() any {
2886 return unsafe_New(x)
2887 }}
2888 lti, _ := layoutCache.LoadOrStore(k, layoutType{
2889 t: x,
2890 framePool: framePool,
2891 abid: abid,
2892 })
2893 lt := lti.(layoutType)
2894 return lt.t, lt.framePool, lt.abid
2895 }
2896
2897
2898 type bitVector struct {
2899 n uint32
2900 data []byte
2901 }
2902
2903
2904 func (bv *bitVector) append(bit uint8) {
2905 if bv.n%(8*goarch.PtrSize) == 0 {
2906
2907
2908
2909 for i := 0; i < goarch.PtrSize; i++ {
2910 bv.data = append(bv.data, 0)
2911 }
2912 }
2913 bv.data[bv.n/8] |= bit << (bv.n % 8)
2914 bv.n++
2915 }
2916
2917 func addTypeBits(bv *bitVector, offset uintptr, t *abi.Type) {
2918 if !t.Pointers() {
2919 return
2920 }
2921
2922 switch Kind(t.Kind()) {
2923 case Chan, Func, Map, Pointer, Slice, String, UnsafePointer:
2924
2925 for bv.n < uint32(offset/goarch.PtrSize) {
2926 bv.append(0)
2927 }
2928 bv.append(1)
2929
2930 case Interface:
2931
2932 for bv.n < uint32(offset/goarch.PtrSize) {
2933 bv.append(0)
2934 }
2935 bv.append(1)
2936 bv.append(1)
2937
2938 case Array:
2939
2940 tt := (*arrayType)(unsafe.Pointer(t))
2941 for i := 0; i < int(tt.Len); i++ {
2942 addTypeBits(bv, offset+uintptr(i)*tt.Elem.Size_, tt.Elem)
2943 }
2944
2945 case Struct:
2946
2947 tt := (*structType)(unsafe.Pointer(t))
2948 for i := range tt.Fields {
2949 f := &tt.Fields[i]
2950 addTypeBits(bv, offset+f.Offset, f.Typ)
2951 }
2952 }
2953 }
2954
View as plain text