[hackers] [scc] Fix switch emittion || Roberto E. Vargas Caballero

From: <git_AT_suckless.org>
Date: Mon, 17 Aug 2015 20:37:59 +0200 (CEST)

commit 1dcded18a01420a8f57227792522897bcf919a88
Author: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
AuthorDate: Mon Aug 17 20:31:53 2015 +0200
Commit: Roberto E. Vargas Caballero <k0ga_AT_shike2.com>
CommitDate: Mon Aug 17 20:31:53 2015 +0200

    Fix switch emittion
    
    Switch was broken in different ways. Case and default statements
    were not composed of label part and statement part, but only
    of the label part. This was not important except in this case:
    
            switch (x)
            case 1:
                    switch (x)
                    case 1:
                            return 0;
    
    The output format for switch is also modified.

diff --git a/cc1/cc1.h b/cc1/cc1.h
index ea8ad78..659fd7e 100644
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
_AT_@ -82,6 +82,9 @@ struct scase {
 struct caselist {
         short nr;
         Symbol *deflabel;
+ Symbol *ltable;
+ Symbol *lbreak;
+ Node *expr;
         struct scase *head;
 };
 
_AT_@ -282,6 +285,7 @@ enum op {
         ORET,
         ODECL,
         OSWITCH,
+ OSWITCHT,
         OAND,
         OOR,
         OEQ,
diff --git a/cc1/code.c b/cc1/code.c
index ec27c71..58bcfe6 100644
--- a/cc1/code.c
+++ b/cc1/code.c
_AT_@ -7,7 +7,7 @@
 #include "../inc/cc.h"
 #include "cc1.h"
 
-static void emitbin(unsigned, void *),
+static void emitbin(unsigned, void *), emitswitcht(unsigned, void *),
             emitcast(unsigned, void *), emitswitch(unsigned, void *),
             emitsym(unsigned, void *),
             emitexp(unsigned, void *),
_AT_@ -55,7 +55,7 @@ char *optxt[] = {
         [OCOMMA] = ",",
         [OLABEL] = "L%d\n",
         [ODEFAULT] = "\tf\tL%d\n",
- [OCASE] = "\tw\tL%d",
+ [OCASE] = "\tv\tL%d",
         [OJUMP] = "\tj\tL%d\n",
         [OBRANCH] = "\tj\tL%d",
         [OEFUN] = "}",
_AT_@ -121,6 +121,7 @@ void (*opcode[])(unsigned, void *) = {
         [ORET] = emitret,
         [ODECL] = emitdcl,
         [OSWITCH] = emitswitch,
+ [OSWITCHT] = emitswitcht,
         [OPAR] = emitbin,
         [OCALL] = emitbin
 };
_AT_@ -368,7 +369,25 @@ emitswitch(unsigned op, void *arg)
 {
         Caselist *lcase = arg;
 
- printf("\teI\t#%0x", lcase->nr);
+ printf("\ts\tL%u", lcase->ltable->id);
+ emitexp(OEXPR, lcase->expr);
+}
+
+static void
+emitswitcht(unsigned op, void *arg)
+{
+ Caselist *lcase = arg;
+ struct scase *p, *next;
+
+ printf("\tt\t#%0x\n", lcase->nr);
+ for (p = lcase->head; p; p = next) {
+ emitsymid(OCASE, p->label);
+ emitexp(OEXPR, p->expr);
+ next = p->next;
+ free(p);
+ }
+ if (lcase->deflabel)
+ emitsymid(ODEFAULT, lcase->deflabel);
 }
 
 Node *
diff --git a/cc1/stmt.c b/cc1/stmt.c
index 294ab5d..c89a131 100644
--- a/cc1/stmt.c
+++ b/cc1/stmt.c
_AT_@ -189,14 +189,13 @@ static void
 Switch(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
 {
         Caselist lcase = {.nr = 0, .head = NULL, .deflabel = NULL};
- struct scase *p, *next;
         Node *cond;
- Symbol *lcond;
- void free(void *ptr);
 
         expect(SWITCH);
         expect ('(');
- cond = expr();
+ cond = eval(expr());
+ /* TODO: why can I not call directly to convert here? */
+
         switch (BTYPE(cond)) {
         case INT:
         case ENUM:
_AT_@ -207,22 +206,16 @@ Switch(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
         }
         expect (')');
 
- lbreak = newsym(NS_LABEL);
- lcond = newsym(NS_LABEL);
- emit(OJUMP, lcond);
- stmt(lbreak, lcont, &lcase);
- emit(OLABEL, lcond);
+ lcase.expr = cond;
+ lcase.lbreak = newsym(NS_LABEL);
+ lcase.ltable = newsym(NS_LABEL);
+
         emit(OSWITCH, &lcase);
- emit(OEXPR, cond);
- for (p = lcase.head; p; p = next) {
- emit(OCASE, p->label);
- emit(OEXPR, p->expr);
- next = p->next;
- free(p);
- }
- if (lcase.deflabel)
- emit(ODEFAULT, lcase.deflabel);
- emit(OLABEL, lbreak);
+ stmt(lbreak, lcont, &lcase);
+ emit(OJUMP, lcase.lbreak);
+ emit(OLABEL, lcase.ltable);
+ emit(OSWITCHT, &lcase);
+ emit(OLABEL, lcase.lbreak);
 }
 
 static void
_AT_@ -243,6 +236,7 @@ Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
         emit(OLABEL, pcase->label = newsym(NS_LABEL));
         lswitch->head = pcase;
         ++lswitch->nr;
+ stmt(lbreak, lcont, lswitch);
 }
 
 static void
_AT_@ -254,6 +248,8 @@ Default(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
         expect(':');
         emit(OLABEL, ldefault);
         lswitch->deflabel = ldefault;
+ ++lswitch->nr;
+ stmt(lbreak, lcont, lswitch);
 }
 
 static void
diff --git a/cc1/tests/test012.c b/cc1/tests/test012.c
new file mode 100644
index 0000000..0457aa8
--- /dev/null
+++ b/cc1/tests/test012.c
_AT_@ -0,0 +1,111 @@
+/*
+name: TEST012
+description: Basic switch test
+output:
+F1
+G1 F1 main
+{
+-
+A2 I x
+ A2 #I0 :I
+ s L4 A2
+L5
+ j L3
+L4
+ t #1
+ v L5 #I0
+L3
+ s L7 A2
+L8
+ s L10 A2
+L11
+ j L12
+L13
+ yI #I1
+ j L9
+L10
+ t #2
+ v L11 #I0
+ f L13
+L9
+ j L6
+L7
+ t #1
+ v L8 #I0
+L6
+ yI #I2
+L12
+ s L15 A2
+L16
+ yI #I3
+ j L14
+L15
+ t #1
+ v L16 #I1
+L14
+ s L18 A2
+ A2 #I2 :I
+L19
+L20
+ yI #I4
+ j L17
+L18
+ t #1
+ v L20 #I1
+L17
+ s L22 A2
+L23
+ yI A2
+L24
+ yI #I1
+L25
+ yI #I1
+ j L21
+L22
+ t #3
+ v L24 #I1
+ v L23 #I0
+ f L25
+L21
+}
+*/
+
+
+
+int
+main()
+{
+ int x;
+
+ x = 0;
+ switch(x)
+ case 0:
+ ;
+ switch(x)
+ case 0:
+ switch(x) {
+ case 0:
+ goto next;
+ default:
+ return 1;
+ }
+ return 2;
+ next:
+ switch(x)
+ case 1:
+ return 3;
+ switch(x) {
+ x = 1 + 1;
+ foo:
+ case 1:
+ return 4;
+ }
+ switch(x) {
+ case 0:
+ return x;
+ case 1:
+ return 1;
+ default:
+ return 1;
+ }
+}
Received on Mon Aug 17 2015 - 20:37:59 CEST

This archive was generated by hypermail 2.3.0 : Mon Aug 17 2015 - 20:48:11 CEST