@@ -100,15 +100,98 @@ mp_integer alignment(const typet &type, const namespacet &ns)
100
100
return result;
101
101
}
102
102
103
- void add_padding (struct_typet &type, const namespacet &ns)
103
+ std::size_t underlying_width (const c_bit_field_typet &type)
104
+ {
105
+ return type.subtype ().get_size_t (ID_width);
106
+ }
107
+
108
+ struct_typet::componentst::iterator pad_bit_field (
109
+ struct_typet::componentst &components,
110
+ struct_typet::componentst::iterator where,
111
+ std::size_t pad_bits)
112
+ {
113
+ c_bit_field_typet padding_type (unsignedbv_typet (pad_bits), pad_bits);
114
+
115
+ struct_typet::componentt component;
116
+ component.type () = padding_type;
117
+ component.set_name (
118
+ " $bit_field_pad" + std::to_string (where - components.begin ()));
119
+ component.set_is_padding (true );
120
+
121
+ auto it = components.insert (where, component);
122
+ it++;
123
+ return it;
124
+ }
125
+
126
+ void bit_field_padding (struct_typet &type, const namespacet &ns)
104
127
{
105
128
struct_typet::componentst &components=type.components ();
106
129
107
- // First do padding for bit-fields to make them
108
- // appear on byte boundaries.
130
+ // bit-field padding depends greatly on compiler
131
+ if (config.ansi_c .mode == configt::ansi_ct::flavourt::VISUAL_STUDIO)
132
+ {
133
+ std::size_t bit_field_bits = 0 , underlying_bits = 0 ;
134
+
135
+ for (struct_typet::componentst::iterator it = components.begin ();
136
+ it != components.end ();
137
+ it++)
138
+ {
139
+ if (
140
+ it->type ().id () == ID_c_bit_field &&
141
+ to_c_bit_field_type (it->type ()).get_width () != 0 )
142
+ {
143
+ const auto &bit_field_type = to_c_bit_field_type (it->type ());
144
+
145
+ std::size_t new_underlying_bits = underlying_width (bit_field_type);
146
+
147
+ CHECK_RETURN (new_underlying_bits != 0 );
148
+
149
+ if (underlying_bits == 0 )
150
+ {
151
+ underlying_bits = new_underlying_bits;
152
+ bit_field_bits = 0 ;
153
+ }
154
+ else if (new_underlying_bits != underlying_bits)
155
+ {
156
+ // new underlying width, we pad up
157
+ if ((bit_field_bits % underlying_bits) != 0 )
158
+ {
159
+ std::size_t pad =
160
+ underlying_bits - (bit_field_bits % underlying_bits);
161
+ it = pad_bit_field (components, it, pad);
162
+ }
163
+
164
+ underlying_bits = new_underlying_bits;
165
+ bit_field_bits = 0 ;
166
+ }
167
+
168
+ // count the bits
169
+ std::size_t width = bit_field_type.get_width ();
170
+ bit_field_bits += width;
171
+ }
172
+ else
173
+ {
174
+ // pad up
175
+ if (underlying_bits != 0 && (bit_field_bits % underlying_bits) != 0 )
176
+ {
177
+ std::size_t pad =
178
+ underlying_bits - (bit_field_bits % underlying_bits);
179
+ it = pad_bit_field (components, it, pad);
180
+ underlying_bits = bit_field_bits = 0 ;
181
+ }
182
+ }
183
+ }
109
184
185
+ // Add padding at the end?
186
+ if (underlying_bits != 0 && (bit_field_bits % underlying_bits) != 0 )
187
+ {
188
+ std::size_t pad = underlying_bits - (bit_field_bits % underlying_bits);
189
+ pad_bit_field (components, components.end (), pad);
190
+ }
191
+ }
192
+ else
110
193
{
111
- std:: size_t padding_counter= 0 ;
194
+ // Make bit-fields appear on byte boundaries
112
195
std::size_t bit_field_bits=0 ;
113
196
114
197
for (struct_typet::componentst::iterator
@@ -129,18 +212,7 @@ void add_padding(struct_typet &type, const namespacet &ns)
129
212
if ((bit_field_bits%8 )!=0 )
130
213
{
131
214
std::size_t pad=8 -bit_field_bits%8 ;
132
- c_bit_field_typet padding_type (unsignedbv_typet (pad), pad);
133
-
134
- struct_typet::componentt component;
135
- component.type ()=padding_type;
136
- component.set_name (
137
- " $bit_field_pad" +std::to_string (padding_counter++));
138
- component.set_is_padding (true );
139
-
140
- it=components.insert (it, component);
141
- it++; // skip over
142
-
143
- bit_field_bits+=pad;
215
+ it = pad_bit_field (components, it, pad);
144
216
}
145
217
146
218
bit_field_bits=0 ;
@@ -151,16 +223,14 @@ void add_padding(struct_typet &type, const namespacet &ns)
151
223
if ((bit_field_bits%8 )!=0 )
152
224
{
153
225
std::size_t pad=8 -bit_field_bits%8 ;
154
- c_bit_field_typet padding_type (unsignedbv_typet (pad), pad);
155
-
156
- struct_typet::componentt component;
157
- component.type ()=padding_type;
158
- component.set_name (" $bit_field_pad" +std::to_string (padding_counter++));
159
- component.set_is_padding (true );
160
-
161
- components.push_back (component);
226
+ pad_bit_field (components, components.end (), pad);
162
227
}
163
228
}
229
+ }
230
+
231
+ void add_padding (struct_typet &type, const namespacet &ns)
232
+ {
233
+ bit_field_padding (type, ns);
164
234
165
235
// Is the struct packed, without any alignment specification?
166
236
if (type.get_bool (ID_C_packed) &&
@@ -172,6 +242,8 @@ void add_padding(struct_typet &type, const namespacet &ns)
172
242
mp_integer max_alignment=0 ;
173
243
std::size_t bit_field_bits=0 ;
174
244
245
+ struct_typet::componentst &components = type.components ();
246
+
175
247
for (struct_typet::componentst::iterator
176
248
it=components.begin ();
177
249
it!=components.end ();
@@ -313,6 +385,19 @@ void add_padding(union_typet &type, const namespacet &ns)
313
385
max_alignment_bits=8 ;
314
386
}
315
387
388
+ if (config.ansi_c .mode == configt::ansi_ct::flavourt::VISUAL_STUDIO)
389
+ {
390
+ // Visual Studio pads up to the underlying width of
391
+ // any bit field.
392
+ for (const auto &c : type.components ())
393
+ if (c.type ().id () == ID_c_bit_field)
394
+ {
395
+ std::size_t w = underlying_width (to_c_bit_field_type (c.type ()));
396
+ if (w > max_alignment_bits)
397
+ max_alignment_bits = w;
398
+ }
399
+ }
400
+
316
401
// The size must be a multiple of the alignment, or
317
402
// we add a padding member to the union.
318
403
0 commit comments