mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-03 04:30:08 +08:00
059aea5d35
I ran into an issue playing with tinycc, and tracked it down to a rather weird assumption in the function calling code. This breaks only when varargs and float/double arguments are combined, I think, and only when calling GCC-generated (or non-TinyCC, at least) code. The problem is we sometimes generate code like this: 804a468: 4c 89 d9 mov %r11,%rcx 804a46b: b8 01 00 00 00 mov $0x1,%eax 804a470: 48 8b 45 c0 mov -0x40(%rbp),%rax 804a474: 4c 8b 18 mov (%rax),%r11 804a477: 41 ff d3 callq *%r11 for a function call. Note how $eax is first set to the correct value, then clobbered when we try to load the function pointer into R11. With the patch, the code generated is: 804a468: 4c 89 d9 mov %r11,%rcx 804a46b: b8 01 00 00 00 mov $0x1,%eax 804a470: 4c 8b 5d c0 mov -0x40(%rbp),%r11 804a474: 4d 8b 1b mov (%r11),%r11 804a477: 41 ff d3 callq *%r11 which is correct. This becomes an issue when get_reg(RC_INT) is modified not always to return %rax after a save_regs(0), because then another register (%ecx, say) is clobbered, and the function passed an invalid argument. A rather convoluted test case that generates the above code is included. Please note that the test will not cause a failure because TinyCC code ignores the %rax argument, but it will cause incorrect behavior when combined with GCC code, which might wrongly fail to save XMM registers and cause data corruption. |
||
---|---|---|
.. | ||
tests2 | ||
abitest.c | ||
asmtest.S | ||
boundtest.c | ||
CMakeLists.txt | ||
gcctestsuite.sh | ||
libtcc_test.c | ||
Makefile | ||
tcctest.c | ||
tcctest.py | ||
vla_test.c |