|
From: | kwisatz haderach |
Subject: | [Tinycc-devel] Libtcc bug ? |
Date: | Tue, 1 Jan 2008 21:10:47 +0000 |
I am compiling TCC on Windows XP using Visual Studio 8. I had to make a few changes to the original code but it works well now. I am mainly using Libtcc, so I compile a string and use the function from code compile using VC8. I think I found a problem with the FPU registers are managed by TCC. Here is the code: #define DF(n) double s ## n = n DF(1); DF(2); DF(3); DF(4); DF(5); DF(6); DF(7); DF(8); double heavy() { double a1 = s1 + s2; double a2 = (a1 - s3) * a1; double a3 = a2 + s4; double a4 = a2 + s4 + s5; double a5 = a2 + s4 + s5 + s6; double a6 = a2 + s4 + s5 + s6 + s7; double a7 = a2 + s4 + s5 + s6 + s7 + s8; double a8 = a2 + s4 + s5 + s6 + s7 + s8 + a7; return a1+a2+a3+a4+a5+a6+a7+a8; } void main() { const char* program = "void dummy()" "{" " double f = 1.0;" " double g = f + 3.0;" "}"; double res; void (*dummy)(); unsigned long addr; TCCState *s; s = tcc_new(); tcc_compile_string(s, program); tcc_relocate(s); tcc_get_symbol(s, &addr, "dummy"); dummy = (void (*)())((void*)addr); // call to TCC compiled function (*dummy)(); // call to VC8 compiled function res = heavy(); } The problem comes from the code compiled by TCC. Here is the assembly: void dummy() { double f = 1.0; double g = f + 3.0; } 00424C18 push ebp 00424C19 mov ebp,esp 00424C1B sub esp,10h 00424C21 nop 00424C22 fld qword ptr ds:[424500h] <---------- 1st register used 00424C28 fst qword ptr [ebp-8] 00424C2B fstp st(1) <---------- still one register used 00424C2D fld qword ptr ds:[424508h] <---------- 2 registers used 00424C33 fadd qword ptr [ebp-8] 00424C36 fst qword ptr [ebp-10h] 00424C39 fstp st(1) <---------- 1 register used 00424C3B leave 00424C3C ret The stack of floating point registers is empty at the begining of the function. At the end, because the fstp st(1) leaves one register in use, the stack is not empty. The problem comes from the fact that the compiler using Libtcc, here VC8 but I am sure gcc works the same way, expects a function with this signature (dummy) to leave the FPU in the same state as before the function call, i.e. no registers should be in use. Therefore if you then manage to create a function that will use all the 8 registers of the stack ( VC8 in release /O2 compiles the heavy function so it uses 8 registers ) you will get a stack overflow and the variable res won't be 143 as expected because it is trying to use 9 registers. If you re-run the same program after commenting the call to "dummy" out, it works as expected. If you only use TCC as a standalone compiler, it does not matter. But as an API, it won't work as soon as you are using functions making an heavy use of the FPU. As anybody ever encountered the same issue ? Did anyone think about a fix ? Thanks for your help. Sounds like? How many syllables? Guess and win prizes with Search Charades! |
[Prev in Thread] | Current Thread | [Next in Thread] |