From 313855c232710378e1d3fad4fb4455991b9f45e9 Mon Sep 17 00:00:00 2001 From: herman ten brugge Date: Mon, 21 Mar 2022 11:40:43 +0100 Subject: [PATCH] Fix multi dimensional vla arrays on stack There is no code generation in post_type for vla arrays. This code generation has to be delayed until gen_function. - post_type save code in type info. - gen_function use this code to generate vla code. - enable testcode for vla arrays. --- tcc.h | 1 + tccgen.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/tcctest.c | 2 -- 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/tcc.h b/tcc.h index 04e68049..97248487 100644 --- a/tcc.h +++ b/tcc.h @@ -572,6 +572,7 @@ typedef struct Sym { }; CType type; /* associated type */ union { + int *vla_array_str; /* vla array code */ struct Sym *next; /* next related symbol (for fields and anoms) */ struct Sym *cleanupstate; /* in defined labels */ int asm_label; /* associated asm label */ diff --git a/tccgen.c b/tccgen.c index 0e0835f0..7d15dbea 100644 --- a/tccgen.c +++ b/tccgen.c @@ -5333,6 +5333,8 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) Sym **plast, *s, *first; AttributeDef ad1; CType pt; + TokenString *vla_array_tok = NULL; + int *vla_array_str = NULL; if (tok == '(') { /* function type, or recursive declarator (return if so) */ @@ -5441,8 +5443,32 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) break; } if (tok != ']') { + int nest = 1; + + /* Code generation is not done now but has to be done + at start of function. Save code here for later use. */ nocode_wanted = 1; + vla_array_tok = tok_str_alloc(); + for (;;) { + if (tok == ']') { + nest--; + if (nest == 0) + break; + } + if (tok == '[') + nest++; + tok_str_add_tok(vla_array_tok); + next(); + } + unget_tok(0); + tok_str_add(vla_array_tok, -1); + tok_str_add(vla_array_tok, 0); + vla_array_str = vla_array_tok->str; + begin_macro(vla_array_tok, 2); + next(); gexpr(); + end_macro(); + next(); goto check; } break; @@ -5504,6 +5530,12 @@ check: s = sym_push(SYM_FIELD, type, 0, n); type->t = (t1 ? VT_VLA : VT_ARRAY) | VT_PTR; type->ref = s; + if (vla_array_str) { + if (t1 & VT_VLA) + s->vla_array_str = vla_array_str; + else + tok_str_free_str(vla_array_str); + } } return 1; } @@ -8592,6 +8624,46 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, nocode_wanted = saved_nocode_wanted; } +/* generate vla code saved in post_type() */ +static void func_vla_arg_code(Sym *arg) +{ + int align; + TokenString *vla_array_tok = NULL; + + if (arg->type.ref) + func_vla_arg_code(arg->type.ref); + + if (arg->type.t & VT_VLA) { + loc -= type_size(&int_type, &align); + loc &= -align; + arg->type.ref->c = loc; + + unget_tok(0); + vla_array_tok = tok_str_alloc(); + vla_array_tok->str = arg->type.ref->vla_array_str; + begin_macro(vla_array_tok, 1); + next(); + gexpr(); + end_macro(); + next(); + vpush_type_size(&arg->type.ref->type, &align); + gen_op('*'); + vset(&int_type, VT_LOCAL|VT_LVAL, arg->type.ref->c); + vswap(); + vstore(); + vpop(); + } +} + +static void func_vla_arg(Sym *sym) +{ + Sym *arg; + + for (arg = sym->type.ref->next; arg; arg = arg->next) + if (arg->type.t & VT_VLA) + func_vla_arg_code(arg); +} + /* parse a function defined by symbol 'sym' and generate its code in 'cur_text_section' */ static void gen_function(Sym *sym) @@ -8626,6 +8698,7 @@ static void gen_function(Sym *sym) local_scope = 0; rsym = 0; clear_temp_local_var_list(); + func_vla_arg(sym); block(0); gsym(rsym); nocode_wanted = 0; diff --git a/tests/tcctest.c b/tests/tcctest.c index 51c9c5bf..dfa5f4f0 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -3025,10 +3025,8 @@ void c99_vla_test_3(void) a[1][2][3] = 2; c99_vla_test_3a(a); c99_vla_test_3b(2, a); -#if 0 // FIXME c99_vla_test_3c(3, a); c99_vla_test_3d(4, a); -#endif } void c99_vla_test(void)