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 func (t *Type) Kind() Kind { return t.Kind_ & KindMask }
181
182 func (t *Type) HasName() bool {
183 return t.TFlag&TFlagNamed != 0
184 }
185
186
187 func (t *Type) Pointers() bool { return t.PtrBytes != 0 }
188
189
190 func (t *Type) IfaceIndir() bool {
191 return t.Kind_&KindDirectIface == 0
192 }
193
194
195 func (t *Type) IsDirectIface() bool {
196 return t.Kind_&KindDirectIface != 0
197 }
198
199 func (t *Type) GcSlice(begin, end uintptr) []byte {
200 return unsafe.Slice(t.GCData, int(end))[begin:]
201 }
202
203
204 type Method struct {
205 Name NameOff
206 Mtyp TypeOff
207 Ifn TextOff
208 Tfn TextOff
209 }
210
211
212
213
214
215 type UncommonType struct {
216 PkgPath NameOff
217 Mcount uint16
218 Xcount uint16
219 Moff uint32
220 _ uint32
221 }
222
223 func (t *UncommonType) Methods() []Method {
224 if t.Mcount == 0 {
225 return nil
226 }
227 return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.mcount > 0"))[:t.Mcount:t.Mcount]
228 }
229
230 func (t *UncommonType) ExportedMethods() []Method {
231 if t.Xcount == 0 {
232 return nil
233 }
234 return (*[1 << 16]Method)(addChecked(unsafe.Pointer(t), uintptr(t.Moff), "t.xcount > 0"))[:t.Xcount:t.Xcount]
235 }
236
237
238
239
240
241
242
243
244 func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
245 return unsafe.Pointer(uintptr(p) + x)
246 }
247
248
249 type Imethod struct {
250 Name NameOff
251 Typ TypeOff
252 }
253
254
255 type ArrayType struct {
256 Type
257 Elem *Type
258 Slice *Type
259 Len uintptr
260 }
261
262
263 func (t *Type) Len() int {
264 if t.Kind() == Array {
265 return int((*ArrayType)(unsafe.Pointer(t)).Len)
266 }
267 return 0
268 }
269
270 func (t *Type) Common() *Type {
271 return t
272 }
273
274 type ChanDir int
275
276 const (
277 RecvDir ChanDir = 1 << iota
278 SendDir
279 BothDir = RecvDir | SendDir
280 InvalidDir ChanDir = 0
281 )
282
283
284 type ChanType struct {
285 Type
286 Elem *Type
287 Dir ChanDir
288 }
289
290 type structTypeUncommon struct {
291 StructType
292 u UncommonType
293 }
294
295
296 func (t *Type) ChanDir() ChanDir {
297 if t.Kind() == Chan {
298 ch := (*ChanType)(unsafe.Pointer(t))
299 return ch.Dir
300 }
301 return InvalidDir
302 }
303
304
305 func (t *Type) Uncommon() *UncommonType {
306 if t.TFlag&TFlagUncommon == 0 {
307 return nil
308 }
309 switch t.Kind() {
310 case Struct:
311 return &(*structTypeUncommon)(unsafe.Pointer(t)).u
312 case Pointer:
313 type u struct {
314 PtrType
315 u UncommonType
316 }
317 return &(*u)(unsafe.Pointer(t)).u
318 case Func:
319 type u struct {
320 FuncType
321 u UncommonType
322 }
323 return &(*u)(unsafe.Pointer(t)).u
324 case Slice:
325 type u struct {
326 SliceType
327 u UncommonType
328 }
329 return &(*u)(unsafe.Pointer(t)).u
330 case Array:
331 type u struct {
332 ArrayType
333 u UncommonType
334 }
335 return &(*u)(unsafe.Pointer(t)).u
336 case Chan:
337 type u struct {
338 ChanType
339 u UncommonType
340 }
341 return &(*u)(unsafe.Pointer(t)).u
342 case Map:
343 type u struct {
344 MapType
345 u UncommonType
346 }
347 return &(*u)(unsafe.Pointer(t)).u
348 case Interface:
349 type u struct {
350 InterfaceType
351 u UncommonType
352 }
353 return &(*u)(unsafe.Pointer(t)).u
354 default:
355 type u struct {
356 Type
357 u UncommonType
358 }
359 return &(*u)(unsafe.Pointer(t)).u
360 }
361 }
362
363
364 func (t *Type) Elem() *Type {
365 switch t.Kind() {
366 case Array:
367 tt := (*ArrayType)(unsafe.Pointer(t))
368 return tt.Elem
369 case Chan:
370 tt := (*ChanType)(unsafe.Pointer(t))
371 return tt.Elem
372 case Map:
373 tt := (*MapType)(unsafe.Pointer(t))
374 return tt.Elem
375 case Pointer:
376 tt := (*PtrType)(unsafe.Pointer(t))
377 return tt.Elem
378 case Slice:
379 tt := (*SliceType)(unsafe.Pointer(t))
380 return tt.Elem
381 }
382 return nil
383 }
384
385
386 func (t *Type) StructType() *StructType {
387 if t.Kind() != Struct {
388 return nil
389 }
390 return (*StructType)(unsafe.Pointer(t))
391 }
392
393
394 func (t *Type) MapType() *MapType {
395 if t.Kind() != Map {
396 return nil
397 }
398 return (*MapType)(unsafe.Pointer(t))
399 }
400
401
402 func (t *Type) ArrayType() *ArrayType {
403 if t.Kind() != Array {
404 return nil
405 }
406 return (*ArrayType)(unsafe.Pointer(t))
407 }
408
409
410 func (t *Type) FuncType() *FuncType {
411 if t.Kind() != Func {
412 return nil
413 }
414 return (*FuncType)(unsafe.Pointer(t))
415 }
416
417
418 func (t *Type) InterfaceType() *InterfaceType {
419 if t.Kind() != Interface {
420 return nil
421 }
422 return (*InterfaceType)(unsafe.Pointer(t))
423 }
424
425
426 func (t *Type) Size() uintptr { return t.Size_ }
427
428
429 func (t *Type) Align() int { return int(t.Align_) }
430
431 func (t *Type) FieldAlign() int { return int(t.FieldAlign_) }
432
433 type InterfaceType struct {
434 Type
435 PkgPath Name
436 Methods []Imethod
437 }
438
439 func (t *Type) ExportedMethods() []Method {
440 ut := t.Uncommon()
441 if ut == nil {
442 return nil
443 }
444 return ut.ExportedMethods()
445 }
446
447 func (t *Type) NumMethod() int {
448 if t.Kind() == Interface {
449 tt := (*InterfaceType)(unsafe.Pointer(t))
450 return tt.NumMethod()
451 }
452 return len(t.ExportedMethods())
453 }
454
455
456 func (t *InterfaceType) NumMethod() int { return len(t.Methods) }
457
458 type MapType struct {
459 Type
460 Key *Type
461 Elem *Type
462 Bucket *Type
463
464 Hasher func(unsafe.Pointer, uintptr) uintptr
465 KeySize uint8
466 ValueSize uint8
467 BucketSize uint16
468 Flags uint32
469 }
470
471
472
473 func (mt *MapType) IndirectKey() bool {
474 return mt.Flags&1 != 0
475 }
476 func (mt *MapType) IndirectElem() bool {
477 return mt.Flags&2 != 0
478 }
479 func (mt *MapType) ReflexiveKey() bool {
480 return mt.Flags&4 != 0
481 }
482 func (mt *MapType) NeedKeyUpdate() bool {
483 return mt.Flags&8 != 0
484 }
485 func (mt *MapType) HashMightPanic() bool {
486 return mt.Flags&16 != 0
487 }
488
489 func (t *Type) Key() *Type {
490 if t.Kind() == Map {
491 return (*MapType)(unsafe.Pointer(t)).Key
492 }
493 return nil
494 }
495
496 type SliceType struct {
497 Type
498 Elem *Type
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512 type FuncType struct {
513 Type
514 InCount uint16
515 OutCount uint16
516 }
517
518 func (t *FuncType) In(i int) *Type {
519 return t.InSlice()[i]
520 }
521
522 func (t *FuncType) NumIn() int {
523 return int(t.InCount)
524 }
525
526 func (t *FuncType) NumOut() int {
527 return int(t.OutCount & (1<<15 - 1))
528 }
529
530 func (t *FuncType) Out(i int) *Type {
531 return (t.OutSlice()[i])
532 }
533
534 func (t *FuncType) InSlice() []*Type {
535 uadd := unsafe.Sizeof(*t)
536 if t.TFlag&TFlagUncommon != 0 {
537 uadd += unsafe.Sizeof(UncommonType{})
538 }
539 if t.InCount == 0 {
540 return nil
541 }
542 return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
543 }
544 func (t *FuncType) OutSlice() []*Type {
545 outCount := uint16(t.NumOut())
546 if outCount == 0 {
547 return nil
548 }
549 uadd := unsafe.Sizeof(*t)
550 if t.TFlag&TFlagUncommon != 0 {
551 uadd += unsafe.Sizeof(UncommonType{})
552 }
553 return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
554 }
555
556 func (t *FuncType) IsVariadic() bool {
557 return t.OutCount&(1<<15) != 0
558 }
559
560 type PtrType struct {
561 Type
562 Elem *Type
563 }
564
565 type StructField struct {
566 Name Name
567 Typ *Type
568 Offset uintptr
569 }
570
571 func (f *StructField) Embedded() bool {
572 return f.Name.IsEmbedded()
573 }
574
575 type StructType struct {
576 Type
577 PkgPath Name
578 Fields []StructField
579 }
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607 type Name struct {
608 Bytes *byte
609 }
610
611
612
613 func (n Name) DataChecked(off int, whySafe string) *byte {
614 return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
615 }
616
617
618
619 func (n Name) Data(off int) *byte {
620 return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
621 }
622
623
624 func (n Name) IsExported() bool {
625 return (*n.Bytes)&(1<<0) != 0
626 }
627
628
629 func (n Name) HasTag() bool {
630 return (*n.Bytes)&(1<<1) != 0
631 }
632
633
634 func (n Name) IsEmbedded() bool {
635 return (*n.Bytes)&(1<<3) != 0
636 }
637
638
639
640 func (n Name) ReadVarint(off int) (int, int) {
641 v := 0
642 for i := 0; ; i++ {
643 x := *n.DataChecked(off+i, "read varint")
644 v += int(x&0x7f) << (7 * i)
645 if x&0x80 == 0 {
646 return i + 1, v
647 }
648 }
649 }
650
651
652 func (n Name) IsBlank() bool {
653 if n.Bytes == nil {
654 return false
655 }
656 _, l := n.ReadVarint(1)
657 return l == 1 && *n.Data(2) == '_'
658 }
659
660
661
662
663 func writeVarint(buf []byte, n int) int {
664 for i := 0; ; i++ {
665 b := byte(n & 0x7f)
666 n >>= 7
667 if n == 0 {
668 buf[i] = b
669 return i + 1
670 }
671 buf[i] = b | 0x80
672 }
673 }
674
675
676 func (n Name) Name() string {
677 if n.Bytes == nil {
678 return ""
679 }
680 i, l := n.ReadVarint(1)
681 return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
682 }
683
684
685 func (n Name) Tag() string {
686 if !n.HasTag() {
687 return ""
688 }
689 i, l := n.ReadVarint(1)
690 i2, l2 := n.ReadVarint(1 + i + l)
691 return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
692 }
693
694 func NewName(n, tag string, exported, embedded bool) Name {
695 if len(n) >= 1<<29 {
696 panic("abi.NewName: name too long: " + n[:1024] + "...")
697 }
698 if len(tag) >= 1<<29 {
699 panic("abi.NewName: tag too long: " + tag[:1024] + "...")
700 }
701 var nameLen [10]byte
702 var tagLen [10]byte
703 nameLenLen := writeVarint(nameLen[:], len(n))
704 tagLenLen := writeVarint(tagLen[:], len(tag))
705
706 var bits byte
707 l := 1 + nameLenLen + len(n)
708 if exported {
709 bits |= 1 << 0
710 }
711 if len(tag) > 0 {
712 l += tagLenLen + len(tag)
713 bits |= 1 << 1
714 }
715 if embedded {
716 bits |= 1 << 3
717 }
718
719 b := make([]byte, l)
720 b[0] = bits
721 copy(b[1:], nameLen[:nameLenLen])
722 copy(b[1+nameLenLen:], n)
723 if len(tag) > 0 {
724 tb := b[1+nameLenLen+len(n):]
725 copy(tb, tagLen[:tagLenLen])
726 copy(tb[tagLenLen:], tag)
727 }
728
729 return Name{Bytes: &b[0]}
730 }
731
732 const (
733 TraceArgsLimit = 10
734 TraceArgsMaxDepth = 5
735
736
737
738
739
740
741 TraceArgsMaxLen = (TraceArgsMaxDepth*3+2)*TraceArgsLimit + 1
742 )
743
744
745
746
747
748
749
750
751
752
753
754
755
756 const (
757 TraceArgsEndSeq = 0xff
758 TraceArgsStartAgg = 0xfe
759 TraceArgsEndAgg = 0xfd
760 TraceArgsDotdotdot = 0xfc
761 TraceArgsOffsetTooLarge = 0xfb
762 TraceArgsSpecial = 0xf0
763 )
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794 const MaxPtrmaskBytes = 2048
795
View as plain text