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
1394}1394}
1395#endif1395#endif
1396 1396
1397static 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
1403static 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
1397/* handle integer constant optimizations and various machine1408/* handle integer constant optimizations and various machine
1398 independent opt */1409 independent opt */
1399static void gen_opic(int op)1410static void gen_opic(int op)
1400{1411{
1401 int c1, c2, t1, t2, n;1412 SValue *v1 = vtop - 1;
1402 SValue *v1, *v2;1413 SValue *v2 = vtop;
1403 long long l1, l2;1414 int t1 = v1->type.t & VT_BTYPE;
1404 typedef unsigned long long U;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;
1405 1421
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;
1412 if (t1 != VT_LLONG)1422 if (t1 != VT_LLONG)
1413 l1 = ((uint32_t)l1 |1423 l1 = ((uint32_t)l1 |
1414 (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));1424 (v1->type.t & VT_UNSIGNED ? 0 : -(l1 & 0x80000000)));
1415
1416 l2 = v2->c.i;
1417 if (t2 != VT_LLONG)1425 if (t2 != VT_LLONG)
1418 l2 = ((uint32_t)l2 |1426 l2 = ((uint32_t)l2 |
1419 (v2->type.t & VT_UNSIGNED ? 0 : -(l2 & 0x80000000)));1427 (v2->type.t & VT_UNSIGNED ? 0 : -(l2 & 0x80000000)));
1420 1428
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;
1424 if (c1 && c2) {1429 if (c1 && c2) {
1425 switch(op) {1430 switch(op) {
1426 case '+': l1 += l2; break;1431 case '+': l1 += l2; break;
@@ -1442,26 +1447,28 @@ static void gen_opic(int op) · 15 unmodified lines
1442 goto general_case;1447 goto general_case;
1443 }1448 }
1444 switch(op) {1449 switch(op) {
1445 default: l1 /= l2; break;1450 default: l1 = gen_opic_sdiv(l1, l2); break;
1446 case '%': l1 %= l2; break;1451 case '%': l1 = l1 - l2 * gen_opic_sdiv(l1, l2); break;
1447 case TOK_UDIV: l1 = (U)l1 / l2; break;1452 case TOK_UDIV: l1 = l1 / l2; break;
1448 case TOK_UMOD: l1 = (U)l1 % l2; break;1453 case TOK_UMOD: l1 = l1 % l2; break;
1449 }1454 }
1450 break;1455 break;
1451 case TOK_SHL: l1 <<= l2; break;1456 case TOK_SHL: l1 <<= (l2 & shm); break;
1452 case TOK_SHR: l1 = (U)l1 >> l2; break;1457 case TOK_SHR: l1 >>= (l2 & shm); break;
1453 case TOK_SAR: l1 >>= l2; break;1458 case TOK_SAR:
1459 l1 = (l1 >> 63) ? ~(~l1 >> (l2 & shm)) : l1 >> (l2 & shm);
1460 break;
1454 /* tests */1461 /* tests */
1455 case TOK_ULT: l1 = (U)l1 < (U)l2; break;1462 case TOK_ULT: l1 = l1 < l2; break;
1456 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;1463 case TOK_UGE: l1 = l1 >= l2; break;
1457 case TOK_EQ: l1 = l1 == l2; break;1464 case TOK_EQ: l1 = l1 == l2; break;
1458 case TOK_NE: l1 = l1 != l2; break;1465 case TOK_NE: l1 = l1 != l2; break;
1459 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;1466 case TOK_ULE: l1 = l1 <= l2; break;
1460 case TOK_UGT: l1 = (U)l1 > (U)l2; break;1467 case TOK_UGT: l1 = l1 > l2; break;
1461 case TOK_LT: l1 = l1 < l2; break;1468 case TOK_LT: l1 = gen_opic_lt(l1, l2); break;
1462 case TOK_GE: l1 = l1 >= l2; break;1469 case TOK_GE: l1 = !gen_opic_lt(l1, l2); break;
1463 case TOK_LE: l1 = l1 <= l2; break;1470 case TOK_LE: l1 = !gen_opic_lt(l2, l1); break;
1464 case TOK_GT: l1 = l1 > l2; break;1471 case TOK_GT: l1 = gen_opic_lt(l2, l1); break;
1465 /* logical */1472 /* logical */
1466 case TOK_LAND: l1 = l1 && l2; break;1473 case TOK_LAND: l1 = l1 && l2; break;
1467 case TOK_LOR: l1 = l1 || l2; break;1474 case TOK_LOR: l1 = l1 || l2; break;
@@ -1507,7 +1514,7 @@ static void gen_opic(int op) · 39 unmodified lines
1507 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {1514 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
1508 /* try to use shifts instead of muls or divs */1515 /* try to use shifts instead of muls or divs */
1509 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {1516 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
1510 n = -1;1517 int n = -1;
1511 while (l2) {1518 while (l2) {
1512 l2 >>= 1;1519 l2 >>= 1;
1513 n++;1520 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