History

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.

grischka committed 9 years ago

Commit f87afa71 parent 9ba76ac4 files · +107 −102Browse files

Unified · Split

4 files
  1. arm64-gen.c +0 −1
  2. tcc.h +18 −13
  3. tccgen.c +83 −84
  4. x86_64-gen.c +6 −4
arm64-gen.c+0−1
@@ -249,7 +249,6 @@ static int arm64_type_size(int t) · 248 unmodified lines
249249 case VT_BYTE: return 0;
250250 case VT_SHORT: return 1;
251251 case VT_PTR: return 3;
252− case VT_ENUM: return 2;
253252 case VT_FUNC: return 3;
254253 case VT_FLOAT: return 2;
255254 case VT_DOUBLE: return 3;
tcc.h+18−13
@@ -416,8 +416,7 @@ struct SymAttr { · 415 unmodified lines
416416 visibility : 2,
417417 dllexport : 1,
418418 dllimport : 1,
419− unsigned_enum : 1,
420− unused : 4;
419+ unused : 5;
421420 };
422421
423422 /* function attributes or temporary attributes for parsing */
@@ -852,14 +851,13 @@ struct filespec { · 428 unmodified lines
852851 #define VT_PTR 5 /* pointer */
853852 #define VT_FUNC 6 /* function type */
854853 #define VT_STRUCT 7 /* struct/union definition */
855−#define VT_ENUM 8 /* enum definition */
856−#define VT_FLOAT 9 /* IEEE float */
857−#define VT_DOUBLE 10 /* IEEE double */
858−#define VT_LDOUBLE 11 /* IEEE long double */
859−#define VT_BOOL 12 /* ISOC99 boolean type */
860−#define VT_LONG 13 /* long integer (NEVER USED as type, only during parsing) */
861−#define VT_QLONG 14 /* 128-bit integer. Only used for x86-64 ABI */
862−#define VT_QFLOAT 15 /* 128-bit float. Only used for x86-64 ABI */
854+#define VT_FLOAT 8 /* IEEE float */
855+#define VT_DOUBLE 9 /* IEEE double */
856+#define VT_LDOUBLE 10 /* IEEE long double */
857+#define VT_BOOL 11 /* ISOC99 boolean type */
858+#define VT_LONG 12 /* long integer (NEVER USED as type, only during parsing) */
859+#define VT_QLONG 13 /* 128-bit integer. Only used for x86-64 ABI */
860+#define VT_QFLOAT 14 /* 128-bit float. Only used for x86-64 ABI */
863861
864862 #define VT_UNSIGNED 0x0010 /* unsigned type */
865863 #define VT_DEFSIGN 0x0020 /* explicitly signed or unsigned */
@@ -868,7 +866,6 @@ struct filespec { · 2 unmodified lines
868866 #define VT_CONSTANT 0x0100 /* const modifier */
869867 #define VT_VOLATILE 0x0200 /* volatile modifier */
870868 #define VT_VLA 0x0400 /* VLA type (also has VT_PTR and VT_ARRAY) */
871−#define VT_UNION (VT_STRUCT|VT_UNSIGNED) /* VT_STRUCT type with some modifier */
872869
873870 /* storage */
874871 #define VT_EXTERN 0x00001000 /* extern definition */
@@ -882,9 +879,17 @@ struct filespec { · 7 unmodified lines
882879 #define BIT_POS(t) (((t) >> VT_STRUCT_SHIFT) & 0x3f)
883880 #define BIT_SIZE(t) (((t) >> (VT_STRUCT_SHIFT + 6)) & 0x3f)
884881
882+#define VT_UNION (1 << VT_STRUCT_SHIFT | VT_STRUCT)
883+#define VT_ENUM (2 << VT_STRUCT_SHIFT) /* integral type is an enum really */
884+#define VT_ENUM_VAL (3 << VT_STRUCT_SHIFT) /* integral type is an enum constant really */
885+
886+#define IS_ENUM(t) ((t & VT_STRUCT_MASK) == VT_ENUM)
887+#define IS_ENUM_VAL(t) ((t & VT_STRUCT_MASK) == VT_ENUM_VAL)
888+#define IS_UNION(t) ((t & (VT_STRUCT_MASK|VT_BTYPE)) == VT_UNION)
889+
885890 /* type mask (except storage) */
886−#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE | VT_STRUCT_MASK)
887−#define VT_TYPE (~VT_STORAGE)
891+#define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
892+#define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
888893
889894
890895 /* token values */
tccgen.c+83−84
@@ -86,7 +86,7 @@ static void expr_eq(void); · 85 unmodified lines
8686 static void vla_runtime_type_size(CType *type, int *a);
8787 static void vla_sp_restore(void);
8888 static void vla_sp_restore_root(void);
89−static int is_compatible_parameter_types(CType *type1, CType *type2);
89+static int is_compatible_unqualified_types(CType *type1, CType *type2);
9090 static inline int64_t expr_const64(void);
9191 ST_FUNC void vpush64(int ty, unsigned long long v);
9292 ST_FUNC void vpush(CType *type);
@@ -1087,10 +1087,8 @@ ST_FUNC int gv(int rc) · 994 unmodified lines
10871087 bits = 64;
10881088 } else
10891089 type.t = VT_INT;
1090− if((vtop->type.t & VT_UNSIGNED) ||
1091− (vtop->type.t & VT_BTYPE) == VT_BOOL ||
1092− (((vtop->type.t & VT_BTYPE) == VT_ENUM) &&
1093− vtop->type.ref->a.unsigned_enum))
1090+ if((vtop->type.t & VT_UNSIGNED)
1091+ || (vtop->type.t & VT_BTYPE) == VT_BOOL)
10941092 type.t |= VT_UNSIGNED;
10951093 gen_cast(&type);
10961094 /* generate shifts */
@@ -2479,6 +2477,8 @@ ST_FUNC int type_size(CType *type, int *a) · 1382 unmodified lines
24792477 *a = PTR_SIZE;
24802478 return PTR_SIZE;
24812479 }
2480+ } else if (IS_ENUM(type->t) && type->ref->c == -1) {
2481+ return -1; /* incomplete enum */
24822482 } else if (bt == VT_LDOUBLE) {
24832483 *a = LDOUBLE_ALIGN;
24842484 return LDOUBLE_SIZE;
@@ -2508,10 +2508,6 @@ ST_FUNC int type_size(CType *type, int *a) · 23 unmodified lines
25082508 } else if (bt == VT_QLONG || bt == VT_QFLOAT) {
25092509 *a = 8;
25102510 return 16;
2511− } else if (bt == VT_ENUM) {
2512− *a = 4;
2513− /* Enums might be incomplete, so don't just return '4' here. */
2514− return type->ref->c;
25152511 } else {
25162512 /* char, void, function, _Bool */
25172513 *a = 1;
@@ -2554,7 +2550,7 @@ ST_FUNC void mk_pointer(CType *type) · 36 unmodified lines
25542550 {
25552551 Sym *s;
25562552 s = sym_push(SYM_FIELD, type, 0, -1);
2557− type->t = VT_PTR | (type->t & ~VT_TYPE);
2553+ type->t = VT_PTR | (type->t & VT_STORAGE);
25582554 type->ref = s;
25592555 }
25602556
@@ -2578,7 +2574,7 @@ static int is_compatible_func(CType *type1, CType *type2) · 17 unmodified lines
25782574 while (s1 != NULL) {
25792575 if (s2 == NULL)
25802576 return 0;
2581− if (!is_compatible_parameter_types(&s1->type, &s2->type))
2577+ if (!is_compatible_unqualified_types(&s1->type, &s2->type))
25822578 return 0;
25832579 s1 = s1->next;
25842580 s2 = s2->next;
@@ -2609,21 +2605,7 @@ static int compare_types(CType *type1, CType *type2, int unqualified) · 24 unmodified lines
26092605 t1 &= ~VT_DEFSIGN;
26102606 t2 &= ~VT_DEFSIGN;
26112607 }
2612− /* An enum is compatible with (unsigned) int. Ideally we would
2613− store the enums signedness in type->ref.a.<some_bit> and
2614− only accept unsigned enums with unsigned int and vice versa.
2615− But one of our callers (gen_assign_cast) always strips VT_UNSIGNED
2616− from pointer target types, so we can't add it here either. */
2617− if ((t1 & VT_BTYPE) == VT_ENUM) {
2618− t1 = VT_INT;
2619− if (type1->ref->a.unsigned_enum)
2620− t1 |= VT_UNSIGNED;
2621− }
2622− if ((t2 & VT_BTYPE) == VT_ENUM) {
2623− t2 = VT_INT;
2624− if (type2->ref->a.unsigned_enum)
2625− t2 |= VT_UNSIGNED;
2626− }
2608+
26272609 /* XXX: bitfields ? */
26282610 if (t1 != t2)
26292611 return 0;
@@ -2652,7 +2634,7 @@ static int is_compatible_types(CType *type1, CType *type2) · 22 unmodified lines
26522634
26532635 /* return true if type1 and type2 are the same (ignoring qualifiers).
26542636 */
2655−static int is_compatible_parameter_types(CType *type1, CType *type2)
2637+static int is_compatible_unqualified_types(CType *type1, CType *type2)
26562638 {
26572639 return compare_types(type1,type2,1);
26582640 }
@@ -2690,6 +2672,10 @@ static void type_to_str(char *buf, int buf_size, · 31 unmodified lines
26902672 pstrcat(buf, buf_size, "inline ");
26912673 buf_size -= strlen(buf);
26922674 buf += strlen(buf);
2675+ if (IS_ENUM(type->t)) {
2676+ tstr = "enum ";
2677+ goto tstruct;
2678+ }
26932679 switch(bt) {
26942680 case VT_VOID:
26952681 tstr = "void";
@@ -2723,12 +2709,11 @@ static void type_to_str(char *buf, int buf_size, · 27 unmodified lines
27232709 add_tstr:
27242710 pstrcat(buf, buf_size, tstr);
27252711 break;
2726− case VT_ENUM:
27272712 case VT_STRUCT:
2728− if (bt == VT_STRUCT)
2729− tstr = "struct ";
2730− else
2731− tstr = "enum ";
2713+ tstr = "struct ";
2714+ if (IS_UNION(t))
2715+ tstr = "union ";
2716+ tstruct:
27322717 pstrcat(buf, buf_size, tstr);
27332718 v = type->ref->v & ~SYM_STRUCT;
27342719 if (v >= SYM_FIRST_ANOM)
@@ -2827,21 +2812,16 @@ static void gen_assign_cast(CType *dt) · 92 unmodified lines
28272812 (type2->t & VT_BTYPE) == VT_VOID) {
28282813 /* void * can match anything */
28292814 } else {
2815+ //printf("types %08x %08x\n", type1->t, type2->t);
28302816 /* exact type match, except for qualifiers */
2831− tmp_type1 = *type1;
2832− tmp_type2 = *type2;
2833− tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
2834− tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
2835− if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
2817+ if (!is_compatible_unqualified_types(type1, type2)) {
28362818 /* Like GCC don't warn by default for merely changes
28372819 in pointer target signedness. Do warn for different
28382820 base types, though, in particular for unsigned enums
28392821 and signed int targets. */
2840− if ((tmp_type1.t & (VT_DEFSIGN | VT_UNSIGNED)) !=
2841− (tmp_type2.t & (VT_DEFSIGN | VT_UNSIGNED)) &&
2842− (tmp_type1.t & VT_BTYPE) == (tmp_type2.t & VT_BTYPE))
2843− ;
2844− else
2822+ if ((type1->t & VT_BTYPE) != (type2->t & VT_BTYPE)
2823+ || IS_ENUM(type1->t) || IS_ENUM(type2->t)
2824+ )
28452825 tcc_warning("assignment from incompatible pointer type");
28462826 }
28472827 }
@@ -3486,7 +3466,7 @@ static void struct_layout(CType *type, AttributeDef *ad) · 638 unmodified lines
34863466 tcc_warning("will touch memory past end of the struct (internal limitation)");
34873467 }
34883468
3489−/* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
3469+/* enum/struct/union declaration. u is VT_ENUM/VT_STRUCT/VT_UNION */
34903470 static void struct_decl(CType *type, int u)
34913471 {
34923472 int v, c, size, align, flexible, alignoverride;
@@ -3506,9 +3486,11 @@ static void struct_decl(CType *type, int u) · 13 unmodified lines
35063486 expect("struct/union/enum name");
35073487 s = struct_find(v);
35083488 if (s && (s->sym_scope == local_scope || tok != '{')) {
3509− if ((s->type.t & (VT_BTYPE|VT_UNION)) != u)
3510− tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
3511− goto do_decl;
3489+ if (u == s->type.t)
3490+ goto do_decl;
3491+ if (u == VT_ENUM && IS_ENUM(s->type.t))
3492+ goto do_decl;
3493+ tcc_error("redefinition of '%s'", get_tok_str(v, NULL));
35123494 }
35133495 } else {
35143496 v = anon_sym++;
@@ -3520,7 +3502,7 @@ static void struct_decl(CType *type, int u) · 5 unmodified lines
35203502 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
35213503 s->r = 0; /* default alignment is zero as gcc */
35223504 do_decl:
3523− type->t = u & VT_BTYPE; /* VT_UNION becomes VT_STRUCT */
3505+ type->t = s->type.t;
35243506 type->ref = s;
35253507
35263508 if (tok == '{') {
@@ -3528,13 +3510,15 @@ do_decl: · 1 unmodified line
35283510 if (s->c != -1)
35293511 tcc_error("struct/union/enum already defined");
35303512 /* cannot be empty */
3531− c = 0;
35323513 /* non empty enums are not allowed */
3514+ ps = &s->next;
35333515 if (u == VT_ENUM) {
3534− int seen_neg = 0;
3535− int seen_wide = 0;
3516+ long long ll = 0, pl = 0, nl = 0;
3517+ CType t;
3518+ t.ref = s;
3519+ /* enum symbols have static storage */
3520+ t.t = VT_INT|VT_STATIC|VT_ENUM_VAL;
35363521 for(;;) {
3537− CType *t = &int_type;
35383522 v = tok;
35393523 if (v < TOK_UIDENT)
35403524 expect("identifier");
@@ -3545,38 +3529,48 @@ do_decl: · 4 unmodified lines
35453529 next();
35463530 if (tok == '=') {
35473531 next();
3548−#if PTR_SIZE == 8
3549− c = expr_const64();
3550−#else
3551− /* We really want to support long long enums
3552− on i386 as well, but the Sym structure only
3553− holds a 'long' for associated constants,
3554− and enlarging it would bump its size (no
3555− available padding). So punt for now. */
3556− c = expr_const();
3557−#endif
3532+ ll = expr_const64();
35583533 }
3559− if (c < 0)
3560− seen_neg = 1;
3561− if (c != (int)c && (unsigned long)c != (unsigned int)c)
3562− seen_wide = 1, t = &size_type;
3563− /* enum symbols have static storage */
3564− ss = sym_push(v, t, VT_CONST, c);
3565− ss->type.t |= VT_STATIC;
3534+ ss = sym_push(v, &t, VT_CONST, 0);
3535+ ss->enum_val = ll;
3536+ *ps = ss, ps = &ss->next;
3537+ if (ll < nl)
3538+ nl = ll;
3539+ if (ll > pl)
3540+ pl = ll;
35663541 if (tok != ',')
35673542 break;
35683543 next();
3569− c++;
3544+ ll++;
35703545 /* NOTE: we accept a trailing comma */
35713546 if (tok == '}')
35723547 break;
35733548 }
3574− if (!seen_neg)
3575− s->a.unsigned_enum = 1;
3576− s->c = type_size(seen_wide ? &size_type : &int_type, &align);
35773549 skip('}');
3550+ /* set integral type of the enum */
3551+ t.t = VT_INT;
3552+ if (nl == 0) {
3553+ if (pl != (unsigned)pl)
3554+ t.t = VT_LLONG;
3555+ t.t |= VT_UNSIGNED;
3556+ } else if (pl != (int)pl || nl != (int)nl)
3557+ t.t = VT_LLONG;
3558+ s->type.t = type->t = t.t | VT_ENUM;
3559+ s->c = 0;
3560+ /* set type for enum members */
3561+ for (ss = s->next; ss; ss = ss->next) {
3562+ ll = ss->enum_val;
3563+ if (ll == (int)ll) /* default is int if it fits */
3564+ continue;
3565+ if (t.t & VT_UNSIGNED) {
3566+ ss->type.t |= VT_UNSIGNED;
3567+ if (ll == (unsigned)ll)
3568+ continue;
3569+ }
3570+ ss->type.t = (ss->type.t & ~VT_BTYPE) | VT_LLONG;
3571+ }
35783572 } else {
3579− ps = &s->next;
3573+ c = 0;
35803574 flexible = 0;
35813575 while (tok != '}') {
35823576 if (!parse_btype(&btype, &ad1)) {
@@ -3646,7 +3640,6 @@ do_decl: · 63 unmodified lines
36463640 bt != VT_BYTE &&
36473641 bt != VT_SHORT &&
36483642 bt != VT_BOOL &&
3649− bt != VT_ENUM &&
36503643 bt != VT_LLONG)
36513644 tcc_error("bitfields must have scalar type");
36523645 bsize = size * 8;
@@ -3657,9 +3650,9 @@ do_decl: · 4 unmodified lines
36573650 /* no need for bit fields */
36583651 ;
36593652 } else {
3660− type1.t |= VT_BITFIELD |
3661− (0 << VT_STRUCT_SHIFT) |
3662− (bit_size << (VT_STRUCT_SHIFT + 6));
3653+ type1.t = (type1.t & ~VT_STRUCT_MASK)
3654+ | VT_BITFIELD
3655+ | (bit_size << (VT_STRUCT_SHIFT + 6));
36633656 }
36643657 }
36653658 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) · 458 unmodified lines
41244117 storage = type->t & VT_STORAGE;
41254118 type->t &= ~VT_STORAGE;
41264119 post = ret = type;
4120+
41274121 while (tok == '*') {
41284122 qualifiers = 0;
41294123 redo:
@@ -4813,8 +4807,11 @@ ST_FUNC void unary(void) · 683 unmodified lines
48134807 Will be used by at least the x86 inline asm parser for
48144808 regvars. */
48154809 vtop->sym = s;
4816− if (vtop->r & VT_SYM) {
4810+
4811+ if (r & VT_SYM) {
48174812 vtop->c.i = 0;
4813+ } else if (r == VT_CONST && IS_ENUM_VAL(s->type.t)) {
4814+ vtop->c.i = s->enum_val;
48184815 }
48194816 break;
48204817 }
@@ -6352,7 +6349,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, · 1531 unmodified lines
63526349 /* Use i_c_parameter_t, to strip toplevel qualifiers.
63536350 The source type might have VT_CONSTANT set, which is
63546351 of course assignable to non-const elements. */
6355− is_compatible_parameter_types(type, &vtop->type)) {
6352+ is_compatible_unqualified_types(type, &vtop->type)) {
63566353 init_putv(type, sec, c);
63576354 } else if (type->t & VT_ARRAY) {
63586355 s = type->ref;
@@ -6858,16 +6855,18 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) · 499 unmodified lines
68586855 break;
68596856 btype.t = VT_INT;
68606857 }
6861− if (((btype.t & VT_BTYPE) == VT_ENUM ||
6862− (btype.t & VT_BTYPE) == VT_STRUCT) &&
6863− tok == ';') {
6858+ if (tok == ';') {
68646859 if ((btype.t & VT_BTYPE) == VT_STRUCT) {
68656860 int v = btype.ref->v;
68666861 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) >= SYM_FIRST_ANOM)
68676862 tcc_warning("unnamed struct/union that defines no instances");
6863+ next();
6864+ continue;
68686865 }
6869− next();
6870− continue;
6866+ if (IS_ENUM(btype.t)) {
6867+ next();
6868+ continue;
6869+ }
68716870 }
68726871 while (1) { /* iterate thru each declaration */
68736872 type = btype;
x86_64-gen.c+6−4
@@ -415,9 +415,11 @@ void load(int r, SValue *sv) · 414 unmodified lines
415415 } else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
416416 b = 0xb70f; /* movzwl */
417417 } else {
418− assert(((ft & VT_BTYPE) == VT_INT) || ((ft & VT_BTYPE) == VT_LLONG)
419− || ((ft & VT_BTYPE) == VT_PTR) || ((ft & VT_BTYPE) == VT_ENUM)
420− || ((ft & VT_BTYPE) == VT_FUNC));
418+ assert(((ft & VT_BTYPE) == VT_INT)
419+ || ((ft & VT_BTYPE) == VT_LLONG)
420+ || ((ft & VT_BTYPE) == VT_PTR)
421+ || ((ft & VT_BTYPE) == VT_FUNC)
422+ );
421423 ll = is64_type(ft);
422424 b = 0x8b;
423425 }
@@ -1092,7 +1094,7 @@ static X86_64_Mode classify_x86_64_inner(CType *ty) · 668 unmodified lines
10921094 case VT_BOOL:
10931095 case VT_PTR:
10941096 case VT_FUNC:
1095− case VT_ENUM: return x86_64_mode_integer;
1097+ return x86_64_mode_integer;
10961098
10971099 case VT_FLOAT:
10981100 case VT_DOUBLE: return x86_64_mode_sse;

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