commit e4c9da7e693f8c2ad9008ad2c895654d563905fe
parent f7fddfcd7659f0545c8b3eb367f11f3f68dab7c0
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 18 Aug 2015 09:56:40 +0200
Merge branch 'master' of ssh://suckless.org/gitrepos/scc
Diffstat:
7 files changed, 155 insertions(+), 25 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -82,6 +82,9 @@ struct scase {
struct caselist {
short nr;
Symbol *deflabel;
+ Symbol *ltable;
+ Symbol *lbreak;
+ Node *expr;
struct scase *head;
};
@@ -282,6 +285,7 @@ enum op {
ORET,
ODECL,
OSWITCH,
+ OSWITCHT,
OAND,
OOR,
OEQ,
diff --git 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 @@ 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] = "}",
@@ -121,6 +121,7 @@ void (*opcode[])(unsigned, void *) = {
[ORET] = emitret,
[ODECL] = emitdcl,
[OSWITCH] = emitswitch,
+ [OSWITCHT] = emitswitcht,
[OPAR] = emitbin,
[OCALL] = emitbin
};
@@ -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/decl.c b/cc1/decl.c
@@ -301,7 +301,8 @@ specifier(int *sclass)
break;
case LONG:
if (size == LONG) {
- size = LLONG;
+ yylval.token = LLONG;
+ size = 0;
break;
}
case SHORT:
diff --git a/cc1/stmt.c b/cc1/stmt.c
@@ -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:
@@ -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
@@ -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
@@ -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/chktest.sh b/cc1/tests/chktest.sh
@@ -23,7 +23,7 @@ do
/^output:$/ {
copyon=1
}
- /^\*/ {
+ /^\*\// {
copyon=0
}
copyon==1 && !/^output:$/ {
diff --git a/cc1/tests/test012.c b/cc1/tests/test012.c
@@ -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;
+ }
+}
diff --git a/cc1/types.c b/cc1/types.c
@@ -222,7 +222,6 @@ ctype(unsigned type, unsigned sign, unsigned size)
goto invalid_type;
return booltype;
case 0:
- warn("type defaults to 'int' in declaration");
/* fallthrough */
case INT:
switch (size) {