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