Mercurial > hg > tinycc
changeset 487:2768f7c24156
Handle long long constants (redo internals of gen_opic() as long long).
author | Rob Landley <rob@landley.net> |
---|---|
date | Tue, 02 Oct 2007 03:38:20 -0500 |
parents | c8a874736ed2 |
children | 2766e2ad73be |
files | tcc.c |
diffstat | 1 files changed, 58 insertions(+), 53 deletions(-) [+] |
line wrap: on
line diff
--- a/tcc.c Thu Sep 27 19:29:20 2007 -0500 +++ b/tcc.c Tue Oct 02 03:38:20 2007 -0500 @@ -4477,32 +4477,35 @@ } } -/* handle integer constant optimizations and various machine - independent opt */ +/* handle long long constant and various machine independent optimizations */ void gen_opic(int op) { - int fc, c1, c2, n; + int c1, c2, t1, t2; SValue *v1, *v2; + long long l1, l2; v1 = vtop - 1; v2 = vtop; - - /* For forward symbols we can only &&, || or == NULL */ - fc = VT_SYM; - if (op == TOK_EQ && (v1->c.i == 0 || v2->c.i == 0)) fc = 0; - if (op == TOK_LAND || op == TOK_LOR) fc = 0; - c1 = (v1->r & (VT_VALMASK | VT_LVAL | fc)) == VT_CONST; - c2 = (v2->r & (VT_VALMASK | VT_LVAL | fc)) == VT_CONST; + t1 = v1->type.t & VT_BTYPE; + t2 = v2->type.t & VT_BTYPE; + 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; if (c1 && c2) { - fc = v2->c.i; switch(op) { - case '+': v1->c.i += fc; break; - case '-': v1->c.i -= fc; break; - case '&': v1->c.i &= fc; break; - case '^': v1->c.i ^= fc; break; - case '|': v1->c.i |= fc; break; - case '*': v1->c.i *= fc; break; + case '+': l1 += l2; break; + case '-': l1 -= l2; break; + case '&': l1 &= l2; break; + case '^': l1 ^= l2; break; + case '|': l1 |= l2; break; + case '*': l1 *= l2; break; case TOK_PDIV: case '/': @@ -4510,38 +4513,39 @@ case TOK_UDIV: case TOK_UMOD: /* if division by zero, generate explicit division */ - if (fc == 0) { + if (l2 == 0) { if (const_wanted) error("division by zero in constant"); goto general_case; } switch(op) { - default: v1->c.i /= fc; break; - case '%': v1->c.i %= fc; break; - case TOK_UDIV: v1->c.i = (unsigned)v1->c.i / fc; break; - case TOK_UMOD: v1->c.i = (unsigned)v1->c.i % fc; break; + default: l1 /= l2; break; + case '%': l1 %= l2; break; + case TOK_UDIV: l1 = (unsigned long long)l1 / l2; break; + case TOK_UMOD: l1 = (unsigned long long)l1 % l2; break; } break; - case TOK_SHL: v1->c.i <<= fc; break; - case TOK_SHR: v1->c.i = (unsigned)v1->c.i >> fc; break; - case TOK_SAR: v1->c.i >>= fc; break; + case TOK_SHL: l1 <<= l2; break; + case TOK_SHR: l1 = (unsigned long long)l1 >> l2; break; + case TOK_SAR: l1 >>= l2; break; /* tests */ - case TOK_ULT: v1->c.i = (unsigned)v1->c.i < (unsigned)fc; break; - case TOK_UGE: v1->c.i = (unsigned)v1->c.i >= (unsigned)fc; break; - case TOK_EQ: v1->c.i = v1->c.i == fc; break; - case TOK_NE: v1->c.i = v1->c.i != fc; break; - case TOK_ULE: v1->c.i = (unsigned)v1->c.i <= (unsigned)fc; break; - case TOK_UGT: v1->c.i = (unsigned)v1->c.i > (unsigned)fc; break; - case TOK_LT: v1->c.i = v1->c.i < fc; break; - case TOK_GE: v1->c.i = v1->c.i >= fc; break; - case TOK_LE: v1->c.i = v1->c.i <= fc; break; - case TOK_GT: v1->c.i = v1->c.i > fc; break; + case TOK_ULT: l1 = (unsigned long long)l1 < (unsigned long long)l2; break; + case TOK_UGE: l1 = (unsigned long long)l1 >= (unsigned long long)l2; break; + case TOK_EQ: l1 = l1 == l2; break; + case TOK_NE: l1 = l1 != l2; break; + case TOK_ULE: l1 = (unsigned long long)l1 <= (unsigned long long)l2; break; + case TOK_UGT: l1 = (unsigned long long)l1 > (unsigned long long)l2; break; + case TOK_LT: l1 = l1 < l2; break; + case TOK_GE: l1 = l1 >= l2; break; + case TOK_LE: l1 = l1 <= l2; break; + case TOK_GT: l1 = l1 > l2; break; /* logical */ - case TOK_LAND: v1->c.i = v1->c.i && fc; break; - case TOK_LOR: v1->c.i = v1->c.i || fc; break; + case TOK_LAND: l1 = l1 && l2; break; + case TOK_LOR: l1 = l1 || l2; break; default: goto general_case; } + v1->c.ll = l1; vtop--; } else { /* if commutative ops, put c2 as constant */ @@ -4549,27 +4553,28 @@ op == '|' || op == '*')) { vswap(); swap(&c1, &c2); - } - fc = vtop->c.i; + l2 = l1; + } + /* Filter out NOP operations like x*1, x-0, x&-1... */ if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV || op == TOK_PDIV) && - fc == 1) || + l2 == 1) || ((op == '+' || op == '-' || op == '|' || op == '^' || op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) && - fc == 0) || + l2 == 0) || (op == '&' && - fc == -1))) { + l2 == -1))) { /* nothing to do */ vtop--; } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) { /* try to use shifts instead of muls or divs */ - if (fc > 0 && (fc & (fc - 1)) == 0) { - n = -1; - while (fc) { - fc >>= 1; + if (l2 > 0 && (l2 & (l2 - 1)) == 0) { + int n = -1; + while (l2) { + l2 >>= 1; n++; } - vtop->c.i = n; + vtop->c.ll = n; if (op == '*') op = TOK_SHL; else if (op == TOK_PDIV) @@ -4583,14 +4588,16 @@ (VT_CONST | VT_SYM)) { /* symbol + constant case */ if (op == '-') - fc = -fc; + l2 = -l2; vtop--; - vtop->c.i += fc; + vtop->c.ll += l2; } else { general_case: /* call low level op generator */ - if (cur_text_section) gen_opi(op); - else vtop--; + if (cur_text_section) { + if (t1 == VT_LLONG|| t2 == VT_LLONG) gen_opl(op); + else gen_opi(op); + } else vtop--; } } } @@ -4848,8 +4855,6 @@ gen_cast(&type1); if (is_float(t)) gen_opif(op); - else if ((t & VT_BTYPE) == VT_LLONG) - gen_opl(op); else gen_opic(op); if (op >= TOK_ULT && op <= TOK_GT) {