summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2021-08-19 07:52:26 +0000
committerAndreas Baumann <mail@andreasbaumann.cc>2021-08-19 07:52:26 +0000
commit9fc685a2237b789800b770f3bc1eecb8e1bfdf7b (patch)
tree1b8e937715d7d11f84ff116acf1b9a2fa7c56c67
parent5dc6889265cb5f0c385778f075279ed8012023a0 (diff)
downloadcompilertests-9fc685a2237b789800b770f3bc1eecb8e1bfdf7b.tar.gz
compilertests-9fc685a2237b789800b770f3bc1eecb8e1bfdf7b.tar.bz2
c4: added switch statement
-rw-r--r--miniany/c4.c50
-rw-r--r--miniany/cc.c143
-rwxr-xr-xminiany/torture.sh12
3 files changed, 141 insertions, 64 deletions
diff --git a/miniany/c4.c b/miniany/c4.c
index a36fb4a..9acba4e 100644
--- a/miniany/c4.c
+++ b/miniany/c4.c
@@ -18,6 +18,9 @@ char *p, *lp, // current position in source code
*data; // data/bss pointer
int *e, *le, // current position in emitted code
+ *cas, // case statement patch-up pointer
+ *brak, // break statement patch-up pointer
+ *def, // default statement patch-up pointer
*id, // currently parsed identifier
*sym, // symbol table (simple list of identifiers)
tk, // current token
@@ -31,7 +34,7 @@ int *e, *le, // current position in emitted code
// tokens and classes (operators last and in precedence order)
enum {
Num = 128, Fun, Sys, Glo, Loc, Id,
- Char, Else, Enum, If, Int, Return, Sizeof, Do, While,
+ Break, Case, Char, Default, Else, Enum, If, Int, Return, Sizeof, Do, Switch, While,
Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak
};
@@ -59,7 +62,7 @@ void next()
while (le < e) {
printf("%8.4s", &"LEA ,IMM ,JMP ,JSR ,BZ ,BNZ ,ENT ,ADJ ,LEV ,LI ,LC ,SI ,SC ,PSH ,"
"OR ,XOR ,AND ,EQ ,NE ,LT ,GT ,LE ,GE ,SHL ,SHR ,ADD ,SUB ,MUL ,DIV ,MOD ,"
- "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU.IALP,SCMP,EXIT,"[*++le * 5]);
+ "OPEN,READ,CLOS,PRTF,MALC,FREE,MSET,MCMP,GETC,PUTS,PUTN,PUTC,PUTI,ISPC,IDGT,IANU,IALP,SCMP,EXIT,"[*++le * 5]);
if (*le <= ADJ) printf(" %d\n", *++le); else printf("\n");
}
}
@@ -293,7 +296,7 @@ void expr(int lev)
void stmt()
{
- int *a, *b;
+ int *a, *b, *d, i;
if (tk == If) {
next();
@@ -333,6 +336,43 @@ void stmt()
*++e = JMP; *++e = (int)a;
*b = (int)(e + 1);
}
+ else if (tk == Switch) {
+ next();
+ if (tk == '(') next(); else { printf("%d: open paren expected\n", line); exit(-1); }
+ expr(Assign);
+ if (tk == ')') next(); else { printf("%d: close paren expected\n", line); exit(-1); }
+ a = cas; *++e = JMP; cas = ++e;
+ b = brak; d = def; brak = def = 0;
+ stmt();
+ *cas = def ? (int)def : (int)(e + 1); cas = a;
+ while (brak) { a = (int *)*brak; *brak = (int)(e + 1); brak = a; }
+ brak = b; def = d;
+ }
+ else if (tk == Case) {
+ *++e = JMP; ++e; *e = (int)(e + 7); *++e = PSH; i = *cas; *cas = (int)e;
+ next();
+ expr(Or);
+ if (e[-1] != IMM) { printf("%d: bad case immediate\n", line); exit(-1); }
+ *e = *e - i; *++e = SUB; *++e = BNZ; cas = ++e; *e = i + e[-3];
+ if (tk == ':') {
+ next();
+ }
+ else {
+ printf("%d: colon expected\n", line); exit(-1);
+ }
+ stmt();
+ }
+ else if (tk == Break) {
+ next();
+ if (tk == ';') next(); else { printf("%d: semicolon expected\n", line); exit(-1); }
+ *++e = JMP; *++e = (int)brak; brak = e;
+ }
+ else if (tk == Default) {
+ next();
+ if (tk == ':') next(); else { printf("%d: colon expected\n", line); exit(-1); }
+ def = e + 1;
+ stmt();
+ }
else if (tk == Return) {
next();
if (tk != ';') expr(Assign);
@@ -376,10 +416,10 @@ int main(int argc, char **argv)
memset(e, 0, poolsz);
memset(data, 0, poolsz);
- p = "char else enum if int return sizeof do while "
+ p = "break case char default else enum if int return sizeof do switch while "
"EOF EXIT_SUCCESS EXIT_FAILURE NULL "
"open read close printf malloc free memset memcmp getchar putstring putnl putchar putint isspace isdigit isalnum isalpha strcmp exit void main";
- i = Char; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table
+ i = Break; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table
// add library constants
next(); id[Class] = Num; id[Type] = INT; id[Val] = -1;
next(); id[Class] = Num; id[Type] = INT; id[Val] = 0;
diff --git a/miniany/cc.c b/miniany/cc.c
index e5b30c7..ba7ead2 100644
--- a/miniany/cc.c
+++ b/miniany/cc.c
@@ -114,15 +114,17 @@ void scanIdent( int c )
int keyword( char *ident )
{
- if( *ident == 'i' ) {
- if( strcmp( ident, "int" ) == 0 ) {
- return S_INT;
- } else {
- return 0;
- }
+ switch( ident[0] ) {
+ case 'i':
+ if( strcmp( ident, "int" ) == 0 ) {
+ return S_INT;
+ } else {
+ return 0;
+ }
+ break;
+ default:
+ return 0;
}
-
- return 0;
}
int getToken( )
@@ -132,55 +134,76 @@ int getToken( )
c = skipWhite( );
- if( c == EOF ) {
- t = S_EOI;
- } else if( c == '+' ) {
- t = S_PLUS;
- } else if( c == '-' ) {
- t = S_MINUS;
- } else if( c == '*' ) {
- t = S_STAR;
- } else if ( c == '/' ) {
- c = getChar( );
- if( c == '/' ) {
- while( c != '\n' ) {
- c = getChar( );
- }
- t = getToken( );
- } else if( c == '*' ) {
- do {
- while( c != '*' ) {
+ switch( c ) {
+ case EOF:
+ t = S_EOI;
+ break;
+ case '+':
+ t = S_PLUS;
+ break;
+ case '-':
+ t = S_MINUS;
+ break;
+ case '*':
+ t = S_STAR;
+ break;
+ case '/':
+ c = getChar( );
+ if( c == '/' ) {
+ while( c != '\n' ) {
c = getChar( );
}
+ t = getToken( );
+ } else if( c == '*' ) {
+ do {
+ while( c != '*' ) {
+ c = getChar( );
+ }
+ c = getChar( );
+ } while( c != '/' );
c = getChar( );
- } while( c != '/' );
- c = getChar( );
- t = getToken( );
- } else {
- pushBack( c );
- t = S_SLASH;
- }
- } else if( c == ';' ) {
- t = S_SEMICOLON;
- } else if( c == '=' ) {
- t = S_EQUALS;
- } else if( isdigit( c ) ) {
- scanNumber( c );
- t = S_NUM;
- } else if( c >= 'a' && c <= 'z' ) {
- scanIdent( c );
- if( ( t = keyword( ident ) ) ) {
- } else {
- t = S_IDENT;
- }
- } else {
- t = S_ERR;
- printErrorHeader( );
- putstring( "unknown token '" );
- putchar( c );
- putstring( "'" );
- putnl( );
- exit( EXIT_FAILURE );
+ t = getToken( );
+ } else {
+ pushBack( c );
+ t = S_SLASH;
+ }
+ break;
+ case ';':
+ t = S_SEMICOLON;
+ break;
+ case '=':
+ t = S_EQUALS;
+ break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ scanNumber( c );
+ t = S_NUM;
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e':
+ case 'f': case 'g': case 'h': case 'i': case 'j':
+ case 'k': case 'l': case 'm': case 'n': case 'o':
+ case 'p': case 'q': case 'r': case 's': case 't':
+ case 'u': case 'v': case 'w': case 'y': case 'z':
+ case 'A': case 'B': case 'C': case 'D': case 'E':
+ case 'F': case 'G': case 'H': case 'I': case 'J':
+ case 'K': case 'L': case 'M': case 'N': case 'O':
+ case 'P': case 'Q': case 'R': case 'S': case 'T':
+ case 'U': case 'V': case 'W': case 'Y': case 'Z':
+ case '_':
+ scanIdent( c );
+ if( ( t = keyword( ident ) ) ) {
+ } else {
+ t = S_IDENT;
+ }
+ break;
+ default:
+ t = S_ERR;
+ printErrorHeader( );
+ putstring( "unknown token '" );
+ putchar( c );
+ putstring( "'" );
+ putnl( );
+ exit( EXIT_FAILURE );
}
if( DEBUG_SCANNER ) {
@@ -253,11 +276,13 @@ void parseExpression( )
}
}
-//~ struct Symbol {
- //~ char *name;
-//~ };
+/*
+struct Symbol {
+ char *name;
+};
-//~ struct Symbol *symbol;
+struct Symbol *symbol;
+*/
void newSymbol( char *s )
{
@@ -298,7 +323,7 @@ int main( int argc, char **argv )
row = 1;
pushback = 0;
DEBUG_SCANNER = 1;
- //~ symbol = NULL;
+ /* symbol = NULL; */
ident = "12345678901234567890";
token = getToken( );
diff --git a/miniany/torture.sh b/miniany/torture.sh
new file mode 100755
index 0000000..06c41c4
--- /dev/null
+++ b/miniany/torture.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+
+for COMPILER in gcc clang pcc tcc; do
+ $COMPILER -m32 -o c4 c4.c
+ for MODE in freestanding hosted; do
+ for LEVEL in 0; do
+ ./build.sh cc $COMPILER $MODE $LEVEL
+ ./cc < cc.c
+ done
+ done
+done