diff options
| author | Michael Matz <matz@suse.de> | 2016-12-20 04:49:22 +0100 |
|---|---|---|
| committer | Michael Matz <matz@suse.de> | 2016-12-20 04:58:34 +0100 |
| commit | 42e2a67f23448dc1ff6a23da650176ebad6e1681 (patch) | |
| tree | 0f9438aa59ea42235156eee0a69bb0db9ac29745 /tests | |
| parent | 559ee1e940c22a49ac8a39f6053917533e71243a (diff) | |
| download | tinycc-42e2a67f23448dc1ff6a23da650176ebad6e1681.tar.gz tinycc-42e2a67f23448dc1ff6a23da650176ebad6e1681.tar.bz2 | |
Fix some code suppression fallout
Some more subtle issues with code suppression:
- outputting asms but not their operand setup is broken
- but global asms must always be output
- statement expressions are transparent to code suppression
- vtop can't be transformed from VT_CMP/VT_JMP when nocode_wanted
Also remove .exe files from tests2 if they don't fail.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/tcctest.c | 32 | ||||
| -rw-r--r-- | tests/tests2/85-asm-outside-function.c | 2 | ||||
| -rw-r--r-- | tests/tests2/85-asm-outside-function.expect | 1 | ||||
| -rw-r--r-- | tests/tests2/88_codeopt.c | 68 | ||||
| -rw-r--r-- | tests/tests2/88_codeopt.expect | 2 | ||||
| -rw-r--r-- | tests/tests2/Makefile | 2 |
6 files changed, 106 insertions, 1 deletions
diff --git a/tests/tcctest.c b/tests/tcctest.c index 2789255..6d5c4b4 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -1404,6 +1404,15 @@ void optimize_out(void) if (defined_function() && 0) refer_to_undefined(); + if (0) { + (void)sizeof( ({ + do { } while (0); + 0; + }) ); + undefined_function(); + } + + /* Leave the "if(1)return; printf()" in this order and last in the function */ if (1) return; printf ("oor:%d\n", undefined_function()); @@ -3251,6 +3260,28 @@ void trace_console(long len, long len2) } #endif } + +void test_asm_dead_code(void) +{ + long rdi; + /* Try to make sure that xdi contains a zero, and hence will + lead to a segfault if the next asm is evaluated without + arguments being set up. */ + asm volatile ("" : "=D" (rdi) : "0" (0)); + (void)sizeof (({ + int var; + /* This shouldn't trigger a segfault, either the argument + registers need to be set up and the asm emitted despite + this being in an unevaluated context, or both the argument + setup _and_ the asm emission need to be suppressed. The latter + is better. Disabling asm code gen when suppression is on + also fixes the above trace_console bug, but that came earlier + than asm suppression. */ + asm volatile ("movl $0,(%0)" : : "D" (&var) : "memory"); + var; + })); +} + void asm_test(void) { char buf[128]; @@ -3334,6 +3365,7 @@ void asm_test(void) printf ("regvar=%x\n", regvar); test_high_clobbers(); trace_console(8, 8); + test_asm_dead_code(); return; label1: goto label2; diff --git a/tests/tests2/85-asm-outside-function.c b/tests/tests2/85-asm-outside-function.c index 0aa7e33..dc5639a 100644 --- a/tests/tests2/85-asm-outside-function.c +++ b/tests/tests2/85-asm-outside-function.c @@ -1,7 +1,9 @@ +extern int printf (const char *, ...); extern void vide(void); __asm__("vide: ret"); int main() { vide(); + printf ("okay\n"); return 0; } diff --git a/tests/tests2/85-asm-outside-function.expect b/tests/tests2/85-asm-outside-function.expect index e69de29..dcf02b2 100644 --- a/tests/tests2/85-asm-outside-function.expect +++ b/tests/tests2/85-asm-outside-function.expect @@ -0,0 +1 @@ +okay diff --git a/tests/tests2/88_codeopt.c b/tests/tests2/88_codeopt.c new file mode 100644 index 0000000..647626f --- /dev/null +++ b/tests/tests2/88_codeopt.c @@ -0,0 +1,68 @@ +/* Check some way in where code suppression caused various + miscompilations. */ +extern int printf (const char *, ...); +typedef unsigned long size_t; + +size_t _brk_start, _brk_end; +void * extend_brk(size_t size, size_t align) +{ + size_t mask = align - 1; + void *ret = 0; + + do { + if (__builtin_expect(!!(_brk_start == 0), 0)) + do { + printf("wrong1\n"); + } while (0); + } while (0); + _brk_end = (_brk_end + mask) & ~mask; + ret = (void *)_brk_end; + _brk_end += size; + + return ret; +} + +static void get_args (int a, int b) +{ + if (a != 1) + printf("wrong2\n"); + else + printf("okay\n"); +} + +void bla(void) +{ + int __ret = 42; + ({ + if (__builtin_expect(!!(0), 0)) { + if (__builtin_expect(!!__ret, 0)) + printf("wrong3\n"); + int x = !!(__ret); + } + __ret; + }); + get_args(!!__ret, sizeof(__ret)); +} + +_Bool chk(unsigned long addr, unsigned long limit, unsigned long size) +{ + _Bool ret; + /* This just needs to compile, no runtime test. (And it doesn't compile + only with certain internal checking added that's not committed). */ + if (0) + ret = 0 != (!!(addr > limit - size)); +} + +int main() +{ + void *r; + _brk_start = 1024; + _brk_end = 1024; + r = extend_brk (4096, 16); + if (!r) + printf("wrong4\n"); + else + printf("okay\n"); + bla(); + return 0; +} diff --git a/tests/tests2/88_codeopt.expect b/tests/tests2/88_codeopt.expect new file mode 100644 index 0000000..439edfd --- /dev/null +++ b/tests/tests2/88_codeopt.expect @@ -0,0 +1,2 @@ +okay +okay diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index ababb43..b52b54a 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -59,7 +59,7 @@ all test: $(filter-out $(SKIP),$(TESTS)) $(TCC) $< -o ./$*.exe $(FILTER) 2>&1 && \ ./$*.exe $(ARGS) >$*.output 2>&1 || true; \ fi - @diff -Nbu $(SRC)/$*.expect $*.output && rm -f $*.output + @diff -Nbu $(SRC)/$*.expect $*.output && rm -f $*.output $*.exe # automatically generate .expect files with gcc: %.expect : %.c |
