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