[Top][All Lists]
[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;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Tinycc-devel] Patch for tcc typecast sign extension bug,
David Heine <=