tinycc-devel
[Top][All Lists]
Advanced

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

[Tinycc-devel] Patch for tcc typecast sign extension bug


From: David Heine
Subject: [Tinycc-devel] Patch for tcc typecast sign extension bug
Date: Wed, 26 Jan 2005 09:53:33 -0800
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20040913

I ran into a bug with tcc-0.9.22 related to incorrect sign extension in typecasts. I ran into it on the x86 target, but it probably exists for all targets. Here is a testcase that demonstrates the problem:

> cat signext.c
int scast(unsigned v) {
   return (short)v;
}
int ccast(unsigned v) {
   return (signed char)v;
}
int main() {
  if (scast(0xf000) != 0xfffff000) {
    printf("test1: FAIL\n");
  } else {
    printf("test1: PASS\n");
  }
  if (ccast(0xf0f0) != 0xfffffff0) {
    printf("test2: FAIL\n");
  } else {
    printf("test2: PASS\n");
  }
}
> ./tcc -run signext.c
test1: FAIL
test2: FAIL


I tracked this down to the function force_charshort_cast(). When the type on the top of the stack is unsigned but it is converting to a signed quantity, it generates
   16(or 24) SHL
   16(or 24) SAR
Because the original value is unsigned, the SHL produces an unsigned value. The SAR on the unsigned value is then incorrectly converted to an SHR in genop(). My proposed patch forces the result of the SHL to be a signed type when casting to a signed value.

I've also included 2 new tests in tcctest.c.
diff -p tcc-0.9.22-orig/tcc.c tcc-0.9.22/tcc.c
*** tcc-0.9.22-orig/tcc.c       Mon Nov  8 12:47:16 2004
--- tcc-0.9.22/tcc.c    Tue Jan 25 14:25:33 2005
*************** void force_charshort_cast(int t)
*** 5613,5618 ****
--- 5613,5623 ----
          bits = 32 - bits;
          vpushi(bits);
          gen_op(TOK_SHL);
+       /* result must be signed or the SAR is converted to an SHL
+          This was not the case when "t" was a signed short
+          and the last value on the stack was an unsigned int
+       */
+       vtop->type.t &= (~VT_UNSIGNED);
          vpushi(bits);
          gen_op(TOK_SAR);
      }
diff -p tcc-0.9.22-orig/tcctest.c tcc-0.9.22/tcctest.c
*** tcc-0.9.22-orig/tcctest.c   Mon Nov  8 12:47:16 2004
--- tcc-0.9.22/tcctest.c        Tue Jan 25 14:17:28 2005
*************** void cast_test()
*** 1058,1063 ****
--- 1058,1065 ----
      int a;
      char c;
      char tab[10];
+     unsigned b,d;
+     short s;
  
      printf("cast_test:\n");
      a = 0xfffff;
*************** void cast_test()
*** 1081,1086 ****
--- 1083,1096 ----
      
      printf("sizeof(c) = %d, sizeof((int)c) = %d\n", sizeof(c), 
sizeof((int)c));
  
+     /* test cast from unsigned to signed short to int */
+     b = 0xf000;
+     d = (short)b;
+     printf("((unsigned)(short)0x%08x) = 0x%08x\n", b, d);
+     b = 0xf0f0;
+     d = (char)b;
+     printf("((unsigned)(char)0x%08x) = 0x%08x\n", b, d);
+ 
      /* test implicit int casting for array accesses */
      c = 0;
      tab[1] = 2;

reply via email to

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