1
2
3
4
5 package abi
6
7 import (
8 "internal/goarch"
9 "unsafe"
10 )
11
12
13
14
15
16
17
18
19
20
21 type Type struct {
22 Size_ uintptr
23 PtrBytes uintptr
24 Hash uint32
25 TFlag TFlag
26 Align_ uint8
27 FieldAlign_ uint8
28 Kind_ Kind
29
30
31 Equal func(unsafe.Pointer, unsafe.Pointer) bool
32
33
34
35
36
37
38
39
40
41
42
43 GCData *byte
44 Str NameOff
45 PtrToThis TypeOff
46 }
47
48
49
50 type Kind uint8
51
52 const (
53 Invalid Kind = iota
54 Bool
55 Int
56 Int8
57 Int16
58 Int32
59 Int64
60 Uint
61 Uint8
62 Uint16
63 Uint32
64 Uint64
65 Uintptr
66 Float32
67 Float64
68 Complex64
69 Complex128
70 Array
71 Chan
72 Func
73 Interface
74 Map
75 Pointer
76 Slice
77 String
78 Struct
79 UnsafePointer
80 )
81
82
83
84 type TFlag uint8
85
86 const (
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 TFlagUncommon TFlag = 1 << 0
103
104
105
106
107
108 TFlagExtraStar TFlag = 1 << 1
109
110
111 TFlagNamed TFlag = 1 << 2
112
113
114
115 TFlagRegularMemory TFlag = 1 << 3
116
117
118
119
120
121
122 TFlagGCMaskOnDemand TFlag = 1 << 4
123
124
125
126
127 TFlagDirectIface TFlag = 1 << 5
128
129
130
131 KindDirectIface Kind = 1 << 5
132 )
133
134
135 type NameOff int32
136
137
138 type TypeOff int32
139
140
141 type TextOff int32
142
143
144 func (k Kind) String() string {
145 if int(k) < len(kindNames) {
146 return kindNames[k]
147 }
148 return kindNames[0]
149 }
150
151 var kindNames = []string{
152 Invalid: "invalid",
153 Bool: "bool",
154 Int: "int",
155 Int8: "int8",
156 Int16: "int16",
157 Int32: "int32",
158 Int64: "int64",
159 Uint: "uint",
160 Uint8: "uint8",
161 Uint16: "uint16",
162 Uint32: "uint32",
163 Uint64: "uint64",
164 Uintptr: "uintptr",
165 Float32: "float32",
166 Float64: "float64",
167 Complex64: "complex64",
168 Complex128: "complex128",
169 Array: "array",
170 Chan: "chan",
171 Func: "func",
172 Interface: "interface",
173 Map: "map",
174 Pointer: "ptr",
175 Slice: "slice",
176 String: "string",
177 Struct: "struct",
178 UnsafePointer: "unsafe.Pointer",
179 }
180
181
182 func TypeOf(a any) *Type {
183 eface := *(*EmptyInterface)(unsafe.Pointer(&a))
184
185
186
187
188
189 return (*Type)(NoEscape(unsafe.Pointer(eface.Type)))
190 }
191
192
193 func TypeFor[T any]() *Type {
194 return (*PtrType)(unsafe.Pointer(TypeOf((*T)(nil)))).Elem
195 }
196
197 func (t *Type) Kind() Kind { return t.Kind_ }
198
199 func (t *Type) HasName() bool {
200 return t.TFlag&TFlagNamed != 0
201 }
202
203
204 func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
205
206
207 func (t *Type) IsDirectIface() bool {
208 return t.TFlag&TFlagDirectIface != 0
209 }
210
211 func (t *Type) GcSlice(begin, end uintptr) []byte {
212 if t.TFlag&TFlagGCMaskOnDemand != 0 {
213 panic("GcSlice can't handle on-demand gcdata types")
214 }
215 return unsafe.Slice(t.GCData, int(end))[begin:]
216 }
217
218
219 type Method struct {
220 Name NameOff
221 Mtyp TypeOff
222 Ifn TextOff
223 Tfn TextOff
224 }
225
226
227
228
229
230 type UncommonType struct {
231 PkgPath NameOff
232 Mcount uint16
233 Xcount uint16
234 Moff uint32
235 _ uint32
236 }
237
238 func (t *UncommonType) Methods() []Method {
239 if t.Mcount == 0 {
240 return nil
241 }
242 return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
243 }
244
245 func (t *UncommonType) ExportedMethods() []Method {
246 if t.Xcount == 0 {
247 return nil
248 }
249 return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
250 }
251
252
253
254
255
256
257
258
259 func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
260 return unsafe.Pointer(uintptr(p) + x)
261 }
262
263
264 type Imethod struct {
265 Name NameOff
266 Typ TypeOff
267 }
268
269
270 type ArrayType struct {
271 Type
272 Elem *Type
273 Slice *Type
274 Len uintptr
275 }
276
277
278 func (t *Type) Len() int {
279 if t.Kind() == Array {
280 return int((*ArrayType)(unsafe.Pointer(t)).Len)
281 }
282 return 0
283 }
284
285 func (t *Type) Common() *Type {
286 return t
287 }
288
289 type ChanDir int
290
291 const (
292 RecvDir ChanDir = 1 << iota
293 SendDir
294 BothDir = RecvDir | SendDir
295 InvalidDir ChanDir = 0
296 )
297
298
299 type ChanType struct {
300 Type
301 Elem *Type
302 Dir ChanDir
303 }
304
305 type structTypeUncommon struct {
306 StructType
307 u UncommonType
308 }
309
310
311 func (t *Type) ChanDir() ChanDir {
312 if t.Kind() == Chan {
313 ch := (*ChanType)(unsafe.Pointer(t))
314 return ch.Dir
315 }
316 return InvalidDir
317 }
318
319
320 func (t *Type) Uncommon() *UncommonType {
321 if t.TFlag&TFlagUncommon == 0 {
322 return nil
323 }
324 switch t.Kind() {
325 case Struct:
326 return &(*structTypeUncommon)(unsafe.Pointer(t)).u
327 case Pointer:
328 type u struct {
329 PtrType
330 u UncommonType
331 }
332 return &(*u)(unsafe.Pointer(t)).u
333 case Func:
334 type u struct {
335 FuncType
336 u UncommonType
337 }
338 return &(*u)(unsafe.Pointer(t)).u
339 case Slice:
340 type u struct {
341 SliceType
342 u UncommonType
343 }
344 return &(*u)(unsafe.Pointer(t)).u
345 case Array:
346 type u struct {
347 ArrayType
348 u UncommonType
349 }
350 return &(*u)(unsafe.Pointer(t)).u
351 case Chan:
352 type u struct {
353 ChanType
354 u UncommonType
355 }
356 return &(*u)(unsafe.Pointer(t)).u
357 case Map:
358 type u struct {
359 MapType
360 u UncommonType
361 }
362 return &(*u)(unsafe.Pointer(t)).u
363 case Interface:
364 type u struct {
365 InterfaceType
366 u UncommonType
367 }
368 return &(*u)(unsafe.Pointer(t)).u
369 default:
370 type u struct {
371 Type
372 u UncommonType
373 }
374 return &(*u)(unsafe.Pointer(t)).u
375 }
376 }
377
378
379 func (t *Type) Elem() *Type {
380 switch t.Kind() {
381 case Array:
382 tt := (*ArrayType)(unsafe.Pointer(t))
383 return tt.Elem
384 case Chan:
385 tt := (*ChanType)(unsafe.Pointer(t))
386 return tt.Elem
387 case Map:
388 tt := (*MapType)(unsafe.Pointer(t))
389 return tt.Elem
390 case Pointer:
391 tt := (*PtrType)(unsafe.Pointer(t))
392 return tt.Elem
393 case Slice:
394 tt := (*SliceType)(unsafe.Pointer(t))
395 return tt.Elem
396 }
397 return nil
398 }
399
400
401 func (t *Type) StructType() *StructType {
402 if t.Kind() != Struct {
403 return nil
404 }
405 return (*StructType)(unsafe.Pointer(t))
406 }
407
408
409 func (t *Type) MapType() *MapType {
410 if t.Kind() != Map {
411 return nil
412 }
413 return (*MapType)(unsafe.Pointer(t))
414 }
415
416
417 func (t *Type) PointerType() *PtrType {
418 if t.Kind() != Pointer {
419 return nil
420 }
421 return (*PtrType)(unsafe.Pointer(t))
422 }
423
424
425 func (t *Type) SliceType() *SliceType {
426 if t.Kind() != Slice {
427 return nil
428 }
429 return (*SliceType)(unsafe.Pointer(t))
430 }
431
432
433 func (t *Type) ArrayType() *ArrayType {
434 if t.Kind() != Array {
435 return nil
436 }
437 return (*ArrayType)(unsafe.Pointer(t))
438 }
439
440
441 func (t *Type) ChanType() *ChanType {
442 if t.Kind() != Chan {
443 return nil
444 }
445 return (*ChanType)(unsafe.Pointer(t))
446 }
447
448
449 func (t *Type) FuncType() *FuncType {
450 if t.Kind() != Func {
451 return nil
452 }
453 return (*FuncType)(unsafe.Pointer(t))
454 }
455
456
457 func (t *Type) InterfaceType() *InterfaceType {
458 if t.Kind() != Interface {
459 return nil
460 }
461 return (*InterfaceType)(unsafe.Pointer(t))
462 }
463
464
465 func (t *Type) Size() uintptr { return t.Size_ }
466
467
468 func (t *Type) Align() int { return int(t.Align_) }
469
470 func (t *Type) FieldAlign() int { return int(t.FieldAlign_) }
471
472 type InterfaceType struct {
473 Type
474 PkgPath Name
475 Methods []Imethod
476 }
477
478 func (t *Type) ExportedMethods() []Method {
479 ut := t.Uncommon()
480 if ut == nil {
481 return nil
482 }
483 return ut.ExportedMethods()
484 }
485
486 func (t *Type) NumMethod() int {
487 if t.Kind() == Interface {
488 tt := (*InterfaceType)(unsafe.Pointer(t))
489 return tt.NumMethod()
490 }
491 return len(t.ExportedMethods())
492 }
493
494
495 func (t *InterfaceType) NumMethod() int { return len(t.Methods) }
496
497 func (t *Type) Key() *Type {
498 if t.Kind() == Map {
499 return (*MapType)(unsafe.Pointer(t)).Key
500 }
501 return nil
502 }
503
504 type SliceType struct {
505 Type
506 Elem *Type
507 }
508
509
510
511
512
513
514
515
516
517
518
519
520 type FuncType struct {
521 Type
522 InCount uint16
523 OutCount uint16
524 }
525
526 func (t *FuncType) In(i int) *Type {
527 return t.InSlice()[i]
528 }
529
530 func (t *FuncType) NumIn() int {
531 return int(t.InCount)
532 }
533
534 func (t *FuncType) NumOut() int {
535 return int(t.OutCount & (1<<15 - 1))
536 }
537
538 func (t *FuncType) Out(i int) *Type {
539 return (t.OutSlice()[i])
540 }
541
542 func (t *FuncType) InSlice() []*Type {
543 uadd := unsafe.Sizeof(*t)
544 if t.TFlag&TFlagUncommon != 0 {
545 uadd += unsafe.Sizeof(UncommonType{})
546 }
547 if t.InCount == 0 {
548 return nil
549 }
550 return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
551 }
552 func (t *FuncType) OutSlice() []*Type {
553 outCount := uint16(t.NumOut())
554 if outCount == 0 {
555 return nil
556 }
557 uadd := unsafe.Sizeof(*t)
558 if t.TFlag&TFlagUncommon != 0 {
559 uadd += unsafe.Sizeof(UncommonType{})
560 }
561 return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
562 }
563
564 func (t *FuncType) IsVariadic() bool {
565 return t.OutCount&(1<<15) != 0
566 }
567
568 type PtrType struct {
569 Type
570 Elem *Type
571 }
572
573 type StructField struct {
574 Name Name
575 Typ *Type
576 Offset uintptr
577 }
578
579 func (f *StructField) Embedded() bool {
580 return f.Name.IsEmbedded()
581 }
582
583 type StructType struct {
584 Type
585 PkgPath Name
586 Fields []StructField
587 }
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615 type Name struct {
616 Bytes *byte
617 }
618
619
620
621 func (n Name) DataChecked(off int, whySafe string) *byte {
622 return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
623 }
624
625
626
627 func (n Name) Data(off int) *byte {
628 return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
629 }
630
631
632 func (n Name) IsExported() bool {
633 return (*n.Bytes)&(1<<0) != 0
634 }
635
636
637 func (n Name) HasTag() bool {
638 return (*n.Bytes)&(1<<1) != 0
639 }
640
641
642 func (n Name) IsEmbedded() bool {
643 return (*n.Bytes)&(1<<3) != 0
644 }
645
646
647
648 func (n Name) ReadVarint(off int) (int, int) {
649 v := 0
650 for i := 0; ; i++ {
651 x := *n.DataChecked(off+i, "read varint")
652 v += int(x&0x7f) << (7 * i)
653 if x&0x80 == 0 {
654 return i + 1, v
655 }
656 }
657 }
658
659
660 func (n Name) IsBlank() bool {
661 if n.Bytes == nil {
662 return false
663 }
664 _, l := n.ReadVarint(1)
665 return l == 1 && *n.Data(2) == '_'
666 }
667
668
669
670
671 func writeVarint(buf []byte, n int) int {
672 for i := 0; ; i++ {
673 b := byte(n & 0x7f)
674 n >>= 7
675 if n == 0 {
676 buf[i] = b
677 return i + 1
678 }
679 buf[i] = b | 0x80
680 }
681 }
682
683
684 func (n Name) Name() string {
685 if n.Bytes == nil {
686 return ""
687 }
688 i, l := n.ReadVarint(1)
689 return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
690 }
691
692
693 func (n Name) Tag() string {
694 if !n.HasTag() {
695 return ""
696 }
697 i, l := n.ReadVarint(1)
698 i2, l2 := n.ReadVarint(1 + i + l)
699 return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
700 }
701
702 func NewName(n, tag string, exported, embedded bool) Name {
703 if len(n) >= 1<<29 {
704 panic("abi.NewName: name too long: " + n[:1024] + "...")
705 }
706 if len(tag) >= 1<<29 {
707 panic("abi.NewName: tag too long: " + tag[:1024] + "...")
708 }
709 var nameLen [10]byte
710 var tagLen [10]byte
711 nameLenLen := writeVarint(nameLen[:], len(n))
712 tagLenLen := writeVarint(tagLen[:], len(tag))
713
714 var bits byte
715 l := 1 + nameLenLen + len(n)
716 if exported {
717 bits |= 1 << 0
718 }
719 if len(tag) > 0 {
720 l += tagLenLen + len(tag)
721 bits |= 1 << 1
722 }
723 if embedded {
724 bits |= 1 << 3
725 }
726
727 b := make([]byte, l)
728 b[0] = bits
729 copy(b[1:], nameLen[:nameLenLen])
730 copy(b[1+nameLenLen:], n)
731 if len(tag) > 0 {
732 tb := b[1+nameLenLen+len(n):]
733 copy(tb, tagLen[:tagLenLen])
734 copy(tb[tagLenLen:], tag)
735 }
736
737 return Name{Bytes: &b[0]}
738 }
739
740
741
742
743
744
745
746
747
748
749
750 func (t *Type) DescriptorSize() int {
751 var baseSize, addSize int
752 switch t.Kind_ {
753 case Array:
754 baseSize, addSize = t.ArrayType().descriptorSizes()
755 case Chan:
756 baseSize, addSize = t.ChanType().descriptorSizes()
757 case Func:
758 baseSize, addSize = t.FuncType().descriptorSizes()
759 case Interface:
760 baseSize, addSize = t.InterfaceType().descriptorSizes()
761 case Map:
762 baseSize, addSize = t.MapType().descriptorSizes()
763 case Pointer:
764 baseSize, addSize = t.PointerType().descriptorSizes()
765 case Slice:
766 baseSize, addSize = t.SliceType().descriptorSizes()
767 case Struct:
768 baseSize, addSize = t.StructType().descriptorSizes()
769 case Bool,
770 Int, Int8, Int16, Int32, Int64,
771 Uint, Uint8, Uint16, Uint32, Uint64, Uintptr,
772 Float32, Float64, Complex64, Complex128,
773 String, UnsafePointer:
774
775 baseSize = int(unsafe.Sizeof(*t))
776 addSize = 0
777
778 default:
779 panic("DescriptorSize: invalid type descriptor")
780 }
781
782
783
784
785 ret := baseSize
786
787 mcount := 0
788 ut := t.Uncommon()
789 if ut != nil {
790 ret += int(unsafe.Sizeof(*ut))
791 mcount = int(ut.Mcount)
792 }
793
794 ret += addSize
795
796 ret += mcount * int(unsafe.Sizeof(Method{}))
797
798 return ret
799 }
800
801 func (at *ArrayType) descriptorSizes() (base, add int) {
802 return int(unsafe.Sizeof(*at)), 0
803 }
804
805 func (ct *ChanType) descriptorSizes() (base, add int) {
806 return int(unsafe.Sizeof(*ct)), 0
807 }
808
809 func (ft *FuncType) descriptorSizes() (base, add int) {
810 base = int(unsafe.Sizeof(*ft))
811 add = (ft.NumIn() + ft.NumOut()) * goarch.PtrSize
812 return base, add
813 }
814
815 func (it *InterfaceType) descriptorSizes() (base, add int) {
816 base = int(unsafe.Sizeof(*it))
817 add = len(it.Methods) * int(unsafe.Sizeof(Imethod{}))
818 return base, add
819 }
820
821 func (mt *MapType) descriptorSizes() (base, add int) {
822 return int(unsafe.Sizeof(*mt)), 0
823 }
824
825 func (pt *PtrType) descriptorSizes() (base, add int) {
826 return int(unsafe.Sizeof(*pt)), 0
827 }
828
829 func (st *SliceType) descriptorSizes() (base, add int) {
830 return int(unsafe.Sizeof(*st)), 0
831 }
832
833 func (st *StructType) descriptorSizes() (base, add int) {
834 base = int(unsafe.Sizeof(*st))
835 add = len(st.Fields) * int(unsafe.Sizeof(StructField{}))
836 return base, add
837 }
838
839 const (
840 TraceArgsLimit = 10
841 TraceArgsMaxDepth = 5
842
843
844
845
846
847
848 TraceArgsMaxLen = (TraceArgsMaxDepth*3+2)*TraceArgsLimit + 1
849 )
850
851
852
853
854
855
856
857
858
859
860
861
862
863 const (
864 TraceArgsEndSeq = 0xff
865 TraceArgsStartAgg = 0xfe
866 TraceArgsEndAgg = 0xfd
867 TraceArgsDotdotdot = 0xfc
868 TraceArgsOffsetTooLarge = 0xfb
869 TraceArgsSpecial = 0xf0
870 )
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886 const MaxPtrmaskBytes = 16
887
View as plain text