History

Support large alignment requests

The linux kernel has some structures that are page aligned, i.e. 4096. Instead of enlarging the bit fields to specify this, use the fact that alignment is always power of two, and store only the log2 minus 1 of it. The 5 bits are enough to specify an alignment of 1 << 30.

Michael Matz committed 10 years ago

Commit 8859dc91 parent d815a0f3 files · +38 −7Browse files

Unified · Split

3 files
  1. tcc.h +1 −1
  2. tccgen.c +30 −6
  3. tests/tcctest.c +7 −0
tcc.h+1−1
@@ -379,7 +379,7 @@ typedef struct SValue { · 378 unmodified lines
379struct Attribute {379struct Attribute {
380 unsigned380 unsigned
381 func_call : 3, /* calling convention (0..5), see below */381 func_call : 3, /* calling convention (0..5), see below */
382 aligned : 5, /* alignement (0..16) */382 aligned : 5, /* alignment as log2+1 (0 == unspecified) */
383 packed : 1,383 packed : 1,
384 func_export : 1,384 func_export : 1,
385 func_import : 1,385 func_import : 1,
tccgen.c+30−6
@@ -3062,6 +3062,24 @@ ST_FUNC void parse_mult_str (CString *astr, const char *msg) · 3061 unmodified lines
3062 cstr_ccat(astr, '\0');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. */
3067static 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/* Parse GNUC __attribute__ extension. Currently, the following3083/* Parse GNUC __attribute__ extension. Currently, the following
3066 extensions are recognized:3084 extensions are recognized:
3067 - aligned(n) : set data/function alignment.3085 - aligned(n) : set data/function alignment.
@@ -3131,7 +3149,9 @@ static void parse_attribute(AttributeDef *ad) · 63 unmodified lines
3131 } else {3149 } else {
3132 n = MAX_ALIGN;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 break;3155 break;
3136 case TOK_PACKED1:3156 case TOK_PACKED1:
3137 case TOK_PACKED2:3157 case TOK_PACKED2:
@@ -3270,7 +3290,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 132 unmodified lines
3270 int pcc = !tcc_state->ms_bitfields;3290 int pcc = !tcc_state->ms_bitfields;
3271 Sym *f;3291 Sym *f;
3272 if (ad->a.aligned)3292 if (ad->a.aligned)
3273 maxalign = ad->a.aligned;3293 maxalign = 1 << (ad->a.aligned - 1);
3274 else3294 else
3275 maxalign = 1;3295 maxalign = 1;
3276 offset = 0;3296 offset = 0;
@@ -3293,6 +3313,8 @@ static void struct_layout(CType *type, AttributeDef *ad) · 16 unmodified lines
3293 align = f->r;3313 align = f->r;
3294 } else if (ad->a.packed || f->r == 1) {3314 } else if (ad->a.packed || f->r == 1) {
3295 align = 1;3315 align = 1;
3316 /* Packed fields or packed records don't let the base type
3317 influence the records type alignment. */
3296 typealign = 1;3318 typealign = 1;
3297 } else {3319 } else {
3298 align = typealign;3320 align = typealign;
@@ -3587,8 +3609,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 288 unmodified lines
3587 /* Only remember non-default alignment. */3609 /* Only remember non-default alignment. */
3588 alignoverride = 0;3610 alignoverride = 0;
3589 if (ad1.a.aligned) {3611 if (ad1.a.aligned) {
3590 if (align < ad1.a.aligned)3612 int speca = 1 << (ad1.a.aligned - 1);
3591 alignoverride = ad1.a.aligned;3613 if (align < speca)
3614 alignoverride = speca;
3592 } else if (ad1.a.packed || ad->a.packed) {3615 } else if (ad1.a.packed || ad->a.packed) {
3593 alignoverride = 1;3616 alignoverride = 1;
3594 } else if (*tcc_state->pack_stack_ptr) {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 * pointed_size(&flexible_array->type);6617 * pointed_size(&flexible_array->type);
6595 /* take into account specified alignment if bigger */6618 /* take into account specified alignment if bigger */
6596 if (ad->a.aligned) {6619 if (ad->a.aligned) {
6597 if (ad->a.aligned > align)6620 int speca = 1 << (ad->a.aligned - 1);
6598 align = ad->a.aligned;6621 if (speca > align)
6622 align = speca;
6599 } else if (ad->a.packed) {6623 } else if (ad->a.packed) {
6600 align = 1;6624 align = 1;
6601 }6625 }
tests/tcctest.c+7−0
@@ -1048,6 +1048,11 @@ int pad1; · 1047 unmodified lines
1048 a copy of it).1048 a copy of it).
1049struct aligntest7 altest7[2] __attribute__((aligned(16)));*/1049struct aligntest7 altest7[2] __attribute__((aligned(16)));*/
1050 1050
1051struct aligntest8
1052{
1053 int i;
1054} __attribute__((aligned(4096)));
1055
1051struct Large {1056struct Large {
1052 unsigned long flags;1057 unsigned long flags;
1053 union {1058 union {
@@ -1129,6 +1134,8 @@ void struct_test() · 75 unmodified lines
1129 sizeof(struct aligntest6), __alignof__(struct aligntest6));1134 sizeof(struct aligntest6), __alignof__(struct aligntest6));
1130 printf("aligntest7 sizeof=%d alignof=%d\n",1135 printf("aligntest7 sizeof=%d alignof=%d\n",
1131 sizeof(struct aligntest7), __alignof__(struct aligntest7));1136 sizeof(struct aligntest7), __alignof__(struct aligntest7));
1137 printf("aligntest8 sizeof=%d alignof=%d\n",
1138 sizeof(struct aligntest8), __alignof__(struct aligntest8));
1132 printf("altest5 sizeof=%d alignof=%d\n",1139 printf("altest5 sizeof=%d alignof=%d\n",
1133 sizeof(altest5), __alignof__(altest5));1140 sizeof(altest5), __alignof__(altest5));
1134 printf("altest6 sizeof=%d alignof=%d\n",1141 printf("altest6 sizeof=%d alignof=%d\n",

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t