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