1
2
3
4
5 package types2
6
7 type gcSizes struct {
8 WordSize int64
9 MaxAlign int64
10 }
11
12 func (s *gcSizes) Alignof(T Type) (result int64) {
13 defer func() {
14 assert(result >= 1)
15 }()
16
17
18
19 switch t := under(T).(type) {
20 case *Array:
21
22
23 return s.Alignof(t.elem)
24 case *Struct:
25 if len(t.fields) == 0 && IsSyncAtomicAlign64(T) {
26
27
28
29
30
31
32
33 return 8
34 }
35
36
37
38
39 max := int64(1)
40 for _, f := range t.fields {
41 if a := s.Alignof(f.typ); a > max {
42 max = a
43 }
44 }
45 return max
46 case *Slice, *Interface:
47
48
49
50
51 assert(!isTypeParam(T))
52 return s.WordSize
53 case *Basic:
54
55 if t.Info()&IsString != 0 {
56 return s.WordSize
57 }
58 case *TypeParam, *Union:
59 panic("unreachable")
60 }
61 a := s.Sizeof(T)
62
63 if a < 1 {
64 return 1
65 }
66
67 if isComplex(T) {
68 a /= 2
69 }
70 if a > s.MaxAlign {
71 return s.MaxAlign
72 }
73 return a
74 }
75
76 func (s *gcSizes) Offsetsof(fields []*Var) []int64 {
77 offsets := make([]int64, len(fields))
78 var offs int64
79 for i, f := range fields {
80 if offs < 0 {
81
82 offsets[i] = -1
83 continue
84 }
85
86 a := s.Alignof(f.typ)
87 offs = align(offs, a)
88 offsets[i] = offs
89 if d := s.Sizeof(f.typ); d >= 0 && offs >= 0 {
90 offs += d
91 } else {
92 offs = -1
93 }
94 }
95 return offsets
96 }
97
98 func (s *gcSizes) Sizeof(T Type) int64 {
99 switch t := under(T).(type) {
100 case *Basic:
101 assert(isTyped(T))
102 k := t.kind
103 if int(k) < len(basicSizes) {
104 if s := basicSizes[k]; s > 0 {
105 return int64(s)
106 }
107 }
108 if k == String {
109 return s.WordSize * 2
110 }
111 case *Array:
112 n := t.len
113 if n <= 0 {
114 return 0
115 }
116
117 esize := s.Sizeof(t.elem)
118 if esize < 0 {
119 return -1
120 }
121 if esize == 0 {
122 return 0
123 }
124
125
126 const maxInt64 = 1<<63 - 1
127 if esize > maxInt64/n {
128 return -1
129 }
130 return esize * n
131 case *Slice:
132 return s.WordSize * 3
133 case *Struct:
134 n := t.NumFields()
135 if n == 0 {
136 return 0
137 }
138 offsets := s.Offsetsof(t.fields)
139 offs := offsets[n-1]
140 size := s.Sizeof(t.fields[n-1].typ)
141 if offs < 0 || size < 0 {
142 return -1
143 }
144
145
146 if offs > 0 && size == 0 {
147 size = 1
148 }
149
150 return align(offs+size, s.Alignof(t))
151 case *Interface:
152
153
154 assert(!isTypeParam(T))
155 return s.WordSize * 2
156 case *TypeParam, *Union:
157 panic("unreachable")
158 }
159 return s.WordSize
160 }
161
162
163
164
165 func gcSizesFor(compiler, arch string) *gcSizes {
166 if compiler != "gc" {
167 return nil
168 }
169 return gcArchSizes[arch]
170 }
171
View as plain text