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