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