Mercurial > hg > qcc
changeset 422:dc756f766bfe
From Dave Dodge: When a long long value is used as test expression, for
example as the controlling expression for an "if" or "while" statement, the tcc
i386 backend does not actually test the upper 32 bits.
The problem is that a statement such as "if(x)" ends up in the gtst()
function in i386-gen.c, which fetches the x value and then emits a
test instruction that assumes it's a 32-bit int. A simple, but
probably not optimal, fix is to treat a long long test the same way as
a floating point test, by inserting an explicit comparison != 0 to
produce a testable 32-bit integer.
author | Rob Landley <rob@landley.net> |
---|---|
date | Sun, 25 Feb 2007 22:43:07 -0500 |
parents | ffd17713a155 |
children | fb849852437e |
files | i386-gen.c tcc.c tests/tcctest.c |
diffstat | 3 files changed, 17 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/i386-gen.c Sun Feb 25 22:18:49 2007 -0500 +++ b/i386-gen.c Sun Feb 25 22:43:07 2007 -0500 @@ -600,7 +600,8 @@ gsym(vtop->c.i); } } else { - if (is_float(vtop->type.t)) { + if (is_float(vtop->type.t) || is_llong(vtop->type.t)) { + /* compare != 0 to get a 32-bit int for testing */ vpushi(0); gen_op(TOK_NE); }
--- a/tcc.c Sun Feb 25 22:18:49 2007 -0500 +++ b/tcc.c Sun Feb 25 22:43:07 2007 -0500 @@ -910,6 +910,14 @@ return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT; } +/* true if long long type */ +static inline int is_llong(int t) +{ + int bt; + bt = t & VT_BTYPE; + return bt == VT_LLONG; +} + #ifdef TCC_TARGET_I386 #include "i386-gen.c" #endif
--- a/tests/tcctest.c Sun Feb 25 22:18:49 2007 -0500 +++ b/tests/tcctest.c Sun Feb 25 22:43:07 2007 -0500 @@ -1587,6 +1587,7 @@ void longlong_test(void) { long long a, b, c; + unsigned long long ull; int ia; unsigned int ua; printf("longlong_test:\n"); @@ -1638,6 +1639,12 @@ p[0]++; printf("%lld\n", *p); } + + /* Make sure long long comparison tests upper 32 bits */ + ull = 0xffffffff00000000ULL; + printf("ull=%llx\n",ull); + printf("ull!=0 ", (ull != 0) ? "true" : "false"); + printf("ull ", ull ? "true" : "false"); } void vprintf1(const char *fmt, ...)