mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-04 06:30:10 +08:00
refactor enums
Eliminate VT_ENUM as a basic type. Instead use the integral types VT_InT/VT_LLONG with an additional flag to indicate that it is an enum.
This commit is contained in:
parent
9ba76ac834
commit
f87afa72e0
@ -249,7 +249,6 @@ static int arm64_type_size(int t)
|
|||||||
case VT_BYTE: return 0;
|
case VT_BYTE: return 0;
|
||||||
case VT_SHORT: return 1;
|
case VT_SHORT: return 1;
|
||||||
case VT_PTR: return 3;
|
case VT_PTR: return 3;
|
||||||
case VT_ENUM: return 2;
|
|
||||||
case VT_FUNC: return 3;
|
case VT_FUNC: return 3;
|
||||||
case VT_FLOAT: return 2;
|
case VT_FLOAT: return 2;
|
||||||
case VT_DOUBLE: return 3;
|
case VT_DOUBLE: return 3;
|
||||||
|
31
tcc.h
31
tcc.h
@ -416,8 +416,7 @@ struct SymAttr {
|
|||||||
visibility : 2,
|
visibility : 2,
|
||||||
dllexport : 1,
|
dllexport : 1,
|
||||||
dllimport : 1,
|
dllimport : 1,
|
||||||
unsigned_enum : 1,
|
unused : 5;
|
||||||
unused : 4;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* function attributes or temporary attributes for parsing */
|
/* function attributes or temporary attributes for parsing */
|
||||||
@ -852,14 +851,13 @@ struct filespec {
|
|||||||
#define VT_PTR 5 /* pointer */
|
#define VT_PTR 5 /* pointer */
|
||||||
#define VT_FUNC 6 /* function type */
|
#define VT_FUNC 6 /* function type */
|
||||||
#define VT_STRUCT 7 /* struct/union definition */
|
#define VT_STRUCT 7 /* struct/union definition */
|
||||||
#define VT_ENUM 8 /* enum definition */
|
#define VT_FLOAT 8 /* IEEE float */
|
||||||
#define VT_FLOAT 9 /* IEEE float */
|
#define VT_DOUBLE 9 /* IEEE double */
|
||||||
#define VT_DOUBLE 10 /* IEEE double */
|
#define VT_LDOUBLE 10 /* IEEE long double */
|
||||||
#define VT_LDOUBLE 11 /* IEEE long double */
|
#define VT_BOOL 11 /* ISOC99 boolean type */
|
||||||
#define VT_BOOL 12 /* ISOC99 boolean type */
|
#define VT_LONG 12 /* long integer (NEVER USED as type, only during parsing) */
|
||||||
#define VT_LONG 13 /* long integer (NEVER USED as type, only during parsing) */
|
#define VT_QLONG 13 /* 128-bit integer. Only used for x86-64 ABI */
|
||||||
#define VT_QLONG 14 /* 128-bit integer. Only used for x86-64 ABI */
|
#define VT_QFLOAT 14 /* 128-bit float. Only used for x86-64 ABI */
|
||||||
#define VT_QFLOAT 15 /* 128-bit float. Only used for x86-64 ABI */
|
|
||||||
|
|
||||||
#define VT_UNSIGNED 0x0010 /* unsigned type */
|
#define VT_UNSIGNED 0x0010 /* unsigned type */
|
||||||
#define VT_DEFSIGN 0x0020 /* explicitly signed or unsigned */
|
#define VT_DEFSIGN 0x0020 /* explicitly signed or unsigned */
|
||||||
@ -868,7 +866,6 @@ struct filespec {
|
|||||||
#define VT_CONSTANT 0x0100 /* const modifier */
|
#define VT_CONSTANT 0x0100 /* const modifier */
|
||||||
#define VT_VOLATILE 0x0200 /* volatile modifier */
|
#define VT_VOLATILE 0x0200 /* volatile modifier */
|
||||||
#define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */
|
#define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */
|
||||||
#define VT_UNION (VT_STRUCT|VT_UNSIGNED) /* VT_STRUCT type with some modifier */
|
|
||||||
|
|
||||||
/* storage */
|
/* storage */
|
||||||
#define VT_EXTERN 0x00001000 /* extern definition */
|
#define VT_EXTERN 0x00001000 /* extern definition */
|
||||||
@ -882,9 +879,17 @@ struct filespec {
|
|||||||
#define BIT_POS(t) (((t) >> VT_STRUCT_SHIFT) & 0x3f)
|
#define BIT_POS(t) (((t) >> VT_STRUCT_SHIFT) & 0x3f)
|
||||||
#define BIT_SIZE(t) (((t) >> (VT_STRUCT_SHIFT + 6)) & 0x3f)
|
#define BIT_SIZE(t) (((t) >> (VT_STRUCT_SHIFT + 6)) & 0x3f)
|
||||||
|
|
||||||
|
#define VT_UNION (1 << VT_STRUCT_SHIFT | VT_STRUCT)
|
||||||
|
#define VT_ENUM (2 << VT_STRUCT_SHIFT) /* integral type is an enum really */
|
||||||
|
#define VT_ENUM_VAL (3 << VT_STRUCT_SHIFT) /* integral type is an enum constant really */
|
||||||
|
|
||||||
|
#define IS_ENUM(t) ((t & VT_STRUCT_MASK) == VT_ENUM)
|
||||||
|
#define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL)
|
||||||
|
#define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION)
|
||||||
|
|
||||||
/* type mask (except storage) */
|
/* type mask (except storage) */
|
||||||
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_STRUCT_MASK)
|
#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
|
||||||
#define VT_TYPE (~VT_STORAGE)
|
#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
|
||||||
|
|
||||||
|
|
||||||
/* token values */
|
/* token values */
|
||||||
|
167
tccgen.c
167
tccgen.c
@ -86,7 +86,7 @@ static void expr_eq(void);
|
|||||||
static void vla_runtime_type_size(CType *type, int *a);
|
static void vla_runtime_type_size(CType *type, int *a);
|
||||||
static void vla_sp_restore(void);
|
static void vla_sp_restore(void);
|
||||||
static void vla_sp_restore_root(void);
|
static void vla_sp_restore_root(void);
|
||||||
static int is_compatible_parameter_types(CType *type1, CType *type2);
|
static int is_compatible_unqualified_types(CType *type1, CType *type2);
|
||||||
static inline int64_t expr_const64(void);
|
static inline int64_t expr_const64(void);
|
||||||
ST_FUNC void vpush64(int ty, unsigned long long v);
|
ST_FUNC void vpush64(int ty, unsigned long long v);
|
||||||
ST_FUNC void vpush(CType *type);
|
ST_FUNC void vpush(CType *type);
|
||||||
@ -1087,10 +1087,8 @@ ST_FUNC int gv(int rc)
|
|||||||
bits = 64;
|
bits = 64;
|
||||||
} else
|
} else
|
||||||
type.t = VT_INT;
|
type.t = VT_INT;
|
||||||
if((vtop->type.t & VT_UNSIGNED) ||
|
if((vtop->type.t & VT_UNSIGNED)
|
||||||
(vtop->type.t & VT_BTYPE) == VT_BOOL ||
|
|| (vtop->type.t & VT_BTYPE) == VT_BOOL)
|
||||||
(((vtop->type.t & VT_BTYPE) == VT_ENUM) &&
|
|
||||||
vtop->type.ref->a.unsigned_enum))
|
|
||||||
type.t |= VT_UNSIGNED;
|
type.t |= VT_UNSIGNED;
|
||||||
gen_cast(&type);
|
gen_cast(&type);
|
||||||
/* generate shifts */
|
/* generate shifts */
|
||||||
@ -2479,6 +2477,8 @@ ST_FUNC int type_size(CType *type, int *a)
|
|||||||
*a = PTR_SIZE;
|
*a = PTR_SIZE;
|
||||||
return PTR_SIZE;
|
return PTR_SIZE;
|
||||||
}
|
}
|
||||||
|
} else if (IS_ENUM(type->t) && type->ref->c == -1) {
|
||||||
|
return -1; /* incomplete enum */
|
||||||
} else if (bt == VT_LDOUBLE) {
|
} else if (bt == VT_LDOUBLE) {
|
||||||
*a = LDOUBLE_ALIGN;
|
*a = LDOUBLE_ALIGN;
|
||||||
return LDOUBLE_SIZE;
|
return LDOUBLE_SIZE;
|
||||||
@ -2508,10 +2508,6 @@ ST_FUNC int type_size(CType *type, int *a)
|
|||||||
} else if (bt == VT_QLONG || bt == VT_QFLOAT) {
|
} else if (bt == VT_QLONG || bt == VT_QFLOAT) {
|
||||||
*a = 8;
|
*a = 8;
|
||||||
return 16;
|
return 16;
|
||||||
} else if (bt == VT_ENUM) {
|
|
||||||
*a = 4;
|
|
||||||
/* Enums might be incomplete, so don't just return '4' here. */
|
|
||||||
return type->ref->c;
|
|
||||||
} else {
|
} else {
|
||||||
/* char, void, function, _Bool */
|
/* char, void, function, _Bool */
|
||||||
*a = 1;
|
*a = 1;
|
||||||
@ -2554,7 +2550,7 @@ ST_FUNC void mk_pointer(CType *type)
|
|||||||
{
|
{
|
||||||
Sym *s;
|
Sym *s;
|
||||||
s = sym_push(SYM_FIELD, type, 0, -1);
|
s = sym_push(SYM_FIELD, type, 0, -1);
|
||||||
type->t = VT_PTR | (type->t & ~VT_TYPE);
|
type->t = VT_PTR | (type->t & VT_STORAGE);
|
||||||
type->ref = s;
|
type->ref = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2578,7 +2574,7 @@ static int is_compatible_func(CType *type1, CType *type2)
|
|||||||
while (s1 != NULL) {
|
while (s1 != NULL) {
|
||||||
if (s2 == NULL)
|
if (s2 == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
if (!is_compatible_parameter_types(&s1->type, &s2->type))
|
if (!is_compatible_unqualified_types(&s1->type, &s2->type))
|
||||||
return 0;
|
return 0;
|
||||||
s1 = s1->next;
|
s1 = s1->next;
|
||||||
s2 = s2->next;
|
s2 = s2->next;
|
||||||
@ -2609,21 +2605,7 @@ static int compare_types(CType *type1, CType *type2, int unqualified)
|
|||||||
t1 &= ~VT_DEFSIGN;
|
t1 &= ~VT_DEFSIGN;
|
||||||
t2 &= ~VT_DEFSIGN;
|
t2 &= ~VT_DEFSIGN;
|
||||||
}
|
}
|
||||||
/* An enum is compatible with (unsigned) int. Ideally we would
|
|
||||||
store the enums signedness in type->ref.a.<some_bit> and
|
|
||||||
only accept unsigned enums with unsigned int and vice versa.
|
|
||||||
But one of our callers (gen_assign_cast) always strips VT_UNSIGNED
|
|
||||||
from pointer target types, so we can't add it here either. */
|
|
||||||
if ((t1 & VT_BTYPE) == VT_ENUM) {
|
|
||||||
t1 = VT_INT;
|
|
||||||
if (type1->ref->a.unsigned_enum)
|
|
||||||
t1 |= VT_UNSIGNED;
|
|
||||||
}
|
|
||||||
if ((t2 & VT_BTYPE) == VT_ENUM) {
|
|
||||||
t2 = VT_INT;
|
|
||||||
if (type2->ref->a.unsigned_enum)
|
|
||||||
t2 |= VT_UNSIGNED;
|
|
||||||
}
|
|
||||||
/* XXX: bitfields ? */
|
/* XXX: bitfields ? */
|
||||||
if (t1 != t2)
|
if (t1 != t2)
|
||||||
return 0;
|
return 0;
|
||||||
@ -2652,7 +2634,7 @@ static int is_compatible_types(CType *type1, CType *type2)
|
|||||||
|
|
||||||
/* return true if type1 and type2 are the same (ignoring qualifiers).
|
/* return true if type1 and type2 are the same (ignoring qualifiers).
|
||||||
*/
|
*/
|
||||||
static int is_compatible_parameter_types(CType *type1, CType *type2)
|
static int is_compatible_unqualified_types(CType *type1, CType *type2)
|
||||||
{
|
{
|
||||||
return compare_types(type1,type2,1);
|
return compare_types(type1,type2,1);
|
||||||
}
|
}
|
||||||
@ -2690,6 +2672,10 @@ static void type_to_str(char *buf, int buf_size,
|
|||||||
pstrcat(buf, buf_size, "inline ");
|
pstrcat(buf, buf_size, "inline ");
|
||||||
buf_size -= strlen(buf);
|
buf_size -= strlen(buf);
|
||||||
buf += strlen(buf);
|
buf += strlen(buf);
|
||||||
|
if (IS_ENUM(type->t)) {
|
||||||
|
tstr = "enum ";
|
||||||
|
goto tstruct;
|
||||||
|
}
|
||||||
switch(bt) {
|
switch(bt) {
|
||||||
case VT_VOID:
|
case VT_VOID:
|
||||||
tstr = "void";
|
tstr = "void";
|
||||||
@ -2723,12 +2709,11 @@ static void type_to_str(char *buf, int buf_size,
|
|||||||
add_tstr:
|
add_tstr:
|
||||||
pstrcat(buf, buf_size, tstr);
|
pstrcat(buf, buf_size, tstr);
|
||||||
break;
|
break;
|
||||||
case VT_ENUM:
|
|
||||||
case VT_STRUCT:
|
case VT_STRUCT:
|
||||||
if (bt == VT_STRUCT)
|
tstr = "struct ";
|
||||||
tstr = "struct ";
|
if (IS_UNION(t))
|
||||||
else
|
tstr = "union ";
|
||||||
tstr = "enum ";
|
tstruct:
|
||||||
pstrcat(buf, buf_size, tstr);
|
pstrcat(buf, buf_size, tstr);
|
||||||
v = type->ref->v & ~SYM_STRUCT;
|
v = type->ref->v & ~SYM_STRUCT;
|
||||||
if (v >= SYM_FIRST_ANOM)
|
if (v >= SYM_FIRST_ANOM)
|
||||||
@ -2827,21 +2812,16 @@ static void gen_assign_cast(CType *dt)
|
|||||||
(type2->t & VT_BTYPE) == VT_VOID) {
|
(type2->t & VT_BTYPE) == VT_VOID) {
|
||||||
/* void * can match anything */
|
/* void * can match anything */
|
||||||
} else {
|
} else {
|
||||||
|
//printf("types %08x %08x\n", type1->t, type2->t);
|
||||||
/* exact type match, except for qualifiers */
|
/* exact type match, except for qualifiers */
|
||||||
tmp_type1 = *type1;
|
if (!is_compatible_unqualified_types(type1, type2)) {
|
||||||
tmp_type2 = *type2;
|
|
||||||
tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
|
|
||||||
tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
|
|
||||||
if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
|
|
||||||
/* Like GCC don't warn by default for merely changes
|
/* Like GCC don't warn by default for merely changes
|
||||||
in pointer target signedness. Do warn for different
|
in pointer target signedness. Do warn for different
|
||||||
base types, though, in particular for unsigned enums
|
base types, though, in particular for unsigned enums
|
||||||
and signed int targets. */
|
and signed int targets. */
|
||||||
if ((tmp_type1.t & (VT_DEFSIGN | VT_UNSIGNED)) !=
|
if ((type1->t & VT_BTYPE) != (type2->t & VT_BTYPE)
|
||||||
(tmp_type2.t & (VT_DEFSIGN | VT_UNSIGNED)) &&
|
|| IS_ENUM(type1->t) || IS_ENUM(type2->t)
|
||||||
(tmp_type1.t & VT_BTYPE) == (tmp_type2.t & VT_BTYPE))
|
)
|
||||||
;
|
|
||||||
else
|
|
||||||
tcc_warning("assignment from incompatible pointer type");
|
tcc_warning("assignment from incompatible pointer type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3486,7 +3466,7 @@ static void struct_layout(CType *type, AttributeDef *ad)
|
|||||||
tcc_warning("will touch memory past end of the struct (internal limitation)");
|
tcc_warning("will touch memory past end of the struct (internal limitation)");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
|
/* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */
|
||||||
static void struct_decl(CType *type, int u)
|
static void struct_decl(CType *type, int u)
|
||||||
{
|
{
|
||||||
int v, c, size, align, flexible, alignoverride;
|
int v, c, size, align, flexible, alignoverride;
|
||||||
@ -3506,9 +3486,11 @@ static void struct_decl(CType *type, int u)
|
|||||||
expect("struct/union/enum name");
|
expect("struct/union/enum name");
|
||||||
s = struct_find(v);
|
s = struct_find(v);
|
||||||
if (s && (s->sym_scope == local_scope || tok != '{')) {
|
if (s && (s->sym_scope == local_scope || tok != '{')) {
|
||||||
if ((s->type.t & (VT_BTYPE|VT_UNION)) != u)
|
if (u == s->type.t)
|
||||||
tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
|
goto do_decl;
|
||||||
goto do_decl;
|
if (u == VT_ENUM && IS_ENUM(s->type.t))
|
||||||
|
goto do_decl;
|
||||||
|
tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
v = anon_sym++;
|
v = anon_sym++;
|
||||||
@ -3520,7 +3502,7 @@ static void struct_decl(CType *type, int u)
|
|||||||
s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
|
s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
|
||||||
s->r = 0; /* default alignment is zero as gcc */
|
s->r = 0; /* default alignment is zero as gcc */
|
||||||
do_decl:
|
do_decl:
|
||||||
type->t = u & VT_BTYPE; /* VT_UNION becomes VT_STRUCT */
|
type->t = s->type.t;
|
||||||
type->ref = s;
|
type->ref = s;
|
||||||
|
|
||||||
if (tok == '{') {
|
if (tok == '{') {
|
||||||
@ -3528,13 +3510,15 @@ do_decl:
|
|||||||
if (s->c != -1)
|
if (s->c != -1)
|
||||||
tcc_error("struct/union/enum already defined");
|
tcc_error("struct/union/enum already defined");
|
||||||
/* cannot be empty */
|
/* cannot be empty */
|
||||||
c = 0;
|
|
||||||
/* non empty enums are not allowed */
|
/* non empty enums are not allowed */
|
||||||
|
ps = &s->next;
|
||||||
if (u == VT_ENUM) {
|
if (u == VT_ENUM) {
|
||||||
int seen_neg = 0;
|
long long ll = 0, pl = 0, nl = 0;
|
||||||
int seen_wide = 0;
|
CType t;
|
||||||
|
t.ref = s;
|
||||||
|
/* enum symbols have static storage */
|
||||||
|
t.t = VT_INT|VT_STATIC|VT_ENUM_VAL;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
CType *t = &int_type;
|
|
||||||
v = tok;
|
v = tok;
|
||||||
if (v < TOK_UIDENT)
|
if (v < TOK_UIDENT)
|
||||||
expect("identifier");
|
expect("identifier");
|
||||||
@ -3545,38 +3529,48 @@ do_decl:
|
|||||||
next();
|
next();
|
||||||
if (tok == '=') {
|
if (tok == '=') {
|
||||||
next();
|
next();
|
||||||
#if PTR_SIZE == 8
|
ll = expr_const64();
|
||||||
c = expr_const64();
|
|
||||||
#else
|
|
||||||
/* We really want to support long long enums
|
|
||||||
on i386 as well, but the Sym structure only
|
|
||||||
holds a 'long' for associated constants,
|
|
||||||
and enlarging it would bump its size (no
|
|
||||||
available padding). So punt for now. */
|
|
||||||
c = expr_const();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (c < 0)
|
ss = sym_push(v, &t, VT_CONST, 0);
|
||||||
seen_neg = 1;
|
ss->enum_val = ll;
|
||||||
if (c != (int)c && (unsigned long)c != (unsigned int)c)
|
*ps = ss, ps = &ss->next;
|
||||||
seen_wide = 1, t = &size_type;
|
if (ll < nl)
|
||||||
/* enum symbols have static storage */
|
nl = ll;
|
||||||
ss = sym_push(v, t, VT_CONST, c);
|
if (ll > pl)
|
||||||
ss->type.t |= VT_STATIC;
|
pl = ll;
|
||||||
if (tok != ',')
|
if (tok != ',')
|
||||||
break;
|
break;
|
||||||
next();
|
next();
|
||||||
c++;
|
ll++;
|
||||||
/* NOTE: we accept a trailing comma */
|
/* NOTE: we accept a trailing comma */
|
||||||
if (tok == '}')
|
if (tok == '}')
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!seen_neg)
|
|
||||||
s->a.unsigned_enum = 1;
|
|
||||||
s->c = type_size(seen_wide ? &size_type : &int_type, &align);
|
|
||||||
skip('}');
|
skip('}');
|
||||||
|
/* set integral type of the enum */
|
||||||
|
t.t = VT_INT;
|
||||||
|
if (nl == 0) {
|
||||||
|
if (pl != (unsigned)pl)
|
||||||
|
t.t = VT_LLONG;
|
||||||
|
t.t |= VT_UNSIGNED;
|
||||||
|
} else if (pl != (int)pl || nl != (int)nl)
|
||||||
|
t.t = VT_LLONG;
|
||||||
|
s->type.t = type->t = t.t | VT_ENUM;
|
||||||
|
s->c = 0;
|
||||||
|
/* set type for enum members */
|
||||||
|
for (ss = s->next; ss; ss = ss->next) {
|
||||||
|
ll = ss->enum_val;
|
||||||
|
if (ll == (int)ll) /* default is int if it fits */
|
||||||
|
continue;
|
||||||
|
if (t.t & VT_UNSIGNED) {
|
||||||
|
ss->type.t |= VT_UNSIGNED;
|
||||||
|
if (ll == (unsigned)ll)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ss->type.t = (ss->type.t & ~VT_BTYPE) | VT_LLONG;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ps = &s->next;
|
c = 0;
|
||||||
flexible = 0;
|
flexible = 0;
|
||||||
while (tok != '}') {
|
while (tok != '}') {
|
||||||
if (!parse_btype(&btype, &ad1)) {
|
if (!parse_btype(&btype, &ad1)) {
|
||||||
@ -3646,7 +3640,6 @@ do_decl:
|
|||||||
bt != VT_BYTE &&
|
bt != VT_BYTE &&
|
||||||
bt != VT_SHORT &&
|
bt != VT_SHORT &&
|
||||||
bt != VT_BOOL &&
|
bt != VT_BOOL &&
|
||||||
bt != VT_ENUM &&
|
|
||||||
bt != VT_LLONG)
|
bt != VT_LLONG)
|
||||||
tcc_error("bitfields must have scalar type");
|
tcc_error("bitfields must have scalar type");
|
||||||
bsize = size * 8;
|
bsize = size * 8;
|
||||||
@ -3657,9 +3650,9 @@ do_decl:
|
|||||||
/* no need for bit fields */
|
/* no need for bit fields */
|
||||||
;
|
;
|
||||||
} else {
|
} else {
|
||||||
type1.t |= VT_BITFIELD |
|
type1.t = (type1.t & ~VT_STRUCT_MASK)
|
||||||
(0 << VT_STRUCT_SHIFT) |
|
| VT_BITFIELD
|
||||||
(bit_size << (VT_STRUCT_SHIFT + 6));
|
| (bit_size << (VT_STRUCT_SHIFT + 6));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
|
if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
|
||||||
@ -4124,6 +4117,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int *v, int td)
|
|||||||
storage = type->t & VT_STORAGE;
|
storage = type->t & VT_STORAGE;
|
||||||
type->t &= ~VT_STORAGE;
|
type->t &= ~VT_STORAGE;
|
||||||
post = ret = type;
|
post = ret = type;
|
||||||
|
|
||||||
while (tok == '*') {
|
while (tok == '*') {
|
||||||
qualifiers = 0;
|
qualifiers = 0;
|
||||||
redo:
|
redo:
|
||||||
@ -4813,8 +4807,11 @@ ST_FUNC void unary(void)
|
|||||||
Will be used by at least the x86 inline asm parser for
|
Will be used by at least the x86 inline asm parser for
|
||||||
regvars. */
|
regvars. */
|
||||||
vtop->sym = s;
|
vtop->sym = s;
|
||||||
if (vtop->r & VT_SYM) {
|
|
||||||
|
if (r & VT_SYM) {
|
||||||
vtop->c.i = 0;
|
vtop->c.i = 0;
|
||||||
|
} else if (r == VT_CONST && IS_ENUM_VAL(s->type.t)) {
|
||||||
|
vtop->c.i = s->enum_val;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6352,7 +6349,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c,
|
|||||||
/* Use i_c_parameter_t, to strip toplevel qualifiers.
|
/* Use i_c_parameter_t, to strip toplevel qualifiers.
|
||||||
The source type might have VT_CONSTANT set, which is
|
The source type might have VT_CONSTANT set, which is
|
||||||
of course assignable to non-const elements. */
|
of course assignable to non-const elements. */
|
||||||
is_compatible_parameter_types(type, &vtop->type)) {
|
is_compatible_unqualified_types(type, &vtop->type)) {
|
||||||
init_putv(type, sec, c);
|
init_putv(type, sec, c);
|
||||||
} else if (type->t & VT_ARRAY) {
|
} else if (type->t & VT_ARRAY) {
|
||||||
s = type->ref;
|
s = type->ref;
|
||||||
@ -6858,16 +6855,18 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym)
|
|||||||
break;
|
break;
|
||||||
btype.t = VT_INT;
|
btype.t = VT_INT;
|
||||||
}
|
}
|
||||||
if (((btype.t & VT_BTYPE) == VT_ENUM ||
|
if (tok == ';') {
|
||||||
(btype.t & VT_BTYPE) == VT_STRUCT) &&
|
|
||||||
tok == ';') {
|
|
||||||
if ((btype.t & VT_BTYPE) == VT_STRUCT) {
|
if ((btype.t & VT_BTYPE) == VT_STRUCT) {
|
||||||
int v = btype.ref->v;
|
int v = btype.ref->v;
|
||||||
if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)
|
if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)
|
||||||
tcc_warning("unnamed struct/union that defines no instances");
|
tcc_warning("unnamed struct/union that defines no instances");
|
||||||
|
next();
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
next();
|
if (IS_ENUM(btype.t)) {
|
||||||
continue;
|
next();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while (1) { /* iterate thru each declaration */
|
while (1) { /* iterate thru each declaration */
|
||||||
type = btype;
|
type = btype;
|
||||||
|
10
x86_64-gen.c
10
x86_64-gen.c
@ -415,9 +415,11 @@ void load(int r, SValue *sv)
|
|||||||
} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
|
} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
|
||||||
b = 0xb70f; /* movzwl */
|
b = 0xb70f; /* movzwl */
|
||||||
} else {
|
} else {
|
||||||
assert(((ft & VT_BTYPE) == VT_INT) || ((ft & VT_BTYPE) == VT_LLONG)
|
assert(((ft & VT_BTYPE) == VT_INT)
|
||||||
|| ((ft & VT_BTYPE) == VT_PTR) || ((ft & VT_BTYPE) == VT_ENUM)
|
|| ((ft & VT_BTYPE) == VT_LLONG)
|
||||||
|| ((ft & VT_BTYPE) == VT_FUNC));
|
|| ((ft & VT_BTYPE) == VT_PTR)
|
||||||
|
|| ((ft & VT_BTYPE) == VT_FUNC)
|
||||||
|
);
|
||||||
ll = is64_type(ft);
|
ll = is64_type(ft);
|
||||||
b = 0x8b;
|
b = 0x8b;
|
||||||
}
|
}
|
||||||
@ -1092,7 +1094,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty)
|
|||||||
case VT_BOOL:
|
case VT_BOOL:
|
||||||
case VT_PTR:
|
case VT_PTR:
|
||||||
case VT_FUNC:
|
case VT_FUNC:
|
||||||
case VT_ENUM: return x86_64_mode_integer;
|
return x86_64_mode_integer;
|
||||||
|
|
||||||
case VT_FLOAT:
|
case VT_FLOAT:
|
||||||
case VT_DOUBLE: return x86_64_mode_sse;
|
case VT_DOUBLE: return x86_64_mode_sse;
|
||||||
|
Loading…
Reference in New Issue
Block a user