mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-26 03:50: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;
|
||||
|
||||
/* 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];
|
||||
vtop[0] = vtop[-1];
|
||||
vtop[-1] = tmp;
|
||||
|
@ -86,6 +86,7 @@ void asm_test(void);
|
||||
void builtin_test(void);
|
||||
void weak_test(void);
|
||||
void global_data_test(void);
|
||||
void cmp_comparison_test(void);
|
||||
|
||||
int fib(int n);
|
||||
void num(int n);
|
||||
@ -592,6 +593,7 @@ int main(int argc, char **argv)
|
||||
builtin_test();
|
||||
weak_test();
|
||||
global_data_test();
|
||||
cmp_comparison_test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2562,3 +2564,31 @@ void global_data_test (void)
|
||||
global_data_callit (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