mirror of
https://github.com/mirror/tinycc.git
synced 2025-01-13 05:10:07 +08:00
Fix comparing comparisons
Sometimes the result of a comparison is not directly used in a jump, but in arithmetic or further comparisons. If those further things do a vswap() with the VT_CMP as current top, and then generate instructions for the new top, this most probably destroys the flags (e.g. if it's a bitfield load like in the example). vswap() must do the same like vsetc() and not allow VT_CMP vtops to be moved down.
This commit is contained in:
parent
718fd591fa
commit
9ca9c82ff8
8
tccgen.c
8
tccgen.c
@ -452,6 +452,14 @@ ST_FUNC void vswap(void)
|
|||||||
{
|
{
|
||||||
SValue tmp;
|
SValue tmp;
|
||||||
|
|
||||||
|
/* cannot let cpu flags if other instruction are generated. Also
|
||||||
|
avoid leaving VT_JMP anywhere except on the top of the stack
|
||||||
|
because it would complicate the code generator. */
|
||||||
|
if (vtop >= vstack) {
|
||||||
|
int v = vtop->r & VT_VALMASK;
|
||||||
|
if (v == VT_CMP || (v & ~1) == VT_JMP)
|
||||||
|
gv(RC_INT);
|
||||||
|
}
|
||||||
tmp = vtop[0];
|
tmp = vtop[0];
|
||||||
vtop[0] = vtop[-1];
|
vtop[0] = vtop[-1];
|
||||||
vtop[-1] = tmp;
|
vtop[-1] = tmp;
|
||||||
|
@ -86,6 +86,7 @@ void asm_test(void);
|
|||||||
void builtin_test(void);
|
void builtin_test(void);
|
||||||
void weak_test(void);
|
void weak_test(void);
|
||||||
void global_data_test(void);
|
void global_data_test(void);
|
||||||
|
void cmp_comparison_test(void);
|
||||||
|
|
||||||
int fib(int n);
|
int fib(int n);
|
||||||
void num(int n);
|
void num(int n);
|
||||||
@ -592,6 +593,7 @@ int main(int argc, char **argv)
|
|||||||
builtin_test();
|
builtin_test();
|
||||||
weak_test();
|
weak_test();
|
||||||
global_data_test();
|
global_data_test();
|
||||||
|
cmp_comparison_test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2562,3 +2564,31 @@ void global_data_test (void)
|
|||||||
global_data_callit (0);
|
global_data_callit (0);
|
||||||
printf ("%d\n", global_data.a[0]);
|
printf ("%d\n", global_data.a[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct cmpcmpS
|
||||||
|
{
|
||||||
|
unsigned char fill : 3;
|
||||||
|
unsigned char b1 : 1;
|
||||||
|
unsigned char b2 : 1;
|
||||||
|
unsigned char fill2 : 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
int glob1, glob2, glob3;
|
||||||
|
|
||||||
|
void compare_comparisons (struct cmpcmpS *s)
|
||||||
|
{
|
||||||
|
if (s->b1 != (glob1 == glob2)
|
||||||
|
|| (s->b2 != (glob1 == glob3)))
|
||||||
|
printf ("comparing comparisons broken\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void cmp_comparison_test(void)
|
||||||
|
{
|
||||||
|
struct cmpcmpS s;
|
||||||
|
s.b1 = 1;
|
||||||
|
glob1 = 42; glob2 = 42;
|
||||||
|
s.b2 = 0;
|
||||||
|
glob3 = 43;
|
||||||
|
compare_comparisons (&s);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user