Mercurial > hg > tinycc
changeset 535:8591acf8ce9f
Fix gen_opic() to properly &&, ||, and == NULL against symbols. Add test.
author | Rob Landley <rob@landley.net> |
---|---|
date | Mon, 10 Dec 2007 16:11:21 -0600 |
parents | c9e388620dcc |
children | 26d8033259bc |
files | tcc.c tests/tcctest.c |
diffstat | 2 files changed, 29 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/tcc.c Sun Dec 09 15:37:23 2007 -0600 +++ b/tcc.c Mon Dec 10 16:11:21 2007 -0600 @@ -4436,10 +4436,11 @@ /* handle long long constant and various machine independent optimizations */ void gen_opic(int op) { - int c1, c2, t1, t2; + int c1, c2, t1, t2, squash; SValue *v1, *v2; long long l1, l2; + /* Grab the two symbols to operate on, their types, and their values */ v1 = vtop - 1; v2 = vtop; t1 = v1->type.t & VT_BTYPE; @@ -4447,12 +4448,21 @@ l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i; l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i; - /* For forward symbols we can only constify &&, || or == NULL */ - c2 = VT_SYM; - if (op == TOK_EQ && (v1->c.ll == 0 || v2->c.ll == 0)) c2 = 0; - if (op == TOK_LAND || op == TOK_LOR) c2 = 0; - c1 = (v1->r & (VT_VALMASK | VT_LVAL | c2)) == VT_CONST; - c2 = (v2->r & (VT_VALMASK | VT_LVAL | c2)) == VT_CONST; + /* For forward symbols we can only constify &&, || or == NULL. If we + do so, we need to remove VT_SYM from the resulting type. */ + squash = VT_SYM; + if (op == TOK_LAND || op == TOK_LOR || + (op == TOK_EQ && (v1->c.ll == 0 || v2->c.ll == 0))) + { + squash = 0; + if (v1->r & VT_SYM) l1=1; + if (v2->r & VT_SYM) l2=1; + } else c2 = VT_SYM; + + /* Are both arguments constant? */ + + c1 = (v1->r & (VT_VALMASK | VT_LVAL | squash)) == VT_CONST; + c2 = (v2->r & (VT_VALMASK | VT_LVAL | squash)) == VT_CONST; if (c1 && c2) { switch(op) { @@ -4502,6 +4512,8 @@ goto general_case; } v1->c.ll = l1; + // If v1 was a symbol, the resulting type is an int. + if (!squash) v1->r &= ~VT_SYM; vtop--; } else { /* if commutative ops, put c2 as constant */ @@ -4548,7 +4560,7 @@ vtop--; vtop->c.ll += l2; } else { - general_case: +general_case: /* call low level op generator */ if (cur_text_section) { if (t1 == VT_LLONG|| t2 == VT_LLONG) gen_opl(op);
--- a/tests/tcctest.c Sun Dec 09 15:37:23 2007 -0600 +++ b/tests/tcctest.c Mon Dec 10 16:11:21 2007 -0600 @@ -714,6 +714,13 @@ printf("res= %d %d\n", a, b); } +int constant_i = "blah" && 0; +int constant_j = "blah" || 0; +int constant_k = vpop && 0; +int constant_l = "blah" && 1; +int constant_m = "blah" || 1; +int constant_n = 0 || vpop; + void constant_expr_test() { int a; @@ -722,6 +729,8 @@ printf("%d\n", a * 16); printf("%d\n", a * 1); printf("%d\n", a + 0); + printf("%d %d %d %d %d %d\n",constant_i,constant_j,constant_k,constant_l, + constant_m,constant_n); } int tab4[10];