From db560e9439deaef3c15aa353828fd4d98a1b5f8c Mon Sep 17 00:00:00 2001 From: Thomas Preud'homme Date: Sat, 5 Feb 2011 02:31:45 +0100 Subject: [PATCH] Revert "Implement C99 Variable Length Arrays" This reverts commit a5a50eaafeea0d3ca47bc8fb6baf983743470c60. --- Changelog | 1 - TODO | 1 + tcc-doc.texi | 16 +---- tcc.h | 2 - tccgen.c | 160 +++++++++--------------------------------------- tests/tcctest.c | 22 ------- 6 files changed, 33 insertions(+), 169 deletions(-) diff --git a/Changelog b/Changelog index 7a9f0c8..fdccdbd 100644 --- a/Changelog +++ b/Changelog @@ -12,7 +12,6 @@ not released: - fix 32 to 64 bit casts, alignment and struct issues (Shinichiro Hamaji) - mimic all GNU -option forms supported by ld (Kirill Smelkov) - support indirect functions as externals (Thomas Preud'homme) -- Add support for C99 variable length arrays (Thomas Preud'homme) version 0.9.25: diff --git a/TODO b/TODO index 74fe8a6..9d19153 100644 --- a/TODO +++ b/TODO @@ -48,6 +48,7 @@ Missing features: - improve '-E' option. - atexit (Nigel Horne) - packed attribute +- C99: add variable size arrays (gcc 3.2 testsuite issue) - C99: add complex types (gcc 3.2 testsuite issue) - postfix compound literals (see 20010124-1.c) diff --git a/tcc-doc.texi b/tcc-doc.texi index 2c1ac3f..14827aa 100644 --- a/tcc-doc.texi +++ b/tcc-doc.texi @@ -929,11 +929,7 @@ be the best solution. #define VT_BTYPE 0x000f /* mask for basic type */ #define VT_UNSIGNED 0x0010 /* unsigned type */ #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ -#define VT_VLA 0x10000 /* VLA type (also has VT_PTR and VT_ARRAY) */ #define VT_BITFIELD 0x0040 /* bitfield modifier */ -#define VT_CONSTANT 0x0800 /* const modifier */ -#define VT_VOLATILE 0x1000 /* volatile modifier */ -#define VT_SIGNED 0x2000 /* signed type */ #define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */ @end example @@ -946,8 +942,7 @@ The @code{VT_UNSIGNED} flag can be set for chars, shorts, ints and long longs. Arrays are considered as pointers @code{VT_PTR} with the flag -@code{VT_ARRAY} set. Variable length arrays are considered as special -arrays and therefore also have flag @code{VT_VLA} set. +@code{VT_ARRAY} set. The @code{VT_BITFIELD} flag can be set for chars, shorts, ints and long longs. If it is set, then the bitfield position is stored from bits @@ -963,10 +958,6 @@ integer: #define VT_EXTERN 0x00000080 /* extern definition */ #define VT_STATIC 0x00000100 /* static variable */ #define VT_TYPEDEF 0x00000200 /* typedef definition */ -#define VT_INLINE 0x00000400 /* inline definition */ -#define VT_IMPORT 0x00004000 /* win32: extern data imported from dll */ -#define VT_EXPORT 0x00008000 /* win32: data exported from dll */ -#define VT_WEAK 0x00010000 /* win32: data exported from dll */ @end example @section Symbols @@ -978,10 +969,7 @@ contains @code{Sym} structures. an idenfier is also a token, so a string is never necessary to store it). @code{Sym.t} gives the type of the symbol. @code{Sym.r} is usually the register in which the corresponding variable is stored. @code{Sym.c} is -usually a constant associated to the symbol like its address for normal -symbols, and the number of entries for symbols representing arrays. -Variable length arrays use @code{Sym.r} instead, which is a pointer to -a @code{SValue} holding its runtime size. +usually a constant associated to the symbol. Four main symbol stacks are defined: diff --git a/tcc.h b/tcc.h index add86a2..edefe92 100644 --- a/tcc.h +++ b/tcc.h @@ -224,7 +224,6 @@ typedef struct Sym { union { long c; /* associated number */ int *d; /* define token stream */ - SValue *s; /* associated stack value */ }; CType type; /* associated type */ union { @@ -617,7 +616,6 @@ struct TCCState { #define VT_BTYPE 0x000f /* mask for basic type */ #define VT_UNSIGNED 0x0010 /* unsigned type */ #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */ -#define VT_VLA 0x10000 /* VLA type (also has VT_PTR and VT_ARRAY) */ #define VT_BITFIELD 0x0040 /* bitfield modifier */ #define VT_CONSTANT 0x0800 /* const modifier */ #define VT_VOLATILE 0x1000 /* volatile modifier */ diff --git a/tccgen.c b/tccgen.c index 7fb7cfe..7144ccd 100644 --- a/tccgen.c +++ b/tccgen.c @@ -78,7 +78,6 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_re static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int has_init, int v, int scope); static void expr_eq(void); static void unary_type(CType *type); -static void vla_runtime_type_size(CType *type, int *a); static int is_compatible_parameter_types(CType *type1, CType *type2); static void expr_type(CType *type); @@ -1456,12 +1455,6 @@ static int pointed_size(CType *type) return type_size(pointed_type(type), &align); } -static void vla_runtime_pointed_size(CType *type) -{ - int align; - vla_runtime_type_size(pointed_type(type), &align); -} - static inline int is_null_pointer(SValue *p) { if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST) @@ -1550,20 +1543,11 @@ ST_FUNC void gen_op(int op) } /* if both pointers, then it must be the '-' op */ if (bt1 == VT_PTR && bt2 == VT_PTR) { - int ptr1_is_vla; - - ptr1_is_vla = 0; if (op != '-') error("cannot use pointers here"); check_comparison_pointer_types(vtop - 1, vtop, op); /* XXX: check that types are compatible */ - if (vtop[-1].type.t & VT_VLA) { - vla_runtime_pointed_size(&vtop[-1].type); - vrott(3); - ptr1_is_vla = 1; - } else { - u = pointed_size(&vtop[-1].type); - } + u = pointed_size(&vtop[-1].type); gen_opic(op); /* set to integer type */ #ifdef TCC_TARGET_X86_64 @@ -1571,10 +1555,7 @@ ST_FUNC void gen_op(int op) #else vtop->type.t = VT_INT; #endif - if (ptr1_is_vla) - vswap(); - else - vpushi(u); + vpushi(u); gen_op(TOK_PDIV); } else { /* exactly one pointer : must be '+' or '-'. */ @@ -1586,20 +1567,16 @@ ST_FUNC void gen_op(int op) swap(&t1, &t2); } type1 = vtop[-1].type; - type1.t &= ~(VT_ARRAY|VT_VLA); - if (vtop[-1].type.t & VT_VLA) - vla_runtime_pointed_size(&vtop[-1].type); - else { - u = pointed_size(&vtop[-1].type); - if (u < 0) - error("unknown array element size"); + type1.t &= ~VT_ARRAY; + u = pointed_size(&vtop[-1].type); + if (u < 0) + error("unknown array element size"); #ifdef TCC_TARGET_X86_64 - vpushll(u); + vpushll(u); #else - /* XXX: cast to int ? (long long case) */ - vpushi(u); + /* XXX: cast to int ? (long long case) */ + vpushi(u); #endif - } gen_op('*'); #ifdef CONFIG_TCC_BCHECK /* if evaluating constant expression, no code should be @@ -1955,7 +1932,7 @@ static void gen_cast(CType *type) vtop->type = *type; } -/* return type size as known at compile time. Put alignment at 'a' */ +/* return type size. Put alignment at 'a' */ ST_FUNC int type_size(CType *type, int *a) { Sym *s; @@ -1968,10 +1945,7 @@ ST_FUNC int type_size(CType *type, int *a) *a = s->r; return s->c; } else if (bt == VT_PTR) { - if (type->t & VT_VLA) { - *a = 1; - return 0; - } else if (type->t & VT_ARRAY) { + if (type->t & VT_ARRAY) { int ts; s = type->ref; @@ -2018,30 +1992,6 @@ ST_FUNC int type_size(CType *type, int *a) } } -/* push type size as known at runtime time on top of value stack. Put - alignment at 'a' */ -ST_FUNC void vla_runtime_type_size(CType *type, int *a) -{ - if (type->t & VT_VLA) { - Sym *s; - - s = type->ref; - vla_runtime_type_size(&s->type, a); - vpushv(s->s); - if ((vtop->r & (VT_SYM|VT_LVAL|VT_VALMASK)) != VT_CONST) { - gv_dup(); - vswap(); - vpop(); - } - gen_op('*'); - } else { - int size; - - size = type_size(type, a); - vpushi(size); - } -} - /* return the pointed type of t */ static inline CType *pointed_type(CType *type) { @@ -3153,43 +3103,25 @@ static void post_type(CType *type, AttributeDef *ad) type->t = t1 | VT_FUNC; type->ref = s; } else if (tok == '[') { - SValue *last_vtop = NULL; - /* array definition */ next(); if (tok == TOK_RESTRICT1) next(); n = -1; if (tok != ']') { - gexpr(); - if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) { - n = vtop->c.i; - last_vtop = vtop; - if (n < 0) - error("invalid array size"); - } else { - if (!is_integer_btype(vtop->type.t & VT_BTYPE)) - error("size of variable length array should be an integer"); - type->t |= VT_VLA; - last_vtop = vtop; - } + n = expr_const(); + if (n < 0) + error("invalid array size"); } skip(']'); /* parse next post type */ - t1 = type->t & (VT_STORAGE|VT_VLA); - type->t &= ~(VT_STORAGE|VT_VLA); + t1 = type->t & VT_STORAGE; + type->t &= ~VT_STORAGE; post_type(type, ad); - t1 |= type->t & VT_VLA; - /* we push an anonymous symbol which will contain the array + /* we push a anonymous symbol which will contain the array element type */ s = sym_push(SYM_FIELD, type, 0, n); - if (t1 & VT_VLA) { - s->s = last_vtop; // That's ok, we don't need n with VLA - } else { - if (n >= 0) - vpop(); - } type->t = t1 | VT_ARRAY | VT_PTR; type->ref = s; } @@ -3558,18 +3490,11 @@ ST_FUNC void unary(void) next(); in_sizeof++; unary_type(&type); // Perform a in_sizeof = 0; - if ((t == TOK_SIZEOF) && (type.t & VT_VLA)) { - vla_runtime_type_size(&type, &align); - size = 0; - } else { - size = type_size(&type, &align); - } + size = type_size(&type, &align); if (t == TOK_SIZEOF) { - if (!(type.t & VT_VLA)) { - if (size < 0) - error("sizeof applied to an incomplete type"); - vpushi(size); - } + if (size < 0) + error("sizeof applied to an incomplete type"); + vpushi(size); } else { vpushi(align); } @@ -3728,10 +3653,7 @@ ST_FUNC void unary(void) } else { r = s->r; } - if (s->type.t & VT_VLA) - vpushv(s->s); - else - vset(&s->type, r, s->c); + vset(&s->type, r, s->c); /* if forward reference, we must point to s */ if (vtop->r & VT_SYM) { vtop->sym = s; @@ -4860,18 +4782,7 @@ static void decl_initializer(CType *type, Section *sec, unsigned long c, Sym *s, *f; CType *t1; - if (type->t & VT_VLA) { - int a; - CValue retcval; - - vpush_global_sym(&func_old_type, TOK_alloca); - vla_runtime_type_size(type, &a); - gfunc_call(1); - - /* return value */ - retcval.i = 0; - vsetc(type, REG_IRET, &retcval); - } else if (type->t & VT_ARRAY) { + if (type->t & VT_ARRAY) { s = type->ref; n = s->c; array_length = 0; @@ -5102,7 +5013,6 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, ParseState saved_parse_state = {0}; TokenString init_str; Section *sec; - Sym *vla = NULL; size = type_size(type, &align); /* If unknown size, we must evaluate it before @@ -5168,12 +5078,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, if ((r & VT_VALMASK) == VT_LOCAL) { sec = NULL; #ifdef CONFIG_TCC_BCHECK - if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { - if (type->t & VT_VLA) - warning("Array bound check don't work for VLA"); - else - loc--; - } + if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) + loc--; #endif loc = (loc - size) & -align; addr = loc; @@ -5181,8 +5087,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, /* handles bounds */ /* XXX: currently, since we do only one pass, we cannot track '&' operators, so we add only arrays */ - if (tcc_state->do_bounds_check && (type->t & VT_ARRAY) && - !(type->t & VT_VLA)) { + if (tcc_state->do_bounds_check && (type->t & VT_ARRAY)) { unsigned long *bounds_ptr; /* add padding between regions */ loc--; @@ -5194,7 +5099,7 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, #endif if (v) { /* local variable */ - vla = sym_push(v, type, r, addr); + sym_push(v, type, r, addr); } else { /* push local reference */ vset(type, r, addr); @@ -5309,10 +5214,8 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, } #endif } - if (has_init || (type->t & VT_VLA)) { + if (has_init) { decl_initializer(type, sec, addr, 1, 0); - if (type->t & VT_VLA) - vla->s = vtop; /* restore parse state if needed */ if (init_str.str) { tok_str_free(init_str.str); @@ -5681,12 +5584,9 @@ ST_FUNC void decl(int l) if (!(type.t & VT_ARRAY)) r |= lvalue_type(type.t); has_init = (tok == '='); - if (has_init && (type.t & VT_VLA)) - error("Variable length array cannot be initialized"); if ((btype.t & VT_EXTERN) || - ((type.t & VT_ARRAY) && (!(type.t & VT_VLA)) && - (type.t & VT_STATIC) && !has_init && l == VT_CONST && - type.ref->c < 0)) { + ((type.t & VT_ARRAY) && (type.t & VT_STATIC) && + !has_init && l == VT_CONST && type.ref->c < 0)) { /* external variable */ /* NOTE: as GCC, uninitialized global static arrays of null size are considered as diff --git a/tests/tcctest.c b/tests/tcctest.c index 499a071..87e7ad1 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -77,7 +77,6 @@ void whitespace_test(void); void relocation_test(void); void old_style_function(void); void alloca_test(void); -void c99_vla_test(int size1, int size2); void sizeof_test(void); void typeof_test(void); void local_label_test(void); @@ -564,7 +563,6 @@ int main(int argc, char **argv) relocation_test(); old_style_function(); alloca_test(); - c99_vla_test(5, 2); sizeof_test(); typeof_test(); statement_expr_test(); @@ -2020,26 +2018,6 @@ void alloca_test() #endif } -void c99_vla_test(int size1, int size2) -{ -#if defined __i386__ || defined __x86_64__ - int tab1[size1 * size2][2], tab2[10][2]; - void *tab1_ptr, *tab2_ptr; - - printf("Test C99 VLA 1 (sizeof): "); - printf("%s\n", (sizeof tab1 == size1 * size2 * 2 * sizeof(int)) ? "PASSED" : "FAILED"); - tab1_ptr = tab1; - tab2_ptr = tab2; - printf("Test C99 VLA 2 (ptrs substract): "); - printf("%s\n", (tab2 - tab1 == (tab2_ptr - tab1_ptr) / (sizeof(int) * 2)) ? "PASSED" : "FAILED"); - printf("Test C99 VLA 3 (ptr add): "); - printf("%s\n", &tab1[5][1] == (tab1_ptr + (5 * 2 + 1) * sizeof(int)) ? "PASSED" : "FAILED"); - printf("Test C99 VLA 4 (ptr access): "); - tab1[size1][1] = 42; - printf("%s\n", (*((int *) (tab1_ptr + (size1 * 2 + 1) * sizeof(int))) == 42) ? "PASSED" : "FAILED"); -#endif -} - void sizeof_test(void) { int a;