aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Matz <matz@suse.de>2016-12-15 17:41:16 +0100
committerMichael Matz <matz@suse.de>2016-12-15 17:53:09 +0100
commitcd9514abc4f4d7d90acce108b98ea2af58a1b80a (patch)
tree6e401550a4eddcc55a9db4b685e6a4968550a661
parent3980e07fe52457579364a098c2e8d2ecc06fa130 (diff)
downloadtinycc-cd9514abc4f4d7d90acce108b98ea2af58a1b80a.tar.gz
tinycc-cd9514abc4f4d7d90acce108b98ea2af58a1b80a.tar.bz2
i386: Fix various testsuite issues
on 32bit long long support was sometimes broken. This fixes code-gen for long long values in switches, disables a x86-64 specific testcase and avoid an undefined shift amount. It comments out a bitfield test involving long long bitfields > 32 bit; with GCC layout they can straddle multiple words and code generation isn't prepared for this.
-rw-r--r--i386-gen.c29
-rw-r--r--tests/tcctest.c24
-rw-r--r--x86_64-gen.c29
3 files changed, 64 insertions, 18 deletions
diff --git a/i386-gen.c b/i386-gen.c
index cd4cebd..a8c6f4a 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -694,14 +694,27 @@ ST_FUNC void gjmp_addr(int a)
ST_FUNC void gtst_addr(int inv, int a)
{
- inv ^= (vtop--)->c.i;
- a -= ind + 2;
- if (a == (char)a) {
- g(inv - 32);
- g(a);
- } else {
- g(0x0f);
- oad(inv - 16, a - 4);
+ int v = vtop->r & VT_VALMASK;
+ if (v == VT_CMP) {
+ inv ^= (vtop--)->c.i;
+ a -= ind + 2;
+ if (a == (char)a) {
+ g(inv - 32);
+ g(a);
+ } else {
+ g(0x0f);
+ oad(inv - 16, a - 4);
+ }
+ } else if ((v & ~1) == VT_JMP) {
+ if ((v & 1) != inv) {
+ gjmp_addr(a);
+ gsym(vtop->c.i);
+ } else {
+ gsym(vtop->c.i);
+ o(0x05eb);
+ gjmp_addr(a);
+ }
+ vtop--;
}
}
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 6c414f7..0f71482 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -610,7 +610,7 @@ struct S_enum {
enum ELong {
/* This is either 0 on L32 machines, or a large number
on L64 machines. We should be able to store this. */
- EL_large = (unsigned long)0xf000 << 32,
+ EL_large = ((unsigned long)0xf000 << 31) << 1,
};
enum { BIASU = -1U<<31 };
@@ -2028,6 +2028,11 @@ void bitfield_test(void)
else
printf("st1.f2 != -1\n");
+#ifndef __i386__
+ /* on i386 we don't correctly support long long bit-fields.
+ The bitfields can straddle long long boundaries (at least with
+ GCC bitfield layout) and code generation isn't prepared for this
+ (would have to work with two words in that case). */
/* bit sizes below must be bigger than 32 since GCC doesn't allow
long-long bitfields whose size is not bigger than int */
struct sbf2 {
@@ -2042,6 +2047,19 @@ void bitfield_test(void)
st2.f3 = a;
st2.f2++;
printf("%lld %lld %lld\n", st2.f1, st2.f2, st2.f3);
+#endif
+#if 0
+ Disabled for now until further clarification re GCC compatibility
+ struct sbf3 {
+ int f1 : 7;
+ int f2 : 1;
+ char f3;
+ int f4 : 8;
+ int f5 : 1;
+ int f6 : 16;
+ } st3;
+ printf("sizeof(st3) = %d\n", sizeof(st3));
+#endif
}
#ifdef __x86_64__
@@ -3100,7 +3118,7 @@ void other_constraints_test(void)
{
unsigned long ret;
int var;
- __asm__ volatile ("movq %P1,%0" : "=r" (ret) : "p" (&var));
+ __asm__ volatile ("mov %P1,%0" : "=r" (ret) : "p" (&var));
printf ("oc1: %d\n", ret == (unsigned long)&var);
}
@@ -3182,6 +3200,7 @@ void test_high_clobbers(void)
static long cpu_number;
void trace_console(long len, long len2)
{
+#ifdef __x86_64__
/* This generated invalid code when the emission of the switch
table isn't disabled. The asms are necessary to show the bug,
normal statements don't work (they need to generate some code
@@ -3228,6 +3247,7 @@ void trace_console(long len, long len2)
{
printf("huh?\n");
}
+#endif
}
void asm_test(void)
{
diff --git a/x86_64-gen.c b/x86_64-gen.c
index b765806..86e097e 100644
--- a/x86_64-gen.c
+++ b/x86_64-gen.c
@@ -1721,14 +1721,27 @@ void gjmp_addr(int a)
ST_FUNC void gtst_addr(int inv, int a)
{
- inv ^= (vtop--)->c.i;
- a -= ind + 2;
- if (a == (char)a) {
- g(inv - 32);
- g(a);
- } else {
- g(0x0f);
- oad(inv - 16, a - 4);
+ int v = vtop->r & VT_VALMASK;
+ if (v == VT_CMP) {
+ inv ^= (vtop--)->c.i;
+ a -= ind + 2;
+ if (a == (char)a) {
+ g(inv - 32);
+ g(a);
+ } else {
+ g(0x0f);
+ oad(inv - 16, a - 4);
+ }
+ } else if ((v & ~1) == VT_JMP) {
+ if ((v & 1) != inv) {
+ gjmp_addr(a);
+ gsym(vtop->c.i);
+ } else {
+ gsym(vtop->c.i);
+ o(0x05eb);
+ gjmp_addr(a);
+ }
+ vtop--;
}
}