diff options
Diffstat (limited to 'ecomp-c/ec.c')
-rw-r--r-- | ecomp-c/ec.c | 111 |
1 files changed, 98 insertions, 13 deletions
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c index c98c766..46ee4b4 100644 --- a/ecomp-c/ec.c +++ b/ecomp-c/ec.c @@ -692,6 +692,7 @@ typedef struct Scope { int label_no; struct Symbol *symbol; struct Scope *parent; + int size_locals; } Scope; static Scope *global_scope; @@ -1028,10 +1029,28 @@ static void emit_expression_code( ExpressionNode *node, Scope *scope ) case EXPRESSION_NODE_TYPE_VAR: switch( get_size( node->symbol ) ) { case 4: - Emit( "mov eax, [%s]\n", node->symbol->name ); + /* TODO: cleanup local global variable access */ + if( node->symbol->offset == 0 ) { + Emit( "mov eax, [%s]\n", node->symbol->name ); + } else { + Emit( "push ebp\n" ); + Emit( "pop ebx\n" ); + Emit( "mov eax, %d\n", node->symbol->offset ); + Emit( "sub ebx, eax\n" ); + Emit( "mov eax, [ebx]\n" ); + } break; case 1: - Emit( "mov al, [%s]\n", node->symbol->name ); + /* TODO: cleanup local global variable access */ + if( node->symbol->offset == 0 ) { + Emit( "mov al, [%s]\n", node->symbol->name ); + } else { + Emit( "push ebp\n" ); + Emit( "pop ebx\n" ); + Emit( "mov eax, %d\n", node->symbol->offset ); + Emit( "sub ebx, eax\n" ); + Emit( "mov al, [ebx]\n" ); + } break; default: Abort( "Unhandled size %d when reading register from memory", node->symbol->size ); @@ -1355,14 +1374,35 @@ static void parseAssignment( Scope *scope ) Emit( "\n" ); emit_expression_code( node, scope ); - Emit( "pop eax\n" ); switch( get_size( symbol ) ) { case 4: - Emit( "mov [%s], eax\n", symbol->name ); + /* TODO: cleanup local global variable access */ + if( symbol->offset == 0 ) { + Emit( "pop eax\n" ); + Emit( "mov [%s], eax\n", symbol->name ); + } else { + Emit( "push ebp\n" ); + Emit( "pop ebx\n" ); + Emit( "mov eax, %d\n", symbol->offset ); + Emit( "sub ebx, eax\n" ); + Emit( "pop eax\n" ); + Emit( "mov [ebx], eax\n" ); + } break; case 1: - Emit( "mov [%s], al\n", symbol->name ); + /* TODO: cleanup local global variable access */ + if( symbol->offset == 0 ) { + Emit( "pop eax\n" ); + Emit( "mov [%s], al\n", symbol->name ); + } else { + Emit( "push ebp\n" ); + Emit( "pop ebx\n" ); + Emit( "mov eax, %d\n", symbol->offset ); + Emit( "sub ebx, eax\n" ); + Emit( "pop eax\n" ); + Emit( "mov [ebx], al\n" ); + } break; default: Abort( "Unhandled size %d when storing register immediately to memory", symbol->size ); @@ -1962,7 +2002,7 @@ static void parseProcedureBlock( Scope *scope ) if( sym == S_const || sym == S_var || sym == S_begin ) { Symbol *sym; - int size_locals; + int offset; Emit( "; PROC %s\n", symbol->name ); @@ -1982,30 +2022,75 @@ static void parseProcedureBlock( Scope *scope ) parseProcedureDeclarationBlock( symbol->scope ); - size_locals = 0; + /* compute sizes of all locals */ + offset = 4; + scope->size_locals = 0; sym = symbol->scope->symbol; while( sym != NULL ) { if( sym->class == SYMBOL_CLASS_VARIABLE ) { - size_locals += get_size( sym ); + int size = get_size( sym ); + scope->size_locals += size; + sym->offset = offset; + offset += size; } sym = sym->next; } - if( size_locals > 0 ) { - Emit( "mov eax, %d\n", size_locals ); + /* reserve space on stack */ + if( scope->size_locals > 0 ) { + Emit( "mov eax, %d\n", scope->size_locals ); Emit( "sub esp, eax\n" ); } + /* initialize local variables (sort of reserve_initialize_local) + * at runtime (every time the stack is created for that procedure) */ + sym = symbol->scope->symbol; + while( sym != NULL ) { + if( sym->class == SYMBOL_CLASS_VARIABLE ) { + /* TODO: use type here! */ + int size = get_size( sym ); + switch( size ) { + case 4: + /* TODO: cleanup local global variable access */ + Emit( "push ebp\n" ); + Emit( "pop ebx\n" ); + Emit( "mov eax, %d\n", sym->offset ); + Emit( "sub ebx, eax\n" ); + Emit( "mov eax, %d\n", sym->integer_value ); + Emit( "mov [ebx], eax\n" ); + break; + case 1: + /* TODO: cleanup local global variable access */ + Emit( "push ebp\n" ); + Emit( "pop ebx\n" ); + Emit( "mov eax, %d\n", sym->offset ); + Emit( "sub ebx, eax\n" ); + Emit( "mov eax, %d\n", sym->boolean_value ); + Emit( "mov [ebx], al\n" ); + break; + default: + Abort( "Not handled case when initializing local variable '%s' on stack", symbol->name ); + } + } + sym = sym->next; + } + /* TODO: allocate space on stack for local variables (and * parameters) */ /* TODO: assign symbols to relative addresses (base pointer) */ /* TODO: initialize local variables */ parseStatementBlock( symbol->scope ); - - free_scope( symbol->scope ); - + /* discard locals, reset base pointer */ + + if( scope->size_locals > 0 ) { + Emit( "mov eax, %d\n", scope->size_locals ); + Emit( "add esp, eax\n" ); + } + + free_scope( symbol->scope ); + Emit( "pop ebp\n" ); Emit( "ret\n" ); |