summaryrefslogtreecommitdiff
path: root/miniany/cc.c
diff options
context:
space:
mode:
Diffstat (limited to 'miniany/cc.c')
-rw-r--r--miniany/cc.c62
1 files changed, 53 insertions, 9 deletions
diff --git a/miniany/cc.c b/miniany/cc.c
index e977bc9..c72d290 100644
--- a/miniany/cc.c
+++ b/miniany/cc.c
@@ -32,6 +32,7 @@ enum {
S_WHILE,
S_DO,
S_PUTINT,
+ S_PUTCHAR,
S_IDENT = 60,
S_NUM = 70,
S_EOI = 98,
@@ -194,6 +195,8 @@ int keyword( char *ident )
case 'p':
if( strcmp( ident, "putint" ) == 0 ) {
return S_PUTINT;
+ } else if( strcmp( ident, "putchar" ) == 0 ) {
+ return S_PUTCHAR;
}
break;
@@ -599,7 +602,7 @@ void putlow8reg( struct Generator *generator, int reg )
break;
default:
scannerPrintErrorHeader( generator->scanner );
- putstring( "error using low 8-bit subreguster of reguster '" );
+ putstring( "error using low 8-bit subreguster of register '" );
putstring( generator->regName[reg] );
putstring( "'" );
putnl( );
@@ -739,27 +742,41 @@ int genLoadImm( struct Generator *generator, int intval )
return reg;
}
-int genLoadIdent( struct Generator *generator, char *ident )
+int genLoadIdent( struct Generator *generator, struct Symbol *sym )
{
int reg;
reg = genAllocReg( generator );
putstring( "mov " );
- putreg( generator, reg );
+ switch( sym->type ) {
+ case S_INT:
+ putreg( generator, reg );
+ break;
+ case S_CHAR:
+ putlow8reg( generator, reg );
+ break;
+ }
putstring( ", [" );
- putstring( ident );
+ putstring( sym->name );
putstring( "]" );
putnl( );
return reg;
}
-int genStoreIdent( struct Generator *generator, int reg, char *ident )
+int genStoreIdent( struct Generator *generator, int reg, struct Symbol *sym )
{
putstring( "mov [" );
- putstring( ident );
+ putstring( sym->name );
putstring( "], " );
- putreg( generator, reg );
+ switch( sym->type ) {
+ case S_INT:
+ putreg( generator, reg );
+ break;
+ case S_CHAR:
+ putlow8reg( generator, reg );
+ break;
+ }
putnl( );
return reg;
@@ -921,10 +938,10 @@ int generateFromAST( struct Generator *generator, struct ASTnode *node, int inre
reg = genLoadImm( generator, node->intval );
break;
case A_IDENT:
- reg = genLoadIdent( generator, node->sym->name );
+ reg = genLoadIdent( generator, node->sym );
break;
case A_LVIDENT:
- reg = genStoreIdent( generator, inreg, node->sym->name );
+ reg = genStoreIdent( generator, inreg, node->sym );
break;
case A_ADD:
reg = genAdd( generator, leftreg, rightreg );
@@ -979,6 +996,14 @@ void genPrologue( struct Compiler *compiler )
putstring( "use32" ); putnl( );
putstring( "org $1000000" ); putnl( );
putstring( "jmp _start" ); putnl( );
+ putstring( "putchar:" ); putnl( );
+ putstring( "mov [putint_string_fmt], eax" ); putnl( );
+ putstring( "mov eax, 4" ); putnl( );
+ putstring( "mov ebx, 1" ); putnl( );
+ putstring( "mov ecx, putint_string_fmt" ); putnl( );
+ putstring( "mov edx, 1" ); putnl( );
+ putstring( "int 0x80" ); putnl( );
+ putstring( "ret" ); putnl( );
putstring( "putint:" ); putnl( );
putstring( "mov esi, 0" ); putnl( );
putstring( "lea edi, [putint_string_fmt]" ); putnl( );
@@ -1301,6 +1326,23 @@ void parsePutint( struct Compiler *compiler )
freeASTnode( node );
}
+void parsePutchar( struct Compiler *compiler )
+{
+ struct Parser *parser;
+ struct ASTnode *node;
+
+ parser = compiler->parser;
+ parserExpect( parser, S_PUTCHAR, "putchar" );
+ parserExpect( parser, S_LPAREN, "(" );
+ node = parseExpression( parser, 0 );
+ parserExpect( parser, S_RPAREN, ")" );
+ parserExpect( parser, S_SEMICOLON, ";" );
+ generateFromAST( compiler->generator, node, NOREG );
+ putstring( "call putchar" ); putnl( );
+ genFreeAllRegs( compiler->generator );
+ freeASTnode( node );
+}
+
/* TODO c4: forward reference of function */
void parseStatementBlock( struct Compiler *compiler );
@@ -1437,6 +1479,8 @@ void parseStatement( struct Compiler *compiler )
parseAssignment( compiler );
} else if( parser->token == S_PUTINT ) {
parsePutint( compiler );
+ } else if( parser->token == S_PUTCHAR ) {
+ parsePutchar( compiler );
} else if( parser->token == S_IF ) {
parseIf( compiler );
} else if( parser->token == S_WHILE ) {