# HG changeset patch # User Rob Landley # Date 1178212133 14400 # Node ID 3f48bed56ab48143fd6abbe4d9cfe917d8f72d8b # Parent 91152e505b77af9aad10632745fd9bcd59618460 Fix bug in ||, &&, ! (save registers through jumps), grischka-2005-09-25 case_2 This saves registers through jumps with ||, &&, and !. This patch was originally posted in grischka's 2005-09-25 email as "required fix" case_2 to compile gcc 2.95. It was tweaked by David A. Wheeler to merge the test case into the standard tcc test suite. The original test case only tested || (case 2.1) and ! (case 2.2); Wheeler added the test cases for && (which happens to completely crash the unpatched compiler at compiler time - pretty solid evidence of a problem in the unpatched program!). diff -r 91152e505b77 -r 3f48bed56ab4 tcc.c --- a/tcc.c Thu May 03 12:10:26 2007 -0400 +++ b/tcc.c Thu May 03 13:08:53 2007 -0400 @@ -6486,8 +6486,10 @@ vtop->c.i = !vtop->c.i; else if ((vtop->r & VT_VALMASK) == VT_CMP) vtop->c.i = vtop->c.i ^ 1; - else + else { + save_regs(1); vseti(VT_JMP, gtst(1, 0)); + } break; case '~': next(); @@ -6900,6 +6902,7 @@ expr_or(); if (tok == TOK_LAND) { t = 0; + save_regs(1); for(;;) { t = gtst(1, t); if (tok != TOK_LAND) { @@ -6919,6 +6922,7 @@ expr_land(); if (tok == TOK_LOR) { t = 0; + save_regs(1); for(;;) { t = gtst(0, t); if (tok != TOK_LOR) { diff -r 91152e505b77 -r 3f48bed56ab4 tests/tcctest.c --- a/tests/tcctest.c Thu May 03 12:10:26 2007 -0400 +++ b/tests/tcctest.c Thu May 03 13:08:53 2007 -0400 @@ -646,6 +646,29 @@ isid('g'), isid('T'), isid('(')); + + { + /* Check that tcc saves registers before a conditional jump */ + /* Addresses bug "grischka case_2" */ + struct test_str { int a, b, c; }; + struct test_str t1 = {0,0,0}; + struct test_str t2 = {1,1,1}; + struct test_str *p1 = &t1; + struct test_str *p2 = &t2; + int f = 0; + int g = 0; + + p1->b = f==0 || isid(0); + printf("case_2.1: Expect 0 1 0 -> %d %d %d\n", p1->a, p1->b, p1->c); + p1->c = !f || isid(0); + printf("case_2.2: Expect 0 1 1 -> %d %d %d\n", p1->a, p1->b, p1->c); + + /* This will crash old versions of tcc during compilation: */ + p2->b = (f==1) && isid(0); + printf("case_2.1AND: Expect 0 1 0 -> %d %d %d\n", p2->a, p2->b, p2->c); + p2->b = (!(f==1)) && isid(0); + printf("case_2.2AND: Expect 0 1 0 -> %d %d %d\n", p2->a, p2->b, p2->c); + } } int isid(int c)