scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

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:
Mcc1/cc1.h | 4++++
Mcc1/code.c | 25++++++++++++++++++++++---
Mcc1/decl.c | 3++-
Mcc1/stmt.c | 34+++++++++++++++-------------------
Mcc1/tests/chktest.sh | 2+-
Acc1/tests/test012.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcc1/types.c | 1-
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) {