tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] PATCH: Fix handling of case_reg in switch statement.


From: Edmund Grimley Evans
Subject: [Tinycc-devel] PATCH: Fix handling of case_reg in switch statement.
Date: Sun, 9 Oct 2016 23:49:36 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

Does this patch look all right?

    Fix handling of case_reg in switch statement.
    
    The back end functions gen_op(comparison) and gtst() might allocate
    registers so case_reg should be left on the value stack while they
    are called and set again afterwards.
    
    This bug fix was first applied as ff3f9aa on 20 Feb 2015, but the fix
    was reverted by fc0fc6a on 21 Sep 2016 ("switch: collect case ranges
    first, then generate code"). Here the fix is updated for the new code.

diff --git a/tccgen.c b/tccgen.c
index abeb924..63480e2 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -4902,7 +4902,7 @@ static int case_cmp(const void *pa, const void *pb)
     return a < b ? -1 : a > b;
 }
 
-static void gcase(struct case_t **base, int len, int case_reg, int *bsym)
+static int gcase(struct case_t **base, int len, int case_reg, int *bsym)
 {
     struct case_t *p;
     int e;
@@ -4910,17 +4910,25 @@ static void gcase(struct case_t **base, int len, int 
case_reg, int *bsym)
         while (len--) {
             p = *base++;
             vseti(case_reg, 0);
+            vdup();
             vpushi(p->v2);
             if (p->v1 == p->v2) {
                 gen_op(TOK_EQ);
                 gtst_addr(0, p->sym);
+                case_reg = gv(RC_INT);
+                vpop();
             } else {
                 gen_op(TOK_LE);
                 e = gtst(1, 0);
+                case_reg = gv(RC_INT);
+                vpop();
                 vseti(case_reg, 0);
+                vdup();
                 vpushi(p->v1);
                 gen_op(TOK_GE);
                 gtst_addr(0, p->sym);
+                case_reg = gv(RC_INT);
+                vpop();
                 gsym(e);
             }
         }
@@ -4928,15 +4936,21 @@ static void gcase(struct case_t **base, int len, int 
case_reg, int *bsym)
         p = base[len/2];
         /* mid */
         vseti(case_reg, 0);
+        vdup();
         vpushi(p->v2);
         gen_op(TOK_LE);
         e = gtst(1, 0);
+        case_reg = gv(RC_INT);
+        vpop();
         vseti(case_reg, 0);
+        vdup();
         vpushi(p->v1);
         gen_op(TOK_GE);
         gtst_addr(0, p->sym);
+        case_reg = gv(RC_INT);
+        vpop();
         /* left */
-        gcase(base, len/2, case_reg, bsym);
+        case_reg = gcase(base, len/2, case_reg, bsym);
         if (cur_switch->def_sym)
             gjmp_addr(cur_switch->def_sym);
         else
@@ -4944,8 +4958,9 @@ static void gcase(struct case_t **base, int len, int 
case_reg, int *bsym)
         /* right */
         gsym(e);
         e = len/2 + 1;
-        gcase(base + e, len - e, case_reg, bsym);
+        case_reg = gcase(base + e, len - e, case_reg, bsym);
     }
+    return case_reg;
 }
 
 static void block(int *bsym, int *csym, int is_expr)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]