tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] TCC bug wilt long long


From: Dave Dodge
Subject: Re: [Tinycc-devel] TCC bug wilt long long
Date: Wed, 3 May 2006 20:55:00 -0400
User-agent: Mutt/1.4.2i

On Tue, May 02, 2006 at 11:10:28PM +0200, Benoit DUPONT-DE-DINECHIN wrote:
> Reproduce using the C file supplied:
> 
>   gcc BugTCC.c  && ./a.out > OK
>   tcc BugTCC.c  && ./a.out > KO
>   diff OK KO

I think the following patch will fix it:

----------------------------------------------------------------------
20060503 Dave Dodge <address@hidden>

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 <stdio.h>
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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]