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
379379 struct Attribute {
380380 unsigned
381381 func_call : 3, /* calling convention (0..5), see below */
382− aligned : 5, /* alignement (0..16) */
382+ aligned : 5, /* alignment as log2+1 (0 == unspecified) */
383383 packed : 1,
384384 func_export : 1,
385385 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
30623062 cstr_ccat(astr, '\0');
30633063 }
30643064
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+
30653083 /* Parse GNUC __attribute__ extension. Currently, the following
30663084 extensions are recognized:
30673085 - aligned(n) : set data/function alignment.
@@ -3131,7 +3149,9 @@ static void parse_attribute(AttributeDef *ad) · 63 unmodified lines
31313149 } else {
31323150 n = MAX_ALIGN;
31333151 }
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);
31353155 break;
31363156 case TOK_PACKED1:
31373157 case TOK_PACKED2:
@@ -3270,7 +3290,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 132 unmodified lines
32703290 int pcc = !tcc_state->ms_bitfields;
32713291 Sym *f;
32723292 if (ad->a.aligned)
3273− maxalign = ad->a.aligned;
3293+ maxalign = 1 << (ad->a.aligned - 1);
32743294 else
32753295 maxalign = 1;
32763296 offset = 0;
@@ -3293,6 +3313,8 @@ static void struct_layout(CType *type, AttributeDef *ad) · 16 unmodified lines
32933313 align = f->r;
32943314 } else if (ad->a.packed || f->r == 1) {
32953315 align = 1;
3316+ /* Packed fields or packed records don't let the base type
3317+ influence the records type alignment. */
32963318 typealign = 1;
32973319 } else {
32983320 align = typealign;
@@ -3587,8 +3609,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u) · 288 unmodified lines
35873609 /* Only remember non-default alignment. */
35883610 alignoverride = 0;
35893611 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;
35923615 } else if (ad1.a.packed || ad->a.packed) {
35933616 alignoverride = 1;
35943617 } 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
65946617 * pointed_size(&flexible_array->type);
65956618 /* take into account specified alignment if bigger */
65966619 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;
65996623 } else if (ad->a.packed) {
66006624 align = 1;
66016625 }
tests/tcctest.c+7−0
@@ -1048,6 +1048,11 @@ int pad1; · 1047 unmodified lines
10481048 a copy of it).
10491049 struct aligntest7 altest7[2] __attribute__((aligned(16)));*/
10501050
1051+struct aligntest8
1052+{
1053+ int i;
1054+} __attribute__((aligned(4096)));
1055+
10511056 struct Large {
10521057 unsigned long flags;
10531058 union {
@@ -1129,6 +1134,8 @@ void struct_test() · 75 unmodified lines
11291134 sizeof(struct aligntest6), __alignof__(struct aligntest6));
11301135 printf("aligntest7 sizeof=%d alignof=%d\n",
11311136 sizeof(struct aligntest7), __alignof__(struct aligntest7));
1137+ printf("aligntest8 sizeof=%d alignof=%d\n",
1138+ sizeof(struct aligntest8), __alignof__(struct aligntest8));
11321139 printf("altest5 sizeof=%d alignof=%d\n",
11331140 sizeof(altest5), __alignof__(altest5));
11341141 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