aboutsummaryrefslogtreecommitdiff
path: root/tccgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'tccgen.c')
-rw-r--r--tccgen.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/tccgen.c b/tccgen.c
index ba1757e..d064024 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -3154,7 +3154,7 @@ static void parse_attribute(AttributeDef *ad)
/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
static void struct_decl(CType *type, AttributeDef *ad, int u)
{
- int a, v, size, align, maxalign, c, offset, flexible;
+ int a, v, size, align, maxalign, c, offset, flexible, extra_bytes;
int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
Sym *s, *ss, *ass, **ps;
AttributeDef ad1;
@@ -3235,6 +3235,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
while (tok != '}') {
parse_btype(&btype, &ad1);
while (1) {
+ extra_bytes = 0;
if (flexible)
tcc_error("flexible array member '%s' not at the end of struct",
get_tok_str(v, NULL));
@@ -3310,9 +3311,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
/* zero size: means to pad */
bit_pos = 0;
} else {
- /* we do not have enough room ?
- did the type change?
- is it a union? */
+ /* if type change, union, or will overrun
+ * allignment slot, start at a newly
+ * alligned slot */
if ((bit_pos + bit_size) > bsize ||
bt != prevbt || a == TOK_UNION)
bit_pos = 0;
@@ -3322,15 +3323,30 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
(bit_pos << VT_STRUCT_SHIFT) |
(bit_size << (VT_STRUCT_SHIFT + 6));
bit_pos += bit_size;
+ /* without ms-bitfields, allocate the
+ * minimum number of bytes necessary,
+ * adding single bytes as needed */
+ if (!tcc_state->ms_bitfields) {
+ if (lbit_pos == 0)
+ /* minimum bytes for new bitfield */
+ size = (bit_size + 7) / 8;
+ else {
+ /* enough spare bits already allocated? */
+ bit_size = (lbit_pos - 1) % 8 + 1 + bit_size;
+ if (bit_size > 8) /* doesn't fit */
+ extra_bytes = (bit_size - 1) / 8;
+ }
+ }
}
prevbt = bt;
} else {
bit_pos = 0;
}
if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
- /* add new memory data only if starting
- bit field */
- if (lbit_pos == 0) {
+ /* add new memory data only if starting bit
+ field or adding bytes to existing bit field */
+ if (extra_bytes) c += extra_bytes;
+ else if (lbit_pos == 0) {
if (a == TOK_STRUCT) {
c = (c + align - 1) & -align;
offset = c;