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, ...)