summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2021-10-10 19:46:42 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2021-10-10 19:46:42 +0200
commitf895cabf52336db0f2a259bbe6fae6e6fc81c98a (patch)
tree7070d2689b0f589c4c0da91f7050c9ce0aafc033
parent121209ac9702979d16b73340ec6a3a38adbe1b03 (diff)
downloadcompilertests-f895cabf52336db0f2a259bbe6fae6e6fc81c98a.tar.gz
compilertests-f895cabf52336db0f2a259bbe6fae6e6fc81c98a.tar.bz2
cc: work on int, char types
-rw-r--r--miniany/TODOS22
-rwxr-xr-xminiany/autobuild.sh24
-rw-r--r--miniany/cc.c101
-rw-r--r--miniany/test1.c3
4 files changed, 123 insertions, 27 deletions
diff --git a/miniany/TODOS b/miniany/TODOS
index e69de29..530d46b 100644
--- a/miniany/TODOS
+++ b/miniany/TODOS
@@ -0,0 +1,22 @@
+- emul-i386:
+ - running without tracing, maybe with trapping, just mmap, execute
+ and setting the stack (simple loader), maybe binfmt-compatible?
+- asm-i386:
+ - device a new version which runs on c4 and is again freestanding
+ - extend the opcodes slightly so we can use our current generator
+ (and not the old inefficient stack machine)
+- c4/cc:
+ - function forward definitons
+ - checkout c5-AST branch
+ - inline assembly
+ - void parameter declaration for functions like f(void) instead of f()
+ - global char array declarations: instead of char *buf, malloc(512) we could
+ use char buf[512]
+ - static: just ignore, we don't have a linker, otoh, just rewrite it whithout static,
+ vararg, etc. so the code will later respect local definitions of functions.
+ do not allow non-reentrant f() { static var; } constructs.
+ - volatile: we are not doing any optimizations for now, so volatile (as const)
+ can just be a ignored keyword.
+ - void * allowing to omit (char *) from and to for instance structs
+ in dynamic memory management
+
diff --git a/miniany/autobuild.sh b/miniany/autobuild.sh
index e174ff4..8de5629 100755
--- a/miniany/autobuild.sh
+++ b/miniany/autobuild.sh
@@ -1,13 +1,29 @@
#!/bin/bash
cat >/tmp/autobuild_tmp_$$.sh <<EOF
-#!/bin/bash
+#!/bin/bash -x
echo "---"
./build.sh cc tcc hosted d
-./cc < test1.c > test1.asm
-fasm test1.asm test1.bin
-../ecomp-c/emul -v test1.bin
+if test \$? -eq 0; then
+ ./cc < test1.c > test1.asm
+ if test \$? -eq 0; then
+ fasm test1.asm test1.bin
+ if test \$? -eq 0; then
+ ../ecomp-c/emul -v test1.bin
+ if test \$? -ne 0; then
+ echo "ERROR: running emulator with test1.bin"
+ fi
+ else
+ echo "ERROR: assembling test1.asm"
+ fi
+ else
+ echo "ERROR: compiling test1.c"
+ grep '; ERROR' test1.asm
+ fi
+else
+ echo "ERROR: building cc"
+fi
EOF
chmod 775 /tmp/autobuild_tmp_$$.sh
diff --git a/miniany/cc.c b/miniany/cc.c
index c630a8f..e977bc9 100644
--- a/miniany/cc.c
+++ b/miniany/cc.c
@@ -25,6 +25,8 @@ enum {
S_MORE,
S_MORE_OR_EQUALS,
S_INT = 50,
+ S_CHAR,
+ S_VOID,
S_IF,
S_ELSE,
S_WHILE,
@@ -50,7 +52,7 @@ struct Scanner {
void scannerPrintErrorHeader( struct Scanner *scanner )
{
putnl( );
- putstring( "Error line " );
+ putstring( "; ERROR: line " );
putint( scanner->row );
putstring( ", pos " );
putint( scanner->col );
@@ -163,6 +165,12 @@ void scanIdent( struct Scanner *scanner )
int keyword( char *ident )
{
switch( ident[0] ) {
+ case 'c':
+ if( strcmp( ident, "char" ) == 0 ) {
+ return S_CHAR;
+ }
+ break;
+
case 'd':
if( strcmp( ident, "do" ) == 0 ) {
return S_DO;
@@ -189,6 +197,12 @@ int keyword( char *ident )
}
break;
+ case 'v':
+ if( strcmp( ident, "void" ) == 0 ) {
+ return S_VOID;
+ }
+ break;
+
case 'w':
if( strcmp( ident, "while" ) == 0 ) {
return S_WHILE;
@@ -330,16 +344,24 @@ int getToken( struct Scanner *scanner )
/* symbol table */
+enum {
+ SYMBOL_CLASS_VARIABLE,
+ SYMBOL_CLASS_FUNCTION
+};
+
struct Symbol {
- char *name;
- struct Symbol *next;
+ int class; /* class SYMBOL_CLASS_XXX */
+ char *name; /* name of the symbol */
+ int type; /* type of variable when type is SYMBOL_CLASS_VARIABLE */
+ struct Symbol *next; /* pointer to next symbol */
};
-struct Symbol *createSymbol( char *s )
+struct Symbol *createSymbol( int class, char *s )
{
struct Symbol *sym;
sym = (struct Symbol *)malloc( sizeof ( struct Symbol ) );
+ sym->class = class;
sym->name = strdup( s );
sym->next = NULL;
@@ -586,11 +608,19 @@ void putlow8reg( struct Generator *generator, int reg )
}
-void genAddGlob( struct Generator *generator, char *ident )
+void genAddGlob( struct Generator *generator, struct Symbol *sym )
{
- putstring( ident );
+ putstring( sym->name );
putstring( ": " );
- putstring( "dd $0" );
+ switch( sym->type ) {
+ case S_INT:
+ putstring( "dd $0" );
+ break;
+
+ case S_CHAR:
+ putstring( "db $0" );
+ break;
+ }
putnl( );
}
@@ -988,7 +1018,9 @@ void genEpilogue( struct Compiler *compiler )
putstring( "hlt" ); putnl( );
sym = compiler->parser->global_scope->sym;
while( sym != NULL ) {
- genAddGlob( compiler->generator, sym->name );
+ if( sym->class == SYMBOL_CLASS_VARIABLE ) {
+ genAddGlob( compiler->generator, sym );
+ }
sym = sym->next;
}
putstring( "putint_string_fmt:" ); putnl( );
@@ -1180,17 +1212,38 @@ struct ASTnode *parseExpression( struct Parser *parser, int level )
return left;
}
-void parseDeclaration( struct Compiler *compiler )
+int parseType( struct Compiler *compiler )
+{
+ struct Parser *parser;
+ int type;
+
+ parser = compiler->parser;
+ if( parser->token == S_INT || parser->token == S_CHAR || parser->token == S_VOID ) {
+ type = parser->token;
+ parser->token = getToken( parser->scanner );
+ } else {
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "type expected" );
+ putnl( );
+ exit( EXIT_FAILURE );
+ }
+
+ return type;
+}
+
+void parseVariableDeclaration( struct Compiler *compiler )
{
struct Parser *parser;
struct Symbol *sym;
+ int type;
parser = compiler->parser;
- parserExpect( parser, S_INT, "int" );
+ type = parseType( compiler );
parserExpect( parser, S_IDENT, "identifier" );
sym = getSymbol( parser->global_scope, parser->scanner->ident );
if( sym == NULL ) {
- sym = createSymbol( parser->scanner->ident );
+ sym = createSymbol( SYMBOL_CLASS_VARIABLE, parser->scanner->ident );
+ sym->type = type;
insertSymbol( parser->global_scope, sym );
} else {
scannerPrintErrorHeader( parser->scanner );
@@ -1338,7 +1391,7 @@ void parseWhile( struct Compiler *compiler )
putstring( "jmp " ); putstring( label2 ); putnl( );
putstring( label1 ); putchar( ':' ); putnl( );
if( parser->debug ) {
- putstring( "; fi" ); putnl( );
+ putstring( "; end while" ); putnl( );
}
free( label2 );
free( label1 );
@@ -1359,6 +1412,9 @@ void parseDo( struct Compiler *compiler )
putstring( label1 ); putchar( ':' ); putnl( );
parseStatementBlock( compiler );
parserExpect( parser, S_WHILE, "while" );
+ if( parser->debug ) {
+ putstring( "; end do, while <cond>" ); putnl( );
+ }
parserExpect( parser, S_LPAREN, "(" );
node = parseExpression( parser, 0 );
generateFromAST( compiler->generator, node, NOREG );
@@ -1375,8 +1431,8 @@ void parseStatement( struct Compiler *compiler )
struct Parser *parser;
parser = compiler->parser;
- if( parser->token == S_INT ) {
- parseDeclaration( compiler );
+ if( parser->token == S_INT || parser->token == S_CHAR ) {
+ parseVariableDeclaration( compiler );
} else if( parser->token == S_IDENT ) {
parseAssignment( compiler );
} else if( parser->token == S_PUTINT ) {
@@ -1415,22 +1471,22 @@ void parseFunctionDeclaration( struct Compiler *compiler )
{
struct Parser *parser;
struct Symbol *sym;
+ int type;
parser = compiler->parser;
- if( parser->token == S_IDENT ) {
- if( strcmp( parser->scanner->ident, "void" ) != 0 ) {
- scannerPrintErrorHeader( parser->scanner );
- putstring( "expected void as return value of a function declaration" );
- putnl( );
- exit( EXIT_FAILURE );
- }
+ type = parseType( compiler );
+ if( type != S_VOID ) {
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "expected void as return value of a function declaration" );
+ putnl( );
+ exit( EXIT_FAILURE );
}
parserExpect( parser, S_IDENT, "identifier" );
sym = getSymbol( parser->global_scope, parser->scanner->ident );
if( sym == NULL ) {
- sym = createSymbol( parser->scanner->ident );
+ sym = createSymbol( SYMBOL_CLASS_FUNCTION, parser->scanner->ident );
insertSymbol( parser->global_scope, sym );
} else {
scannerPrintErrorHeader( parser->scanner );
@@ -1450,7 +1506,6 @@ void parseFunctionDeclaration( struct Compiler *compiler )
putstring( parser->scanner->ident ); putchar( ':' ); putnl( );
putstring( "push ebp" ); putnl( );
putstring( "mov ebp, esp" ); putnl( );
- parser->token = getToken( compiler->parser->scanner );
parserExpect( parser, S_LPAREN, "(" );
parserExpect( parser, S_RPAREN, ")" );
parseStatementBlock( compiler );
diff --git a/miniany/test1.c b/miniany/test1.c
index 9c971ca..2358298 100644
--- a/miniany/test1.c
+++ b/miniany/test1.c
@@ -2,6 +2,7 @@
void main( )
{
+ char c;
int i;
int j;
int k;
@@ -37,4 +38,6 @@ void main( )
putint( i );
i = i+1;
} while( i <= 5 );
+
+ c = 42;
}