summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2021-10-29 20:32:34 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2021-10-29 20:32:34 +0200
commitdf1a8de0d0667f39b51cffa812dca780cc48bc14 (patch)
tree2ac78c7146ca9c06cfddefad6f1f0d9985b423ff
parent62924274b391dbfd16f4349bd46a2136f2a78b0e (diff)
downloadcompilertests-df1a8de0d0667f39b51cffa812dca780cc48bc14.tar.gz
compilertests-df1a8de0d0667f39b51cffa812dca780cc48bc14.tar.bz2
cc:
- some work on function calls (with default EAX return and no params), also added a return statement - fix code generator for division (case when EDX is the operand resulting in endless loops)
-rw-r--r--README.bootstrapping3
-rw-r--r--miniany/cc.c166
-rw-r--r--miniany/cc.wg8
-rw-r--r--miniany/test1.c38
4 files changed, 173 insertions, 42 deletions
diff --git a/README.bootstrapping b/README.bootstrapping
index d68295b..6d77295 100644
--- a/README.bootstrapping
+++ b/README.bootstrapping
@@ -17,7 +17,8 @@ https://github.com/ras52/bootstrap
bcompiler
---------
-https://web.archive.org/web/20061108010907/http://www.rano.org/bcompiler.html
+https://web.archive.org/web/20061108010907/
+http://www.rano.org/bcompiler.html
https://github.com/certik/bcompiler
asmc
diff --git a/miniany/cc.c b/miniany/cc.c
index c72d290..44cdd76 100644
--- a/miniany/cc.c
+++ b/miniany/cc.c
@@ -31,6 +31,7 @@ enum {
S_ELSE,
S_WHILE,
S_DO,
+ S_RETURN,
S_PUTINT,
S_PUTCHAR,
S_IDENT = 60,
@@ -199,6 +200,12 @@ int keyword( char *ident )
return S_PUTCHAR;
}
break;
+
+ case 'r':
+ if( strcmp( ident, "return" ) == 0 ) {
+ return S_RETURN;
+ }
+ break;
case 'v':
if( strcmp( ident, "void" ) == 0 ) {
@@ -355,8 +362,9 @@ enum {
struct Symbol {
int class; /* class SYMBOL_CLASS_XXX */
char *name; /* name of the symbol */
- int type; /* type of variable when type is SYMBOL_CLASS_VARIABLE */
+ int type; /* type of variable when class is SYMBOL_CLASS_VARIABLE */
struct Symbol *next; /* pointer to next symbol */
+ int return_type; /* return type when class is SYMBOL_CLASS_FUNCTION */
};
struct Symbol *createSymbol( int class, char *s )
@@ -455,6 +463,7 @@ enum {
A_LESS_OR_EQUALS,
A_MORE,
A_MORE_OR_EQUALS,
+ A_FUNC_CALL,
A_ERR = 99
};
@@ -480,6 +489,11 @@ struct ASTnode *createASTnode( int op, struct ASTnode *left, struct ASTnode *rig
return node;
}
+struct ASTnode *createASTunary( int op, struct ASTnode *left )
+{
+ return createASTnode( op, left, NULL, 0, NULL );
+}
+
struct ASTnode *createASTbinary( int op, struct ASTnode *left, struct ASTnode *right )
{
return createASTnode( op, left, right, 0, NULL );
@@ -751,15 +765,23 @@ int genLoadIdent( struct Generator *generator, struct Symbol *sym )
switch( sym->type ) {
case S_INT:
putreg( generator, reg );
+ putstring( ", [" );
+ putstring( sym->name );
+ putstring( "]" );
+ putnl( );
break;
case S_CHAR:
putlow8reg( generator, reg );
+ putstring( ", [" );
+ putstring( sym->name );
+ putstring( "]" );
+ putnl( );
+ putstring( "and " );
+ putreg( generator, reg );
+ putstring( ", $FF" );
+ putnl( );
break;
}
- putstring( ", [" );
- putstring( sym->name );
- putstring( "]" );
- putnl( );
return reg;
}
@@ -868,17 +890,18 @@ int genDiv( struct Generator *generator, int leftreg, int rightreg )
if( !generator->regFree[EDX] ) {
genSaveReg( generator, EDX );
}
- if( rightreg == EAX ) {
+ if( rightreg == EAX || rightreg == EDX ) {
genSaveReg( generator, EBX );
- putstring( "mov ebx, eax" );
+ putstring( "mov ebx, " );
+ putreg( generator, rightreg );
putnl( );
- }
+ }
putstring( "mov eax, " );
putreg( generator, leftreg );
putnl( );
putstring( "mov edx, 0" );
putnl( );
- if( rightreg == EAX ) {
+ if( rightreg == EAX || rightreg == EDX ) {
reg = genBinary( "div", generator, EAX, EBX, 1 );
genRestoreReg( generator, EBX );
} else {
@@ -920,6 +943,15 @@ int genCompare( char *op, struct Generator *generator, int leftreg, int rightreg
return leftreg;
}
+int genFuncCall( struct Generator *generator, char *name )
+{
+ putstring( "call " );
+ putstring( name );
+ putnl( );
+
+ return EAX;
+}
+
int generateFromAST( struct Generator *generator, struct ASTnode *node, int inreg )
{
int leftreg, rightreg, reg;
@@ -976,11 +1008,16 @@ int generateFromAST( struct Generator *generator, struct ASTnode *node, int inre
case A_MORE_OR_EQUALS:
reg = genCompare( "setge", generator, leftreg, rightreg );
break;
+ case A_FUNC_CALL:
+ reg = genFuncCall( generator, node->sym->name );
+ break;
default:
+ scannerPrintErrorHeader( generator->scanner );
+ putstring( "unhandled AST node operation '" );
putint( node->op );
- putstring( "?" );
- break;
-
+ putstring( "'" );
+ putnl( );
+ exit( EXIT_FAILURE );
}
return reg;
@@ -1182,6 +1219,24 @@ int parserOperatorPrecedence( struct Parser *parser, int operator )
return precedence;
}
+struct ASTnode *parseExpression( struct Parser *parser, int level );
+
+struct ASTnode *parseFunctionCall( struct Parser *parser, struct Symbol *sym )
+{
+ struct ASTnode *node, *left;
+
+ parserExpect( parser, S_LPAREN, "(" );
+ /* TODO: parse parameters as expressions:
+ left = parseExpression( parser, 0 );
+ */
+ left = NULL;
+ parserExpect( parser, S_RPAREN, ")" );
+ node = createASTunary( A_FUNC_CALL, left );
+ node->sym = sym;
+
+ return node;
+}
+
struct ASTnode *parseExpression( struct Parser *parser, int level )
{
struct ASTnode *left, *right;
@@ -1197,6 +1252,7 @@ struct ASTnode *parseExpression( struct Parser *parser, int level )
if( parser->token == S_NUM ) {
left = createASTleafInt( A_INT_LITERAL, parser->scanner->num );
+ parser->token = getToken( parser->scanner );
} else if( parser->token == S_IDENT ) {
sym = getSymbol( parser->global_scope, parser->scanner->ident );
if( sym == NULL ) {
@@ -1207,7 +1263,23 @@ struct ASTnode *parseExpression( struct Parser *parser, int level )
putnl( );
exit( EXIT_FAILURE );
}
- left = createASTleafSym( A_IDENT, sym );
+ if( sym->class == SYMBOL_CLASS_VARIABLE ) {
+ left = createASTleafSym( A_IDENT, sym );
+ parser->token = getToken( parser->scanner );
+ } else if( sym->class == SYMBOL_CLASS_FUNCTION ) {
+ parser->token = getToken( parser->scanner );
+ left = parseFunctionCall( parser, sym );
+ } else {
+ left = NULL;
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "unknown class '" );
+ putint( sym->class );
+ putstring( "' of identifier '" );
+ putstring( parser->scanner->ident );
+ putstring( "' in expression" );
+ putnl( );
+ exit( EXIT_FAILURE );
+ }
} else {
left = NULL;
scannerPrintErrorHeader( parser->scanner );
@@ -1218,7 +1290,6 @@ struct ASTnode *parseExpression( struct Parser *parser, int level )
exit( EXIT_FAILURE );
}
- parser->token = getToken( parser->scanner );
if( parser->token == S_EOI || parser->token == S_SEMICOLON || parser->token == S_RPAREN ) {
return left;
}
@@ -1240,7 +1311,7 @@ struct ASTnode *parseExpression( struct Parser *parser, int level )
int parseType( struct Compiler *compiler )
{
struct Parser *parser;
- int type;
+ int type = S_ERR;
parser = compiler->parser;
if( parser->token == S_INT || parser->token == S_CHAR || parser->token == S_VOID ) {
@@ -1298,15 +1369,31 @@ void parseAssignment( struct Compiler *compiler )
putnl( );
exit( EXIT_FAILURE );
}
- right = createASTleafSym( A_LVIDENT, sym );
- parserExpect( parser, S_ASSIGN, "=" );
- left = parseExpression( parser, 0 );
- parserExpect( parser, S_SEMICOLON, ";" );
-
- node = createASTbinary( A_ASSIGN, left, right );
- generateFromAST( compiler->generator, node, NOREG );
- genFreeAllRegs( compiler->generator );
- freeASTnode( node );
+ if( sym->class == SYMBOL_CLASS_VARIABLE ) {
+ right = createASTleafSym( A_LVIDENT, sym );
+ parserExpect( parser, S_ASSIGN, "=" );
+ left = parseExpression( parser, 0 );
+ parserExpect( parser, S_SEMICOLON, ";" );
+
+ node = createASTbinary( A_ASSIGN, left, right );
+ generateFromAST( compiler->generator, node, NOREG );
+ genFreeAllRegs( compiler->generator );
+ freeASTnode( node );
+ } else if( sym->class == SYMBOL_CLASS_FUNCTION ) {
+ node = parseFunctionCall( parser, sym );
+ parserExpect( parser, S_SEMICOLON, ";" );
+ generateFromAST( compiler->generator, node, NOREG );
+ freeASTnode( node );
+ } else {
+ scannerPrintErrorHeader( parser->scanner );
+ putstring( "symbol '" );
+ putstring( parser->scanner->ident );
+ putstring( "' has unexpected class '" );
+ putint( sym->class );
+ putstring( "'" );
+ putnl( );
+ exit( EXIT_FAILURE );
+ }
}
void parsePutint( struct Compiler *compiler )
@@ -1378,6 +1465,7 @@ void parseIf( struct Compiler *compiler )
putstring( "; if <cond> then" ); putnl( );
}
generateFromAST( compiler->generator, node, NOREG );
+ freeASTnode( node );
/* TODO: this should be condensed and optimized for the normal path
* (rare ifs, invert the condition, jmpXX directly */
putstring( "cmp al, 0" ); putnl( );
@@ -1424,6 +1512,7 @@ void parseWhile( struct Compiler *compiler )
label2 = genGetLabel( compiler, compiler->parser->global_scope );
putstring( label2 ); putchar( ':' ); putnl( );
generateFromAST( compiler->generator, node, NOREG );
+ freeASTnode( node );
putstring( "cmp al, 0" ); putnl( );
genFreeAllRegs( compiler->generator );
label1 = genGetLabel( compiler, compiler->parser->global_scope );
@@ -1460,6 +1549,7 @@ void parseDo( struct Compiler *compiler )
parserExpect( parser, S_LPAREN, "(" );
node = parseExpression( parser, 0 );
generateFromAST( compiler->generator, node, NOREG );
+ freeASTnode( node );
putstring( "cmp al, 0" ); putnl( );
genFreeAllRegs( compiler->generator );
putstring( "jne " ); putstring( label1 ); putnl( );
@@ -1468,6 +1558,19 @@ void parseDo( struct Compiler *compiler )
free( label1 );
}
+void parseReturn( struct Compiler *compiler )
+{
+ struct Parser *parser;
+ struct ASTnode *node;
+
+ parser = compiler->parser;
+ parserExpect( parser, S_RETURN, "return" );
+ node = parseExpression( parser, 0 );
+ generateFromAST( compiler->generator, node, NOREG );
+ freeASTnode( node );
+ parserExpect( parser, S_SEMICOLON, ";" );
+}
+
void parseStatement( struct Compiler *compiler )
{
struct Parser *parser;
@@ -1487,6 +1590,8 @@ void parseStatement( struct Compiler *compiler )
parseWhile( compiler );
} else if( parser->token == S_DO ) {
parseDo( compiler );
+ } else if( parser->token == S_RETURN ) {
+ parseReturn( compiler );
} else if( parser->token == S_RBRACE || parser->token == S_EOI ) {
return;
} else {
@@ -1520,18 +1625,13 @@ void parseFunctionDeclaration( struct Compiler *compiler )
parser = compiler->parser;
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( SYMBOL_CLASS_FUNCTION, parser->scanner->ident );
insertSymbol( parser->global_scope, sym );
+ sym->return_type = type;
} else {
scannerPrintErrorHeader( parser->scanner );
putstring( "duplicate global symbol '" );
@@ -1551,10 +1651,12 @@ void parseFunctionDeclaration( struct Compiler *compiler )
putstring( "push ebp" ); putnl( );
putstring( "mov ebp, esp" ); putnl( );
parserExpect( parser, S_LPAREN, "(" );
+ /* TODO: parse parameter list */
parserExpect( parser, S_RPAREN, ")" );
parseStatementBlock( compiler );
putstring( "pop ebp" ); putnl( );
putstring( "ret" ); putnl( );
+ genFreeAllRegs( compiler->generator );
}
/* compiler */
@@ -1589,7 +1691,9 @@ int main( int argc, char **argv )
/* compiler->generator->debug = 1; */
genPrologue( compiler );
compiler->parser->token = getToken( compiler->parser->scanner );
- parseFunctionDeclaration( compiler );
+ while( compiler->parser->token != S_EOI ) {
+ parseFunctionDeclaration( compiler );
+ }
genEpilogue( compiler );
freeCompiler( compiler );
diff --git a/miniany/cc.wg b/miniany/cc.wg
index 2a0ad6d..352d664 100644
--- a/miniany/cc.wg
+++ b/miniany/cc.wg
@@ -29,9 +29,9 @@ WordGrinder dumpfile v3: this is a text file; diff me!
.clipboard.margin: 0
.clipboard.viewmode: 1
.clipboard.wordcount: 6
-.documents.1.co: 7
-.documents.1.cp: 31
-.documents.1.cw: 25
+.documents.1.co: 6
+.documents.1.cp: 38
+.documents.1.cw: 8
.documents.1.margin: 0
.documents.1.name: "main"
.documents.1.sticky_selection: false
@@ -141,7 +141,7 @@ WordGrinder dumpfile v3: this is a text file; diff me!
.menu.accelerators.ZU: "UP"
.menu.accelerators.ZWL: "^LEFT"
.menu.accelerators.ZWR: "^RIGHT"
-.name: "/media/sd/abaumann/projects/compilertests/miniany/cc.wg"
+.name: "/home/abaumann/projects/compilertests/miniany/cc.wg"
.replacetext: ""
.statusbar: true
.current: 1
diff --git a/miniany/test1.c b/miniany/test1.c
index 30650f0..4c919ce 100644
--- a/miniany/test1.c
+++ b/miniany/test1.c
@@ -1,8 +1,23 @@
/* test1 */
+/* TODO: check void (no return allowed) and check for int (in this case it is required) */
+int f( )
+{
+ return 42;
+}
+
+void f2( )
+{
+ putint( 44 );
+}
+
void main( )
{
- char c;
+ // TODO: allow enumeration of variable declarations
+ char c1;
+ char c2;
+ char c3;
+ char c4;
int i;
int j;
int k;
@@ -31,15 +46,26 @@ void main( )
i = 5;
while( i > 0 ) {
putint( i );
- i = i-1;
+ i = i - 1;
}
i = 1;
do {
putint( i );
- i = i+1;
+ i = i + 1;
} while( i <= 5 );
- c = 41;
- c = c + 1;
- putchar( c );
+ c1 = 422; // TODO: wrong narrowing from int const to char type, must be catched
+ c1 = 41;
+ c2 = c1 + 1;
+ c3 = c2 + 1;
+ c4 = c3 + 1;
+ putchar( c1 );
+ putchar( c2 );
+ putchar( c3 );
+ putchar( c4 );
+ i = f( );
+ putint( i );
+ f2( );
+ // TODO: disallow this assignment, LHS is a function, RHS is an integer literal
+ //f = 1;
}