| @@ -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) { if (!nocode_wanted) {t = gjmp(t); CODE_OFF(); } return t; } |
| 70 | +static int gjmp_acs(int t) { 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 |
| @@ -122,6 +122,11 @@ static struct scope { · 48 unmodified lines |
| 122 | 122 | Sym *lstk, *llstk; |
| 123 | 123 | } *cur_scope, *loop_scope, *root_scope; |
| 124 | 124 | |
| 125 | +/********************************************************/ |
| 126 | +#if 1 |
| 127 | +#define precedence_parser |
| 128 | +static void init_prec(void); |
| 129 | +#endif |
| 125 | 130 | /********************************************************/ |
| 126 | 131 | #ifndef CONFIG_TCC_ASM |
| 127 | 132 | ST_FUNC void asm_instr(void) |
| @@ -135,7 +140,6 @@ ST_FUNC void asm_global_instr(void) · 7 unmodified lines |
| 135 | 140 | #endif |
| 136 | 141 | |
| 137 | 142 | /* ------------------------------------------------------------------------- */ |
| 138 | | − |
| 139 | 143 | static void gen_cast(CType *type); |
| 140 | 144 | static void gen_cast_s(int t); |
| 141 | 145 | static inline CType *pointed_type(CType *type); |
| @@ -455,6 +459,9 @@ ST_FUNC void tccgen_init(TCCState *s1) · 313 unmodified lines |
| 455 | 459 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); |
| 456 | 460 | func_old_type.ref->f.func_call = FUNC_CDECL; |
| 457 | 461 | func_old_type.ref->f.func_type = FUNC_OLD; |
| 462 | +#ifdef precedence_parser |
| 463 | + init_prec(); |
| 464 | +#endif |
| 458 | 465 | } |
| 459 | 466 | |
| 460 | 467 | ST_FUNC int tccgen_compile(TCCState *s1) |
| @@ -877,7 +884,7 @@ static void vcheck_cmp(void) · 416 unmodified lines |
| 877 | 884 | again, so that the VT_CMP/VT_JMP value will be in vtop |
| 878 | 885 | when code is unsuppressed again. */ |
| 879 | 886 | |
| 880 | | − if (vtop->r == VT_CMP && !nocode_wanted && vtop->cmp_op > 1) |
| 887 | + if (vtop->r == VT_CMP && !nocode_wanted) |
| 881 | 888 | gv(RC_INT); |
| 882 | 889 | } |
| 883 | 890 | |
| @@ -1040,14 +1047,11 @@ ST_FUNC void vset_VT_CMP(int op) · 156 unmodified lines |
| 1040 | 1047 | static void vset_VT_JMP(void) |
| 1041 | 1048 | { |
| 1042 | 1049 | int op = vtop->cmp_op; |
| 1050 | + |
| 1043 | 1051 | if (vtop->jtrue || vtop->jfalse) { |
| 1044 | 1052 | /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */ |
| 1045 | 1053 | int inv = op & (op < 2); /* small optimization */ |
| 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); |
| 1054 | + vseti(VT_JMP+inv, gvtst(inv, 0)); |
| 1051 | 1055 | } else { |
| 1052 | 1056 | /* otherwise convert flags (rsp. 0/1) to register */ |
| 1053 | 1057 | vtop->c.i = op; |
| @@ -1060,18 +1064,14 @@ static void vset_VT_JMP(void) · 6 unmodified lines |
| 1060 | 1064 | static void gvtst_set(int inv, int t) |
| 1061 | 1065 | { |
| 1062 | 1066 | int *p; |
| 1067 | + |
| 1063 | 1068 | if (vtop->r != VT_CMP) { |
| 1064 | 1069 | vpushi(0); |
| 1065 | 1070 | gen_op(TOK_NE); |
| 1066 | | − if (vtop->r == VT_CMP) /* must be VT_CONST otherwise */ |
| 1067 | | − ; |
| 1068 | | − else if (vtop->r == VT_CONST) { |
| 1069 | | − if (!t) |
| 1070 | | − return; |
| 1071 | + if (vtop->r != VT_CMP) /* must be VT_CONST then */ |
| 1071 | 1072 | vset_VT_CMP(vtop->c.i != 0); |
| 1072 | | − } else |
| 1073 | | − tcc_error("ICE"); |
| 1074 | 1073 | } |
| 1074 | + |
| 1075 | 1075 | p = inv ? &vtop->jfalse : &vtop->jtrue; |
| 1076 | 1076 | *p = gjmp_append(*p, t); |
| 1077 | 1077 | } |
| @@ -1082,20 +1082,16 @@ static void gvtst_set(int inv, int t) · 4 unmodified lines |
| 1082 | 1082 | static int gvtst(int inv, int t) |
| 1083 | 1083 | { |
| 1084 | 1084 | int op, x, u; |
| 1085 | + |
| 1085 | 1086 | gvtst_set(inv, t); |
| 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 | | − } |
| 1087 | + t = vtop->jtrue, u = vtop->jfalse; |
| 1088 | + if (inv) |
| 1089 | + x = u, u = t, t = x; |
| 1090 | + op = vtop->cmp_op; |
| 1095 | 1091 | |
| 1096 | 1092 | /* jump to the wanted target */ |
| 1097 | 1093 | if (op > 1) |
| 1098 | | − t = gjmp_cond(op ^ inv, t), op = inv;//, op = 1; |
| 1094 | + t = gjmp_cond(op ^ inv, t); |
| 1099 | 1095 | else if (op != inv) |
| 1100 | 1096 | t = gjmp(t); |
| 1101 | 1097 | /* resolve complementary jumps to here */ |
| @@ -5690,22 +5686,120 @@ special_math_val: · 4588 unmodified lines |
| 5690 | 5686 | } |
| 5691 | 5687 | } |
| 5692 | 5688 | |
| 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) |
| 5689 | +#ifndef precedence_parser /* original top-down parser */ |
| 5690 | + |
| 5691 | +static void expr_prod(void) |
| 5697 | 5692 | { |
| 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(); |
| 5693 | + int t; |
| 5694 | + |
| 5695 | + unary(); |
| 5696 | + while ((t = tok) == '*' || t == '/' || t == '%') { |
| 5697 | + next(); |
| 5698 | + unary(); |
| 5699 | + gen_op(t); |
| 5700 | + } |
| 5701 | +} |
| 5702 | + |
| 5703 | +static void expr_sum(void) |
| 5704 | +{ |
| 5705 | + int t; |
| 5706 | + |
| 5707 | + expr_prod(); |
| 5708 | + while ((t = tok) == '+' || t == '-') { |
| 5709 | + next(); |
| 5710 | + expr_prod(); |
| 5711 | + gen_op(t); |
| 5712 | + } |
| 5713 | +} |
| 5714 | + |
| 5715 | +static void expr_shift(void) |
| 5716 | +{ |
| 5717 | + int t; |
| 5718 | + |
| 5719 | + expr_sum(); |
| 5720 | + while ((t = tok) == TOK_SHL || t == TOK_SAR) { |
| 5721 | + next(); |
| 5722 | + expr_sum(); |
| 5723 | + gen_op(t); |
| 5724 | + } |
| 5725 | +} |
| 5726 | + |
| 5727 | +static void expr_cmp(void) |
| 5728 | +{ |
| 5729 | + int t; |
| 5730 | + |
| 5731 | + expr_shift(); |
| 5732 | + while (((t = tok) >= TOK_ULE && t <= TOK_GT) || |
| 5733 | + t == TOK_ULT || t == TOK_UGE) { |
| 5734 | + next(); |
| 5735 | + expr_shift(); |
| 5736 | + gen_op(t); |
| 5737 | + } |
| 5738 | +} |
| 5739 | + |
| 5740 | +static void expr_cmpeq(void) |
| 5741 | +{ |
| 5742 | + int t; |
| 5743 | + |
| 5744 | + expr_cmp(); |
| 5745 | + while ((t = tok) == TOK_EQ || t == TOK_NE) { |
| 5746 | + next(); |
| 5747 | + expr_cmp(); |
| 5748 | + gen_op(t); |
| 5749 | + } |
| 5750 | +} |
| 5751 | + |
| 5752 | +static void expr_and(void) |
| 5753 | +{ |
| 5754 | + expr_cmpeq(); |
| 5755 | + while (tok == '&') { |
| 5756 | + next(); |
| 5757 | + expr_cmpeq(); |
| 5758 | + gen_op('&'); |
| 5705 | 5759 | } |
| 5706 | | − return c; |
| 5707 | 5760 | } |
| 5708 | 5761 | |
| 5762 | +static void expr_xor(void) |
| 5763 | +{ |
| 5764 | + expr_and(); |
| 5765 | + while (tok == '^') { |
| 5766 | + next(); |
| 5767 | + expr_and(); |
| 5768 | + gen_op('^'); |
| 5769 | + } |
| 5770 | +} |
| 5771 | + |
| 5772 | +static void expr_or(void) |
| 5773 | +{ |
| 5774 | + expr_xor(); |
| 5775 | + while (tok == '|') { |
| 5776 | + next(); |
| 5777 | + expr_xor(); |
| 5778 | + gen_op('|'); |
| 5779 | + } |
| 5780 | +} |
| 5781 | + |
| 5782 | +static void expr_landor(int op); |
| 5783 | + |
| 5784 | +static void expr_land(void) |
| 5785 | +{ |
| 5786 | + expr_or(); |
| 5787 | + if (tok == TOK_LAND) |
| 5788 | + expr_landor(tok); |
| 5789 | +} |
| 5790 | + |
| 5791 | +static void expr_lor(void) |
| 5792 | +{ |
| 5793 | + expr_land(); |
| 5794 | + if (tok == TOK_LOR) |
| 5795 | + expr_landor(tok); |
| 5796 | +} |
| 5797 | + |
| 5798 | +# define expr_landor_next(op) op == TOK_LAND ? expr_or() : expr_land() |
| 5799 | +#else /* defined precedence_parser */ |
| 5800 | +# define expr_landor_next(op) unary(), expr_infix(precedence(op) + 1) |
| 5801 | +# define expr_lor() unary(), expr_infix(1) |
| 5802 | + |
| 5709 | 5803 | static int precedence(int tok) |
| 5710 | 5804 | { |
| 5711 | 5805 | switch (tok) { |
| @@ -5725,44 +5819,23 @@ static int precedence(int tok) · 13 unmodified lines |
| 5725 | 5819 | return 0; |
| 5726 | 5820 | } |
| 5727 | 5821 | } |
| 5728 | | − |
| 5729 | 5822 | static unsigned char prec[256]; |
| 5730 | | −ST_FUNC void init_prec(void) |
| 5823 | +static void init_prec(void) |
| 5731 | 5824 | { |
| 5732 | 5825 | int i; |
| 5733 | 5826 | for (i = 0; i < 256; i++) |
| 5734 | 5827 | prec[i] = precedence(i); |
| 5735 | 5828 | } |
| 5736 | | − |
| 5737 | 5829 | #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0) |
| 5738 | 5830 | |
| 5739 | | −static void expr_infix(int p); |
| 5740 | | −static void expr_landor(int p, int e_op, int i) |
| 5741 | | −{ |
| 5742 | | − int t = 0, f = 0; |
| 5743 | | − save_regs(1); |
| 5744 | | − do { |
| 5745 | | − if (!f && condition_3way() == !i) |
| 5746 | | − nocode_wanted++, f = 1; |
| 5747 | | − t = gvtst(i, t); |
| 5748 | | − next(); |
| 5749 | | − unary(); |
| 5750 | | − expr_infix(p); |
| 5751 | | − } while (tok == e_op); |
| 5752 | | − if (f) { |
| 5753 | | − vpop(); |
| 5754 | | − vpushi(i ^ f); |
| 5755 | | − } |
| 5756 | | − gvtst_set(i, t); |
| 5757 | | − nocode_wanted -= f; |
| 5758 | | −} |
| 5831 | +static void expr_landor(int op); |
| 5759 | 5832 | |
| 5760 | 5833 | static void expr_infix(int p) |
| 5761 | 5834 | { |
| 5762 | 5835 | int t = tok, p2; |
| 5763 | 5836 | while ((p2 = precedence(t)) >= p) { |
| 5764 | 5837 | if (t == TOK_LOR || t == TOK_LAND) { |
| 5765 | | − expr_landor(p2 + 1, t, t == TOK_LAND); |
| 5838 | + expr_landor(t); |
| 5766 | 5839 | } else { |
| 5767 | 5840 | next(); |
| 5768 | 5841 | unary(); |
| @@ -5773,6 +5846,51 @@ static void expr_infix(int p) · 4 unmodified lines |
| 5773 | 5846 | t = tok; |
| 5774 | 5847 | } |
| 5775 | 5848 | } |
| 5849 | +#endif |
| 5850 | + |
| 5851 | +/* Assuming vtop is a value used in a conditional context |
| 5852 | + (i.e. compared with zero) return 0 if it's false, 1 if |
| 5853 | + true and -1 if it can't be statically determined. */ |
| 5854 | +static int condition_3way(void) |
| 5855 | +{ |
| 5856 | + int c = -1; |
| 5857 | + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && |
| 5858 | + (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) { |
| 5859 | + vdup(); |
| 5860 | + gen_cast_s(VT_BOOL); |
| 5861 | + c = vtop->c.i; |
| 5862 | + vpop(); |
| 5863 | + } |
| 5864 | + return c; |
| 5865 | +} |
| 5866 | + |
| 5867 | +static void expr_landor(int op) |
| 5868 | +{ |
| 5869 | + int t = 0, cc = 1, f = 0, i = op == TOK_LAND, c; |
| 5870 | + for(;;) { |
| 5871 | + c = f ? i : condition_3way(); |
| 5872 | + if (c < 0) |
| 5873 | + save_regs(1), cc = 0; |
| 5874 | + else if (c != i) |
| 5875 | + nocode_wanted++, f = 1; |
| 5876 | + if (tok != op) |
| 5877 | + break; |
| 5878 | + if (c < 0) |
| 5879 | + t = gvtst(i, t); |
| 5880 | + else |
| 5881 | + vpop(); |
| 5882 | + next(); |
| 5883 | + expr_landor_next(op); |
| 5884 | + } |
| 5885 | + if (cc || f) { |
| 5886 | + vpop(); |
| 5887 | + vpushi(i ^ f); |
| 5888 | + gsym(t); |
| 5889 | + nocode_wanted -= f; |
| 5890 | + } else { |
| 5891 | + gvtst_set(i, t); |
| 5892 | + } |
| 5893 | +} |
| 5776 | 5894 | |
| 5777 | 5895 | static int is_cond_bool(SValue *sv) |
| 5778 | 5896 | { |
| @@ -5791,11 +5909,11 @@ static void expr_cond(void) · 12 unmodified lines |
| 5791 | 5909 | CType type, type1, type2; |
| 5792 | 5910 | int ncw_prev; |
| 5793 | 5911 | |
| 5794 | | − unary(); |
| 5795 | | − expr_infix(1); |
| 5912 | + expr_lor(); |
| 5796 | 5913 | if (tok == '?') { |
| 5797 | 5914 | next(); |
| 5798 | 5915 | c = condition_3way(); |
| 5916 | + ncw_prev = nocode_wanted; |
| 5799 | 5917 | g = (tok == ':' && gnu_ext); |
| 5800 | 5918 | tt = 0; |
| 5801 | 5919 | if (!g) { |
| @@ -5813,7 +5931,6 @@ static void expr_cond(void) · 11 unmodified lines |
| 5813 | 5931 | tt = gvtst(0, 0); |
| 5814 | 5932 | } |
| 5815 | 5933 | |
| 5816 | | − ncw_prev = nocode_wanted; |
| 5817 | 5934 | if (1) { |
| 5818 | 5935 | if (c == 0) |
| 5819 | 5936 | nocode_wanted++; |
| @@ -6013,12 +6130,11 @@ static void expr_eq(void) · 193 unmodified lines |
| 6013 | 6130 | int t; |
| 6014 | 6131 | |
| 6015 | 6132 | expr_cond(); |
| 6016 | | − if (tok == '=' || |
| 6017 | | − (tok >= TOK_A_MOD && tok <= TOK_A_DIV) || |
| 6018 | | − tok == TOK_A_XOR || tok == TOK_A_OR || |
| 6019 | | − tok == TOK_A_SHL || tok == TOK_A_SAR) { |
| 6133 | + if ((t = tok) == '=' |
| 6134 | + || (t >= TOK_A_MOD && t <= TOK_A_DIV) |
| 6135 | + || t == TOK_A_XOR || t == TOK_A_OR |
| 6136 | + || t == TOK_A_SHL || t == TOK_A_SAR) { |
| 6020 | 6137 | test_lvalue(); |
| 6021 | | − t = tok; |
| 6022 | 6138 | next(); |
| 6023 | 6139 | if (t == '=') { |
| 6024 | 6140 | expr_eq(); |