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 := T.Underlying().(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 := T.Underlying().(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 *Interface:
152 return s.WordSize * 2
153 }
154 return s.WordSize
155 }
156
157
158 var gcArchSizes = map[string]*StdSizes{
159 "386": {4, 4},
160 "arm": {4, 4},
161 "arm64": {8, 8},
162 "amd64": {8, 8},
163 "amd64p32": {4, 8},
164 "mips": {4, 4},
165 "mipsle": {4, 4},
166 "mips64": {8, 8},
167 "mips64le": {8, 8},
168 "ppc64": {8, 8},
169 "ppc64le": {8, 8},
170 "riscv64": {8, 8},
171 "s390x": {8, 8},
172 "sparc64": {8, 8},
173 "wasm": {8, 8},
174
175
176 }
177
178
179
180
181
182
183
184 func SizesFor(compiler, arch string) Sizes {
185 var m map[string]*StdSizes
186 switch compiler {
187 case "gc":
188 m = gcArchSizes
189 case "gccgo":
190 m = gccgoArchSizes
191 default:
192 return nil
193 }
194 s, ok := m[arch]
195 if !ok {
196 return nil
197 }
198 return s
199 }
200
201
202 var stdSizes = SizesFor("gc", "amd64")
203
204 func (conf *Config) alignof(T Type) int64 {
205 if s := conf.Sizes; s != nil {
206 if a := s.Alignof(T); a >= 1 {
207 return a
208 }
209 panic("Config.Sizes.Alignof returned an alignment < 1")
210 }
211 return stdSizes.Alignof(T)
212 }
213
214 func (conf *Config) offsetsof(T *Struct) []int64 {
215 var offsets []int64
216 if T.NumFields() > 0 {
217
218 if s := conf.Sizes; s != nil {
219 offsets = s.Offsetsof(T.fields)
220
221 if len(offsets) != T.NumFields() {
222 panic("Config.Sizes.Offsetsof returned the wrong number of offsets")
223 }
224 for _, o := range offsets {
225 if o < 0 {
226 panic("Config.Sizes.Offsetsof returned an offset < 0")
227 }
228 }
229 } else {
230 offsets = stdSizes.Offsetsof(T.fields)
231 }
232 }
233 return offsets
234 }
235
236
237
238
239 func (conf *Config) offsetof(typ Type, index []int) int64 {
240 var o int64
241 for _, i := range index {
242 s := typ.Underlying().(*Struct)
243 o += conf.offsetsof(s)[i]
244 typ = s.fields[i].typ
245 }
246 return o
247 }
248
249 func (conf *Config) sizeof(T Type) int64 {
250 if s := conf.Sizes; s != nil {
251 if z := s.Sizeof(T); z >= 0 {
252 return z
253 }
254 panic("Config.Sizes.Sizeof returned a size < 0")
255 }
256 return stdSizes.Sizeof(T)
257 }
258
259
260 func align(x, a int64) int64 {
261 y := x + a - 1
262 return y - y%a
263 }
264
View as plain text