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 t = toType(typ)
1825
1826
1827 ckey := cacheKey{Chan, typ, nil, uintptr(dir)}
1828 if ch, ok := lookupCache.Load(ckey); ok {
1829 return ch.(*rtype)
1830 }
1831
1832
1833 if typ.Size_ >= 1<<16 {
1834 panic("reflect.ChanOf: element size too large")
1835 }
1836
1837
1838 var s string
1839 switch dir {
1840 default:
1841 panic("reflect.ChanOf: invalid dir")
1842 case SendDir:
1843 s = "chan<- " + stringFor(typ)
1844 case RecvDir:
1845 s = "<-chan " + stringFor(typ)
1846 case BothDir:
1847 typeStr := stringFor(typ)
1848 if typeStr[0] == '<' {
1849
1850
1851
1852
1853 s = "chan (" + typeStr + ")"
1854 } else {
1855 s = "chan " + typeStr
1856 }
1857 }
1858 for _, tt := range typesByString(s) {
1859 ch := (*chanType)(unsafe.Pointer(tt))
1860 if ch.Elem == typ && ch.Dir == abi.ChanDir(dir) {
1861 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
1862 return ti.(Type)
1863 }
1864 }
1865
1866
1867 var ichan any = (chan unsafe.Pointer)(nil)
1868 prototype := *(**chanType)(unsafe.Pointer(&ichan))
1869 ch := *prototype
1870 ch.TFlag = abi.TFlagRegularMemory | abi.TFlagDirectIface
1871 ch.Dir = abi.ChanDir(dir)
1872 ch.Str = resolveReflectName(newName(s, "", false, false))
1873 ch.Hash = fnv1(typ.Hash, 'c', byte(dir))
1874 ch.Elem = typ
1875
1876 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&ch.Type))
1877 return ti.(Type)
1878 }
1879
1880 var funcTypes []Type
1881 var funcTypesMutex sync.Mutex
1882
1883 func initFuncTypes(n int) Type {
1884 funcTypesMutex.Lock()
1885 defer funcTypesMutex.Unlock()
1886 if n >= len(funcTypes) {
1887 newFuncTypes := make([]Type, n+1)
1888 copy(newFuncTypes, funcTypes)
1889 funcTypes = newFuncTypes
1890 }
1891 if funcTypes[n] != nil {
1892 return funcTypes[n]
1893 }
1894
1895 funcTypes[n] = StructOf([]StructField{
1896 {
1897 Name: "FuncType",
1898 Type: TypeOf(funcType{}),
1899 },
1900 {
1901 Name: "Args",
1902 Type: ArrayOf(n, TypeOf(&rtype{})),
1903 },
1904 })
1905 return funcTypes[n]
1906 }
1907
1908
1909
1910
1911
1912
1913
1914
1915 func FuncOf(in, out []Type, variadic bool) Type {
1916 if variadic && (len(in) == 0 || toType(in[len(in)-1].common()).Kind() != Slice) {
1917 panic("reflect.FuncOf: last arg of variadic func must be slice")
1918 }
1919
1920
1921 var ifunc any = (func())(nil)
1922 prototype := *(**funcType)(unsafe.Pointer(&ifunc))
1923 n := len(in) + len(out)
1924
1925 if n > 128 {
1926 panic("reflect.FuncOf: too many arguments")
1927 }
1928
1929 o := New(initFuncTypes(n)).Elem()
1930 ft := (*funcType)(unsafe.Pointer(o.Field(0).Addr().Pointer()))
1931 args := unsafe.Slice((**rtype)(unsafe.Pointer(o.Field(1).Addr().Pointer())), n)[0:0:n]
1932 *ft = *prototype
1933
1934
1935 var hash uint32
1936 for _, in := range in {
1937 t := in.(*rtype)
1938 args = append(args, t)
1939 hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
1940 }
1941 if variadic {
1942 hash = fnv1(hash, 'v')
1943 }
1944 hash = fnv1(hash, '.')
1945 for _, out := range out {
1946 t := out.(*rtype)
1947 args = append(args, t)
1948 hash = fnv1(hash, byte(t.t.Hash>>24), byte(t.t.Hash>>16), byte(t.t.Hash>>8), byte(t.t.Hash))
1949 }
1950
1951 ft.TFlag = abi.TFlagDirectIface
1952 ft.Hash = hash
1953 ft.InCount = uint16(len(in))
1954 ft.OutCount = uint16(len(out))
1955 if variadic {
1956 ft.OutCount |= 1 << 15
1957 }
1958
1959
1960 if ts, ok := funcLookupCache.m.Load(hash); ok {
1961 for _, t := range ts.([]*abi.Type) {
1962 if haveIdenticalUnderlyingType(&ft.Type, t, true) {
1963 return toRType(t)
1964 }
1965 }
1966 }
1967
1968
1969 funcLookupCache.Lock()
1970 defer funcLookupCache.Unlock()
1971 if ts, ok := funcLookupCache.m.Load(hash); ok {
1972 for _, t := range ts.([]*abi.Type) {
1973 if haveIdenticalUnderlyingType(&ft.Type, t, true) {
1974 return toRType(t)
1975 }
1976 }
1977 }
1978
1979 addToCache := func(tt *abi.Type) Type {
1980 var rts []*abi.Type
1981 if rti, ok := funcLookupCache.m.Load(hash); ok {
1982 rts = rti.([]*abi.Type)
1983 }
1984 funcLookupCache.m.Store(hash, append(rts, tt))
1985 return toType(tt)
1986 }
1987
1988
1989 str := funcStr(ft)
1990 for _, tt := range typesByString(str) {
1991 if haveIdenticalUnderlyingType(&ft.Type, tt, true) {
1992 return addToCache(tt)
1993 }
1994 }
1995
1996
1997 ft.Str = resolveReflectName(newName(str, "", false, false))
1998 ft.PtrToThis = 0
1999 return addToCache(&ft.Type)
2000 }
2001 func stringFor(t *abi.Type) string {
2002 return toRType(t).String()
2003 }
2004
2005
2006 func funcStr(ft *funcType) string {
2007 repr := make([]byte, 0, 64)
2008 repr = append(repr, "func("...)
2009 for i, t := range ft.InSlice() {
2010 if i > 0 {
2011 repr = append(repr, ", "...)
2012 }
2013 if ft.IsVariadic() && i == int(ft.InCount)-1 {
2014 repr = append(repr, "..."...)
2015 repr = append(repr, stringFor((*sliceType)(unsafe.Pointer(t)).Elem)...)
2016 } else {
2017 repr = append(repr, stringFor(t)...)
2018 }
2019 }
2020 repr = append(repr, ')')
2021 out := ft.OutSlice()
2022 if len(out) == 1 {
2023 repr = append(repr, ' ')
2024 } else if len(out) > 1 {
2025 repr = append(repr, " ("...)
2026 }
2027 for i, t := range out {
2028 if i > 0 {
2029 repr = append(repr, ", "...)
2030 }
2031 repr = append(repr, stringFor(t)...)
2032 }
2033 if len(out) > 1 {
2034 repr = append(repr, ')')
2035 }
2036 return string(repr)
2037 }
2038
2039
2040
2041 func isReflexive(t *abi.Type) bool {
2042 switch Kind(t.Kind()) {
2043 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, String, UnsafePointer:
2044 return true
2045 case Float32, Float64, Complex64, Complex128, Interface:
2046 return false
2047 case Array:
2048 tt := (*arrayType)(unsafe.Pointer(t))
2049 return isReflexive(tt.Elem)
2050 case Struct:
2051 tt := (*structType)(unsafe.Pointer(t))
2052 for _, f := range tt.Fields {
2053 if !isReflexive(f.Typ) {
2054 return false
2055 }
2056 }
2057 return true
2058 default:
2059
2060 panic("isReflexive called on non-key type " + stringFor(t))
2061 }
2062 }
2063
2064
2065 func needKeyUpdate(t *abi.Type) bool {
2066 switch Kind(t.Kind()) {
2067 case Bool, Int, Int8, Int16, Int32, Int64, Uint, Uint8, Uint16, Uint32, Uint64, Uintptr, Chan, Pointer, UnsafePointer:
2068 return false
2069 case Float32, Float64, Complex64, Complex128, Interface, String:
2070
2071
2072
2073 return true
2074 case Array:
2075 tt := (*arrayType)(unsafe.Pointer(t))
2076 return needKeyUpdate(tt.Elem)
2077 case Struct:
2078 tt := (*structType)(unsafe.Pointer(t))
2079 for _, f := range tt.Fields {
2080 if needKeyUpdate(f.Typ) {
2081 return true
2082 }
2083 }
2084 return false
2085 default:
2086
2087 panic("needKeyUpdate called on non-key type " + stringFor(t))
2088 }
2089 }
2090
2091
2092 func hashMightPanic(t *abi.Type) bool {
2093 switch Kind(t.Kind()) {
2094 case Interface:
2095 return true
2096 case Array:
2097 tt := (*arrayType)(unsafe.Pointer(t))
2098 return hashMightPanic(tt.Elem)
2099 case Struct:
2100 tt := (*structType)(unsafe.Pointer(t))
2101 for _, f := range tt.Fields {
2102 if hashMightPanic(f.Typ) {
2103 return true
2104 }
2105 }
2106 return false
2107 default:
2108 return false
2109 }
2110 }
2111
2112
2113
2114 func emitGCMask(out []byte, base uintptr, typ *abi.Type, n uintptr) {
2115 ptrs := typ.PtrBytes / goarch.PtrSize
2116 words := typ.Size_ / goarch.PtrSize
2117 mask := typ.GcSlice(0, (ptrs+7)/8)
2118 for j := uintptr(0); j < ptrs; j++ {
2119 if (mask[j/8]>>(j%8))&1 != 0 {
2120 for i := uintptr(0); i < n; i++ {
2121 k := base + i*words + j
2122 out[k/8] |= 1 << (k % 8)
2123 }
2124 }
2125 }
2126 }
2127
2128
2129
2130 func SliceOf(t Type) Type {
2131 typ := t.common()
2132 t = toType(typ)
2133
2134
2135 ckey := cacheKey{Slice, typ, nil, 0}
2136 if slice, ok := lookupCache.Load(ckey); ok {
2137 return slice.(Type)
2138 }
2139
2140
2141 s := "[]" + stringFor(typ)
2142 for _, tt := range typesByString(s) {
2143 slice := (*sliceType)(unsafe.Pointer(tt))
2144 if slice.Elem == typ {
2145 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
2146 return ti.(Type)
2147 }
2148 }
2149
2150
2151 var islice any = ([]unsafe.Pointer)(nil)
2152 prototype := *(**sliceType)(unsafe.Pointer(&islice))
2153 slice := *prototype
2154 slice.TFlag = 0
2155 slice.Str = resolveReflectName(newName(s, "", false, false))
2156 slice.Hash = fnv1(typ.Hash, '[')
2157 slice.Elem = typ
2158 slice.PtrToThis = 0
2159
2160 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&slice.Type))
2161 return ti.(Type)
2162 }
2163
2164
2165
2166
2167 var structLookupCache struct {
2168 sync.Mutex
2169
2170
2171
2172 m sync.Map
2173 }
2174
2175 type structTypeUncommon struct {
2176 structType
2177 u uncommonType
2178 }
2179
2180
2181 func isLetter(ch rune) bool {
2182 return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= utf8.RuneSelf && unicode.IsLetter(ch)
2183 }
2184
2185
2186
2187
2188
2189
2190
2191 func isValidFieldName(fieldName string) bool {
2192 for i, c := range fieldName {
2193 if i == 0 && !isLetter(c) {
2194 return false
2195 }
2196
2197 if !(isLetter(c) || unicode.IsDigit(c)) {
2198 return false
2199 }
2200 }
2201
2202 return len(fieldName) > 0
2203 }
2204
2205
2206 func isRegularMemory(t Type) bool {
2207 switch t.Kind() {
2208 case Array:
2209 elem := t.Elem()
2210 if isRegularMemory(elem) {
2211 return true
2212 }
2213 return elem.Comparable() && t.Len() == 0
2214 case Int8, Int16, Int32, Int64, Int, Uint8, Uint16, Uint32, Uint64, Uint, Uintptr, Chan, Pointer, Bool, UnsafePointer:
2215 return true
2216 case Struct:
2217 num := t.NumField()
2218 switch num {
2219 case 0:
2220 return true
2221 case 1:
2222 field := t.Field(0)
2223 if field.Name == "_" {
2224 return false
2225 }
2226 return isRegularMemory(field.Type)
2227 default:
2228 for i := range num {
2229 field := t.Field(i)
2230 if field.Name == "_" || !isRegularMemory(field.Type) || isPaddedField(t, i) {
2231 return false
2232 }
2233 }
2234 return true
2235 }
2236 }
2237 return false
2238 }
2239
2240
2241
2242 func isPaddedField(t Type, i int) bool {
2243 field := t.Field(i)
2244 if i+1 < t.NumField() {
2245 return field.Offset+field.Type.Size() != t.Field(i+1).Offset
2246 }
2247 return field.Offset+field.Type.Size() != t.Size()
2248 }
2249
2250
2251
2252
2253
2254
2255
2256 func StructOf(fields []StructField) Type {
2257 var (
2258 hash = fnv1(0, []byte("struct {")...)
2259 size uintptr
2260 typalign uint8
2261 comparable = true
2262 methods []abi.Method
2263
2264 fs = make([]structField, len(fields))
2265 repr = make([]byte, 0, 64)
2266 fset = map[string]struct{}{}
2267 )
2268
2269 lastzero := uintptr(0)
2270 repr = append(repr, "struct {"...)
2271 pkgpath := ""
2272 for i, field := range fields {
2273 if field.Name == "" {
2274 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no name")
2275 }
2276 if !isValidFieldName(field.Name) {
2277 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has invalid name")
2278 }
2279 if field.Type == nil {
2280 panic("reflect.StructOf: field " + strconv.Itoa(i) + " has no type")
2281 }
2282 f, fpkgpath := runtimeStructField(field)
2283 ft := f.Typ
2284 if fpkgpath != "" {
2285 if pkgpath == "" {
2286 pkgpath = fpkgpath
2287 } else if pkgpath != fpkgpath {
2288 panic("reflect.StructOf: fields with different PkgPath " + pkgpath + " and " + fpkgpath)
2289 }
2290 }
2291
2292
2293 name := f.Name.Name()
2294 hash = fnv1(hash, []byte(name)...)
2295 if !f.Embedded() {
2296 repr = append(repr, (" " + name)...)
2297 } else {
2298
2299 if f.Typ.Kind() == abi.Pointer {
2300
2301 elem := ft.Elem()
2302 if k := elem.Kind(); k == abi.Pointer || k == abi.Interface {
2303 panic("reflect.StructOf: illegal embedded field type " + stringFor(ft))
2304 }
2305 }
2306
2307 switch Kind(f.Typ.Kind()) {
2308 case Interface:
2309 ift := (*interfaceType)(unsafe.Pointer(ft))
2310 for _, m := range ift.Methods {
2311 if pkgPath(ift.nameOff(m.Name)) != "" {
2312
2313 panic("reflect: embedded interface with unexported method(s) not implemented")
2314 }
2315
2316 fnStub := resolveReflectText(unsafe.Pointer(abi.FuncPCABIInternal(embeddedIfaceMethStub)))
2317 methods = append(methods, abi.Method{
2318 Name: resolveReflectName(ift.nameOff(m.Name)),
2319 Mtyp: resolveReflectType(ift.typeOff(m.Typ)),
2320 Ifn: fnStub,
2321 Tfn: fnStub,
2322 })
2323 }
2324 case Pointer:
2325 ptr := (*ptrType)(unsafe.Pointer(ft))
2326 if unt := ptr.Uncommon(); unt != nil {
2327 if i > 0 && unt.Mcount > 0 {
2328
2329 panic("reflect: embedded type with methods not implemented if type is not first field")
2330 }
2331 if len(fields) > 1 {
2332 panic("reflect: embedded type with methods not implemented if there is more than one field")
2333 }
2334 for _, m := range unt.Methods() {
2335 mname := nameOffFor(ft, m.Name)
2336 if pkgPath(mname) != "" {
2337
2338
2339 panic("reflect: embedded interface with unexported method(s) not implemented")
2340 }
2341 methods = append(methods, abi.Method{
2342 Name: resolveReflectName(mname),
2343 Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
2344 Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
2345 Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
2346 })
2347 }
2348 }
2349 if unt := ptr.Elem.Uncommon(); unt != nil {
2350 for _, m := range unt.Methods() {
2351 mname := nameOffFor(ft, m.Name)
2352 if pkgPath(mname) != "" {
2353
2354
2355 panic("reflect: embedded interface with unexported method(s) not implemented")
2356 }
2357 methods = append(methods, abi.Method{
2358 Name: resolveReflectName(mname),
2359 Mtyp: resolveReflectType(typeOffFor(ptr.Elem, m.Mtyp)),
2360 Ifn: resolveReflectText(textOffFor(ptr.Elem, m.Ifn)),
2361 Tfn: resolveReflectText(textOffFor(ptr.Elem, m.Tfn)),
2362 })
2363 }
2364 }
2365 default:
2366 if unt := ft.Uncommon(); unt != nil {
2367 if i > 0 && unt.Mcount > 0 {
2368
2369 panic("reflect: embedded type with methods not implemented if type is not first field")
2370 }
2371 if len(fields) > 1 && ft.IsDirectIface() {
2372 panic("reflect: embedded type with methods not implemented for non-pointer type")
2373 }
2374 for _, m := range unt.Methods() {
2375 mname := nameOffFor(ft, m.Name)
2376 if pkgPath(mname) != "" {
2377
2378
2379 panic("reflect: embedded interface with unexported method(s) not implemented")
2380 }
2381 methods = append(methods, abi.Method{
2382 Name: resolveReflectName(mname),
2383 Mtyp: resolveReflectType(typeOffFor(ft, m.Mtyp)),
2384 Ifn: resolveReflectText(textOffFor(ft, m.Ifn)),
2385 Tfn: resolveReflectText(textOffFor(ft, m.Tfn)),
2386 })
2387
2388 }
2389 }
2390 }
2391 }
2392 if _, dup := fset[name]; dup && name != "_" {
2393 panic("reflect.StructOf: duplicate field " + name)
2394 }
2395 fset[name] = struct{}{}
2396
2397 hash = fnv1(hash, byte(ft.Hash>>24), byte(ft.Hash>>16), byte(ft.Hash>>8), byte(ft.Hash))
2398
2399 repr = append(repr, (" " + stringFor(ft))...)
2400 if f.Name.HasTag() {
2401 hash = fnv1(hash, []byte(f.Name.Tag())...)
2402 repr = append(repr, (" " + strconv.Quote(f.Name.Tag()))...)
2403 }
2404 if i < len(fields)-1 {
2405 repr = append(repr, ';')
2406 }
2407
2408 comparable = comparable && (ft.Equal != nil)
2409
2410 offset := align(size, uintptr(ft.Align_))
2411 if offset < size {
2412 panic("reflect.StructOf: struct size would exceed virtual address space")
2413 }
2414 if ft.Align_ > typalign {
2415 typalign = ft.Align_
2416 }
2417 size = offset + ft.Size_
2418 if size < offset {
2419 panic("reflect.StructOf: struct size would exceed virtual address space")
2420 }
2421 f.Offset = offset
2422
2423 if ft.Size_ == 0 {
2424 lastzero = size
2425 }
2426
2427 fs[i] = f
2428 }
2429
2430 if size > 0 && lastzero == size {
2431
2432
2433
2434
2435
2436 size++
2437 if size == 0 {
2438 panic("reflect.StructOf: struct size would exceed virtual address space")
2439 }
2440 }
2441
2442 var typ *structType
2443 var ut *uncommonType
2444
2445 if len(methods) == 0 {
2446 t := new(structTypeUncommon)
2447 typ = &t.structType
2448 ut = &t.u
2449 } else {
2450
2451
2452
2453
2454
2455 tt := New(StructOf([]StructField{
2456 {Name: "S", Type: TypeOf(structType{})},
2457 {Name: "U", Type: TypeOf(uncommonType{})},
2458 {Name: "M", Type: ArrayOf(len(methods), TypeOf(methods[0]))},
2459 }))
2460
2461 typ = (*structType)(tt.Elem().Field(0).Addr().UnsafePointer())
2462 ut = (*uncommonType)(tt.Elem().Field(1).Addr().UnsafePointer())
2463
2464 copy(tt.Elem().Field(2).Slice(0, len(methods)).Interface().([]abi.Method), methods)
2465 }
2466
2467
2468
2469
2470 ut.Mcount = uint16(len(methods))
2471 ut.Xcount = ut.Mcount
2472 ut.Moff = uint32(unsafe.Sizeof(uncommonType{}))
2473
2474 if len(fs) > 0 {
2475 repr = append(repr, ' ')
2476 }
2477 repr = append(repr, '}')
2478 hash = fnv1(hash, '}')
2479 str := string(repr)
2480
2481
2482 s := align(size, uintptr(typalign))
2483 if s < size {
2484 panic("reflect.StructOf: struct size would exceed virtual address space")
2485 }
2486 size = s
2487
2488
2489 var istruct any = struct{}{}
2490 prototype := *(**structType)(unsafe.Pointer(&istruct))
2491 *typ = *prototype
2492 typ.Fields = fs
2493 if pkgpath != "" {
2494 typ.PkgPath = newName(pkgpath, "", false, false)
2495 }
2496
2497
2498 if ts, ok := structLookupCache.m.Load(hash); ok {
2499 for _, st := range ts.([]Type) {
2500 t := st.common()
2501 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2502 return toType(t)
2503 }
2504 }
2505 }
2506
2507
2508 structLookupCache.Lock()
2509 defer structLookupCache.Unlock()
2510 if ts, ok := structLookupCache.m.Load(hash); ok {
2511 for _, st := range ts.([]Type) {
2512 t := st.common()
2513 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2514 return toType(t)
2515 }
2516 }
2517 }
2518
2519 addToCache := func(t Type) Type {
2520 var ts []Type
2521 if ti, ok := structLookupCache.m.Load(hash); ok {
2522 ts = ti.([]Type)
2523 }
2524 structLookupCache.m.Store(hash, append(ts, t))
2525 return t
2526 }
2527
2528
2529 for _, t := range typesByString(str) {
2530 if haveIdenticalUnderlyingType(&typ.Type, t, true) {
2531
2532
2533
2534 return addToCache(toType(t))
2535 }
2536 }
2537
2538 typ.Str = resolveReflectName(newName(str, "", false, false))
2539 if isRegularMemory(toType(&typ.Type)) {
2540 typ.TFlag = abi.TFlagRegularMemory
2541 } else {
2542 typ.TFlag = 0
2543 }
2544 typ.Hash = hash
2545 typ.Size_ = size
2546 typ.PtrBytes = typeptrdata(&typ.Type)
2547 typ.Align_ = typalign
2548 typ.FieldAlign_ = typalign
2549 typ.PtrToThis = 0
2550 if len(methods) > 0 {
2551 typ.TFlag |= abi.TFlagUncommon
2552 }
2553
2554 if typ.PtrBytes == 0 {
2555 typ.GCData = nil
2556 } else if typ.PtrBytes <= abi.MaxPtrmaskBytes*8*goarch.PtrSize {
2557 bv := new(bitVector)
2558 addTypeBits(bv, 0, &typ.Type)
2559 typ.GCData = &bv.data[0]
2560 } else {
2561
2562
2563 typ.TFlag |= abi.TFlagGCMaskOnDemand
2564 typ.GCData = (*byte)(unsafe.Pointer(new(uintptr)))
2565 if runtime.GOOS == "aix" {
2566 typ.GCData = adjustAIXGCData(typ.GCData)
2567 }
2568 }
2569
2570 typ.Equal = nil
2571 if comparable {
2572 typ.Equal = func(p, q unsafe.Pointer) bool {
2573 for _, ft := range typ.Fields {
2574 pi := add(p, ft.Offset, "&x.field safe")
2575 qi := add(q, ft.Offset, "&x.field safe")
2576 if !ft.Typ.Equal(pi, qi) {
2577 return false
2578 }
2579 }
2580 return true
2581 }
2582 }
2583
2584 switch {
2585 case typ.Size_ == goarch.PtrSize && typ.PtrBytes == goarch.PtrSize:
2586 typ.TFlag |= abi.TFlagDirectIface
2587 default:
2588 typ.TFlag &^= abi.TFlagDirectIface
2589 }
2590
2591 return addToCache(toType(&typ.Type))
2592 }
2593
2594 func embeddedIfaceMethStub() {
2595 panic("reflect: StructOf does not support methods of embedded interfaces")
2596 }
2597
2598
2599
2600
2601 func runtimeStructField(field StructField) (structField, string) {
2602 if field.Anonymous && field.PkgPath != "" {
2603 panic("reflect.StructOf: field \"" + field.Name + "\" is anonymous but has PkgPath set")
2604 }
2605
2606 if field.IsExported() {
2607
2608
2609 c := field.Name[0]
2610 if 'a' <= c && c <= 'z' || c == '_' {
2611 panic("reflect.StructOf: field \"" + field.Name + "\" is unexported but missing PkgPath")
2612 }
2613 }
2614
2615 resolveReflectType(field.Type.common())
2616 f := structField{
2617 Name: newName(field.Name, string(field.Tag), field.IsExported(), field.Anonymous),
2618 Typ: field.Type.common(),
2619 Offset: 0,
2620 }
2621 return f, field.PkgPath
2622 }
2623
2624
2625
2626
2627 func typeptrdata(t *abi.Type) uintptr {
2628 switch t.Kind() {
2629 case abi.Struct:
2630 st := (*structType)(unsafe.Pointer(t))
2631
2632 field := -1
2633 for i := range st.Fields {
2634 ft := st.Fields[i].Typ
2635 if ft.Pointers() {
2636 field = i
2637 }
2638 }
2639 if field == -1 {
2640 return 0
2641 }
2642 f := st.Fields[field]
2643 return f.Offset + f.Typ.PtrBytes
2644
2645 default:
2646 panic("reflect.typeptrdata: unexpected type, " + stringFor(t))
2647 }
2648 }
2649
2650
2651
2652
2653
2654
2655 func ArrayOf(length int, elem Type) Type {
2656 if length < 0 {
2657 panic("reflect: negative length passed to ArrayOf")
2658 }
2659
2660 typ := elem.common()
2661 elem = toType(typ)
2662
2663
2664 ckey := cacheKey{Array, typ, nil, uintptr(length)}
2665 if array, ok := lookupCache.Load(ckey); ok {
2666 return array.(Type)
2667 }
2668
2669
2670 s := "[" + strconv.Itoa(length) + "]" + stringFor(typ)
2671 for _, tt := range typesByString(s) {
2672 array := (*arrayType)(unsafe.Pointer(tt))
2673 if array.Elem == typ {
2674 ti, _ := lookupCache.LoadOrStore(ckey, toRType(tt))
2675 return ti.(Type)
2676 }
2677 }
2678
2679
2680 var iarray any = [1]unsafe.Pointer{}
2681 prototype := *(**arrayType)(unsafe.Pointer(&iarray))
2682 array := *prototype
2683 array.TFlag = typ.TFlag & abi.TFlagRegularMemory
2684 array.Str = resolveReflectName(newName(s, "", false, false))
2685 array.Hash = fnv1(typ.Hash, '[')
2686 for n := uint32(length); n > 0; n >>= 8 {
2687 array.Hash = fnv1(array.Hash, byte(n))
2688 }
2689 array.Hash = fnv1(array.Hash, ']')
2690 array.Elem = typ
2691 array.PtrToThis = 0
2692 if typ.Size_ > 0 {
2693 max := ^uintptr(0) / typ.Size_
2694 if uintptr(length) > max {
2695 panic("reflect.ArrayOf: array size would exceed virtual address space")
2696 }
2697 }
2698 array.Size_ = typ.Size_ * uintptr(length)
2699 if length > 0 && typ.Pointers() {
2700 array.PtrBytes = typ.Size_*uintptr(length-1) + typ.PtrBytes
2701 } else {
2702 array.PtrBytes = 0
2703 }
2704 array.Align_ = typ.Align_
2705 array.FieldAlign_ = typ.FieldAlign_
2706 array.Len = uintptr(length)
2707 array.Slice = &(SliceOf(elem).(*rtype).t)
2708
2709 switch {
2710 case array.PtrBytes == 0:
2711
2712 array.GCData = nil
2713
2714 case length == 1:
2715
2716
2717 array.TFlag |= typ.TFlag & abi.TFlagGCMaskOnDemand
2718 array.GCData = typ.GCData
2719
2720 case array.PtrBytes <= abi.MaxPtrmaskBytes*8*goarch.PtrSize:
2721
2722 n := (array.PtrBytes/goarch.PtrSize + 7) / 8
2723
2724 n = (n + goarch.PtrSize - 1) &^ (goarch.PtrSize - 1)
2725 mask := make([]byte, n)
2726 emitGCMask(mask, 0, typ, array.Len)
2727 array.GCData = &mask[0]
2728
2729 default:
2730
2731
2732 array.TFlag |= abi.TFlagGCMaskOnDemand
2733 array.GCData = (*byte)(unsafe.Pointer(new(uintptr)))
2734 if runtime.GOOS == "aix" {
2735 array.GCData = adjustAIXGCData(array.GCData)
2736 }
2737 }
2738
2739 etyp := typ
2740 esize := etyp.Size()
2741
2742 array.Equal = nil
2743 if eequal := etyp.Equal; eequal != nil {
2744 array.Equal = func(p, q unsafe.Pointer) bool {
2745 for i := 0; i < length; i++ {
2746 pi := arrayAt(p, i, esize, "i < length")
2747 qi := arrayAt(q, i, esize, "i < length")
2748 if !eequal(pi, qi) {
2749 return false
2750 }
2751
2752 }
2753 return true
2754 }
2755 }
2756
2757 switch {
2758 case array.Size_ == goarch.PtrSize && array.PtrBytes == goarch.PtrSize:
2759 array.TFlag |= abi.TFlagDirectIface
2760 default:
2761 array.TFlag &^= abi.TFlagDirectIface
2762 }
2763
2764 ti, _ := lookupCache.LoadOrStore(ckey, toRType(&array.Type))
2765 return ti.(Type)
2766 }
2767
2768
2769
2770 func adjustAIXGCData(addr *byte) *byte {
2771 adjusted := adjustAIXGCDataForRuntime(addr)
2772 if adjusted != addr {
2773 pinAIXGCDataMu.Lock()
2774 pinAIXGCData = append(pinAIXGCData, addr)
2775 pinAIXGCDataMu.Unlock()
2776 }
2777 return adjusted
2778 }
2779
2780
2781
2782
2783
2784
2785 func adjustAIXGCDataForRuntime(*byte) *byte
2786
2787
2788 var pinAIXGCDataMu sync.Mutex
2789
2790
2791
2792
2793
2794 var pinAIXGCData []*byte
2795
2796 func appendVarint(x []byte, v uintptr) []byte {
2797 for ; v >= 0x80; v >>= 7 {
2798 x = append(x, byte(v|0x80))
2799 }
2800 x = append(x, byte(v))
2801 return x
2802 }
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822 func toType(t *abi.Type) Type {
2823 if t == nil {
2824 return nil
2825 }
2826 return toRType(t)
2827 }
2828
2829 type layoutKey struct {
2830 ftyp *funcType
2831 rcvr *abi.Type
2832 }
2833
2834 type layoutType struct {
2835 t *abi.Type
2836 framePool *sync.Pool
2837 abid abiDesc
2838 }
2839
2840 var layoutCache sync.Map
2841
2842
2843
2844
2845
2846
2847
2848
2849 func funcLayout(t *funcType, rcvr *abi.Type) (frametype *abi.Type, framePool *sync.Pool, abid abiDesc) {
2850 if t.Kind() != abi.Func {
2851 panic("reflect: funcLayout of non-func type " + stringFor(&t.Type))
2852 }
2853 if rcvr != nil && rcvr.Kind() == abi.Interface {
2854 panic("reflect: funcLayout with interface receiver " + stringFor(rcvr))
2855 }
2856 k := layoutKey{t, rcvr}
2857 if lti, ok := layoutCache.Load(k); ok {
2858 lt := lti.(layoutType)
2859 return lt.t, lt.framePool, lt.abid
2860 }
2861
2862
2863 abid = newAbiDesc(t, rcvr)
2864
2865
2866 x := &abi.Type{
2867 Align_: goarch.PtrSize,
2868
2869
2870
2871
2872 Size_: align(abid.retOffset+abid.ret.stackBytes, goarch.PtrSize),
2873 PtrBytes: uintptr(abid.stackPtrs.n) * goarch.PtrSize,
2874 }
2875 if abid.stackPtrs.n > 0 {
2876 x.GCData = &abid.stackPtrs.data[0]
2877 }
2878
2879 var s string
2880 if rcvr != nil {
2881 s = "methodargs(" + stringFor(rcvr) + ")(" + stringFor(&t.Type) + ")"
2882 } else {
2883 s = "funcargs(" + stringFor(&t.Type) + ")"
2884 }
2885 x.Str = resolveReflectName(newName(s, "", false, false))
2886
2887
2888 framePool = &sync.Pool{New: func() any {
2889 return unsafe_New(x)
2890 }}
2891 lti, _ := layoutCache.LoadOrStore(k, layoutType{
2892 t: x,
2893 framePool: framePool,
2894 abid: abid,
2895 })
2896 lt := lti.(layoutType)
2897 return lt.t, lt.framePool, lt.abid
2898 }
2899
2900
2901 type bitVector struct {
2902 n uint32
2903 data []byte
2904 }
2905
2906
2907 func (bv *bitVector) append(bit uint8) {
2908 if bv.n%(8*goarch.PtrSize) == 0 {
2909
2910
2911
2912 for i := 0; i < goarch.PtrSize; i++ {
2913 bv.data = append(bv.data, 0)
2914 }
2915 }
2916 bv.data[bv.n/8] |= bit << (bv.n % 8)
2917 bv.n++
2918 }
2919
2920 func addTypeBits(bv *bitVector, offset uintptr, t *abi.Type) {
2921 if !t.Pointers() {
2922 return
2923 }
2924
2925 switch Kind(t.Kind()) {
2926 case Chan, Func, Map, Pointer, Slice, String, UnsafePointer:
2927
2928 for bv.n < uint32(offset/goarch.PtrSize) {
2929 bv.append(0)
2930 }
2931 bv.append(1)
2932
2933 case Interface:
2934
2935 for bv.n < uint32(offset/goarch.PtrSize) {
2936 bv.append(0)
2937 }
2938 bv.append(1)
2939 bv.append(1)
2940
2941 case Array:
2942
2943 tt := (*arrayType)(unsafe.Pointer(t))
2944 for i := 0; i < int(tt.Len); i++ {
2945 addTypeBits(bv, offset+uintptr(i)*tt.Elem.Size_, tt.Elem)
2946 }
2947
2948 case Struct:
2949
2950 tt := (*structType)(unsafe.Pointer(t))
2951 for i := range tt.Fields {
2952 f := &tt.Fields[i]
2953 addTypeBits(bv, offset+f.Offset, f.Typ)
2954 }
2955 }
2956 }
2957
View as plain text