Source file
src/go/types/sizes.go
1
2
3
4
5
6
7 package types
8
9
10 type Sizes interface {
11
12
13 Alignof(T Type) int64
14
15
16
17 Offsetsof(fields []*Var) []int64
18
19
20
21 Sizeof(T Type) int64
22 }
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 type StdSizes struct {
44 WordSize int64
45 MaxAlign int64
46 }
47
48 func (s *StdSizes) Alignof(T Type) int64 {
49
50
51 switch t := under(T).(type) {
52 case *Array:
53
54
55 return s.Alignof(t.elem)
56 case *Struct:
57
58
59
60 max := int64(1)
61 for _, f := range t.fields {
62 if a := s.Alignof(f.typ); a > max {
63 max = a
64 }
65 }
66 return max
67 case *Slice, *Interface:
68
69
70
71
72 assert(!isTypeParam(T))
73 return s.WordSize
74 case *Basic:
75
76 if t.Info()&IsString != 0 {
77 return s.WordSize
78 }
79 case *TypeParam, *Union:
80 unreachable()
81 }
82 a := s.Sizeof(T)
83
84 if a < 1 {
85 return 1
86 }
87
88 if isComplex(T) {
89 a /= 2
90 }
91 if a > s.MaxAlign {
92 return s.MaxAlign
93 }
94 return a
95 }
96
97 func (s *StdSizes) Offsetsof(fields []*Var) []int64 {
98 offsets := make([]int64, len(fields))
99 var o int64
100 for i, f := range fields {
101 a := s.Alignof(f.typ)
102 o = align(o, a)
103 offsets[i] = o
104 o += s.Sizeof(f.typ)
105 }
106 return offsets
107 }
108
109 var basicSizes = [...]byte{
110 Bool: 1,
111 Int8: 1,
112 Int16: 2,
113 Int32: 4,
114 Int64: 8,
115 Uint8: 1,
116 Uint16: 2,
117 Uint32: 4,
118 Uint64: 8,
119 Float32: 4,
120 Float64: 8,
121 Complex64: 8,
122 Complex128: 16,
123 }
124
125 func (s *StdSizes) Sizeof(T Type) int64 {
126 switch t := under(T).(type) {
127 case *Basic:
128 assert(isTyped(T))
129 k := t.kind
130 if int(k) < len(basicSizes) {
131 if s := basicSizes[k]; s > 0 {
132 return int64(s)
133 }
134 }
135 if k == String {
136 return s.WordSize * 2
137 }
138 case *Array:
139 n := t.len
140 if n <= 0 {
141 return 0
142 }
143
144 a := s.Alignof(t.elem)
145 z := s.Sizeof(t.elem)
146 return align(z, a)*(n-1) + z
147 case *Slice:
148 return s.WordSize * 3
149 case *Struct:
150 n := t.NumFields()
151 if n == 0 {
152 return 0
153 }
154 offsets := s.Offsetsof(t.fields)
155 return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
156 case *Interface:
157
158
159 assert(!isTypeParam(T))
160 return s.WordSize * 2
161 case *TypeParam, *Union:
162 unreachable()
163 }
164 return s.WordSize
165 }
166
167
168 var gcArchSizes = map[string]*StdSizes{
169 "386": {4, 4},
170 "arm": {4, 4},
171 "arm64": {8, 8},
172 "amd64": {8, 8},
173 "amd64p32": {4, 8},
174 "mips": {4, 4},
175 "mipsle": {4, 4},
176 "mips64": {8, 8},
177 "mips64le": {8, 8},
178 "ppc64": {8, 8},
179 "ppc64le": {8, 8},
180 "riscv64": {8, 8},
181 "s390x": {8, 8},
182 "sparc64": {8, 8},
183 "wasm": {8, 8},
184
185
186 }
187
188
189
190
191
192
193
194 func SizesFor(compiler, arch string) Sizes {
195 var m map[string]*StdSizes
196 switch compiler {
197 case "gc":
198 m = gcArchSizes
199 case "gccgo":
200 m = gccgoArchSizes
201 default:
202 return nil
203 }
204 s, ok := m[arch]
205 if !ok {
206 return nil
207 }
208 return s
209 }
210
211
212 var stdSizes = SizesFor("gc", "amd64")
213
214 func (conf *Config) alignof(T Type) int64 {
215 if s := conf.Sizes; s != nil {
216 if a := s.Alignof(T); a >= 1 {
217 return a
218 }
219 panic("Config.Sizes.Alignof returned an alignment < 1")
220 }
221 return stdSizes.Alignof(T)
222 }
223
224 func (conf *Config) offsetsof(T *Struct) []int64 {
225 var offsets []int64
226 if T.NumFields() > 0 {
227
228 if s := conf.Sizes; s != nil {
229 offsets = s.Offsetsof(T.fields)
230
231 if len(offsets) != T.NumFields() {
232 panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
233 }
234 for _, o := range offsets {
235 if o < 0 {
236 panic("Config.Sizes.Offsetsof returned an offset < 0")
237 }
238 }
239 } else {
240 offsets = stdSizes.Offsetsof(T.fields)
241 }
242 }
243 return offsets
244 }
245
246
247
248
249 func (conf *Config) offsetof(typ Type, index []int) int64 {
250 var o int64
251 for _, i := range index {
252 s := under(typ).(*Struct)
253 o += conf.offsetsof(s)[i]
254 typ = s.fields[i].typ
255 }
256 return o
257 }
258
259 func (conf *Config) sizeof(T Type) int64 {
260 if s := conf.Sizes; s != nil {
261 if z := s.Sizeof(T); z >= 0 {
262 return z
263 }
264 panic("Config.Sizes.Sizeof returned a size < 0")
265 }
266 return stdSizes.Sizeof(T)
267 }
268
269
270 func align(x, a int64) int64 {
271 y := x + a - 1
272 return y - y%a
273 }
274
View as plain text