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