@@ -100,15 +100,98 @@ mp_integer alignment(const typet &type, const namespacet &ns)
100100 return result;
101101}
102102
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)
104127{
105128 struct_typet::componentst &components=type.components ();
106129
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+ }
109184
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
110193 {
111- std:: size_t padding_counter= 0 ;
194+ // Make bit-fields appear on byte boundaries
112195 std::size_t bit_field_bits=0 ;
113196
114197 for (struct_typet::componentst::iterator
@@ -129,18 +212,7 @@ void add_padding(struct_typet &type, const namespacet &ns)
129212 if ((bit_field_bits%8 )!=0 )
130213 {
131214 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);
144216 }
145217
146218 bit_field_bits=0 ;
@@ -151,16 +223,14 @@ void add_padding(struct_typet &type, const namespacet &ns)
151223 if ((bit_field_bits%8 )!=0 )
152224 {
153225 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);
162227 }
163228 }
229+ }
230+
231+ void add_padding (struct_typet &type, const namespacet &ns)
232+ {
233+ bit_field_padding (type, ns);
164234
165235 // Is the struct packed, without any alignment specification?
166236 if (type.get_bool (ID_C_packed) &&
@@ -172,6 +242,8 @@ void add_padding(struct_typet &type, const namespacet &ns)
172242 mp_integer max_alignment=0 ;
173243 std::size_t bit_field_bits=0 ;
174244
245+ struct_typet::componentst &components = type.components ();
246+
175247 for (struct_typet::componentst::iterator
176248 it=components.begin ();
177249 it!=components.end ();
@@ -313,6 +385,19 @@ void add_padding(union_typet &type, const namespacet &ns)
313385 max_alignment_bits=8 ;
314386 }
315387
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+
316401 // The size must be a multiple of the alignment, or
317402 // we add a padding member to the union.
318403
0 commit comments