20060503 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. This program demonstrates the bug: #include int main(void) { unsigned long long x = 0xffffffff00000000ULL; printf("x=%llx\n",x); if(x != 0) printf("x!=0 true\n"); else printf("x!=0 false\n"); if(x) printf("x true\n"); else printf("x false\n"); printf("x!=0 %s\n",(x != 0) ? "true" : "false"); printf("x %s\n",x ? "true" : "false"); return 0; } 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. Index: tcc-0.9.23/i386-gen.c =================================================================== --- tcc-0.9.23.orig/i386-gen.c 2005-06-17 18:09:15.000000000 -0400 +++ tcc-0.9.23/i386-gen.c 2006-05-03 20:39:31.000000000 -0400 @@ -585,7 +585,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); } Index: tcc-0.9.23/tcc.c =================================================================== --- tcc-0.9.23.orig/tcc.c 2005-06-17 18:09:15.000000000 -0400 +++ tcc-0.9.23/tcc.c 2006-05-03 20:37:54.000000000 -0400 @@ -883,6 +883,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