forked from Mirrors/tinycc
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.master
parent
d815a0f658
commit
8859dc9e6d
2
tcc.h
2
tcc.h
|
@ -379,7 +379,7 @@ typedef struct SValue {
|
||||||
struct Attribute {
|
struct Attribute {
|
||||||
unsigned
|
unsigned
|
||||||
func_call : 3, /* calling convention (0..5), see below */
|
func_call : 3, /* calling convention (0..5), see below */
|
||||||
aligned : 5, /* alignement (0..16) */
|
aligned : 5, /* alignment as log2+1 (0 == unspecified) */
|
||||||
packed : 1,
|
packed : 1,
|
||||||
func_export : 1,
|
func_export : 1,
|
||||||
func_import : 1,
|
func_import : 1,
|
||||||
|
|
36
tccgen.c
36
tccgen.c
|
@ -3062,6 +3062,24 @@ ST_FUNC void parse_mult_str (CString *astr, const char *msg)
|
||||||
cstr_ccat(astr, '\0');
|
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
|
/* Parse GNUC __attribute__ extension. Currently, the following
|
||||||
extensions are recognized:
|
extensions are recognized:
|
||||||
- aligned(n) : set data/function alignment.
|
- aligned(n) : set data/function alignment.
|
||||||
|
@ -3131,7 +3149,9 @@ static void parse_attribute(AttributeDef *ad)
|
||||||
} else {
|
} else {
|
||||||
n = MAX_ALIGN;
|
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;
|
break;
|
||||||
case TOK_PACKED1:
|
case TOK_PACKED1:
|
||||||
case TOK_PACKED2:
|
case TOK_PACKED2:
|
||||||
|
@ -3270,7 +3290,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||||
int pcc = !tcc_state->ms_bitfields;
|
int pcc = !tcc_state->ms_bitfields;
|
||||||
Sym *f;
|
Sym *f;
|
||||||
if (ad->a.aligned)
|
if (ad->a.aligned)
|
||||||
maxalign = ad->a.aligned;
|
maxalign = 1 << (ad->a.aligned - 1);
|
||||||
else
|
else
|
||||||
maxalign = 1;
|
maxalign = 1;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
@ -3293,6 +3313,8 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
||||||
align = f->r;
|
align = f->r;
|
||||||
} else if (ad->a.packed || f->r == 1) {
|
} else if (ad->a.packed || f->r == 1) {
|
||||||
align = 1;
|
align = 1;
|
||||||
|
/* Packed fields or packed records don't let the base type
|
||||||
|
influence the records type alignment. */
|
||||||
typealign = 1;
|
typealign = 1;
|
||||||
} else {
|
} else {
|
||||||
align = typealign;
|
align = typealign;
|
||||||
|
@ -3587,8 +3609,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
|
||||||
/* Only remember non-default alignment. */
|
/* Only remember non-default alignment. */
|
||||||
alignoverride = 0;
|
alignoverride = 0;
|
||||||
if (ad1.a.aligned) {
|
if (ad1.a.aligned) {
|
||||||
if (align < ad1.a.aligned)
|
int speca = 1 << (ad1.a.aligned - 1);
|
||||||
alignoverride = ad1.a.aligned;
|
if (align < speca)
|
||||||
|
alignoverride = speca;
|
||||||
} else if (ad1.a.packed || ad->a.packed) {
|
} else if (ad1.a.packed || ad->a.packed) {
|
||||||
alignoverride = 1;
|
alignoverride = 1;
|
||||||
} else if (*tcc_state->pack_stack_ptr) {
|
} 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);
|
* pointed_size(&flexible_array->type);
|
||||||
/* take into account specified alignment if bigger */
|
/* take into account specified alignment if bigger */
|
||||||
if (ad->a.aligned) {
|
if (ad->a.aligned) {
|
||||||
if (ad->a.aligned > align)
|
int speca = 1 << (ad->a.aligned - 1);
|
||||||
align = ad->a.aligned;
|
if (speca > align)
|
||||||
|
align = speca;
|
||||||
} else if (ad->a.packed) {
|
} else if (ad->a.packed) {
|
||||||
align = 1;
|
align = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1048,6 +1048,11 @@ int pad1;
|
||||||
a copy of it).
|
a copy of it).
|
||||||
struct aligntest7 altest7[2] __attribute__((aligned(16)));*/
|
struct aligntest7 altest7[2] __attribute__((aligned(16)));*/
|
||||||
|
|
||||||
|
struct aligntest8
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
} __attribute__((aligned(4096)));
|
||||||
|
|
||||||
struct Large {
|
struct Large {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
union {
|
union {
|
||||||
|
@ -1129,6 +1134,8 @@ void struct_test()
|
||||||
sizeof(struct aligntest6), __alignof__(struct aligntest6));
|
sizeof(struct aligntest6), __alignof__(struct aligntest6));
|
||||||
printf("aligntest7 sizeof=%d alignof=%d\n",
|
printf("aligntest7 sizeof=%d alignof=%d\n",
|
||||||
sizeof(struct aligntest7), __alignof__(struct aligntest7));
|
sizeof(struct aligntest7), __alignof__(struct aligntest7));
|
||||||
|
printf("aligntest8 sizeof=%d alignof=%d\n",
|
||||||
|
sizeof(struct aligntest8), __alignof__(struct aligntest8));
|
||||||
printf("altest5 sizeof=%d alignof=%d\n",
|
printf("altest5 sizeof=%d alignof=%d\n",
|
||||||
sizeof(altest5), __alignof__(altest5));
|
sizeof(altest5), __alignof__(altest5));
|
||||||
printf("altest6 sizeof=%d alignof=%d\n",
|
printf("altest6 sizeof=%d alignof=%d\n",
|
||||||
|
|
Loading…
Reference in New Issue