ref: 1dcded18a01420a8f57227792522897bcf919a88
parent: 6c7885a58e1d1202fbad71e09d423f8d637e25f8
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Mon Aug 17 16:31:53 EDT 2015
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.
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -82,6 +82,9 @@
struct caselist {
short nr;
Symbol *deflabel;
+ Symbol *ltable;
+ Symbol *lbreak;
+ Node *expr;
struct scase *head;
};
@@ -282,6 +285,7 @@
ORET,
ODECL,
OSWITCH,
+ OSWITCHT,
OAND,
OOR,
OEQ,
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -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 *),
@@ -55,7 +55,7 @@
[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] = "}",
@@ -121,6 +121,7 @@
[ORET] = emitret,
[ODECL] = emitdcl,
[OSWITCH] = emitswitch,
+ [OSWITCHT] = emitswitcht,
[OPAR] = emitbin,
[OCALL] = emitbin
};
@@ -368,7 +369,25 @@
{
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 *
--- a/cc1/stmt.c
+++ b/cc1/stmt.c
@@ -189,14 +189,13 @@
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:
@@ -207,22 +206,16 @@
}
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
@@ -243,6 +236,7 @@
emit(OLABEL, pcase->label = newsym(NS_LABEL));
lswitch->head = pcase;
++lswitch->nr;
+ stmt(lbreak, lcont, lswitch);
}
static void
@@ -254,6 +248,8 @@
expect(':');
emit(OLABEL, ldefault);
lswitch->deflabel = ldefault;
+ ++lswitch->nr;
+ stmt(lbreak, lcont, lswitch);
}
static void
--- /dev/null
+++ b/cc1/tests/test012.c
@@ -1,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;
+ }
+}