diff options
| author | Philip <pipcet@gmail.com> | 2015-04-27 16:38:27 +0000 |
|---|---|---|
| committer | Philip <pipcet@gmail.com> | 2015-04-27 16:42:27 +0000 |
| commit | d2dd6fdbfb491c87138eb8d7590fbb28f471ec8d (patch) | |
| tree | b0da2ce92c02d0759c6e89227a0f5e7d4e0953b2 | |
| parent | bd489a48153aeb24ffa5eccb1fa0199f9c7ea994 (diff) | |
| download | tinycc-d2dd6fdbfb491c87138eb8d7590fbb28f471ec8d.tar.gz tinycc-d2dd6fdbfb491c87138eb8d7590fbb28f471ec8d.tar.bz2 | |
fix VLA/continue issue
as reported in
http://lists.nongnu.org/archive/html/tinycc-devel/2015-04/msg00131.html. Note
that this is one of two separate VLA bugs:
A. labels aren't reached by program execution, so the stack pointer is
never saved
B. continue doesn't restore the stack pointer as goto does
This fixes only B. I'm not sure whether the same issue applies to break
as well as continue.
Add a test case, but disable tests #78 and #79 for now as they're not
fully fixed until the issue described in
http://lists.nongnu.org/archive/html/tinycc-devel/2015-04/msg00110.html
is resolved.
| -rw-r--r-- | tccgen.c | 23 | ||||
| -rw-r--r-- | tests/tests2/79_vla_continue.c | 92 | ||||
| -rw-r--r-- | tests/tests2/79_vla_continue.expect | 4 | ||||
| -rw-r--r-- | tests/tests2/Makefile | 5 |
4 files changed, 122 insertions, 2 deletions
@@ -4794,6 +4794,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, } else if (tok == TOK_WHILE) { next(); d = ind; + if (vla_flags & VLA_IN_SCOPE) { + gen_vla_sp_restore(*vla_sp_loc); + vla_flags |= VLA_NEED_NEW_FRAME; + } skip('('); gexpr(); skip(')'); @@ -4958,6 +4962,13 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, /* compute jump */ if (!csym) tcc_error("cannot continue"); + if (vla_flags & VLA_IN_SCOPE) { + /* If VLAs are in use, save the current stack pointer and + reset the stack pointer to what it was at function entry + (label will restore stack pointer in inner scopes) */ + vla_sp_save(); + gen_vla_sp_restore(vla_sp_root_loc); + } *csym = gjmp(*csym); next(); skip(';'); @@ -4980,6 +4991,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, skip(';'); d = ind; c = ind; + if (vla_flags & VLA_IN_SCOPE) { + gen_vla_sp_restore(*vla_sp_loc); + vla_flags |= VLA_NEED_NEW_FRAME; + } a = 0; b = 0; if (tok != ';') { @@ -4990,6 +5005,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, if (tok != ')') { e = gjmp(0); c = ind; + if (vla_flags & VLA_IN_SCOPE) { + gen_vla_sp_restore(*vla_sp_loc); + vla_flags |= VLA_NEED_NEW_FRAME; + } gexpr(); vpop(); gjmp_addr(d); @@ -5008,6 +5027,10 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, a = 0; b = 0; d = ind; + if (vla_flags & VLA_IN_SCOPE) { + gen_vla_sp_restore(*vla_sp_loc); + vla_flags |= VLA_NEED_NEW_FRAME; + } block(&a, &b, case_sym, def_sym, case_reg, 0); skip(TOK_WHILE); skip('('); diff --git a/tests/tests2/79_vla_continue.c b/tests/tests2/79_vla_continue.c new file mode 100644 index 0000000..9c48c1d --- /dev/null +++ b/tests/tests2/79_vla_continue.c @@ -0,0 +1,92 @@ +#include <stdio.h> + +int f(void) +{ + return 5; +} + +void test1() +{ + int count = 10; + void *addr[10]; + for(;count--;) { + int a[f()]; + + addr[count] = a; + + continue; + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test2() +{ + int count = 10; + void *addr[count]; + for(;count--;) { + int a[f()]; + + addr[count] = a; + + continue; + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test3() +{ + int count = 10; + void *addr[count]; + while(count--) { + int a[f()]; + + addr[count] = a; + + continue; + } + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +void test4() +{ + int count = 10; + void *addr[count]; + do { + int a[f()]; + + addr[count] = a; + + continue; + } while(count--); + + if(addr[9] == addr[0]) { + printf("OK\n"); + } else { + printf("NOT OK\n"); + } +} + +int main(void) +{ + test1(); + test2(); + test3(); + test4(); + + return 0; +} diff --git a/tests/tests2/79_vla_continue.expect b/tests/tests2/79_vla_continue.expect new file mode 100644 index 0000000..b462a5a --- /dev/null +++ b/tests/tests2/79_vla_continue.expect @@ -0,0 +1,4 @@ +OK +OK +OK +OK diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 470716b..6148c0b 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -96,8 +96,9 @@ TESTS = \ 74_nocode_wanted.test \ 75_array_in_struct_init.test \ 76_dollars_in_identifiers.test \ - 77_push_pop_macro.test \ - 78_vla_label.test + 77_push_pop_macro.test +# 78_vla_label.test -- currently broken +# 79_vla_continue.test -- currently broken # 34_array_assignment.test -- array assignment is not in C standard |
