History

Rework expr_infix

- revert const-folding in gvtst() and put it back into expr_landor(). Although it did make sense, one reason not to do it is __builtin_constant_p() which may return true when it shouldn't because of nocode_wanted, see test. - tccgen_init() can do init_prec(), also for tcc -E. - for nostalgic reasons, keep the original expression parser functions in the source. - Makefile: remove stale stuff

grischka committed 6 years ago

Commit 7e901291 parent aeac24d5 files · +191 −82Browse files

Unified · Split

5 files
  1. Makefile +3 −10
  2. tcc.h +0 −1
  3. tccgen.c +185 −69
  4. tccpp.c +0 −2
  5. tests/tcctest.c +3 −0
Makefile+3−10
@@ -238,20 +238,13 @@ XTCC ?= ./tcc$(EXESUF) · 237 unmodified lines
238 238
239# TinyCC runtime libraries239# TinyCC runtime libraries
240libtcc1.a : tcc$(EXESUF) FORCE240libtcc1.a : tcc$(EXESUF) FORCE
241 @$(MAKE) -C lib DEFINES='$(DEF-$T)'241 @$(MAKE) -C lib
242 242
243# Cross libtcc1.a243# Cross libtcc1.a
244%-libtcc1.a : %-tcc$(EXESUF) FORCE244%-libtcc1.a : %-tcc$(EXESUF) FORCE
245 @$(MAKE) -C lib DEFINES='$(DEF-$*)' CROSS_TARGET=$*245 @$(MAKE) -C lib CROSS_TARGET=$*
246 246
247# TinyCC runtime libraries247.PRECIOUS: %-libtcc1.a
248libtccb1.a : libtcc1.a
249
250# Cross libtcc1.a
251%-libtccb1.a : %-tcc$(EXESUF) FORCE
252 @$(MAKE) -C lib DEFINES='$(DEF-$*)' CROSS_TARGET=$*
253
254.PRECIOUS: %-libtcc1.a %-libtccb1.a
255FORCE:248FORCE:
256 249
257# --------------------------------------------------------------------------250# --------------------------------------------------------------------------
tcc.h+0−1
@@ -1434,7 +1434,6 @@ ST_FUNC void parse_mult_str (CString *astr, const char *msg); · 1433 unmodified lines
1434ST_FUNC void parse_asm_str(CString *astr);1434ST_FUNC void parse_asm_str(CString *astr);
1435ST_FUNC void indir(void);1435ST_FUNC void indir(void);
1436ST_FUNC void unary(void);1436ST_FUNC void unary(void);
1437ST_FUNC void init_prec(void);
1438ST_FUNC void gexpr(void);1437ST_FUNC void gexpr(void);
1439ST_FUNC int expr_const(void);1438ST_FUNC int expr_const(void);
1440#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C671439#if defined CONFIG_TCC_BCHECK || defined TCC_TARGET_C67
tccgen.c+185−69
@@ -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 */
69static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); }69static void gjmp_addr_acs(int t) { gjmp_addr(t); CODE_OFF(); }
70static int gjmp_acs(int t) { if (!nocode_wanted) {t = gjmp(t); CODE_OFF(); } return t; }70static 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_acs73#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
128static void init_prec(void);
129#endif
125/********************************************************/130/********************************************************/
126#ifndef CONFIG_TCC_ASM131#ifndef CONFIG_TCC_ASM
127ST_FUNC void asm_instr(void)132ST_FUNC void asm_instr(void)
@@ -135,7 +140,6 @@ ST_FUNC void asm_global_instr(void) · 7 unmodified lines
135#endif140#endif
136 141
137/* ------------------------------------------------------------------------- */142/* ------------------------------------------------------------------------- */
138
139static void gen_cast(CType *type);143static void gen_cast(CType *type);
140static void gen_cast_s(int t);144static void gen_cast_s(int t);
141static inline CType *pointed_type(CType *type);145static 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
460ST_FUNC int tccgen_compile(TCCState *s1)467ST_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 vtop884 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
1040static void vset_VT_JMP(void)1047static 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
1060static void gvtst_set(int inv, int t)1064static 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
1082static int gvtst(int inv, int t)1082static 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 context5689#ifndef precedence_parser /* original top-down parser */
5694 (i.e. compared with zero) return 0 if it's false, 1 if5690
5695 true and -1 if it can't be statically determined. */5691static void expr_prod(void)
5696static 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
5703static 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
5715static 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
5727static 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
5740static 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
5752static 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
5762static void expr_xor(void)
5763{
5764 expr_and();
5765 while (tok == '^') {
5766 next();
5767 expr_and();
5768 gen_op('^');
5769 }
5770}
5771
5772static void expr_or(void)
5773{
5774 expr_xor();
5775 while (tok == '|') {
5776 next();
5777 expr_xor();
5778 gen_op('|');
5779 }
5780}
5781
5782static void expr_landor(int op);
5783
5784static void expr_land(void)
5785{
5786 expr_or();
5787 if (tok == TOK_LAND)
5788 expr_landor(tok);
5789}
5790
5791static 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
5709static int precedence(int tok)5803static 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
5729static unsigned char prec[256];5822static unsigned char prec[256];
5730ST_FUNC void init_prec(void)5823static 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
5739static void expr_infix(int p);5831static void expr_landor(int op);
5740static 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
5760static void expr_infix(int p)5833static 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. */
5854static 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
5867static 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
5777static int is_cond_bool(SValue *sv)5895static 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();
tccpp.c+0−2
@@ -3679,8 +3679,6 @@ ST_FUNC void tccpp_new(TCCState *s) · 3678 unmodified lines
3679 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);3679 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
3680 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);3680 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
3681 define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);3681 define_push(TOK___COUNTER__, MACRO_OBJ, NULL, NULL);
3682
3683 init_prec();
3684}3682}
3685 3683
3686ST_FUNC void tccpp_delete(TCCState *s)3684ST_FUNC void tccpp_delete(TCCState *s)
tests/tcctest.c+3−0
@@ -3736,6 +3736,9 @@ void builtin_test(void) · 3735 unmodified lines
3736 printf("res = %d\n", __builtin_constant_p(&constant_p_var));3736 printf("res = %d\n", __builtin_constant_p(&constant_p_var));
3737 printf("res = %d\n", __builtin_constant_p(constant_p_var));3737 printf("res = %d\n", __builtin_constant_p(constant_p_var));
3738 printf("res = %d\n", __builtin_constant_p(100000 / constant_p_var));3738 printf("res = %d\n", __builtin_constant_p(100000 / constant_p_var));
3739 printf("res = %d\n", __builtin_constant_p(i && 0));
3740 printf("res = %d\n", __builtin_constant_p(i && 1));
3741 printf("res = %d\n", __builtin_constant_p(i && 0 ? i : 34));
3739 s = 1;3742 s = 1;
3740 ll = 2;3743 ll = 2;
3741 i = __builtin_choose_expr (1 != 0, ll, s);3744 i = __builtin_choose_expr (1 != 0, ll, s);

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