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