| @@ -67,7 +67,7 @@ static int gind(void) { CODE_ON(); return ind; } · 66 unmodified lines |
| 67 | | 67 | |
| 68 | /* Set 'nocode_wanted' after unconditional jumps */ | 68 | /* Set 'nocode_wanted' after unconditional jumps */ |
| 69 | static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); } | 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 | /* These are #undef'd at the end of this file */ | 72 | /* These are #undef'd at the end of this file */ |
| 73 | #define gjmp_addr gjmp_addr_acs | 73 | #define gjmp_addr gjmp_addr_acs |
| @@ -877,7 +877,7 @@ static void vcheck_cmp(void) · 803 unmodified lines |
| 877 | again, so that the VT_CMP/VT_JMP value will be in vtop | 877 | again, so that the VT_CMP/VT_JMP value will be in vtop |
| 878 | when code is unsuppressed again. */ | 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 | gv(RC_INT); | 881 | gv(RC_INT); |
| 882 | } | 882 | } |
| 883 | | 883 | |
| @@ -1043,7 +1043,11 @@ static void vset_VT_JMP(void) · 159 unmodified lines |
| 1043 | if (vtop->jtrue || vtop->jfalse) { | 1043 | if (vtop->jtrue || vtop->jfalse) { |
| 1044 | /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */ | 1044 | /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */ |
| 1045 | int inv = op & (op < 2); /* small optimization */ | 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 | } else { | 1051 | } else { |
| 1048 | /* otherwise convert flags (rsp. 0/1) to register */ | 1052 | /* otherwise convert flags (rsp. 0/1) to register */ |
| 1049 | vtop->c.i = op; | 1053 | vtop->c.i = op; |
| @@ -1061,9 +1065,11 @@ static void gvtst_set(int inv, int t) · 11 unmodified lines |
| 1061 | gen_op(TOK_NE); | 1065 | gen_op(TOK_NE); |
| 1062 | if (vtop->r == VT_CMP) /* must be VT_CONST otherwise */ | 1066 | if (vtop->r == VT_CMP) /* must be VT_CONST otherwise */ |
| 1063 | ; | 1067 | ; |
| 1064 | else if (vtop->r == VT_CONST) | 1068 | else if (vtop->r == VT_CONST) { |
| 1065 | vset_VT_CMP(vtop->c.i != 0); | 1069 | if (!t) |
| 1066 | else | 1070 | return; |
| | 1071 | vset_VT_CMP(vtop->c.i != 0); |
| | 1072 | } else |
| 1067 | tcc_error("ICE"); | 1073 | tcc_error("ICE"); |
| 1068 | } | 1074 | } |
| 1069 | p = inv ? &vtop->jfalse : &vtop->jtrue; | 1075 | p = inv ? &vtop->jfalse : &vtop->jtrue; |
| @@ -1075,18 +1081,21 @@ static void gvtst_set(int inv, int t) · 5 unmodified lines |
| 1075 | * Generate a test for any value (jump, comparison and integers) */ | 1081 | * Generate a test for any value (jump, comparison and integers) */ |
| 1076 | static int gvtst(int inv, int t) | 1082 | static int gvtst(int inv, int t) |
| 1077 | { | 1083 | { |
| 1078 | int op, u, x; | 1084 | int op, x, u; |
| 1079 | | | |
| 1080 | gvtst_set(inv, t); | 1085 | gvtst_set(inv, t); |
| 1081 | | 1086 | if (vtop->r != VT_CMP) { |
| 1082 | t = vtop->jtrue, u = vtop->jfalse; | 1087 | t = u = x = 0; |
| 1083 | if (inv) | 1088 | op = vtop->c.i; |
| 1084 | x = u, u = t, t = x; | 1089 | } else { |
| 1085 | op = vtop->cmp_op; | 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 | /* jump to the wanted target */ | 1096 | /* jump to the wanted target */ |
| 1088 | if (op > 1) | 1097 | if (op > 1) |
| 1089 | t = gjmp_cond(op ^ inv, t); | 1098 | t = gjmp_cond(op ^ inv, t), op = inv;//, op = 1; |
| 1090 | else if (op != inv) | 1099 | else if (op != inv) |
| 1091 | t = gjmp(t); | 1100 | t = gjmp(t); |
| 1092 | /* resolve complementary jumps to here */ | 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 | static int precedence(int tok) | 5709 | static int precedence(int tok) |
| 5685 | { | 5710 | { |
| 5686 | switch (tok) { | 5711 | switch (tok) { |
| 5687 | case '|': return 1; | 5712 | case TOK_LOR: return 1; |
| 5688 | case '^': return 2; | 5713 | case TOK_LAND: return 2; |
| 5689 | case '&': return 3; | 5714 | case '|': return 3; |
| 5690 | case TOK_EQ: case TOK_NE: return 4; | 5715 | case '^': return 4; |
| 5691 | relat: case TOK_ULT: case TOK_UGE: return 5; | 5716 | case '&': return 5; |
| 5692 | case TOK_SHL: case TOK_SAR: return 6; | 5717 | case TOK_EQ: case TOK_NE: return 6; |
| 5693 | case '+': case '-': return 7; | 5718 | relat: case TOK_ULT: case TOK_UGE: return 7; |
| 5694 | case '*': case '/': case '%': return 8; | 5719 | case TOK_SHL: case TOK_SAR: return 8; |
| | 5720 | case '+': case '-': return 9; |
| | 5721 | case '*': case '/': case '%': return 10; |
| 5695 | default: | 5722 | default: |
| 5696 | if (tok >= TOK_ULE && tok <= TOK_GT) | 5723 | if (tok >= TOK_ULE && tok <= TOK_GT) |
| 5697 | goto relat; | 5724 | goto relat; |
| @@ -5709,86 +5736,42 @@ ST_FUNC void init_prec(void) · 11 unmodified lines |
| 5709 | | 5736 | |
| 5710 | #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0) | 5737 | #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0) |
| 5711 | | 5738 | |
| 5712 | static void expr_infix(int p) | 5739 | static void expr_infix(int p); |
| 5713 | { | 5740 | static void expr_landor(int p, int e_op, int i) |
| 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) | | |
| 5735 | { | 5741 | { |
| 5736 | int t = 0, cc = 1, f = 0, c; | 5742 | int t = 0, f = 0; |
| 5737 | for(;;) { | 5743 | save_regs(1); |
| 5738 | c = f ? i : condition_3way(); | 5744 | do { |
| 5739 | if (c < 0) { | 5745 | if (!f && condition_3way() == !i) |
| 5740 | save_regs(1), cc = 0; | | |
| 5741 | } else if (c != i) { | | |
| 5742 | nocode_wanted++, f = 1; | 5746 | nocode_wanted++, f = 1; |
| 5743 | } | 5747 | t = gvtst(i, t); |
| 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(); | | |
| 5759 | next(); | 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) | 5760 | static void expr_infix(int p) |
| 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) | | |
| 5782 | { | 5761 | { |
| 5783 | int c = -1; | 5762 | int t = tok, p2; |
| 5784 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && | 5763 | while ((p2 = precedence(t)) >= p) { |
| 5785 | (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) { | 5764 | if (t == TOK_LOR || t == TOK_LAND) { |
| 5786 | vdup(); | 5765 | expr_landor(p2 + 1, t, t == TOK_LAND); |
| 5787 | gen_cast_s(VT_BOOL); | 5766 | } else { |
| 5788 | c = vtop->c.i; | 5767 | next(); |
| 5789 | vpop(); | 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 | static int is_cond_bool(SValue *sv) | 5777 | static int is_cond_bool(SValue *sv) |
| @@ -5808,7 +5791,8 @@ static void expr_cond(void) · 13 unmodified lines |
| 5808 | CType type, type1, type2; | 5791 | CType type, type1, type2; |
| 5809 | int ncw_prev; | 5792 | int ncw_prev; |
| 5810 | | 5793 | |
| 5811 | expr_lor(); | 5794 | unary(); |
| | 5795 | expr_infix(1); |
| 5812 | if (tok == '?') { | 5796 | if (tok == '?') { |
| 5813 | next(); | 5797 | next(); |
| 5814 | c = condition_3way(); | 5798 | c = condition_3way(); |