1
2
3
4
5 package types
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/internal/objabi"
10 "cmd/internal/src"
11 "fmt"
12 "go/constant"
13 "internal/types/errors"
14 "sync"
15 )
16
17
18
19
20 type Object interface {
21 Pos() src.XPos
22 Sym() *Sym
23 Type() *Type
24 }
25
26
27
28
29 type Kind uint8
30
31 const (
32 Txxx Kind = iota
33
34 TINT8
35 TUINT8
36 TINT16
37 TUINT16
38 TINT32
39 TUINT32
40 TINT64
41 TUINT64
42 TINT
43 TUINT
44 TUINTPTR
45
46 TCOMPLEX64
47 TCOMPLEX128
48
49 TFLOAT32
50 TFLOAT64
51
52 TBOOL
53
54 TPTR
55 TFUNC
56 TSLICE
57 TARRAY
58 TSTRUCT
59 TCHAN
60 TMAP
61 TINTER
62 TFORW
63 TANY
64 TSTRING
65 TUNSAFEPTR
66
67
68 TIDEAL
69 TNIL
70 TBLANK
71
72
73 TFUNCARGS
74 TCHANARGS
75
76
77 TSSA
78 TTUPLE
79 TRESULTS
80
81 NTYPE
82 )
83
84
85 type ChanDir uint8
86
87 func (c ChanDir) CanRecv() bool { return c&Crecv != 0 }
88 func (c ChanDir) CanSend() bool { return c&Csend != 0 }
89
90 const (
91
92
93 Crecv ChanDir = 1 << 0
94 Csend ChanDir = 1 << 1
95 Cboth ChanDir = Crecv | Csend
96 )
97
98
99
100
101
102
103
104
105
106 var Types [NTYPE]*Type
107
108 var (
109
110
111
112 AnyType *Type
113 ByteType *Type
114 RuneType *Type
115
116
117 ErrorType *Type
118
119 ComparableType *Type
120
121
122 UntypedString = newType(TSTRING)
123 UntypedBool = newType(TBOOL)
124
125
126 UntypedInt = newType(TIDEAL)
127 UntypedRune = newType(TIDEAL)
128 UntypedFloat = newType(TIDEAL)
129 UntypedComplex = newType(TIDEAL)
130 )
131
132
133
134 var UntypedTypes = [...]*Type{
135 constant.Bool: UntypedBool,
136 constant.String: UntypedString,
137 constant.Int: UntypedInt,
138 constant.Float: UntypedFloat,
139 constant.Complex: UntypedComplex,
140 }
141
142
143 var DefaultKinds = [...]Kind{
144 constant.Bool: TBOOL,
145 constant.String: TSTRING,
146 constant.Int: TINT,
147 constant.Float: TFLOAT64,
148 constant.Complex: TCOMPLEX128,
149 }
150
151
152
153
154
155
156
157
158
159
160 type Type struct {
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 extra any
178
179
180 width int64
181
182
183 methods fields
184
185 allMethods fields
186
187
188 obj Object
189
190 underlying *Type
191
192
193 cache struct {
194 ptr *Type
195 slice *Type
196 }
197
198 kind Kind
199 align uint8
200
201 intRegs, floatRegs uint8
202
203 flags bitset16
204 alg AlgKind
205
206
207
208
209 ptrBytes int64
210 }
211
212
213
214
215
216
217
218 func (t *Type) Registers() (uint8, uint8) {
219 CalcSize(t)
220 return t.intRegs, t.floatRegs
221 }
222
223 func (*Type) CanBeAnSSAAux() {}
224
225 const (
226 typeNotInHeap = 1 << iota
227 typeNoalg
228 typeDeferwidth
229 typeRecur
230 typeIsShape
231 typeHasShape
232
233
234 typeIsFullyInstantiated
235 typeIsSIMDTag
236 typeIsSIMD
237 )
238
239 func (t *Type) NotInHeap() bool { return t.flags&typeNotInHeap != 0 }
240 func (t *Type) Noalg() bool { return t.flags&typeNoalg != 0 }
241 func (t *Type) Deferwidth() bool { return t.flags&typeDeferwidth != 0 }
242 func (t *Type) Recur() bool { return t.flags&typeRecur != 0 }
243 func (t *Type) IsShape() bool { return t.flags&typeIsShape != 0 }
244 func (t *Type) HasShape() bool { return t.flags&typeHasShape != 0 }
245 func (t *Type) IsFullyInstantiated() bool { return t.flags&typeIsFullyInstantiated != 0 }
246
247 func (t *Type) SetNotInHeap(b bool) { t.flags.set(typeNotInHeap, b) }
248 func (t *Type) SetNoalg(b bool) { t.flags.set(typeNoalg, b) }
249 func (t *Type) SetDeferwidth(b bool) { t.flags.set(typeDeferwidth, b) }
250 func (t *Type) SetRecur(b bool) { t.flags.set(typeRecur, b) }
251 func (t *Type) SetIsFullyInstantiated(b bool) { t.flags.set(typeIsFullyInstantiated, b) }
252
253
254 func (t *Type) SetIsShape(b bool) { t.flags.set(typeIsShape, b) }
255 func (t *Type) SetHasShape(b bool) { t.flags.set(typeHasShape, b) }
256
257
258 func (t *Type) Kind() Kind { return t.kind }
259
260
261 func (t *Type) Sym() *Sym {
262 if t.obj != nil {
263 return t.obj.Sym()
264 }
265 return nil
266 }
267
268
269 func (t *Type) Underlying() *Type { return t.underlying }
270
271
272
273 func (t *Type) Pos() src.XPos {
274 if t.obj != nil {
275 return t.obj.Pos()
276 }
277 return src.NoXPos
278 }
279
280
281 type Map struct {
282 Key *Type
283 Elem *Type
284
285 Group *Type
286 }
287
288
289 func (t *Type) MapType() *Map {
290 t.wantEtype(TMAP)
291 return t.extra.(*Map)
292 }
293
294
295 type Forward struct {
296 Copyto []*Type
297 Embedlineno src.XPos
298 }
299
300
301 func (t *Type) forwardType() *Forward {
302 t.wantEtype(TFORW)
303 return t.extra.(*Forward)
304 }
305
306
307 type Func struct {
308 allParams []*Field
309
310 startParams int
311 startResults int
312
313 resultsTuple *Type
314
315
316
317
318 Argwid int64
319 }
320
321 func (ft *Func) recvs() []*Field { return ft.allParams[:ft.startParams] }
322 func (ft *Func) params() []*Field { return ft.allParams[ft.startParams:ft.startResults] }
323 func (ft *Func) results() []*Field { return ft.allParams[ft.startResults:] }
324 func (ft *Func) recvParams() []*Field { return ft.allParams[:ft.startResults] }
325 func (ft *Func) paramsResults() []*Field { return ft.allParams[ft.startParams:] }
326
327
328 func (t *Type) funcType() *Func {
329 t.wantEtype(TFUNC)
330 return t.extra.(*Func)
331 }
332
333
334 type Struct struct {
335 fields fields
336
337
338
339 Map *Type
340
341 ParamTuple bool
342 }
343
344
345 func (t *Type) StructType() *Struct {
346 t.wantEtype(TSTRUCT)
347 return t.extra.(*Struct)
348 }
349
350
351 type Interface struct {
352 }
353
354
355 type Ptr struct {
356 Elem *Type
357 }
358
359
360 type ChanArgs struct {
361 T *Type
362 }
363
364
365 type FuncArgs struct {
366 T *Type
367 }
368
369
370 type Chan struct {
371 Elem *Type
372 Dir ChanDir
373 }
374
375
376 func (t *Type) chanType() *Chan {
377 t.wantEtype(TCHAN)
378 return t.extra.(*Chan)
379 }
380
381 type Tuple struct {
382 first *Type
383 second *Type
384
385 }
386
387
388 type Results struct {
389 Types []*Type
390 }
391
392
393 type Array struct {
394 Elem *Type
395 Bound int64
396 }
397
398
399 type Slice struct {
400 Elem *Type
401 }
402
403
404
405
406
407
408 type Field struct {
409 flags bitset8
410
411 Embedded uint8
412
413 Pos src.XPos
414
415
416
417 Sym *Sym
418 Type *Type
419 Note string
420
421
422
423
424 Nname Object
425
426
427
428 Offset int64
429 }
430
431 const (
432 fieldIsDDD = 1 << iota
433 fieldNointerface
434 )
435
436 func (f *Field) IsDDD() bool { return f.flags&fieldIsDDD != 0 }
437 func (f *Field) Nointerface() bool { return f.flags&fieldNointerface != 0 }
438
439 func (f *Field) SetIsDDD(b bool) { f.flags.set(fieldIsDDD, b) }
440 func (f *Field) SetNointerface(b bool) { f.flags.set(fieldNointerface, b) }
441
442
443 func (f *Field) End() int64 {
444 return f.Offset + f.Type.width
445 }
446
447
448 func (f *Field) IsMethod() bool {
449 return f.Type.kind == TFUNC && f.Type.Recv() != nil
450 }
451
452
453 func CompareFields(a, b *Field) int {
454 return CompareSyms(a.Sym, b.Sym)
455 }
456
457
458
459
460 type fields struct {
461 s *[]*Field
462 }
463
464
465
466 func (f *fields) Slice() []*Field {
467 if f.s == nil {
468 return nil
469 }
470 return *f.s
471 }
472
473
474
475 func (f *fields) Set(s []*Field) {
476 if len(s) == 0 {
477 f.s = nil
478 } else {
479
480
481 t := s
482 f.s = &t
483 }
484 }
485
486
487 func newType(et Kind) *Type {
488 t := &Type{
489 kind: et,
490 width: BADWIDTH,
491 }
492 t.underlying = t
493
494 switch t.kind {
495 case TMAP:
496 t.extra = new(Map)
497 case TFORW:
498 t.extra = new(Forward)
499 case TFUNC:
500 t.extra = new(Func)
501 case TSTRUCT:
502 t.extra = new(Struct)
503 case TINTER:
504 t.extra = new(Interface)
505 case TPTR:
506 t.extra = Ptr{}
507 case TCHANARGS:
508 t.extra = ChanArgs{}
509 case TFUNCARGS:
510 t.extra = FuncArgs{}
511 case TCHAN:
512 t.extra = new(Chan)
513 case TTUPLE:
514 t.extra = new(Tuple)
515 case TRESULTS:
516 t.extra = new(Results)
517 }
518 return t
519 }
520
521
522 func NewArray(elem *Type, bound int64) *Type {
523 if bound < 0 {
524 base.Fatalf("NewArray: invalid bound %v", bound)
525 }
526 t := newType(TARRAY)
527 t.extra = &Array{Elem: elem, Bound: bound}
528 if elem.HasShape() {
529 t.SetHasShape(true)
530 }
531 if elem.NotInHeap() {
532 t.SetNotInHeap(true)
533 }
534 return t
535 }
536
537
538 func NewSlice(elem *Type) *Type {
539 if t := elem.cache.slice; t != nil {
540 if t.Elem() != elem {
541 base.Fatalf("elem mismatch")
542 }
543 if elem.HasShape() != t.HasShape() {
544 base.Fatalf("Incorrect HasShape flag for cached slice type")
545 }
546 return t
547 }
548
549 t := newType(TSLICE)
550 t.extra = Slice{Elem: elem}
551 elem.cache.slice = t
552 if elem.HasShape() {
553 t.SetHasShape(true)
554 }
555 return t
556 }
557
558
559 func NewChan(elem *Type, dir ChanDir) *Type {
560 t := newType(TCHAN)
561 ct := t.chanType()
562 ct.Elem = elem
563 ct.Dir = dir
564 if elem.HasShape() {
565 t.SetHasShape(true)
566 }
567 return t
568 }
569
570 func NewTuple(t1, t2 *Type) *Type {
571 t := newType(TTUPLE)
572 t.extra.(*Tuple).first = t1
573 t.extra.(*Tuple).second = t2
574 if t1.HasShape() || t2.HasShape() {
575 t.SetHasShape(true)
576 }
577 return t
578 }
579
580 func newResults(types []*Type) *Type {
581 t := newType(TRESULTS)
582 t.extra.(*Results).Types = types
583 return t
584 }
585
586 func NewResults(types []*Type) *Type {
587 if len(types) == 1 && types[0] == TypeMem {
588 return TypeResultMem
589 }
590 return newResults(types)
591 }
592
593 func newSSA(name string) *Type {
594 t := newType(TSSA)
595 t.extra = name
596 return t
597 }
598
599 func newSIMD(name string) *Type {
600 t := newSSA(name)
601 t.flags |= typeIsSIMD
602 return t
603 }
604
605
606 func NewMap(k, v *Type) *Type {
607 t := newType(TMAP)
608 mt := t.MapType()
609 mt.Key = k
610 mt.Elem = v
611 if k.HasShape() || v.HasShape() {
612 t.SetHasShape(true)
613 }
614 return t
615 }
616
617
618
619
620 var NewPtrCacheEnabled = true
621
622
623 func NewPtr(elem *Type) *Type {
624 if elem == nil {
625 base.Fatalf("NewPtr: pointer to elem Type is nil")
626 }
627
628 if t := elem.cache.ptr; t != nil {
629 if t.Elem() != elem {
630 base.Fatalf("NewPtr: elem mismatch")
631 }
632 if elem.HasShape() != t.HasShape() {
633 base.Fatalf("Incorrect HasShape flag for cached pointer type")
634 }
635 return t
636 }
637
638 t := newType(TPTR)
639 t.extra = Ptr{Elem: elem}
640 t.width = int64(PtrSize)
641 t.align = uint8(PtrSize)
642 t.intRegs = 1
643 if NewPtrCacheEnabled {
644 elem.cache.ptr = t
645 }
646 if elem.HasShape() {
647 t.SetHasShape(true)
648 }
649 t.alg = AMEM
650 if elem.Noalg() {
651 t.SetNoalg(true)
652 t.alg = ANOALG
653 }
654
655
656 t.ptrBytes = int64(PtrSize)
657 return t
658 }
659
660
661 func NewChanArgs(c *Type) *Type {
662 t := newType(TCHANARGS)
663 t.extra = ChanArgs{T: c}
664 return t
665 }
666
667
668 func NewFuncArgs(f *Type) *Type {
669 t := newType(TFUNCARGS)
670 t.extra = FuncArgs{T: f}
671 return t
672 }
673
674 func NewField(pos src.XPos, sym *Sym, typ *Type) *Field {
675 f := &Field{
676 Pos: pos,
677 Sym: sym,
678 Type: typ,
679 Offset: BADWIDTH,
680 }
681 if typ == nil {
682 base.Fatalf("typ is nil")
683 }
684 return f
685 }
686
687
688
689 func SubstAny(t *Type, types *[]*Type) *Type {
690 if t == nil {
691 return nil
692 }
693
694 switch t.kind {
695 default:
696
697
698 case TANY:
699 if len(*types) == 0 {
700 base.Fatalf("SubstArgTypes: not enough argument types")
701 }
702 t = (*types)[0]
703 *types = (*types)[1:]
704
705 case TPTR:
706 elem := SubstAny(t.Elem(), types)
707 if elem != t.Elem() {
708 t = t.copy()
709 t.extra = Ptr{Elem: elem}
710 }
711
712 case TARRAY:
713 elem := SubstAny(t.Elem(), types)
714 if elem != t.Elem() {
715 t = t.copy()
716 t.extra.(*Array).Elem = elem
717 }
718
719 case TSLICE:
720 elem := SubstAny(t.Elem(), types)
721 if elem != t.Elem() {
722 t = t.copy()
723 t.extra = Slice{Elem: elem}
724 }
725
726 case TCHAN:
727 elem := SubstAny(t.Elem(), types)
728 if elem != t.Elem() {
729 t = t.copy()
730 t.extra.(*Chan).Elem = elem
731 }
732
733 case TMAP:
734 key := SubstAny(t.Key(), types)
735 elem := SubstAny(t.Elem(), types)
736 if key != t.Key() || elem != t.Elem() {
737 t = t.copy()
738 t.extra.(*Map).Key = key
739 t.extra.(*Map).Elem = elem
740 }
741
742 case TFUNC:
743 ft := t.funcType()
744 allParams := substFields(ft.allParams, types)
745
746 t = t.copy()
747 ft = t.funcType()
748 ft.allParams = allParams
749
750 rt := ft.resultsTuple
751 rt = rt.copy()
752 ft.resultsTuple = rt
753 rt.setFields(t.Results())
754
755 case TSTRUCT:
756
757
758
759 nfs := substFields(t.Fields(), types)
760 t = t.copy()
761 t.setFields(nfs)
762 }
763
764 return t
765 }
766
767 func substFields(fields []*Field, types *[]*Type) []*Field {
768 nfs := make([]*Field, len(fields))
769 for i, f := range fields {
770 nft := SubstAny(f.Type, types)
771 nfs[i] = f.Copy()
772 nfs[i].Type = nft
773 }
774 return nfs
775 }
776
777
778 func (t *Type) copy() *Type {
779 if t == nil {
780 return nil
781 }
782 nt := *t
783
784 switch t.kind {
785 case TMAP:
786 x := *t.extra.(*Map)
787 nt.extra = &x
788 case TFORW:
789 x := *t.extra.(*Forward)
790 nt.extra = &x
791 case TFUNC:
792 x := *t.extra.(*Func)
793 nt.extra = &x
794 case TSTRUCT:
795 x := *t.extra.(*Struct)
796 nt.extra = &x
797 case TINTER:
798 x := *t.extra.(*Interface)
799 nt.extra = &x
800 case TCHAN:
801 x := *t.extra.(*Chan)
802 nt.extra = &x
803 case TARRAY:
804 x := *t.extra.(*Array)
805 nt.extra = &x
806 case TTUPLE, TSSA, TRESULTS:
807 base.Fatalf("ssa types cannot be copied")
808 }
809
810 if t.underlying == t {
811 nt.underlying = &nt
812 }
813 return &nt
814 }
815
816 func (f *Field) Copy() *Field {
817 nf := *f
818 return &nf
819 }
820
821 func (t *Type) wantEtype(et Kind) {
822 if t.kind != et {
823 base.Fatalf("want %v, but have %v", et, t)
824 }
825 }
826
827
828
829 func (t *Type) ResultsTuple() *Type { return t.funcType().resultsTuple }
830
831
832
833 func (t *Type) Recvs() []*Field { return t.funcType().recvs() }
834
835
836 func (t *Type) Params() []*Field { return t.funcType().params() }
837
838
839 func (t *Type) Results() []*Field { return t.funcType().results() }
840
841
842
843
844 func (t *Type) RecvParamsResults() []*Field { return t.funcType().allParams }
845
846
847
848 func (t *Type) RecvParams() []*Field { return t.funcType().recvParams() }
849
850
851
852 func (t *Type) ParamsResults() []*Field { return t.funcType().paramsResults() }
853
854 func (t *Type) NumRecvs() int { return len(t.Recvs()) }
855 func (t *Type) NumParams() int { return len(t.Params()) }
856 func (t *Type) NumResults() int { return len(t.Results()) }
857
858
859 func (t *Type) IsVariadic() bool {
860 n := t.NumParams()
861 return n > 0 && t.Param(n-1).IsDDD()
862 }
863
864
865 func (t *Type) Recv() *Field {
866 if s := t.Recvs(); len(s) == 1 {
867 return s[0]
868 }
869 return nil
870 }
871
872
873 func (t *Type) Param(i int) *Field { return t.Params()[i] }
874
875
876 func (t *Type) Result(i int) *Field { return t.Results()[i] }
877
878
879 func (t *Type) Key() *Type {
880 t.wantEtype(TMAP)
881 return t.extra.(*Map).Key
882 }
883
884
885
886 func (t *Type) Elem() *Type {
887 switch t.kind {
888 case TPTR:
889 return t.extra.(Ptr).Elem
890 case TARRAY:
891 return t.extra.(*Array).Elem
892 case TSLICE:
893 return t.extra.(Slice).Elem
894 case TCHAN:
895 return t.extra.(*Chan).Elem
896 case TMAP:
897 return t.extra.(*Map).Elem
898 }
899 base.Fatalf("Type.Elem %s", t.kind)
900 return nil
901 }
902
903
904 func (t *Type) ChanArgs() *Type {
905 t.wantEtype(TCHANARGS)
906 return t.extra.(ChanArgs).T
907 }
908
909
910 func (t *Type) FuncArgs() *Type {
911 t.wantEtype(TFUNCARGS)
912 return t.extra.(FuncArgs).T
913 }
914
915
916 func (t *Type) IsFuncArgStruct() bool {
917 return t.kind == TSTRUCT && t.extra.(*Struct).ParamTuple
918 }
919
920
921
922
923 func (t *Type) Methods() []*Field {
924 return t.methods.Slice()
925 }
926
927
928
929
930
931 func (t *Type) AllMethods() []*Field {
932 if t.kind == TINTER {
933
934
935 CalcSize(t)
936 }
937 return t.allMethods.Slice()
938 }
939
940
941
942 func (t *Type) SetMethods(fs []*Field) {
943 t.methods.Set(fs)
944 }
945
946
947
948 func (t *Type) SetAllMethods(fs []*Field) {
949 t.allMethods.Set(fs)
950 }
951
952
953 func (t *Type) fields() *fields {
954 t.wantEtype(TSTRUCT)
955 return &t.extra.(*Struct).fields
956 }
957
958
959 func (t *Type) Field(i int) *Field { return t.Fields()[i] }
960
961
962
963 func (t *Type) Fields() []*Field { return t.fields().Slice() }
964
965
966 func (t *Type) setFields(fields []*Field) {
967
968
969
970
971
972
973 if t.widthCalculated() {
974 base.Fatalf("SetFields of %v: width previously calculated", t)
975 }
976 t.wantEtype(TSTRUCT)
977 t.fields().Set(fields)
978 }
979
980
981 func (t *Type) SetInterface(methods []*Field) {
982 t.wantEtype(TINTER)
983 t.methods.Set(methods)
984 }
985
986
987
988 func (t *Type) ArgWidth() int64 {
989 t.wantEtype(TFUNC)
990 return t.extra.(*Func).Argwid
991 }
992
993
994 func (t *Type) Size() int64 {
995 if t.kind == TSSA {
996 return t.width
997 }
998 CalcSize(t)
999 return t.width
1000 }
1001
1002
1003 func (t *Type) Alignment() int64 {
1004 CalcSize(t)
1005 return int64(t.align)
1006 }
1007
1008 func (t *Type) SimpleString() string {
1009 return t.kind.String()
1010 }
1011
1012
1013
1014
1015
1016
1017 type Cmp int8
1018
1019 const (
1020 CMPlt = Cmp(-1)
1021 CMPeq = Cmp(0)
1022 CMPgt = Cmp(1)
1023 )
1024
1025
1026
1027
1028
1029
1030
1031 func (t *Type) Compare(x *Type) Cmp {
1032 if x == t {
1033 return CMPeq
1034 }
1035 return t.cmp(x)
1036 }
1037
1038 func cmpForNe(x bool) Cmp {
1039 if x {
1040 return CMPlt
1041 }
1042 return CMPgt
1043 }
1044
1045 func (r *Sym) cmpsym(s *Sym) Cmp {
1046 if r == s {
1047 return CMPeq
1048 }
1049 if r == nil {
1050 return CMPlt
1051 }
1052 if s == nil {
1053 return CMPgt
1054 }
1055
1056 if len(r.Name) != len(s.Name) {
1057 return cmpForNe(len(r.Name) < len(s.Name))
1058 }
1059 if r.Pkg != s.Pkg {
1060 if len(r.Pkg.Prefix) != len(s.Pkg.Prefix) {
1061 return cmpForNe(len(r.Pkg.Prefix) < len(s.Pkg.Prefix))
1062 }
1063 if r.Pkg.Prefix != s.Pkg.Prefix {
1064 return cmpForNe(r.Pkg.Prefix < s.Pkg.Prefix)
1065 }
1066 }
1067 if r.Name != s.Name {
1068 return cmpForNe(r.Name < s.Name)
1069 }
1070 return CMPeq
1071 }
1072
1073
1074
1075
1076
1077
1078 func (t *Type) cmp(x *Type) Cmp {
1079
1080
1081
1082
1083
1084 if t == x {
1085 return CMPeq
1086 }
1087 if t == nil {
1088 return CMPlt
1089 }
1090 if x == nil {
1091 return CMPgt
1092 }
1093
1094 if t.kind != x.kind {
1095 return cmpForNe(t.kind < x.kind)
1096 }
1097
1098 if t.obj != nil || x.obj != nil {
1099
1100
1101 switch t.kind {
1102 case TUINT8:
1103 if (t == Types[TUINT8] || t == ByteType) && (x == Types[TUINT8] || x == ByteType) {
1104 return CMPeq
1105 }
1106
1107 case TINT32:
1108 if (t == Types[RuneType.kind] || t == RuneType) && (x == Types[RuneType.kind] || x == RuneType) {
1109 return CMPeq
1110 }
1111
1112 case TINTER:
1113
1114 if t == AnyType && x.IsEmptyInterface() || x == AnyType && t.IsEmptyInterface() {
1115 return CMPeq
1116 }
1117 }
1118 }
1119
1120 if c := t.Sym().cmpsym(x.Sym()); c != CMPeq {
1121 return c
1122 }
1123
1124 if x.obj != nil {
1125 return CMPeq
1126 }
1127
1128
1129 switch t.kind {
1130 case TBOOL, TFLOAT32, TFLOAT64, TCOMPLEX64, TCOMPLEX128, TUNSAFEPTR, TUINTPTR,
1131 TINT8, TINT16, TINT32, TINT64, TINT, TUINT8, TUINT16, TUINT32, TUINT64, TUINT:
1132 return CMPeq
1133
1134 case TSSA:
1135 tname := t.extra.(string)
1136 xname := x.extra.(string)
1137
1138 if len(tname) == len(xname) {
1139 if tname == xname {
1140 return CMPeq
1141 }
1142 if tname < xname {
1143 return CMPlt
1144 }
1145 return CMPgt
1146 }
1147 if len(tname) > len(xname) {
1148 return CMPgt
1149 }
1150 return CMPlt
1151
1152 case TTUPLE:
1153 xtup := x.extra.(*Tuple)
1154 ttup := t.extra.(*Tuple)
1155 if c := ttup.first.Compare(xtup.first); c != CMPeq {
1156 return c
1157 }
1158 return ttup.second.Compare(xtup.second)
1159
1160 case TRESULTS:
1161 xResults := x.extra.(*Results)
1162 tResults := t.extra.(*Results)
1163 xl, tl := len(xResults.Types), len(tResults.Types)
1164 if tl != xl {
1165 if tl < xl {
1166 return CMPlt
1167 }
1168 return CMPgt
1169 }
1170 for i := 0; i < tl; i++ {
1171 if c := tResults.Types[i].Compare(xResults.Types[i]); c != CMPeq {
1172 return c
1173 }
1174 }
1175 return CMPeq
1176
1177 case TMAP:
1178 if c := t.Key().cmp(x.Key()); c != CMPeq {
1179 return c
1180 }
1181 return t.Elem().cmp(x.Elem())
1182
1183 case TPTR, TSLICE:
1184
1185
1186
1187 case TSTRUCT:
1188
1189 if t.StructType().Map == nil {
1190 if x.StructType().Map != nil {
1191 return CMPlt
1192 }
1193
1194 } else if x.StructType().Map == nil {
1195 return CMPgt
1196 }
1197
1198
1199
1200
1201
1202
1203 tfs := t.Fields()
1204 xfs := x.Fields()
1205 for i := 0; i < len(tfs) && i < len(xfs); i++ {
1206 t1, x1 := tfs[i], xfs[i]
1207 if t1.Embedded != x1.Embedded {
1208 return cmpForNe(t1.Embedded < x1.Embedded)
1209 }
1210 if t1.Note != x1.Note {
1211 return cmpForNe(t1.Note < x1.Note)
1212 }
1213 if c := t1.Sym.cmpsym(x1.Sym); c != CMPeq {
1214 return c
1215 }
1216 if c := t1.Type.cmp(x1.Type); c != CMPeq {
1217 return c
1218 }
1219 }
1220 if len(tfs) != len(xfs) {
1221 return cmpForNe(len(tfs) < len(xfs))
1222 }
1223 return CMPeq
1224
1225 case TINTER:
1226 tfs := t.AllMethods()
1227 xfs := x.AllMethods()
1228 for i := 0; i < len(tfs) && i < len(xfs); i++ {
1229 t1, x1 := tfs[i], xfs[i]
1230 if c := t1.Sym.cmpsym(x1.Sym); c != CMPeq {
1231 return c
1232 }
1233 if c := t1.Type.cmp(x1.Type); c != CMPeq {
1234 return c
1235 }
1236 }
1237 if len(tfs) != len(xfs) {
1238 return cmpForNe(len(tfs) < len(xfs))
1239 }
1240 return CMPeq
1241
1242 case TFUNC:
1243 if tn, xn := t.NumRecvs(), x.NumRecvs(); tn != xn {
1244 return cmpForNe(tn < xn)
1245 }
1246 if tn, xn := t.NumParams(), x.NumParams(); tn != xn {
1247 return cmpForNe(tn < xn)
1248 }
1249 if tn, xn := t.NumResults(), x.NumResults(); tn != xn {
1250 return cmpForNe(tn < xn)
1251 }
1252 if tv, xv := t.IsVariadic(), x.IsVariadic(); tv != xv {
1253 return cmpForNe(!tv)
1254 }
1255
1256 tfs := t.RecvParamsResults()
1257 xfs := x.RecvParamsResults()
1258 for i, tf := range tfs {
1259 if c := tf.Type.cmp(xfs[i].Type); c != CMPeq {
1260 return c
1261 }
1262 }
1263 return CMPeq
1264
1265 case TARRAY:
1266 if t.NumElem() != x.NumElem() {
1267 return cmpForNe(t.NumElem() < x.NumElem())
1268 }
1269
1270 case TCHAN:
1271 if t.ChanDir() != x.ChanDir() {
1272 return cmpForNe(t.ChanDir() < x.ChanDir())
1273 }
1274
1275 default:
1276 e := fmt.Sprintf("Do not know how to compare %v with %v", t, x)
1277 panic(e)
1278 }
1279
1280
1281 return t.Elem().cmp(x.Elem())
1282 }
1283
1284
1285 func (t *Type) IsKind(et Kind) bool {
1286 return t != nil && t.kind == et
1287 }
1288
1289 func (t *Type) IsBoolean() bool {
1290 return t.kind == TBOOL
1291 }
1292
1293 var unsignedEType = [...]Kind{
1294 TINT8: TUINT8,
1295 TUINT8: TUINT8,
1296 TINT16: TUINT16,
1297 TUINT16: TUINT16,
1298 TINT32: TUINT32,
1299 TUINT32: TUINT32,
1300 TINT64: TUINT64,
1301 TUINT64: TUINT64,
1302 TINT: TUINT,
1303 TUINT: TUINT,
1304 TUINTPTR: TUINTPTR,
1305 }
1306
1307
1308 func (t *Type) ToUnsigned() *Type {
1309 if !t.IsInteger() {
1310 base.Fatalf("unsignedType(%v)", t)
1311 }
1312 return Types[unsignedEType[t.kind]]
1313 }
1314
1315 func (t *Type) IsInteger() bool {
1316 switch t.kind {
1317 case TINT8, TUINT8, TINT16, TUINT16, TINT32, TUINT32, TINT64, TUINT64, TINT, TUINT, TUINTPTR:
1318 return true
1319 }
1320 return t == UntypedInt || t == UntypedRune
1321 }
1322
1323 func (t *Type) IsSigned() bool {
1324 switch t.kind {
1325 case TINT8, TINT16, TINT32, TINT64, TINT:
1326 return true
1327 }
1328 return false
1329 }
1330
1331 func (t *Type) IsUnsigned() bool {
1332 switch t.kind {
1333 case TUINT8, TUINT16, TUINT32, TUINT64, TUINT, TUINTPTR:
1334 return true
1335 }
1336 return false
1337 }
1338
1339 func (t *Type) IsFloat() bool {
1340 return t.kind == TFLOAT32 || t.kind == TFLOAT64 || t == UntypedFloat
1341 }
1342
1343 func (t *Type) IsComplex() bool {
1344 return t.kind == TCOMPLEX64 || t.kind == TCOMPLEX128 || t == UntypedComplex
1345 }
1346
1347
1348
1349 func (t *Type) IsPtr() bool {
1350 return t.kind == TPTR
1351 }
1352
1353
1354 func (t *Type) IsPtrElem() bool {
1355 return t.cache.ptr != nil
1356 }
1357
1358
1359 func (t *Type) IsUnsafePtr() bool {
1360 return t.kind == TUNSAFEPTR
1361 }
1362
1363
1364 func (t *Type) IsUintptr() bool {
1365 return t.kind == TUINTPTR
1366 }
1367
1368
1369
1370
1371
1372
1373 func (t *Type) IsPtrShaped() bool {
1374 return t.kind == TPTR || t.kind == TUNSAFEPTR ||
1375 t.kind == TMAP || t.kind == TCHAN || t.kind == TFUNC
1376 }
1377
1378
1379 func (t *Type) HasNil() bool {
1380 switch t.kind {
1381 case TCHAN, TFUNC, TINTER, TMAP, TNIL, TPTR, TSLICE, TUNSAFEPTR:
1382 return true
1383 }
1384 return false
1385 }
1386
1387 func (t *Type) IsString() bool {
1388 return t.kind == TSTRING
1389 }
1390
1391 func (t *Type) IsMap() bool {
1392 return t.kind == TMAP
1393 }
1394
1395 func (t *Type) IsChan() bool {
1396 return t.kind == TCHAN
1397 }
1398
1399 func (t *Type) IsSlice() bool {
1400 return t.kind == TSLICE
1401 }
1402
1403 func (t *Type) IsArray() bool {
1404 return t.kind == TARRAY
1405 }
1406
1407 func (t *Type) IsStruct() bool {
1408 return t.kind == TSTRUCT
1409 }
1410
1411 func (t *Type) IsInterface() bool {
1412 return t.kind == TINTER
1413 }
1414
1415
1416 func (t *Type) IsEmptyInterface() bool {
1417 return t.IsInterface() && len(t.AllMethods()) == 0
1418 }
1419
1420
1421
1422
1423
1424 func (t *Type) IsScalar() bool {
1425 switch t.kind {
1426 case TBOOL, TINT8, TUINT8, TINT16, TUINT16, TINT32,
1427 TUINT32, TINT64, TUINT64, TINT, TUINT,
1428 TUINTPTR, TCOMPLEX64, TCOMPLEX128, TFLOAT32, TFLOAT64:
1429 return true
1430 }
1431 return false
1432 }
1433
1434 func (t *Type) PtrTo() *Type {
1435 return NewPtr(t)
1436 }
1437
1438 func (t *Type) NumFields() int {
1439 if t.kind == TRESULTS {
1440 return len(t.extra.(*Results).Types)
1441 }
1442 return len(t.Fields())
1443 }
1444 func (t *Type) FieldType(i int) *Type {
1445 if t.kind == TTUPLE {
1446 switch i {
1447 case 0:
1448 return t.extra.(*Tuple).first
1449 case 1:
1450 return t.extra.(*Tuple).second
1451 default:
1452 panic("bad tuple index")
1453 }
1454 }
1455 if t.kind == TRESULTS {
1456 return t.extra.(*Results).Types[i]
1457 }
1458 return t.Field(i).Type
1459 }
1460 func (t *Type) FieldOff(i int) int64 {
1461 return t.Field(i).Offset
1462 }
1463 func (t *Type) FieldName(i int) string {
1464 return t.Field(i).Sym.Name
1465 }
1466
1467
1468
1469 func (t *Type) OffsetOf(name string) int64 {
1470 if t.kind != TSTRUCT {
1471 base.Fatalf("can't call OffsetOf on non-struct %v", t)
1472 }
1473 for _, f := range t.Fields() {
1474 if f.Sym.Name == name {
1475 return f.Offset
1476 }
1477 }
1478 base.Fatalf("couldn't find field %s in %v", name, t)
1479 return -1
1480 }
1481
1482 func (t *Type) NumElem() int64 {
1483 t.wantEtype(TARRAY)
1484 return t.extra.(*Array).Bound
1485 }
1486
1487 type componentsIncludeBlankFields bool
1488
1489 const (
1490 IgnoreBlankFields componentsIncludeBlankFields = false
1491 CountBlankFields componentsIncludeBlankFields = true
1492 )
1493
1494
1495
1496
1497
1498
1499
1500 func (t *Type) NumComponents(countBlank componentsIncludeBlankFields) int64 {
1501 switch t.kind {
1502 case TSTRUCT:
1503 if t.IsFuncArgStruct() {
1504 base.Fatalf("NumComponents func arg struct")
1505 }
1506 var n int64
1507 for _, f := range t.Fields() {
1508 if countBlank == IgnoreBlankFields && f.Sym.IsBlank() {
1509 continue
1510 }
1511 n += f.Type.NumComponents(countBlank)
1512 }
1513 return n
1514 case TARRAY:
1515 return t.NumElem() * t.Elem().NumComponents(countBlank)
1516 }
1517 return 1
1518 }
1519
1520
1521
1522
1523
1524 func (t *Type) SoleComponent() *Type {
1525 switch t.kind {
1526 case TSTRUCT:
1527 if t.IsFuncArgStruct() {
1528 base.Fatalf("SoleComponent func arg struct")
1529 }
1530 if t.NumFields() != 1 {
1531 return nil
1532 }
1533 return t.Field(0).Type.SoleComponent()
1534 case TARRAY:
1535 if t.NumElem() != 1 {
1536 return nil
1537 }
1538 return t.Elem().SoleComponent()
1539 }
1540 return t
1541 }
1542
1543
1544
1545 func (t *Type) ChanDir() ChanDir {
1546 t.wantEtype(TCHAN)
1547 return t.extra.(*Chan).Dir
1548 }
1549
1550 func (t *Type) IsMemory() bool {
1551 if t == TypeMem || t.kind == TTUPLE && t.extra.(*Tuple).second == TypeMem {
1552 return true
1553 }
1554 if t.kind == TRESULTS {
1555 if types := t.extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem {
1556 return true
1557 }
1558 }
1559 return false
1560 }
1561 func (t *Type) IsFlags() bool { return t == TypeFlags }
1562 func (t *Type) IsVoid() bool { return t == TypeVoid }
1563 func (t *Type) IsTuple() bool { return t.kind == TTUPLE }
1564 func (t *Type) IsResults() bool { return t.kind == TRESULTS }
1565
1566
1567 func (t *Type) IsUntyped() bool {
1568 if t == nil {
1569 return false
1570 }
1571 if t == UntypedString || t == UntypedBool {
1572 return true
1573 }
1574 switch t.kind {
1575 case TNIL, TIDEAL:
1576 return true
1577 }
1578 return false
1579 }
1580
1581
1582
1583 func (t *Type) HasPointers() bool {
1584 return PtrDataSize(t) > 0
1585 }
1586
1587 var recvType *Type
1588
1589
1590 func FakeRecvType() *Type {
1591 if recvType == nil {
1592 recvType = NewPtr(newType(TSTRUCT))
1593 }
1594 return recvType
1595 }
1596
1597 func FakeRecv() *Field {
1598 return NewField(base.AutogeneratedPos, nil, FakeRecvType())
1599 }
1600
1601 var (
1602
1603 TypeInvalid = newSSA("invalid")
1604 TypeMem = newSSA("mem")
1605 TypeFlags = newSSA("flags")
1606 TypeVoid = newSSA("void")
1607 TypeInt128 = newSSA("int128")
1608 TypeVec128 = newSIMD("vec128")
1609 TypeVec256 = newSIMD("vec256")
1610 TypeVec512 = newSIMD("vec512")
1611 TypeMask = newSIMD("mask")
1612 TypeResultMem = newResults([]*Type{TypeMem})
1613 )
1614
1615 func init() {
1616 TypeInt128.width = 16
1617 TypeInt128.align = 8
1618
1619 TypeVec128.width = 16
1620 TypeVec128.align = 8
1621 TypeVec256.width = 32
1622 TypeVec256.align = 8
1623 TypeVec512.width = 64
1624 TypeVec512.align = 8
1625
1626 TypeMask.width = 8
1627 TypeMask.align = 8
1628 }
1629
1630
1631
1632
1633
1634
1635 func NewNamed(obj Object) *Type {
1636 t := newType(TFORW)
1637 t.obj = obj
1638 sym := obj.Sym()
1639 if sym.Pkg == ShapePkg {
1640 t.SetIsShape(true)
1641 t.SetHasShape(true)
1642 }
1643 if sym.Pkg.Path == "internal/runtime/sys" && sym.Name == "nih" {
1644
1645
1646
1647
1648 t.SetNotInHeap(true)
1649 }
1650 return t
1651 }
1652
1653
1654 func (t *Type) Obj() Object {
1655 return t.obj
1656 }
1657
1658
1659
1660
1661 func (t *Type) SetUnderlying(underlying *Type) {
1662 if underlying.kind == TFORW {
1663
1664 underlying.forwardType().Copyto = append(underlying.forwardType().Copyto, t)
1665 return
1666 }
1667
1668 ft := t.forwardType()
1669
1670
1671 t.kind = underlying.kind
1672 t.extra = underlying.extra
1673 t.width = underlying.width
1674 t.align = underlying.align
1675 t.alg = underlying.alg
1676 t.ptrBytes = underlying.ptrBytes
1677 t.intRegs = underlying.intRegs
1678 t.floatRegs = underlying.floatRegs
1679 t.underlying = underlying.underlying
1680
1681 if underlying.NotInHeap() {
1682 t.SetNotInHeap(true)
1683 }
1684 if underlying.HasShape() {
1685 t.SetHasShape(true)
1686 }
1687 if underlying.flags&typeIsSIMD != 0 {
1688 simdify(t, underlying.flags&typeIsSIMDTag != 0)
1689 }
1690
1691
1692
1693
1694 if t.IsInterface() {
1695 t.methods = underlying.methods
1696 t.allMethods = underlying.allMethods
1697 }
1698
1699
1700 for _, w := range ft.Copyto {
1701 w.SetUnderlying(t)
1702 }
1703
1704
1705 if ft.Embedlineno.IsKnown() {
1706 if t.IsPtr() || t.IsUnsafePtr() {
1707 base.ErrorfAt(ft.Embedlineno, errors.InvalidPtrEmbed, "embedded type cannot be a pointer")
1708 }
1709 }
1710 }
1711
1712 func fieldsHasShape(fields []*Field) bool {
1713 for _, f := range fields {
1714 if f.Type != nil && f.Type.HasShape() {
1715 return true
1716 }
1717 }
1718 return false
1719 }
1720
1721
1722
1723 func NewInterface(methods []*Field) *Type {
1724 t := newType(TINTER)
1725 t.SetInterface(methods)
1726 for _, f := range methods {
1727
1728 if f.Type != nil && f.Type.HasShape() {
1729 t.SetHasShape(true)
1730 break
1731 }
1732 }
1733 return t
1734 }
1735
1736
1737
1738 func NewSignature(recv *Field, params, results []*Field) *Type {
1739 startParams := 0
1740 if recv != nil {
1741 startParams = 1
1742 }
1743 startResults := startParams + len(params)
1744
1745 allParams := make([]*Field, startResults+len(results))
1746 if recv != nil {
1747 allParams[0] = recv
1748 }
1749 copy(allParams[startParams:], params)
1750 copy(allParams[startResults:], results)
1751
1752 t := newType(TFUNC)
1753 ft := t.funcType()
1754
1755 funargs := func(fields []*Field) *Type {
1756 s := NewStruct(fields)
1757 s.StructType().ParamTuple = true
1758 return s
1759 }
1760
1761 ft.allParams = allParams
1762 ft.startParams = startParams
1763 ft.startResults = startResults
1764
1765 ft.resultsTuple = funargs(allParams[startResults:])
1766
1767 if fieldsHasShape(allParams) {
1768 t.SetHasShape(true)
1769 }
1770
1771 return t
1772 }
1773
1774
1775 func NewStruct(fields []*Field) *Type {
1776 t := newType(TSTRUCT)
1777 t.setFields(fields)
1778 if fieldsHasShape(fields) {
1779 t.SetHasShape(true)
1780 }
1781 for _, f := range fields {
1782 if f.Type.NotInHeap() {
1783 t.SetNotInHeap(true)
1784 break
1785 }
1786 }
1787
1788 return t
1789 }
1790
1791 var (
1792 IsInt [NTYPE]bool
1793 IsFloat [NTYPE]bool
1794 IsComplex [NTYPE]bool
1795 IsSimple [NTYPE]bool
1796 )
1797
1798 var IsOrdered [NTYPE]bool
1799
1800
1801
1802 func IsReflexive(t *Type) bool {
1803 switch t.Kind() {
1804 case TBOOL,
1805 TINT,
1806 TUINT,
1807 TINT8,
1808 TUINT8,
1809 TINT16,
1810 TUINT16,
1811 TINT32,
1812 TUINT32,
1813 TINT64,
1814 TUINT64,
1815 TUINTPTR,
1816 TPTR,
1817 TUNSAFEPTR,
1818 TSTRING,
1819 TCHAN:
1820 return true
1821
1822 case TFLOAT32,
1823 TFLOAT64,
1824 TCOMPLEX64,
1825 TCOMPLEX128,
1826 TINTER:
1827 return false
1828
1829 case TARRAY:
1830 return IsReflexive(t.Elem())
1831
1832 case TSTRUCT:
1833 for _, t1 := range t.Fields() {
1834 if !IsReflexive(t1.Type) {
1835 return false
1836 }
1837 }
1838 return true
1839
1840 default:
1841 base.Fatalf("bad type for map key: %v", t)
1842 return false
1843 }
1844 }
1845
1846
1847
1848 func IsDirectIface(t *Type) bool {
1849 return t.Size() == int64(PtrSize) && PtrDataSize(t) == int64(PtrSize)
1850 }
1851
1852
1853
1854
1855 func IsInterfaceMethod(f *Type) bool {
1856 return f.Recv().Type == FakeRecvType()
1857 }
1858
1859
1860
1861
1862
1863 func IsMethodApplicable(t *Type, m *Field) bool {
1864 return t.IsPtr() || !m.Type.Recv().Type.IsPtr() || IsInterfaceMethod(m.Type) || m.Embedded == 2
1865 }
1866
1867
1868
1869 func RuntimeSymName(s *Sym) string {
1870 if s.Pkg.Path == "runtime" {
1871 return s.Name
1872 }
1873 return ""
1874 }
1875
1876
1877
1878 func ReflectSymName(s *Sym) string {
1879 if s.Pkg.Path == "reflect" {
1880 return s.Name
1881 }
1882 return ""
1883 }
1884
1885
1886
1887 func IsNoInstrumentPkg(p *Pkg) bool {
1888 return objabi.LookupPkgSpecial(p.Path).NoInstrument
1889 }
1890
1891
1892
1893 func IsNoRacePkg(p *Pkg) bool {
1894 return objabi.LookupPkgSpecial(p.Path).NoRaceFunc
1895 }
1896
1897
1898 func IsRuntimePkg(p *Pkg) bool {
1899 return objabi.LookupPkgSpecial(p.Path).Runtime
1900 }
1901
1902
1903
1904
1905 func ReceiverBaseType(t *Type) *Type {
1906 if t == nil {
1907 return nil
1908 }
1909
1910
1911 if t.IsPtr() {
1912 if t.Sym() != nil {
1913 return nil
1914 }
1915 t = t.Elem()
1916 if t == nil {
1917 return nil
1918 }
1919 }
1920
1921
1922 if t.Sym() == nil && !t.IsStruct() {
1923 return nil
1924 }
1925
1926
1927 if IsSimple[t.Kind()] {
1928 return t
1929 }
1930 switch t.Kind() {
1931 case TARRAY, TCHAN, TFUNC, TMAP, TSLICE, TSTRING, TSTRUCT:
1932 return t
1933 }
1934 return nil
1935 }
1936
1937 func FloatForComplex(t *Type) *Type {
1938 switch t.Kind() {
1939 case TCOMPLEX64:
1940 return Types[TFLOAT32]
1941 case TCOMPLEX128:
1942 return Types[TFLOAT64]
1943 }
1944 base.Fatalf("unexpected type: %v", t)
1945 return nil
1946 }
1947
1948 func ComplexForFloat(t *Type) *Type {
1949 switch t.Kind() {
1950 case TFLOAT32:
1951 return Types[TCOMPLEX64]
1952 case TFLOAT64:
1953 return Types[TCOMPLEX128]
1954 }
1955 base.Fatalf("unexpected type: %v", t)
1956 return nil
1957 }
1958
1959 func TypeSym(t *Type) *Sym {
1960 return TypeSymLookup(TypeSymName(t))
1961 }
1962
1963 func TypeSymLookup(name string) *Sym {
1964 typepkgmu.Lock()
1965 s := typepkg.Lookup(name)
1966 typepkgmu.Unlock()
1967 return s
1968 }
1969
1970 func TypeSymName(t *Type) string {
1971 name := t.LinkString()
1972
1973 if TypeHasNoAlg(t) {
1974 name = "noalg." + name
1975 }
1976 return name
1977 }
1978
1979
1980
1981 var (
1982 typepkgmu sync.Mutex
1983 typepkg = NewPkg("type", "type")
1984 )
1985
1986 var SimType [NTYPE]Kind
1987
1988
1989 var ShapePkg = NewPkg("go.shape", "go.shape")
1990
1991 func (t *Type) IsSIMD() bool {
1992 return t.flags&typeIsSIMD != 0
1993 }
1994
View as plain text