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 := optype(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 return s.WordSize
71 case *Basic:
72
73 if t.Info()&IsString != 0 {
74 return s.WordSize
75 }
76 }
77 a := s.Sizeof(T)
78
79 if a < 1 {
80 return 1
81 }
82
83 if isComplex(T) {
84 a /= 2
85 }
86 if a > s.MaxAlign {
87 return s.MaxAlign
88 }
89 return a
90 }
91
92 func (s *StdSizes) Offsetsof(fields []*Var) []int64 {
93 offsets := make([]int64, len(fields))
94 var o int64
95 for i, f := range fields {
96 a := s.Alignof(f.typ)
97 o = align(o, a)
98 offsets[i] = o
99 o += s.Sizeof(f.typ)
100 }
101 return offsets
102 }
103
104 var basicSizes = [...]byte{
105 Bool: 1,
106 Int8: 1,
107 Int16: 2,
108 Int32: 4,
109 Int64: 8,
110 Uint8: 1,
111 Uint16: 2,
112 Uint32: 4,
113 Uint64: 8,
114 Float32: 4,
115 Float64: 8,
116 Complex64: 8,
117 Complex128: 16,
118 }
119
120 func (s *StdSizes) Sizeof(T Type) int64 {
121 switch t := optype(T).(type) {
122 case *Basic:
123 assert(isTyped(T))
124 k := t.kind
125 if int(k) < len(basicSizes) {
126 if s := basicSizes[k]; s > 0 {
127 return int64(s)
128 }
129 }
130 if k == String {
131 return s.WordSize * 2
132 }
133 case *Array:
134 n := t.len
135 if n <= 0 {
136 return 0
137 }
138
139 a := s.Alignof(t.elem)
140 z := s.Sizeof(t.elem)
141 return align(z, a)*(n-1) + z
142 case *Slice:
143 return s.WordSize * 3
144 case *Struct:
145 n := t.NumFields()
146 if n == 0 {
147 return 0
148 }
149 offsets := s.Offsetsof(t.fields)
150 return offsets[n-1] + s.Sizeof(t.fields[n-1].typ)
151 case *_Sum:
152 panic("Sizeof unimplemented for type sum")
153 case *Interface:
154 return s.WordSize * 2
155 }
156 return s.WordSize
157 }
158
159
160 var gcArchSizes = map[string]*StdSizes{
161 "386": {4, 4},
162 "arm": {4, 4},
163 "arm64": {8, 8},
164 "amd64": {8, 8},
165 "amd64p32": {4, 8},
166 "mips": {4, 4},
167 "mipsle": {4, 4},
168 "mips64": {8, 8},
169 "mips64le": {8, 8},
170 "ppc64": {8, 8},
171 "ppc64le": {8, 8},
172 "riscv64": {8, 8},
173 "s390x": {8, 8},
174 "sparc64": {8, 8},
175 "wasm": {8, 8},
176
177
178 }
179
180
181
182
183
184
185
186 func SizesFor(compiler, arch string) Sizes {
187 var m map[string]*StdSizes
188 switch compiler {
189 case "gc":
190 m = gcArchSizes
191 case "gccgo":
192 m = gccgoArchSizes
193 default:
194 return nil
195 }
196 s, ok := m[arch]
197 if !ok {
198 return nil
199 }
200 return s
201 }
202
203
204 var stdSizes = SizesFor("gc", "amd64")
205
206 func (conf *Config) alignof(T Type) int64 {
207 if s := conf.Sizes; s != nil {
208 if a := s.Alignof(T); a >= 1 {
209 return a
210 }
211 panic("Config.Sizes.Alignof returned an alignment < 1")
212 }
213 return stdSizes.Alignof(T)
214 }
215
216 func (conf *Config) offsetsof(T *Struct) []int64 {
217 var offsets []int64
218 if T.NumFields() > 0 {
219
220 if s := conf.Sizes; s != nil {
221 offsets = s.Offsetsof(T.fields)
222
223 if len(offsets) != T.NumFields() {
224 panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
225 }
226 for _, o := range offsets {
227 if o < 0 {
228 panic("Config.Sizes.Offsetsof returned an offset < 0")
229 }
230 }
231 } else {
232 offsets = stdSizes.Offsetsof(T.fields)
233 }
234 }
235 return offsets
236 }
237
238
239
240
241 func (conf *Config) offsetof(typ Type, index []int) int64 {
242 var o int64
243 for _, i := range index {
244 s := asStruct(typ)
245 o += conf.offsetsof(s)[i]
246 typ = s.fields[i].typ
247 }
248 return o
249 }
250
251 func (conf *Config) sizeof(T Type) int64 {
252 if s := conf.Sizes; s != nil {
253 if z := s.Sizeof(T); z >= 0 {
254 return z
255 }
256 panic("Config.Sizes.Sizeof returned a size < 0")
257 }
258 return stdSizes.Sizeof(T)
259 }
260
261
262 func align(x, a int64) int64 {
263 y := x + a - 1
264 return y - y%a
265 }
266
View as plain text