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