diff options
Diffstat (limited to 'tccgen.c')
| -rw-r--r-- | tccgen.c | 36 |
1 files changed, 30 insertions, 6 deletions
@@ -3062,6 +3062,24 @@ ST_FUNC void parse_mult_str (CString *astr, const char *msg) cstr_ccat(astr, '\0'); } +/* If I is >= 1 and a power of two, returns log2(i)+1. + If I is 0 returns 0. */ +static int exact_log2p1(int i) +{ + int ret; + if (!i) + return 0; + for (ret = 1; i >= 1 << 8; ret += 8) + i >>= 8; + if (i >= 1 << 4) + ret += 4, i >>= 4; + if (i >= 1 << 2) + ret += 2, i >>= 2; + if (i >= 1 << 1) + ret++; + return ret; +} + /* Parse GNUC __attribute__ extension. Currently, the following extensions are recognized: - aligned(n) : set data/function alignment. @@ -3131,7 +3149,9 @@ static void parse_attribute(AttributeDef *ad) } else { n = MAX_ALIGN; } - ad->a.aligned = n; + ad->a.aligned = exact_log2p1(n); + if (n != 1 << (ad->a.aligned - 1)) + tcc_error("alignment of %d is larger than implemented", n); break; case TOK_PACKED1: case TOK_PACKED2: @@ -3270,7 +3290,7 @@ static void struct_layout(CType *type, AttributeDef *ad) int pcc = !tcc_state->ms_bitfields; Sym *f; if (ad->a.aligned) - maxalign = ad->a.aligned; + maxalign = 1 << (ad->a.aligned - 1); else maxalign = 1; offset = 0; @@ -3293,6 +3313,8 @@ static void struct_layout(CType *type, AttributeDef *ad) align = f->r; } else if (ad->a.packed || f->r == 1) { align = 1; + /* Packed fields or packed records don't let the base type + influence the records type alignment. */ typealign = 1; } else { align = typealign; @@ -3587,8 +3609,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) /* Only remember non-default alignment. */ alignoverride = 0; if (ad1.a.aligned) { - if (align < ad1.a.aligned) - alignoverride = ad1.a.aligned; + int speca = 1 << (ad1.a.aligned - 1); + if (align < speca) + alignoverride = speca; } else if (ad1.a.packed || ad->a.packed) { alignoverride = 1; } else if (*tcc_state->pack_stack_ptr) { @@ -6594,8 +6617,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, * pointed_size(&flexible_array->type); /* take into account specified alignment if bigger */ if (ad->a.aligned) { - if (ad->a.aligned > align) - align = ad->a.aligned; + int speca = 1 << (ad->a.aligned - 1); + if (speca > align) + align = speca; } else if (ad->a.packed) { align = 1; } |
