History

tccgen.c: Avoid undefined behaviour in constant propagation.

Edmund Grimley Evans committed 11 years ago

Commit 5d496b11 parent 569fba61 file · +38 −31Browse files

Unified · Split

tccgen.c+38−31
@@ -1394,33 +1394,38 @@ static void gen_opl(int op) · 1393 unmodified lines
13941394 }
13951395 #endif
13961396
1397+static uint64_t gen_opic_sdiv(uint64_t a, uint64_t b)
1398+{
1399+ uint64_t x = (a >> 63 ? -a : a) / (b >> 63 ? -b : b);
1400+ return (a ^ b) >> 63 ? -x : x;
1401+}
1402+
1403+static int gen_opic_lt(uint64_t a, uint64_t b)
1404+{
1405+ return (a ^ (uint64_t)1 << 63) < (b ^ (uint64_t)1 << 63);
1406+}
1407+
13971408 /* handle integer constant optimizations and various machine
13981409 independent opt */
13991410 static void gen_opic(int op)
14001411 {
1401− int c1, c2, t1, t2, n;
1402− SValue *v1, *v2;
1403− long long l1, l2;
1404− typedef unsigned long long U;
1412+ SValue *v1 = vtop - 1;
1413+ SValue *v2 = vtop;
1414+ int t1 = v1->type.t & VT_BTYPE;
1415+ int t2 = v2->type.t & VT_BTYPE;
1416+ int c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1417+ int c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1418+ uint64_t l1 = c1 ? v1->c.i : 0;
1419+ uint64_t l2 = c2 ? v2->c.i : 0;
1420+ int shm = (t1 == VT_LLONG) ? 63 : 31;
14051421
1406− v1 = vtop - 1;
1407− v2 = vtop;
1408− t1 = v1->type.t & VT_BTYPE;
1409− t2 = v2->type.t & VT_BTYPE;
1410−
1411− l1 = v1->c.i;
14121422 if (t1 != VT_LLONG)
14131423 l1 = ((uint32_t)l1 |
14141424 (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));
1415−
1416− l2 = v2->c.i;
14171425 if (t2 != VT_LLONG)
14181426 l2 = ((uint32_t)l2 |
14191427 (v2->type.t & VT_UNSIGNED ? 0 : -(l2 & 0x80000000)));
14201428
1421− /* currently, we cannot do computations with forward symbols */
1422− c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
1423− c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
14241429 if (c1 && c2) {
14251430 switch(op) {
14261431 case '+': l1 += l2; break;
@@ -1442,26 +1447,28 @@ static void gen_opic(int op) · 15 unmodified lines
14421447 goto general_case;
14431448 }
14441449 switch(op) {
1445− default: l1 /= l2; break;
1446− case '%': l1 %= l2; break;
1447− case TOK_UDIV: l1 = (U)l1 / l2; break;
1448− case TOK_UMOD: l1 = (U)l1 % l2; break;
1450+ default: l1 = gen_opic_sdiv(l1, l2); break;
1451+ case '%': l1 = l1 - l2 * gen_opic_sdiv(l1, l2); break;
1452+ case TOK_UDIV: l1 = l1 / l2; break;
1453+ case TOK_UMOD: l1 = l1 % l2; break;
14491454 }
14501455 break;
1451− case TOK_SHL: l1 <<= l2; break;
1452− case TOK_SHR: l1 = (U)l1 >> l2; break;
1453− case TOK_SAR: l1 >>= l2; break;
1456+ case TOK_SHL: l1 <<= (l2 & shm); break;
1457+ case TOK_SHR: l1 >>= (l2 & shm); break;
1458+ case TOK_SAR:
1459+ l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm);
1460+ break;
14541461 /* tests */
1455− case TOK_ULT: l1 = (U)l1 < (U)l2; break;
1456− case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
1462+ case TOK_ULT: l1 = l1 < l2; break;
1463+ case TOK_UGE: l1 = l1 >= l2; break;
14571464 case TOK_EQ: l1 = l1 == l2; break;
14581465 case TOK_NE: l1 = l1 != l2; break;
1459− case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
1460− case TOK_UGT: l1 = (U)l1 > (U)l2; break;
1461− case TOK_LT: l1 = l1 < l2; break;
1462− case TOK_GE: l1 = l1 >= l2; break;
1463− case TOK_LE: l1 = l1 <= l2; break;
1464− case TOK_GT: l1 = l1 > l2; break;
1466+ case TOK_ULE: l1 = l1 <= l2; break;
1467+ case TOK_UGT: l1 = l1 > l2; break;
1468+ case TOK_LT: l1 = gen_opic_lt(l1, l2); break;
1469+ case TOK_GE: l1 = !gen_opic_lt(l1, l2); break;
1470+ case TOK_LE: l1 = !gen_opic_lt(l2, l1); break;
1471+ case TOK_GT: l1 = gen_opic_lt(l2, l1); break;
14651472 /* logical */
14661473 case TOK_LAND: l1 = l1 && l2; break;
14671474 case TOK_LOR: l1 = l1 || l2; break;
@@ -1507,7 +1514,7 @@ static void gen_opic(int op) · 39 unmodified lines
15071514 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
15081515 /* try to use shifts instead of muls or divs */
15091516 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
1510− n = -1;
1517+ int n = -1;
15111518 while (l2) {
15121519 l2 >>= 1;
15131520 n++;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t