Source file src/pkg/cmd/compile/internal/gc/align.go
1
2
3
4
5 package gc
6
7 import (
8 "cmd/compile/internal/types"
9 "sort"
10 )
11
12
13
14 var sizeCalculationDisabled bool
15
16
17
18 var defercalc int
19
20 func Rnd(o int64, r int64) int64 {
21 if r < 1 || r > 8 || r&(r-1) != 0 {
22 Fatalf("rnd %d", r)
23 }
24 return (o + r - 1) &^ (r - 1)
25 }
26
27
28
29 func expandiface(t *types.Type) {
30 var fields []*types.Field
31 for _, m := range t.Methods().Slice() {
32 if m.Sym != nil {
33 fields = append(fields, m)
34 checkwidth(m.Type)
35 continue
36 }
37
38 if !m.Type.IsInterface() {
39 yyerrorl(m.Pos, "interface contains embedded non-interface %v", m.Type)
40 m.SetBroke(true)
41 t.SetBroke(true)
42
43
44
45
46 fields = append(fields, m)
47 continue
48 }
49
50
51
52
53 for _, t1 := range m.Type.Fields().Slice() {
54 f := types.NewField()
55 f.Pos = m.Pos
56 f.Sym = t1.Sym
57 f.Type = t1.Type
58 f.SetBroke(t1.Broke())
59 fields = append(fields, f)
60 }
61 }
62 sort.Sort(methcmp(fields))
63
64
65
66 t.Extra.(*types.Interface).Fields.Set(fields)
67 }
68
69 func offmod(t *types.Type) {
70 o := int32(0)
71 for _, f := range t.Fields().Slice() {
72 f.Offset = int64(o)
73 o += int32(Widthptr)
74 if int64(o) >= thearch.MAXWIDTH {
75 yyerror("interface too large")
76 o = int32(Widthptr)
77 }
78 }
79 }
80
81 func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 {
82 starto := o
83 maxalign := int32(flag)
84 if maxalign < 1 {
85 maxalign = 1
86 }
87 lastzero := int64(0)
88 for _, f := range t.Fields().Slice() {
89 if f.Type == nil {
90
91
92 continue
93 }
94
95 dowidth(f.Type)
96 if int32(f.Type.Align) > maxalign {
97 maxalign = int32(f.Type.Align)
98 }
99 if f.Type.Align > 0 {
100 o = Rnd(o, int64(f.Type.Align))
101 }
102 f.Offset = o
103 if n := asNode(f.Nname); n != nil {
104
105
106
107
108
109
110
111 if n.Name.Param.Stackcopy != nil {
112 n.Name.Param.Stackcopy.Xoffset = o
113 n.Xoffset = 0
114 } else {
115 n.Xoffset = o
116 }
117 }
118
119 w := f.Type.Width
120 if w < 0 {
121 Fatalf("invalid width %d", f.Type.Width)
122 }
123 if w == 0 {
124 lastzero = o
125 }
126 o += w
127 maxwidth := thearch.MAXWIDTH
128
129
130 if maxwidth < 1<<32 {
131 maxwidth = 1<<31 - 1
132 }
133 if o >= maxwidth {
134 yyerror("type %L too large", errtype)
135 o = 8
136 }
137 }
138
139
140
141
142
143 if flag == 1 && o > starto && o == lastzero {
144 o++
145 }
146
147
148 if flag != 0 {
149 o = Rnd(o, int64(maxalign))
150 }
151 t.Align = uint8(maxalign)
152
153
154 t.Width = o - starto
155
156 return o
157 }
158
159
160
161
162
163 func dowidth(t *types.Type) {
164 if Widthptr == 0 {
165 Fatalf("dowidth without betypeinit")
166 }
167
168 if t == nil {
169 return
170 }
171
172 if t.Width == -2 {
173 if !t.Broke() {
174 t.SetBroke(true)
175
176
177
178
179
180 if t.Nod == nil {
181 yyerror("invalid recursive type %v", t)
182 } else {
183 yyerrorl(asNode(t.Nod).Pos, "invalid recursive type %v", t)
184 }
185 }
186
187 t.Width = 0
188 t.Align = 1
189 return
190 }
191
192 if t.WidthCalculated() {
193 return
194 }
195
196 if sizeCalculationDisabled {
197 if t.Broke() {
198
199 return
200 }
201 t.SetBroke(true)
202 Fatalf("width not calculated: %v", t)
203 }
204
205
206
207 if t.Broke() && t.Width == 0 {
208 return
209 }
210
211
212 defercalc++
213
214 lno := lineno
215 if asNode(t.Nod) != nil {
216 lineno = asNode(t.Nod).Pos
217 }
218
219 t.Width = -2
220 t.Align = 0
221
222 et := t.Etype
223 switch et {
224 case TFUNC, TCHAN, TMAP, TSTRING:
225 break
226
227
228 default:
229 if simtype[t.Etype] != 0 {
230 et = simtype[t.Etype]
231 }
232 }
233
234 var w int64
235 switch et {
236 default:
237 Fatalf("dowidth: unknown type: %v", t)
238
239
240 case TINT8, TUINT8, TBOOL:
241
242 w = 1
243
244 case TINT16, TUINT16:
245 w = 2
246
247 case TINT32, TUINT32, TFLOAT32:
248 w = 4
249
250 case TINT64, TUINT64, TFLOAT64:
251 w = 8
252 t.Align = uint8(Widthreg)
253
254 case TCOMPLEX64:
255 w = 8
256 t.Align = 4
257
258 case TCOMPLEX128:
259 w = 16
260 t.Align = uint8(Widthreg)
261
262 case TPTR:
263 w = int64(Widthptr)
264 checkwidth(t.Elem())
265
266 case TUNSAFEPTR:
267 w = int64(Widthptr)
268
269 case TINTER:
270 w = 2 * int64(Widthptr)
271 t.Align = uint8(Widthptr)
272 expandiface(t)
273
274 case TCHAN:
275 w = int64(Widthptr)
276
277 checkwidth(t.Elem())
278
279
280
281 t1 := types.NewChanArgs(t)
282 checkwidth(t1)
283
284 case TCHANARGS:
285 t1 := t.ChanArgs()
286 dowidth(t1)
287 if t1.Elem().Width >= 1<<16 {
288 yyerror("channel element type too large (>64kB)")
289 }
290 w = 1
291
292 case TMAP:
293 w = int64(Widthptr)
294 checkwidth(t.Elem())
295 checkwidth(t.Key())
296
297 case TFORW:
298 if !t.Broke() {
299 t.SetBroke(true)
300 yyerror("invalid recursive type %v", t)
301 }
302 w = 1
303
304 case TANY:
305
306 Fatalf("dowidth any")
307
308 case TSTRING:
309 if sizeof_String == 0 {
310 Fatalf("early dowidth string")
311 }
312 w = int64(sizeof_String)
313 t.Align = uint8(Widthptr)
314
315 case TARRAY:
316 if t.Elem() == nil {
317 break
318 }
319 if t.IsDDDArray() {
320 if !t.Broke() {
321 yyerror("use of [...] array outside of array literal")
322 t.SetBroke(true)
323 }
324 break
325 }
326
327 dowidth(t.Elem())
328 if t.Elem().Width != 0 {
329 cap := (uint64(thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width)
330 if uint64(t.NumElem()) > cap {
331 yyerror("type %L larger than address space", t)
332 }
333 }
334 w = t.NumElem() * t.Elem().Width
335 t.Align = t.Elem().Align
336
337 case TSLICE:
338 if t.Elem() == nil {
339 break
340 }
341 w = int64(sizeof_Array)
342 checkwidth(t.Elem())
343 t.Align = uint8(Widthptr)
344
345 case TSTRUCT:
346 if t.IsFuncArgStruct() {
347 Fatalf("dowidth fn struct %v", t)
348 }
349 w = widstruct(t, t, 0, 1)
350
351
352
353 case TFUNC:
354 t1 := types.NewFuncArgs(t)
355 checkwidth(t1)
356 w = int64(Widthptr)
357
358
359
360 case TFUNCARGS:
361 t1 := t.FuncArgs()
362 w = widstruct(t1, t1.Recvs(), 0, 0)
363 w = widstruct(t1, t1.Params(), w, Widthreg)
364 w = widstruct(t1, t1.Results(), w, Widthreg)
365 t1.Extra.(*types.Func).Argwid = w
366 if w%int64(Widthreg) != 0 {
367 Warn("bad type %v %d\n", t1, w)
368 }
369 t.Align = 1
370 }
371
372 if Widthptr == 4 && w != int64(int32(w)) {
373 yyerror("type %v too large", t)
374 }
375
376 t.Width = w
377 if t.Align == 0 {
378 if w == 0 || w > 8 || w&(w-1) != 0 {
379 Fatalf("invalid alignment for %v", t)
380 }
381 t.Align = uint8(w)
382 }
383
384 if t.Etype == TINTER {
385
386
387
388 checkdupfields("method", t)
389 offmod(t)
390 }
391
392 lineno = lno
393
394 if defercalc == 1 {
395 resumecheckwidth()
396 } else {
397 defercalc--
398 }
399 }
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 var deferredTypeStack []*types.Type
418
419 func checkwidth(t *types.Type) {
420 if t == nil {
421 return
422 }
423
424
425
426 if t.IsFuncArgStruct() {
427 Fatalf("checkwidth %v", t)
428 }
429
430 if defercalc == 0 {
431 dowidth(t)
432 return
433 }
434
435
436 if !t.Deferwidth() {
437 t.SetDeferwidth(true)
438 deferredTypeStack = append(deferredTypeStack, t)
439 }
440 }
441
442 func defercheckwidth() {
443
444 if defercalc != 0 && nerrors == 0 {
445 Fatalf("defercheckwidth")
446 }
447 defercalc = 1
448 }
449
450 func resumecheckwidth() {
451 if defercalc == 0 {
452 Fatalf("resumecheckwidth")
453 }
454
455 for len(deferredTypeStack) > 0 {
456 t := deferredTypeStack[len(deferredTypeStack)-1]
457 deferredTypeStack = deferredTypeStack[:len(deferredTypeStack)-1]
458 t.SetDeferwidth(false)
459 dowidth(t)
460 }
461
462 defercalc = 0
463 }
464
View as plain text