added static bit fields init - version change - #error and #warning fix - support aligned attribute without parameter

This commit is contained in:
bellard
2002-11-24 16:00:08 +00:00
parent 2ec23ab858
commit abf909e1ac

48
tcc.c
View File

@ -2541,6 +2541,7 @@ static void preprocess(int is_bof)
case TOK_ERROR: case TOK_ERROR:
case TOK_WARNING: case TOK_WARNING:
c = tok; c = tok;
ch = file->buf_ptr[0];
skip_spaces(); skip_spaces();
q = buf; q = buf;
while (ch != '\n' && ch != CH_EOF) { while (ch != '\n' && ch != CH_EOF) {
@ -5567,12 +5568,16 @@ void parse_attribute(AttributeDef *ad)
break; break;
case TOK_ALIGNED: case TOK_ALIGNED:
case TOK___ALIGNED__: case TOK___ALIGNED__:
skip('('); if (tok == '(') {
n = expr_const(); next();
if (n <= 0 || (n & (n - 1)) != 0) n = expr_const();
error("alignment must be a positive power of two"); if (n <= 0 || (n & (n - 1)) != 0)
error("alignment must be a positive power of two");
skip(')');
} else {
n = MAX_ALIGN;
}
ad->aligned = n; ad->aligned = n;
skip(')');
break; break;
case TOK_UNUSED: case TOK_UNUSED:
case TOK___UNUSED__: case TOK___UNUSED__:
@ -7263,8 +7268,9 @@ static void decl_designator(CType *type, Section *sec, unsigned long c,
static void init_putv(CType *type, Section *sec, unsigned long c, static void init_putv(CType *type, Section *sec, unsigned long c,
int v, int expr_type) int v, int expr_type)
{ {
int saved_global_expr, bt; int saved_global_expr, bt, bit_pos, bit_size;
void *ptr; void *ptr;
unsigned long long bit_mask;
switch(expr_type) { switch(expr_type) {
case EXPR_VAL: case EXPR_VAL:
@ -7291,19 +7297,30 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
gen_assign_cast(type); gen_assign_cast(type);
bt = type->t & VT_BTYPE; bt = type->t & VT_BTYPE;
ptr = sec->data + c; ptr = sec->data + c;
/* XXX: make code faster ? */
if (!(type->t & VT_BITFIELD)) {
bit_pos = 0;
bit_size = 32;
bit_mask = -1LL;
} else {
bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
bit_mask = (1LL << bit_size) - 1;
}
if ((vtop->r & VT_SYM) && if ((vtop->r & VT_SYM) &&
(bt == VT_BYTE || (bt == VT_BYTE ||
bt == VT_SHORT || bt == VT_SHORT ||
bt == VT_DOUBLE || bt == VT_DOUBLE ||
bt == VT_LDOUBLE || bt == VT_LDOUBLE ||
bt == VT_LLONG)) bt == VT_LLONG ||
(bt == VT_INT && bit_size != 32)))
error("initializer element is not computable at load time"); error("initializer element is not computable at load time");
switch(bt) { switch(bt) {
case VT_BYTE: case VT_BYTE:
*(char *)ptr = vtop->c.i; *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
break; break;
case VT_SHORT: case VT_SHORT:
*(short *)ptr = vtop->c.i; *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
break; break;
case VT_DOUBLE: case VT_DOUBLE:
*(double *)ptr = vtop->c.d; *(double *)ptr = vtop->c.d;
@ -7312,13 +7329,13 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
*(long double *)ptr = vtop->c.ld; *(long double *)ptr = vtop->c.ld;
break; break;
case VT_LLONG: case VT_LLONG:
*(long long *)ptr = vtop->c.ll; *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
break; break;
default: default:
if (vtop->r & VT_SYM) { if (vtop->r & VT_SYM) {
greloc(sec, vtop->sym, c, R_DATA_32); greloc(sec, vtop->sym, c, R_DATA_32);
} }
*(int *)ptr = vtop->c.i; *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
break; break;
} }
vtop--; vtop--;
@ -7467,7 +7484,6 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
/* NOTE: the previous test is a specific case for automatic /* NOTE: the previous test is a specific case for automatic
struct/union init */ struct/union init */
/* XXX: union needs only one init */ /* XXX: union needs only one init */
/* XXX: handle bit fields */
no_oblock = 1; no_oblock = 1;
if (first || tok == '{') { if (first || tok == '{') {
skip('{'); skip('{');
@ -7480,8 +7496,6 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
n = s->c; n = s->c;
while (tok != '}') { while (tok != '}') {
decl_designator(type, sec, c, NULL, &f, size_only); decl_designator(type, sec, c, NULL, &f, size_only);
/* XXX: bitfields ? */
/* fill with zero between fields */
index = f->c; index = f->c;
if (!size_only && array_length < index) { if (!size_only && array_length < index) {
init_putz(type, sec, c + array_length, init_putz(type, sec, c + array_length,
@ -7490,12 +7504,12 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
index = index + type_size(&f->type, &align1); index = index + type_size(&f->type, &align1);
if (index > array_length) if (index > array_length)
array_length = index; array_length = index;
if (no_oblock && f->next == NULL) f = f->next;
if (no_oblock && f == NULL)
break; break;
if (tok == '}') if (tok == '}')
break; break;
skip(','); skip(',');
f = f->next;
} }
/* put zeros at the end */ /* put zeros at the end */
if (!size_only && array_length < n) { if (!size_only && array_length < n) {
@ -8843,7 +8857,7 @@ static int64_t getclock_us(void)
void help(void) void help(void)
{ {
printf("tcc version 0.9.13 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n" printf("tcc version 0.9.14 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
"usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n" "usage: tcc [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
" [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n" " [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
" [--] infile1 [infile2... --] [infile_args...]\n" " [--] infile1 [infile2... --] [infile_args...]\n"