Skip to content

Commit 703bc3e

Browse files
author
Daniel Kroening
committed
Visual Studio packs bit-fields differently
1 parent ae1d039 commit 703bc3e

File tree

5 files changed

+146
-34
lines changed

5 files changed

+146
-34
lines changed

appveyor.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ test_script:
7070
rmdir /s /q ansi-c\arch_flags_mthumb_good
7171
rmdir /s /q ansi-c\Forward_Declaration2
7272
rmdir /s /q ansi-c\Incomplete_Type1
73-
rmdir /s /q ansi-c\Union_Padding1
7473
rmdir /s /q ansi-c\Universal_characters1
7574
rmdir /s /q ansi-c\function_return1
7675
rmdir /s /q ansi-c\gcc_attributes7

buildspec-windows.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ phases:
3434
Remove-Item ansi-c\arch_flags_mthumb_good -Force -Recurse
3535
Remove-Item ansi-c\Forward_Declaration2 -Force -Recurse
3636
Remove-Item ansi-c\Incomplete_Type1 -Force -Recurse
37-
Remove-Item ansi-c\Union_Padding1 -Force -Recurse
3837
Remove-Item ansi-c\Universal_characters1 -Force -Recurse
3938
Remove-Item ansi-c\function_return1 -Force -Recurse
4039
Remove-Item ansi-c\gcc_attributes7 -Force -Recurse

regression/ansi-c/Struct_Padding5/main.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,46 @@ STATIC_ASSERT(sizeof(struct flowi)==8);
2828
STATIC_ASSERT(__builtin_offsetof(struct flowi, flexible)==1);
2929
#endif
3030

31+
// bit-fields are very evil
32+
#pragma pack(push, 1)
33+
struct bit_field0
34+
{
35+
int i:23;
36+
};
37+
38+
struct bit_field1
39+
{
40+
int i:1;
41+
unsigned int j:1;
42+
// in MSC, it matters that the underlying type changes!
43+
short c:1;
44+
};
45+
46+
struct bit_field2
47+
{
48+
int i:23;
49+
char ch;
50+
};
51+
#pragma pack(pop)
52+
53+
struct bit_field3
54+
{
55+
int i:23;
56+
char ch;
57+
};
58+
59+
#ifdef _MSC_VER
60+
STATIC_ASSERT(sizeof(struct bit_field0)==4);
61+
STATIC_ASSERT(sizeof(struct bit_field1)==6);
62+
STATIC_ASSERT(sizeof(struct bit_field2)==5);
63+
STATIC_ASSERT(sizeof(struct bit_field3)==8);
64+
#else
65+
STATIC_ASSERT(sizeof(struct bit_field0)==3);
66+
STATIC_ASSERT(sizeof(struct bit_field1)==1);
67+
STATIC_ASSERT(sizeof(struct bit_field2)==4);
68+
STATIC_ASSERT(sizeof(struct bit_field3)==4);
69+
#endif
70+
3171
int main()
3272
{
3373
}

regression/ansi-c/Union_Padding1/main.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@ STATIC_ASSERT(sizeof(union some_union3)==sizeof(int));
4141
#ifdef _MSC_VER
4242

4343
// bit-fields are evil
44-
#pragma pack(1)
44+
#pragma pack(push,1)
4545
union some_union4
4646
{
4747
int i:23;
4848
};
49+
#pragma pack(pop)
4950

5051
// Visual Studio ignores the 'packed'
5152
STATIC_ASSERT(sizeof(union some_union4)==sizeof(int));
53+
STATIC_ASSERT(__alignof(union some_union4)==1);
5254

5355
#else
5456

@@ -59,34 +61,39 @@ union some_union4
5961
} __attribute__((__packed__));
6062

6163
STATIC_ASSERT(sizeof(union some_union4)==3);
64+
STATIC_ASSERT(_Alignof(union some_union4)==1);
6265

6366
#endif
6467

65-
#ifdef _MSC_VER
66-
6768
union some_union5
6869
{
6970
int i;
7071
};
7172

72-
STATIC_ASSERT(__alignof(union some_union5)==1);
73-
73+
#ifdef _MSC_VER
74+
STATIC_ASSERT(__alignof(union some_union5)==4);
7475
#else
76+
STATIC_ASSERT(_Alignof(union some_union5)==4);
77+
#endif
7578

76-
union some_union5
79+
#ifdef _MSC_VER
80+
#pragma pack(push,1)
81+
union some_union6
7782
{
7883
int i;
7984
};
85+
#pragma pack(pop)
8086

87+
// Packing may affect alignment
88+
STATIC_ASSERT(__alignof(union some_union6)==1);
89+
#else
8190
union some_union6
8291
{
8392
int i;
8493
} __attribute__((__packed__));
8594

8695
// Packing may affect alignment
87-
STATIC_ASSERT(_Alignof(union some_union5)==4);
8896
STATIC_ASSERT(_Alignof(union some_union6)==1);
89-
9097
#endif
9198

9299
int main()

src/ansi-c/padding.cpp

Lines changed: 91 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,93 @@ 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+
struct_typet::componentst::iterator pad_bit_field(
104+
struct_typet::componentst &components,
105+
struct_typet::componentst::iterator where,
106+
std::size_t pad_bits)
107+
{
108+
c_bit_field_typet padding_type(
109+
unsignedbv_typet(pad_bits), pad_bits);
110+
111+
struct_typet::componentt component;
112+
component.type()=padding_type;
113+
component.set_name(
114+
"$bit_field_pad"+std::to_string(where-components.begin()));
115+
component.set_is_padding(true);
116+
117+
auto it=components.insert(where, component);
118+
it++;
119+
return it;
120+
}
121+
122+
void bit_field_padding(struct_typet &type, const namespacet &ns)
104123
{
105124
struct_typet::componentst &components=type.components();
106125

107-
// First do padding for bit-fields to make them
108-
// appear on byte boundaries.
126+
// bit-field padding depends greatly on compiler
127+
if(config.ansi_c.mode == configt::ansi_ct::flavourt::VISUAL_STUDIO)
128+
{
129+
std::size_t bit_field_bits=0, underlying_bits=0;
130+
131+
for(struct_typet::componentst::iterator
132+
it=components.begin();
133+
it!=components.end();
134+
it++)
135+
{
136+
if(it->type().id()==ID_c_bit_field &&
137+
to_c_bit_field_type(it->type()).get_width()!=0)
138+
{
139+
const auto &bit_field_type=to_c_bit_field_type(it->type());
140+
141+
std::size_t new_underlying_bits=
142+
bit_field_type.subtype().get_size_t(ID_width);
109143

144+
CHECK_RETURN(new_underlying_bits!=0);
145+
146+
if(underlying_bits==0)
147+
{
148+
underlying_bits=new_underlying_bits;
149+
bit_field_bits=0;
150+
}
151+
else if(new_underlying_bits!=underlying_bits)
152+
{
153+
// new underlying width, we pad up
154+
if((bit_field_bits%underlying_bits)!=0)
155+
{
156+
std::size_t pad=underlying_bits-(bit_field_bits%underlying_bits);
157+
it=pad_bit_field(components, it, pad);
158+
}
159+
160+
underlying_bits=new_underlying_bits;
161+
bit_field_bits=0;
162+
}
163+
164+
// count the bits
165+
std::size_t width=bit_field_type.get_width();
166+
bit_field_bits+=width;
167+
}
168+
else
169+
{
170+
// pad up
171+
if(underlying_bits!=0 && (bit_field_bits%underlying_bits)!=0)
172+
{
173+
std::size_t pad=underlying_bits-(bit_field_bits%underlying_bits);
174+
it=pad_bit_field(components, it, pad);
175+
underlying_bits=bit_field_bits=0;
176+
}
177+
}
178+
}
179+
180+
// Add padding at the end?
181+
if(underlying_bits!=0 && (bit_field_bits%underlying_bits)!=0)
182+
{
183+
std::size_t pad=underlying_bits-(bit_field_bits%underlying_bits);
184+
pad_bit_field(components, components.end(), pad);
185+
}
186+
}
187+
else
110188
{
111-
std::size_t padding_counter=0;
189+
// Make bit-fields appear on byte boundaries
112190
std::size_t bit_field_bits=0;
113191

114192
for(struct_typet::componentst::iterator
@@ -129,18 +207,7 @@ void add_padding(struct_typet &type, const namespacet &ns)
129207
if((bit_field_bits%8)!=0)
130208
{
131209
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;
210+
it=pad_bit_field(components, it, pad);
144211
}
145212

146213
bit_field_bits=0;
@@ -151,16 +218,14 @@ void add_padding(struct_typet &type, const namespacet &ns)
151218
if((bit_field_bits%8)!=0)
152219
{
153220
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);
221+
pad_bit_field(components, components.end(), pad);
162222
}
163223
}
224+
}
225+
226+
void add_padding(struct_typet &type, const namespacet &ns)
227+
{
228+
bit_field_padding(type, ns);
164229

165230
// Is the struct packed, without any alignment specification?
166231
if(type.get_bool(ID_C_packed) &&
@@ -172,6 +237,8 @@ void add_padding(struct_typet &type, const namespacet &ns)
172237
mp_integer max_alignment=0;
173238
std::size_t bit_field_bits=0;
174239

240+
struct_typet::componentst &components=type.components();
241+
175242
for(struct_typet::componentst::iterator
176243
it=components.begin();
177244
it!=components.end();

0 commit comments

Comments
 (0)