History

Rework expr_landor

so that it also is called from the precedence parser. This is complicated by the fact that something needs to be done before the second operand is parsed in a single pass compiler, so it doesn't quite fit into expr_infix itself. It turns out the smallest code changes result when expr_landor remains separate. But it can be tidied a bit.

Michael Matz committed 6 years ago

Commit aeac24d1 parent 23a8bac3 files · +117 −96Browse files

Unified · Split

3 files
  1. tccgen.c +79 −95
  2. tests/tcctest.c +36 −0
  3. tests/tests2/11_precedence.c +2 −1
tccgen.c+79−95
@@ -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) { t = gjmp(t); CODE_OFF(); return t; }70static 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_acs73#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 vtop877 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 else1070 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) */
1076static int gvtst(int inv, int t)1082static 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. */
5696static 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
5684static int precedence(int tok)5709static 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;
5691relat: 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
5712static void expr_infix(int p)5739static void expr_infix(int p);
5713{5740static 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
5726static void expr_or(void)
5727{
5728 unary();
5729 expr_infix(1);
5730}
5731
5732static int condition_3way(void);
5733
5734static 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
5764static void expr_land(void)5760static void expr_infix(int p)
5765{
5766 expr_or();
5767 if (tok == TOK_LAND)
5768 expr_landor(expr_or, TOK_LAND, 1);
5769}
5770
5771static 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. */
5781static 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
5794static int is_cond_bool(SValue *sv)5777static 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();
tests/tcctest.c+36−0
@@ -84,6 +84,7 @@ void scope_test(); · 83 unmodified lines
84void scope_test2();84void scope_test2();
85void forward_test();85void forward_test();
86void funcptr_test();86void funcptr_test();
87void if_test();
87void loop_test();88void loop_test();
88void switch_test();89void switch_test();
89void goto_test();90void goto_test();
@@ -513,6 +514,40 @@ void string_test() · 423 unmodified lines
513 }514 }
514}515}
515 516
517void if1t(int n, int a, int b, int c)
518{
519 if (a && b) printf("if1t: %d 1 %d %d\n", n, a, b);
520 if (a && !b) printf("if1t: %d 2 %d %d\n", n, a, b);
521 if (!a && b) printf("if1t: %d 3 %d %d\n", n, a, b);
522 if (!a && !b) printf("if1t: %d 4 %d %d\n", n, a, b);
523 if (a || b) printf("if1t: %d 5 %d %d\n", n, a, b);
524 if (a || !b) printf("if1t: %d 6 %d %d\n", n, a, b);
525 if (!a || b) printf("if1t: %d 7 %d %d\n", n, a, b);
526 if (!a || !b) printf("if1t: %d 8 %d %d\n", n, a, b);
527 if (a && b || c) printf("if1t: %d 9 %d %d %d\n", n, a, b, c);
528 if (a || b && c) printf("if1t: %d 10 %d %d %d\n", n, a, b, c);
529 if (a > b - 1 && c) printf("if1t: %d 11 %d %d %d\n", n, a, b, c);
530 if (a > b - 1 || c) printf("if1t: %d 12 %d %d %d\n", n, a, b, c);
531 if (a > 0 && 1) printf("if1t: %d 13 %d %d %d\n", n, a, b, c);
532 if (a > 0 || 0) printf("if1t: %d 14 %d %d %d\n", n, a, b, c);
533}
534
535void if2t(void)
536{
537 if (0 && 1 || printf("if2t:ok\n") || 1)
538 printf("if2t:ok2\n");
539 printf("if2t:ok3\n");
540}
541
542void if_test(void)
543{
544 if1t(1, 0, 0, 0);
545 if1t(2, 0, 3, 0);
546 if1t(3, 2, 0, 0);
547 if1t(4, 2, 3, 0);
548 if2t();
549}
550
516void loop_test()551void loop_test()
517{552{
518 int i;553 int i;
@@ -728,6 +763,7 @@ int main(int argc, char **argv) · 209 unmodified lines
728 scope_test2();763 scope_test2();
729 forward_test();764 forward_test();
730 funcptr_test();765 funcptr_test();
766 if_test();
731 loop_test();767 loop_test();
732 switch_test();768 switch_test();
733 goto_test();769 goto_test();
tests/tests2/11_precedence.c+2−1
@@ -1,4 +1,5 @@
1#include <stdio.h>1//#include <stdio.h>
2extern int printf(const char *, ...);
2 3
3int main()4int main()
4{5{

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