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