From 1da96894b6c25c3be9c1a1549befbfe1b8efd8a6 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Sat, 8 Aug 2020 20:02:53 +0200 Subject: more work on local variables --- ecomp-c/ec.c | 111 ++++++++++++++++++++++++++---- ecomp-c/tests/procedure_local_variables.e | 6 +- ecomp-c/tests/procedure_scoping.easm | 10 ++- 3 files changed, 111 insertions(+), 16 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" ); diff --git a/ecomp-c/tests/procedure_local_variables.e b/ecomp-c/tests/procedure_local_variables.e index 2838203..31373ea 100644 --- a/ecomp-c/tests/procedure_local_variables.e +++ b/ecomp-c/tests/procedure_local_variables.e @@ -5,18 +5,20 @@ module procedure_call; var - i : integer := 0; + i : integer := 1; procedure proc; + const C : integer = 42; + var j : integer; k : integer := C; begin j := i; - i := k; + i := j; end begin diff --git a/ecomp-c/tests/procedure_scoping.easm b/ecomp-c/tests/procedure_scoping.easm index 72a9dfb..8f6dc6f 100644 --- a/ecomp-c/tests/procedure_scoping.easm +++ b/ecomp-c/tests/procedure_scoping.easm @@ -15,6 +15,8 @@ pop ebp ; DECL x -> array 2 of integer, array 2 of integer = { ... } ; DECL y -> array 3 of integer, array 3 of integer = { ... } ; DECL z -> integer, 0 +mov eax, 4 +sub esp, eax ; LET x[2 ] <- 3 mov eax, 2 push eax @@ -34,8 +36,14 @@ mov [ebx], eax ; LET z <- 4 mov eax, 4 push eax +push ebp +pop ebx +mov eax, 4 +sub ebx, eax pop eax -mov [z], eax +mov [ebx], eax +mov eax, 4 +add esp, eax pop ebp ret ; PROC B -- cgit v1.2.3-54-g00ecf