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 func (t *Type) Key() *Type {
468 if t.Kind() == Map {
469 return (*mapType)(unsafe.Pointer(t)).Key
470 }
471 return nil
472 }
473
474 type SliceType struct {
475 Type
476 Elem *Type
477 }
478
479
480
481
482
483
484
485
486
487
488
489
490 type FuncType struct {
491 Type
492 InCount uint16
493 OutCount uint16
494 }
495
496 func (t *FuncType) In(i int) *Type {
497 return t.InSlice()[i]
498 }
499
500 func (t *FuncType) NumIn() int {
501 return int(t.InCount)
502 }
503
504 func (t *FuncType) NumOut() int {
505 return int(t.OutCount & (1<<15 - 1))
506 }
507
508 func (t *FuncType) Out(i int) *Type {
509 return (t.OutSlice()[i])
510 }
511
512 func (t *FuncType) InSlice() []*Type {
513 uadd := unsafe.Sizeof(*t)
514 if t.TFlag&TFlagUncommon != 0 {
515 uadd += unsafe.Sizeof(UncommonType{})
516 }
517 if t.InCount == 0 {
518 return nil
519 }
520 return (*[1 << 16]*Type)(addChecked(unsafe.Pointer(t), uadd, "t.inCount > 0"))[:t.InCount:t.InCount]
521 }
522 func (t *FuncType) OutSlice() []*Type {
523 outCount := uint16(t.NumOut())
524 if outCount == 0 {
525 return nil
526 }
527 uadd := unsafe.Sizeof(*t)
528 if t.TFlag&TFlagUncommon != 0 {
529 uadd += unsafe.Sizeof(UncommonType{})
530 }
531 return (*[1 << 17]*Type)(addChecked(unsafe.Pointer(t), uadd, "outCount > 0"))[t.InCount : t.InCount+outCount : t.InCount+outCount]
532 }
533
534 func (t *FuncType) IsVariadic() bool {
535 return t.OutCount&(1<<15) != 0
536 }
537
538 type PtrType struct {
539 Type
540 Elem *Type
541 }
542
543 type StructField struct {
544 Name Name
545 Typ *Type
546 Offset uintptr
547 }
548
549 func (f *StructField) Embedded() bool {
550 return f.Name.IsEmbedded()
551 }
552
553 type StructType struct {
554 Type
555 PkgPath Name
556 Fields []StructField
557 }
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585 type Name struct {
586 Bytes *byte
587 }
588
589
590
591 func (n Name) DataChecked(off int, whySafe string) *byte {
592 return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), whySafe))
593 }
594
595
596
597 func (n Name) Data(off int) *byte {
598 return (*byte)(addChecked(unsafe.Pointer(n.Bytes), uintptr(off), "the runtime doesn't need to give you a reason"))
599 }
600
601
602 func (n Name) IsExported() bool {
603 return (*n.Bytes)&(1<<0) != 0
604 }
605
606
607 func (n Name) HasTag() bool {
608 return (*n.Bytes)&(1<<1) != 0
609 }
610
611
612 func (n Name) IsEmbedded() bool {
613 return (*n.Bytes)&(1<<3) != 0
614 }
615
616
617
618 func (n Name) ReadVarint(off int) (int, int) {
619 v := 0
620 for i := 0; ; i++ {
621 x := *n.DataChecked(off+i, "read varint")
622 v += int(x&0x7f) << (7 * i)
623 if x&0x80 == 0 {
624 return i + 1, v
625 }
626 }
627 }
628
629
630 func (n Name) IsBlank() bool {
631 if n.Bytes == nil {
632 return false
633 }
634 _, l := n.ReadVarint(1)
635 return l == 1 && *n.Data(2) == '_'
636 }
637
638
639
640
641 func writeVarint(buf []byte, n int) int {
642 for i := 0; ; i++ {
643 b := byte(n & 0x7f)
644 n >>= 7
645 if n == 0 {
646 buf[i] = b
647 return i + 1
648 }
649 buf[i] = b | 0x80
650 }
651 }
652
653
654 func (n Name) Name() string {
655 if n.Bytes == nil {
656 return ""
657 }
658 i, l := n.ReadVarint(1)
659 return unsafe.String(n.DataChecked(1+i, "non-empty string"), l)
660 }
661
662
663 func (n Name) Tag() string {
664 if !n.HasTag() {
665 return ""
666 }
667 i, l := n.ReadVarint(1)
668 i2, l2 := n.ReadVarint(1 + i + l)
669 return unsafe.String(n.DataChecked(1+i+l+i2, "non-empty string"), l2)
670 }
671
672 func NewName(n, tag string, exported, embedded bool) Name {
673 if len(n) >= 1<<29 {
674 panic("abi.NewName: name too long: " + n[:1024] + "...")
675 }
676 if len(tag) >= 1<<29 {
677 panic("abi.NewName: tag too long: " + tag[:1024] + "...")
678 }
679 var nameLen [10]byte
680 var tagLen [10]byte
681 nameLenLen := writeVarint(nameLen[:], len(n))
682 tagLenLen := writeVarint(tagLen[:], len(tag))
683
684 var bits byte
685 l := 1 + nameLenLen + len(n)
686 if exported {
687 bits |= 1 << 0
688 }
689 if len(tag) > 0 {
690 l += tagLenLen + len(tag)
691 bits |= 1 << 1
692 }
693 if embedded {
694 bits |= 1 << 3
695 }
696
697 b := make([]byte, l)
698 b[0] = bits
699 copy(b[1:], nameLen[:nameLenLen])
700 copy(b[1+nameLenLen:], n)
701 if len(tag) > 0 {
702 tb := b[1+nameLenLen+len(n):]
703 copy(tb, tagLen[:tagLenLen])
704 copy(tb[tagLenLen:], tag)
705 }
706
707 return Name{Bytes: &b[0]}
708 }
709
710 const (
711 TraceArgsLimit = 10
712 TraceArgsMaxDepth = 5
713
714
715
716
717
718
719 TraceArgsMaxLen = (TraceArgsMaxDepth*3+2)*TraceArgsLimit + 1
720 )
721
722
723
724
725
726
727
728
729
730
731
732
733
734 const (
735 TraceArgsEndSeq = 0xff
736 TraceArgsStartAgg = 0xfe
737 TraceArgsEndAgg = 0xfd
738 TraceArgsDotdotdot = 0xfc
739 TraceArgsOffsetTooLarge = 0xfb
740 TraceArgsSpecial = 0xf0
741 )
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772 const MaxPtrmaskBytes = 2048
773
View as plain text