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
6767
6868 /* Set 'nocode_wanted' after unconditional jumps */
6969 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; }
7171
7272 /* These are #undef'd at the end of this file */
7373 #define gjmp_addr gjmp_addr_acs
@@ -877,7 +877,7 @@ static void vcheck_cmp(void) · 803 unmodified lines
877877 again, so that the VT_CMP/VT_JMP value will be in vtop
878878 when code is unsuppressed again. */
879879
880− if (vtop->r == VT_CMP && !nocode_wanted)
880+ if (vtop->r == VT_CMP && !nocode_wanted && vtop->cmp_op > 1)
881881 gv(RC_INT);
882882 }
883883
@@ -1043,7 +1043,11 @@ static void vset_VT_JMP(void) · 159 unmodified lines
10431043 if (vtop->jtrue || vtop->jfalse) {
10441044 /* we need to jump to 'mov $0,%R' or 'mov $1,%R' */
10451045 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);
10471051 } else {
10481052 /* otherwise convert flags (rsp. 0/1) to register */
10491053 vtop->c.i = op;
@@ -1061,9 +1065,11 @@ static void gvtst_set(int inv, int t) · 11 unmodified lines
10611065 gen_op(TOK_NE);
10621066 if (vtop->r == VT_CMP) /* must be VT_CONST otherwise */
10631067 ;
1064− else if (vtop->r == VT_CONST)
1065− vset_VT_CMP(vtop->c.i != 0);
1066− else
1068+ else if (vtop->r == VT_CONST) {
1069+ if (!t)
1070+ return;
1071+ vset_VT_CMP(vtop->c.i != 0);
1072+ } else
10671073 tcc_error("ICE");
10681074 }
10691075 p = inv ? &vtop->jfalse : &vtop->jtrue;
@@ -1075,18 +1081,21 @@ static void gvtst_set(int inv, int t) · 5 unmodified lines
10751081 * Generate a test for any value (jump, comparison and integers) */
10761082 static int gvtst(int inv, int t)
10771083 {
1078− int op, u, x;
1079−
1084+ int op, x, u;
10801085 gvtst_set(inv, t);
1081−
1082− t = vtop->jtrue, u = vtop->jfalse;
1083− if (inv)
1084− x = u, u = t, t = x;
1085− op = vtop->cmp_op;
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+ }
10861095
10871096 /* jump to the wanted target */
10881097 if (op > 1)
1089− t = gjmp_cond(op ^ inv, t);
1098+ t = gjmp_cond(op ^ inv, t), op = inv;//, op = 1;
10901099 else if (op != inv)
10911100 t = gjmp(t);
10921101 /* resolve complementary jumps to here */
@@ -5681,17 +5690,35 @@ special_math_val: · 4588 unmodified lines
56815690 }
56825691 }
56835692
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+
56845709 static int precedence(int tok)
56855710 {
56865711 switch (tok) {
5687− case '|': return 1;
5688− case '^': return 2;
5689− case '&': return 3;
5690− case TOK_EQ: case TOK_NE: return 4;
5691−relat: case TOK_ULT: case TOK_UGE: return 5;
5692− case TOK_SHL: case TOK_SAR: return 6;
5693− case '+': case '-': return 7;
5694− case '*': case '/': case '%': return 8;
5712+ case TOK_LOR: return 1;
5713+ case TOK_LAND: return 2;
5714+ case '|': return 3;
5715+ case '^': return 4;
5716+ case '&': return 5;
5717+ case TOK_EQ: case TOK_NE: return 6;
5718+ relat: case TOK_ULT: case TOK_UGE: return 7;
5719+ case TOK_SHL: case TOK_SAR: return 8;
5720+ case '+': case '-': return 9;
5721+ case '*': case '/': case '%': return 10;
56955722 default:
56965723 if (tok >= TOK_ULE && tok <= TOK_GT)
56975724 goto relat;
@@ -5709,86 +5736,42 @@ ST_FUNC void init_prec(void) · 11 unmodified lines
57095736
57105737 #define precedence(i) ((unsigned)i < 256 ? prec[i] : 0)
57115738
5712−static void expr_infix(int p)
5713−{
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)
5739+static void expr_infix(int p);
5740+static void expr_landor(int p, int e_op, int i)
57355741 {
5736− int t = 0, cc = 1, f = 0, c;
5737− for(;;) {
5738− c = f ? i : condition_3way();
5739− if (c < 0) {
5740− save_regs(1), cc = 0;
5741− } else if (c != i) {
5742+ int t = 0, f = 0;
5743+ save_regs(1);
5744+ do {
5745+ if (!f && condition_3way() == !i)
57425746 nocode_wanted++, f = 1;
5743− }
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();
5747+ t = gvtst(i, t);
57595748 next();
5760− e_fn();
5749+ unary();
5750+ expr_infix(p);
5751+ } while (tok == e_op);
5752+ if (f) {
5753+ vpop();
5754+ vpushi(i ^ f);
57615755 }
5756+ gvtst_set(i, t);
5757+ nocode_wanted -= f;
57625758 }
57635759
5764−static void expr_land(void)
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)
5760+static void expr_infix(int p)
57825761 {
5783− int c = -1;
5784− if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST &&
5785− (!(vtop->r & VT_SYM) || !vtop->sym->a.weak)) {
5786− vdup();
5787− gen_cast_s(VT_BOOL);
5788− c = vtop->c.i;
5789− vpop();
5762+ int t = tok, p2;
5763+ while ((p2 = precedence(t)) >= p) {
5764+ if (t == TOK_LOR || t == TOK_LAND) {
5765+ expr_landor(p2 + 1, t, t == TOK_LAND);
5766+ } else {
5767+ next();
5768+ unary();
5769+ if (precedence(tok) > p2)
5770+ expr_infix(p2 + 1);
5771+ gen_op(t);
5772+ }
5773+ t = tok;
57905774 }
5791− return c;
57925775 }
57935776
57945777 static int is_cond_bool(SValue *sv)
@@ -5808,7 +5791,8 @@ static void expr_cond(void) · 13 unmodified lines
58085791 CType type, type1, type2;
58095792 int ncw_prev;
58105793
5811− expr_lor();
5794+ unary();
5795+ expr_infix(1);
58125796 if (tok == '?') {
58135797 next();
58145798 c = condition_3way();
tests/tcctest.c+36−0
@@ -84,6 +84,7 @@ void scope_test(); · 83 unmodified lines
8484 void scope_test2();
8585 void forward_test();
8686 void funcptr_test();
87+void if_test();
8788 void loop_test();
8889 void switch_test();
8990 void goto_test();
@@ -513,6 +514,40 @@ void string_test() · 423 unmodified lines
513514 }
514515 }
515516
517+void 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+
535+void if2t(void)
536+{
537+ if (0 && 1 || printf("if2t:ok\n") || 1)
538+ printf("if2t:ok2\n");
539+ printf("if2t:ok3\n");
540+}
541+
542+void 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+
516551 void loop_test()
517552 {
518553 int i;
@@ -728,6 +763,7 @@ int main(int argc, char **argv) · 209 unmodified lines
728763 scope_test2();
729764 forward_test();
730765 funcptr_test();
766+ if_test();
731767 loop_test();
732768 switch_test();
733769 goto_test();
tests/tests2/11_precedence.c+2−1
@@ -1,4 +1,5 @@
1−#include <stdio.h>
1+//#include <stdio.h>
2+extern int printf(const char *, ...);
23
34 int main()
45 {

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