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