| @@ -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) { 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 | /* 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 |
| @@ -122,6 +122,11 @@ static struct scope { · 48 unmodified lines |
| 122 | Sym *lstk, *llstk; | 122 | Sym *lstk, *llstk; |
| 123 | } *cur_scope, *loop_scope, *root_scope; | 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 | #ifndef CONFIG_TCC_ASM | 131 | #ifndef CONFIG_TCC_ASM |
| 127 | ST_FUNC void asm_instr(void) | 132 | ST_FUNC void asm_instr(void) |
| @@ -135,7 +140,6 @@ ST_FUNC void asm_global_instr(void) · 7 unmodified lines |
| 135 | #endif | 140 | #endif |
| 136 | | 141 | |
| 137 | /* ------------------------------------------------------------------------- */ | 142 | /* ------------------------------------------------------------------------- */ |
| 138 | | | |
| 139 | static void gen_cast(CType *type); | 143 | static void gen_cast(CType *type); |
| 140 | static void gen_cast_s(int t); | 144 | static void gen_cast_s(int t); |
| 141 | static inline CType *pointed_type(CType *type); | 145 | static inline CType *pointed_type(CType *type); |
| @@ -455,6 +459,9 @@ ST_FUNC void tccgen_init(TCCState *s1) · 313 unmodified lines |
| 455 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); | 459 | func_old_type.ref = sym_push(SYM_FIELD, &int_type, 0, 0); |
| 456 | func_old_type.ref->f.func_call = FUNC_CDECL; | 460 | func_old_type.ref->f.func_call = FUNC_CDECL; |
| 457 | func_old_type.ref->f.func_type = FUNC_OLD; | 461 | func_old_type.ref->f.func_type = FUNC_OLD; |
| | 462 | #ifdef precedence_parser |
| | 463 | init_prec(); |
| | 464 | #endif |
| 458 | } | 465 | } |
| 459 | | 466 | |
| 460 | ST_FUNC int tccgen_compile(TCCState *s1) | 467 | ST_FUNC int tccgen_compile(TCCState *s1) |
| @@ -877,7 +884,7 @@ static void vcheck_cmp(void) · 416 unmodified lines |
| 877 | again, so that the VT_CMP/VT_JMP value will be in vtop | 884 | again, so that the VT_CMP/VT_JMP value will be in vtop |
| 878 | when code is unsuppressed again. */ | 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 | gv(RC_INT); | 888 | gv(RC_INT); |
| 882 | } | 889 | } |
| 883 | | 890 | |
| @@ -1040,14 +1047,11 @@ ST_FUNC void vset_VT_CMP(int op) · 156 unmodified lines |
| 1040 | static void vset_VT_JMP(void) | 1047 | static void vset_VT_JMP(void) |
| 1041 | { | 1048 | { |
| 1042 | int op = vtop->cmp_op; | 1049 | int op = vtop->cmp_op; |
| | 1050 | |
| 1043 | if (vtop->jtrue || vtop->jfalse) { | 1051 | if (vtop->jtrue || vtop->jfalse) { |
| 1044 | /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */ | 1052 | /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */ |
| 1045 | int inv = op & (op < 2); /* small optimization */ | 1053 | int inv = op & (op < 2); /* small optimization */ |
| 1046 | int t = gvtst(inv, 0); | 1054 | vseti(VT_JMP+inv, 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); | | |
| 1051 | } else { | 1055 | } else { |
| 1052 | /* otherwise convert flags (rsp. 0/1) to register */ | 1056 | /* otherwise convert flags (rsp. 0/1) to register */ |
| 1053 | vtop->c.i = op; | 1057 | vtop->c.i = op; |
| @@ -1060,18 +1064,14 @@ static void vset_VT_JMP(void) · 6 unmodified lines |
| 1060 | static void gvtst_set(int inv, int t) | 1064 | static void gvtst_set(int inv, int t) |
| 1061 | { | 1065 | { |
| 1062 | int *p; | 1066 | int *p; |
| | 1067 | |
| 1063 | if (vtop->r != VT_CMP) { | 1068 | if (vtop->r != VT_CMP) { |
| 1064 | vpushi(0); | 1069 | vpushi(0); |
| 1065 | gen_op(TOK_NE); | 1070 | gen_op(TOK_NE); |
| 1066 | if (vtop->r == VT_CMP) /* must be VT_CONST otherwise */ | 1071 | if (vtop->r != VT_CMP) /* must be VT_CONST then */ |
| 1067 | ; | | |
| 1068 | else if (vtop->r == VT_CONST) { | | |
| 1069 | if (!t) | | |
| 1070 | return; | | |
| 1071 | vset_VT_CMP(vtop->c.i != 0); | 1072 | vset_VT_CMP(vtop->c.i != 0); |
| 1072 | } else | | |
| 1073 | tcc_error("ICE"); | | |
| 1074 | } | 1073 | } |
| | 1074 | |
| 1075 | p = inv ? &vtop->jfalse : &vtop->jtrue; | 1075 | p = inv ? &vtop->jfalse : &vtop->jtrue; |
| 1076 | *p = gjmp_append(*p, t); | 1076 | *p = gjmp_append(*p, t); |
| 1077 | } | 1077 | } |
| @@ -1082,20 +1082,16 @@ static void gvtst_set(int inv, int t) · 4 unmodified lines |
| 1082 | static int gvtst(int inv, int t) | 1082 | static int gvtst(int inv, int t) |
| 1083 | { | 1083 | { |
| 1084 | int op, x, u; | 1084 | int op, x, u; |
| | 1085 | |
| 1085 | gvtst_set(inv, t); | 1086 | gvtst_set(inv, t); |
| 1086 | if (vtop->r != VT_CMP) { | 1087 | t = vtop->jtrue, u = vtop->jfalse; |
| 1087 | t = u = x = 0; | 1088 | if (inv) |
| 1088 | op = vtop->c.i; | 1089 | x = u, u = t, t = x; |
| 1089 | } else { | 1090 | 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 | } | | |
| 1095 | | 1091 | |
| 1096 | /* jump to the wanted target */ | 1092 | /* jump to the wanted target */ |
| 1097 | if (op > 1) | 1093 | if (op > 1) |
| 1098 | t = gjmp_cond(op ^ inv, t), op = inv;//, op = 1; | 1094 | t = gjmp_cond(op ^ inv, t); |
| 1099 | else if (op != inv) | 1095 | else if (op != inv) |
| 1100 | t = gjmp(t); | 1096 | t = gjmp(t); |
| 1101 | /* resolve complementary jumps to here */ | 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 | 5689 | #ifndef precedence_parser /* original top-down parser */ |
| 5694 | (i.e. compared with zero) return 0 if it's false, 1 if | 5690 | |
| 5695 | true and -1 if it can't be statically determined. */ | 5691 | static void expr_prod(void) |
| 5696 | static int condition_3way(void) | | |
| 5697 | { | 5692 | { |
| 5698 | int c = -1; | 5693 | int t; |
| 5699 | if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST && | 5694 | |
| 5700 | (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) { | 5695 | unary(); |
| 5701 | vdup(); | 5696 | while ((t = tok) == '*' || t == '/' || t == '%') { |
| 5702 | gen_cast_s(VT_BOOL); | 5697 | next(); |
| 5703 | c = vtop->c.i; | 5698 | unary(); |
| 5704 | vpop(); | 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 | static int precedence(int tok) | 5803 | static int precedence(int tok) |
| 5710 | { | 5804 | { |
| 5711 | switch (tok) { | 5805 | switch (tok) { |
| @@ -5725,44 +5819,23 @@ static int precedence(int tok) · 13 unmodified lines |
| 5725 | return 0; | 5819 | return 0; |
| 5726 | } | 5820 | } |
| 5727 | } | 5821 | } |
| 5728 | | | |
| 5729 | static unsigned char prec[256]; | 5822 | static unsigned char prec[256]; |
| 5730 | ST_FUNC void init_prec(void) | 5823 | static void init_prec(void) |
| 5731 | { | 5824 | { |
| 5732 | int i; | 5825 | int i; |
| 5733 | for (i = 0; i < 256; i++) | 5826 | for (i = 0; i < 256; i++) |
| 5734 | prec[i] = precedence(i); | 5827 | prec[i] = precedence(i); |
| 5735 | } | 5828 | } |
| 5736 | | | |
| 5737 | #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0) | 5829 | #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0) |
| 5738 | | 5830 | |
| 5739 | static void expr_infix(int p); | 5831 | static void expr_landor(int op); |
| 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 | } | | |
| 5759 | | 5832 | |
| 5760 | static void expr_infix(int p) | 5833 | static void expr_infix(int p) |
| 5761 | { | 5834 | { |
| 5762 | int t = tok, p2; | 5835 | int t = tok, p2; |
| 5763 | while ((p2 = precedence(t)) >= p) { | 5836 | while ((p2 = precedence(t)) >= p) { |
| 5764 | if (t == TOK_LOR || t == TOK_LAND) { | 5837 | if (t == TOK_LOR || t == TOK_LAND) { |
| 5765 | expr_landor(p2 + 1, t, t == TOK_LAND); | 5838 | expr_landor(t); |
| 5766 | } else { | 5839 | } else { |
| 5767 | next(); | 5840 | next(); |
| 5768 | unary(); | 5841 | unary(); |
| @@ -5773,6 +5846,51 @@ static void expr_infix(int p) · 4 unmodified lines |
| 5773 | t = tok; | 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 | static int is_cond_bool(SValue *sv) | 5895 | static int is_cond_bool(SValue *sv) |
| 5778 | { | 5896 | { |
| @@ -5791,11 +5909,11 @@ static void expr_cond(void) · 12 unmodified lines |
| 5791 | CType type, type1, type2; | 5909 | CType type, type1, type2; |
| 5792 | int ncw_prev; | 5910 | int ncw_prev; |
| 5793 | | 5911 | |
| 5794 | unary(); | 5912 | expr_lor(); |
| 5795 | expr_infix(1); | | |
| 5796 | if (tok == '?') { | 5913 | if (tok == '?') { |
| 5797 | next(); | 5914 | next(); |
| 5798 | c = condition_3way(); | 5915 | c = condition_3way(); |
| | 5916 | ncw_prev = nocode_wanted; |
| 5799 | g = (tok == ':' && gnu_ext); | 5917 | g = (tok == ':' && gnu_ext); |
| 5800 | tt = 0; | 5918 | tt = 0; |
| 5801 | if (!g) { | 5919 | if (!g) { |
| @@ -5813,7 +5931,6 @@ static void expr_cond(void) · 11 unmodified lines |
| 5813 | tt = gvtst(0, 0); | 5931 | tt = gvtst(0, 0); |
| 5814 | } | 5932 | } |
| 5815 | | 5933 | |
| 5816 | ncw_prev = nocode_wanted; | | |
| 5817 | if (1) { | 5934 | if (1) { |
| 5818 | if (c == 0) | 5935 | if (c == 0) |
| 5819 | nocode_wanted++; | 5936 | nocode_wanted++; |
| @@ -6013,12 +6130,11 @@ static void expr_eq(void) · 193 unmodified lines |
| 6013 | int t; | 6130 | int t; |
| 6014 | | 6131 | |
| 6015 | expr_cond(); | 6132 | expr_cond(); |
| 6016 | if (tok == '=' || | 6133 | if ((t = tok) == '=' |
| 6017 | (tok >= TOK_A_MOD && tok <= TOK_A_DIV) || | 6134 | || (t >= TOK_A_MOD && t <= TOK_A_DIV) |
| 6018 | tok == TOK_A_XOR || tok == TOK_A_OR || | 6135 | || t == TOK_A_XOR || t == TOK_A_OR |
| 6019 | tok == TOK_A_SHL || tok == TOK_A_SAR) { | 6136 | || t == TOK_A_SHL || t == TOK_A_SAR) { |
| 6020 | test_lvalue(); | 6137 | test_lvalue(); |
| 6021 | t = tok; | | |
| 6022 | next(); | 6138 | next(); |
| 6023 | if (t == '=') { | 6139 | if (t == '=') { |
| 6024 | expr_eq(); | 6140 | expr_eq(); |