| @@ -3062,6 +3062,24 @@ ST_FUNC void parse_mult_str (CString *astr, const char *msg) · 3061 unmodified lines |
| 3062 | 3062 | cstr_ccat(astr, '\0'); |
| 3063 | 3063 | } |
| 3064 | 3064 | |
| 3065 | +/* If I is >= 1 and a power of two, returns log2(i)+1. |
| 3066 | + If I is 0 returns 0. */ |
| 3067 | +static int exact_log2p1(int i) |
| 3068 | +{ |
| 3069 | + int ret; |
| 3070 | + if (!i) |
| 3071 | + return 0; |
| 3072 | + for (ret = 1; i >= 1 << 8; ret += 8) |
| 3073 | + i >>= 8; |
| 3074 | + if (i >= 1 << 4) |
| 3075 | + ret += 4, i >>= 4; |
| 3076 | + if (i >= 1 << 2) |
| 3077 | + ret += 2, i >>= 2; |
| 3078 | + if (i >= 1 << 1) |
| 3079 | + ret++; |
| 3080 | + return ret; |
| 3081 | +} |
| 3082 | + |
| 3065 | 3083 | /* Parse GNUC __attribute__ extension. Currently, the following |
| 3066 | 3084 | extensions are recognized: |
| 3067 | 3085 | - aligned(n) : set data/function alignment. |
| @@ -3131,7 +3149,9 @@ static void parse_attribute(AttributeDef *ad) · 63 unmodified lines |
| 3131 | 3149 | } else { |
| 3132 | 3150 | n = MAX_ALIGN; |
| 3133 | 3151 | } |
| 3134 | | − ad->a.aligned = n; |
| 3152 | + ad->a.aligned = exact_log2p1(n); |
| 3153 | + if (n != 1 << (ad->a.aligned - 1)) |
| 3154 | + tcc_error("alignment of %d is larger than implemented", n); |
| 3135 | 3155 | break; |
| 3136 | 3156 | case TOK_PACKED1: |
| 3137 | 3157 | case TOK_PACKED2: |
| @@ -3270,7 +3290,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 132 unmodified lines |
| 3270 | 3290 | int pcc = !tcc_state->ms_bitfields; |
| 3271 | 3291 | Sym *f; |
| 3272 | 3292 | if (ad->a.aligned) |
| 3273 | | − maxalign = ad->a.aligned; |
| 3293 | + maxalign = 1 << (ad->a.aligned - 1); |
| 3274 | 3294 | else |
| 3275 | 3295 | maxalign = 1; |
| 3276 | 3296 | offset = 0; |
| @@ -3293,6 +3313,8 @@ static void struct_layout(CType *type, AttributeDef *ad) · 16 unmodified lines |
| 3293 | 3313 | align = f->r; |
| 3294 | 3314 | } else if (ad->a.packed || f->r == 1) { |
| 3295 | 3315 | align = 1; |
| 3316 | + /* Packed fields or packed records don't let the base type |
| 3317 | + influence the records type alignment. */ |
| 3296 | 3318 | typealign = 1; |
| 3297 | 3319 | } else { |
| 3298 | 3320 | align = typealign; |
| @@ -3587,8 +3609,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 288 unmodified lines |
| 3587 | 3609 | /* Only remember non-default alignment. */ |
| 3588 | 3610 | alignoverride = 0; |
| 3589 | 3611 | if (ad1.a.aligned) { |
| 3590 | | − if (align < ad1.a.aligned) |
| 3591 | | − alignoverride = ad1.a.aligned; |
| 3612 | + int speca = 1 << (ad1.a.aligned - 1); |
| 3613 | + if (align < speca) |
| 3614 | + alignoverride = speca; |
| 3592 | 3615 | } else if (ad1.a.packed || ad->a.packed) { |
| 3593 | 3616 | alignoverride = 1; |
| 3594 | 3617 | } else if (*tcc_state->pack_stack_ptr) { |
| @@ -6594,8 +6617,9 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 2999 unmodified lines |
| 6594 | 6617 | * pointed_size(&flexible_array->type); |
| 6595 | 6618 | /* take into account specified alignment if bigger */ |
| 6596 | 6619 | if (ad->a.aligned) { |
| 6597 | | − if (ad->a.aligned > align) |
| 6598 | | − align = ad->a.aligned; |
| 6620 | + int speca = 1 << (ad->a.aligned - 1); |
| 6621 | + if (speca > align) |
| 6622 | + align = speca; |
| 6599 | 6623 | } else if (ad->a.packed) { |
| 6600 | 6624 | align = 1; |
| 6601 | 6625 | } |