From f895cabf52336db0f2a259bbe6fae6e6fc81c98a Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sun, 10 Oct 2021 19:46:42 +0200 Subject: cc: work on int, char types --- miniany/TODOS | 22 +++++++++++ miniany/autobuild.sh | 24 ++++++++++-- miniany/cc.c | 101 +++++++++++++++++++++++++++++++++++++++------------ miniany/test1.c | 3 ++ 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 < 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 " ); 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; } -- cgit v1.2.3-54-g00ecf