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