| @@ -67,7 +67,7 @@ static int gind(void) { CODE_ON(); return ind; } · 66 unmodified lines |
| 67 | 67 | |
| 68 | 68 | /* Set 'nocode_wanted' after unconditional jumps */ |
| 69 | 69 | static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } |
| 70 | | −static int gjmp_acs(int t) { t = gjmp(t); CODE_OFF(); return t; } |
| 70 | +static int gjmp_acs(int t) { if (!nocode_wanted) {t = gjmp(t); CODE_OFF(); } return t; } |
| 71 | 71 | |
| 72 | 72 | /* These are #undef'd at the end of this file */ |
| 73 | 73 | #define gjmp_addr gjmp_addr_acs |
| @@ -877,7 +877,7 @@ static void vcheck_cmp(void) · 803 unmodified lines |
| 877 | 877 | again, so that the VT_CMP/VT_JMP value will be in vtop |
| 878 | 878 | when code is unsuppressed again. */ |
| 879 | 879 | |
| 880 | | − if (vtop->r == VT_CMP && !nocode_wanted) |
| 880 | + if (vtop->r == VT_CMP && !nocode_wanted && vtop->cmp_op > 1) |
| 881 | 881 | gv(RC_INT); |
| 882 | 882 | } |
| 883 | 883 | |
| @@ -1043,7 +1043,11 @@ static void vset_VT_JMP(void) · 159 unmodified lines |
| 1043 | 1043 | if (vtop->jtrue || vtop->jfalse) { |
| 1044 | 1044 | /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */ |
| 1045 | 1045 | int inv = op & (op < 2); /* small optimization */ |
| 1046 | | − vseti(VT_JMP+inv, gvtst(inv, 0)); |
| 1046 | + int t = gvtst(inv, 0); |
| 1047 | + if (t) /* in case gvtst only needed to do a gsym */ |
| 1048 | + vseti(VT_JMP+inv, t); |
| 1049 | + else |
| 1050 | + vpushi(inv); |
| 1047 | 1051 | } else { |
| 1048 | 1052 | /* otherwise convert flags (rsp. 0/1) to register */ |
| 1049 | 1053 | vtop->c.i = op; |
| @@ -1061,9 +1065,11 @@ static void gvtst_set(int inv, int t) · 11 unmodified lines |
| 1061 | 1065 | gen_op(TOK_NE); |
| 1062 | 1066 | if (vtop->r == VT_CMP) /* must be VT_CONST otherwise */ |
| 1063 | 1067 | ; |
| 1064 | | − else if (vtop->r == VT_CONST) |
| 1065 | | − vset_VT_CMP(vtop->c.i != 0); |
| 1066 | | − else |
| 1068 | + else if (vtop->r == VT_CONST) { |
| 1069 | + if (!t) |
| 1070 | + return; |
| 1071 | + vset_VT_CMP(vtop->c.i != 0); |
| 1072 | + } else |
| 1067 | 1073 | tcc_error("ICE"); |
| 1068 | 1074 | } |
| 1069 | 1075 | p = inv ? &vtop->jfalse : &vtop->jtrue; |
| @@ -1075,18 +1081,21 @@ static void gvtst_set(int inv, int t) · 5 unmodified lines |
| 1075 | 1081 | * Generate a test for any value (jump, comparison and integers) */ |
| 1076 | 1082 | static int gvtst(int inv, int t) |
| 1077 | 1083 | { |
| 1078 | | − int op, u, x; |
| 1079 | | − |
| 1084 | + int op, x, u; |
| 1080 | 1085 | gvtst_set(inv, t); |
| 1081 | | − |
| 1082 | | − t = vtop->jtrue, u = vtop->jfalse; |
| 1083 | | − if (inv) |
| 1084 | | − x = u, u = t, t = x; |
| 1085 | | − op = vtop->cmp_op; |
| 1086 | + if (vtop->r != VT_CMP) { |
| 1087 | + t = u = x = 0; |
| 1088 | + op = vtop->c.i; |
| 1089 | + } else { |
| 1090 | + t = vtop->jtrue, u = vtop->jfalse; |
| 1091 | + if (inv) |
| 1092 | + x = u, u = t, t = x; |
| 1093 | + op = vtop->cmp_op; |
| 1094 | + } |
| 1086 | 1095 | |
| 1087 | 1096 | /* jump to the wanted target */ |
| 1088 | 1097 | if (op > 1) |
| 1089 | | − t = gjmp_cond(op ^ inv, t); |
| 1098 | + t = gjmp_cond(op ^ inv, t), op = inv;//, op = 1; |
| 1090 | 1099 | else if (op != inv) |
| 1091 | 1100 | t = gjmp(t); |
| 1092 | 1101 | /* resolve complementary jumps to here */ |
| @@ -5681,17 +5690,35 @@ special_math_val: · 4588 unmodified lines |
| 5681 | 5690 | } |
| 5682 | 5691 | } |
| 5683 | 5692 | |
| 5693 | +/* Assuming vtop is a value used in a conditional context |
| 5694 | + (i.e. compared with zero) return 0 if it's false, 1 if |
| 5695 | + true and -1 if it can't be statically determined. */ |
| 5696 | +static int condition_3way(void) |
| 5697 | +{ |
| 5698 | + int c = -1; |
| 5699 | + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && |
| 5700 | + (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) { |
| 5701 | + vdup(); |
| 5702 | + gen_cast_s(VT_BOOL); |
| 5703 | + c = vtop->c.i; |
| 5704 | + vpop(); |
| 5705 | + } |
| 5706 | + return c; |
| 5707 | +} |
| 5708 | + |
| 5684 | 5709 | static int precedence(int tok) |
| 5685 | 5710 | { |
| 5686 | 5711 | switch (tok) { |
| 5687 | | − case '|': return 1; |
| 5688 | | − case '^': return 2; |
| 5689 | | − case '&': return 3; |
| 5690 | | − case TOK_EQ: case TOK_NE: return 4; |
| 5691 | | −relat: case TOK_ULT: case TOK_UGE: return 5; |
| 5692 | | − case TOK_SHL: case TOK_SAR: return 6; |
| 5693 | | − case '+': case '-': return 7; |
| 5694 | | − case '*': case '/': case '%': return 8; |
| 5712 | + case TOK_LOR: return 1; |
| 5713 | + case TOK_LAND: return 2; |
| 5714 | + case '|': return 3; |
| 5715 | + case '^': return 4; |
| 5716 | + case '&': return 5; |
| 5717 | + case TOK_EQ: case TOK_NE: return 6; |
| 5718 | + relat: case TOK_ULT: case TOK_UGE: return 7; |
| 5719 | + case TOK_SHL: case TOK_SAR: return 8; |
| 5720 | + case '+': case '-': return 9; |
| 5721 | + case '*': case '/': case '%': return 10; |
| 5695 | 5722 | default: |
| 5696 | 5723 | if (tok >= TOK_ULE && tok <= TOK_GT) |
| 5697 | 5724 | goto relat; |
| @@ -5709,86 +5736,42 @@ ST_FUNC void init_prec(void) · 11 unmodified lines |
| 5709 | 5736 | |
| 5710 | 5737 | #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0) |
| 5711 | 5738 | |
| 5712 | | −static void expr_infix(int p) |
| 5713 | | −{ |
| 5714 | | − int t = tok, p2, p3; |
| 5715 | | − while ((p2 = precedence(t)) >= p) { |
| 5716 | | − next(); |
| 5717 | | − unary(); |
| 5718 | | − while ((p3 = precedence(tok)) > p2) { |
| 5719 | | − expr_infix(p3); |
| 5720 | | − } |
| 5721 | | − gen_op(t); |
| 5722 | | − t = tok; |
| 5723 | | − } |
| 5724 | | −} |
| 5725 | | − |
| 5726 | | −static void expr_or(void) |
| 5727 | | −{ |
| 5728 | | − unary(); |
| 5729 | | − expr_infix(1); |
| 5730 | | −} |
| 5731 | | − |
| 5732 | | −static int condition_3way(void); |
| 5733 | | − |
| 5734 | | −static void expr_landor(void(*e_fn)(void), int e_op, int i) |
| 5739 | +static void expr_infix(int p); |
| 5740 | +static void expr_landor(int p, int e_op, int i) |
| 5735 | 5741 | { |
| 5736 | | − int t = 0, cc = 1, f = 0, c; |
| 5737 | | − for(;;) { |
| 5738 | | − c = f ? i : condition_3way(); |
| 5739 | | − if (c < 0) { |
| 5740 | | − save_regs(1), cc = 0; |
| 5741 | | − } else if (c != i) { |
| 5742 | + int t = 0, f = 0; |
| 5743 | + save_regs(1); |
| 5744 | + do { |
| 5745 | + if (!f && condition_3way() == !i) |
| 5742 | 5746 | nocode_wanted++, f = 1; |
| 5743 | | − } |
| 5744 | | − if (tok != e_op) { |
| 5745 | | − if (cc || f) { |
| 5746 | | − vpop(); |
| 5747 | | − vpushi(i ^ f); |
| 5748 | | − gsym(t); |
| 5749 | | − nocode_wanted -= f; |
| 5750 | | − } else { |
| 5751 | | − gvtst_set(i, t); |
| 5752 | | − } |
| 5753 | | − break; |
| 5754 | | − } |
| 5755 | | − if (c < 0) |
| 5756 | | − t = gvtst(i, t); |
| 5757 | | − else |
| 5758 | | − vpop(); |
| 5747 | + t = gvtst(i, t); |
| 5759 | 5748 | next(); |
| 5760 | | − e_fn(); |
| 5749 | + unary(); |
| 5750 | + expr_infix(p); |
| 5751 | + } while (tok == e_op); |
| 5752 | + if (f) { |
| 5753 | + vpop(); |
| 5754 | + vpushi(i ^ f); |
| 5761 | 5755 | } |
| 5756 | + gvtst_set(i, t); |
| 5757 | + nocode_wanted -= f; |
| 5762 | 5758 | } |
| 5763 | 5759 | |
| 5764 | | −static void expr_land(void) |
| 5765 | | −{ |
| 5766 | | − expr_or(); |
| 5767 | | − if (tok == TOK_LAND) |
| 5768 | | − expr_landor(expr_or, TOK_LAND, 1); |
| 5769 | | −} |
| 5770 | | − |
| 5771 | | −static void expr_lor(void) |
| 5772 | | −{ |
| 5773 | | − expr_land(); |
| 5774 | | − if (tok == TOK_LOR) |
| 5775 | | − expr_landor(expr_land, TOK_LOR, 0); |
| 5776 | | −} |
| 5777 | | − |
| 5778 | | −/* Assuming vtop is a value used in a conditional context |
| 5779 | | − (i.e. compared with zero) return 0 if it's false, 1 if |
| 5780 | | − true and -1 if it can't be statically determined. */ |
| 5781 | | −static int condition_3way(void) |
| 5760 | +static void expr_infix(int p) |
| 5782 | 5761 | { |
| 5783 | | − int c = -1; |
| 5784 | | − if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && |
| 5785 | | − (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) { |
| 5786 | | − vdup(); |
| 5787 | | − gen_cast_s(VT_BOOL); |
| 5788 | | − c = vtop->c.i; |
| 5789 | | − vpop(); |
| 5762 | + int t = tok, p2; |
| 5763 | + while ((p2 = precedence(t)) >= p) { |
| 5764 | + if (t == TOK_LOR || t == TOK_LAND) { |
| 5765 | + expr_landor(p2 + 1, t, t == TOK_LAND); |
| 5766 | + } else { |
| 5767 | + next(); |
| 5768 | + unary(); |
| 5769 | + if (precedence(tok) > p2) |
| 5770 | + expr_infix(p2 + 1); |
| 5771 | + gen_op(t); |
| 5772 | + } |
| 5773 | + t = tok; |
| 5790 | 5774 | } |
| 5791 | | − return c; |
| 5792 | 5775 | } |
| 5793 | 5776 | |
| 5794 | 5777 | static int is_cond_bool(SValue *sv) |
| @@ -5808,7 +5791,8 @@ static void expr_cond(void) · 13 unmodified lines |
| 5808 | 5791 | CType type, type1, type2; |
| 5809 | 5792 | int ncw_prev; |
| 5810 | 5793 | |
| 5811 | | − expr_lor(); |
| 5794 | + unary(); |
| 5795 | + expr_infix(1); |
| 5812 | 5796 | if (tok == '?') { |
| 5813 | 5797 | next(); |
| 5814 | 5798 | c = condition_3way(); |