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