From 102450c101cb1496c7e0eaf2240aa9e6a8bd90f2 Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Thu, 20 Aug 2020 15:12:14 +0200 Subject: got parameter type checking working properly --- ecomp-c/ec.c | 108 ++++++++++++++------- ...rocedure_call_value_parameters_wrong_types.easm | 48 +++++++++ ...ure_call_value_parameters_wrong_types.ecomp_err | 1 + 3 files changed, 121 insertions(+), 36 deletions(-) create mode 100644 ecomp-c/tests/procedure_call_value_parameters_wrong_types.easm create mode 100644 ecomp-c/tests/procedure_call_value_parameters_wrong_types.ecomp_err diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c index 1e8dc63..7501ec5 100644 --- a/ecomp-c/ec.c +++ b/ecomp-c/ec.c @@ -681,6 +681,7 @@ typedef struct Symbol { /* procedure type */ char *label; struct Scope *scope; + struct Symbol *param; } Symbol; static Symbol *integer_type; @@ -722,6 +723,15 @@ static void free_symbol( Symbol *sym ) if( sym->label != NULL ) { free( sym->label ); } + if( sym->param != NULL ) { + Symbol *param, *tmp; + param = sym->param; + while( param != NULL ) { + tmp = param->next; + free_symbol( param ); + param = tmp; + } + } free( sym->name ); free( sym ); } @@ -779,36 +789,61 @@ static Symbol *get_symbol( Scope *scope, char *name ) return NULL; } +static Symbol *create_symbol( char *name, SymbolClass class ) +{ + Symbol *symbol; + + symbol = Allocate( sizeof( Symbol ) ); + symbol->class = class; + symbol->name = Allocate( strlen( name ) + 1 ); + strlcpy( symbol->name, name, strlen( name ) + 1 ); + symbol->size = 0; + symbol->offset = 0; + symbol->dim = 0; + symbol->string_value = NULL; + symbol->intarr_value = NULL; + symbol->type = NULL; + symbol->label = NULL; + symbol->param = NULL; + + return symbol; +} + +static Symbol *copy_symbol( Symbol *symbol ) +{ + Symbol *copy; + + copy = Allocate( sizeof( Symbol ) ); + memcpy( copy, symbol, sizeof( Symbol ) ); + copy->name = AllocateAndCopyStr( symbol->name ); + copy->string_value = AllocateAndCopyStr( symbol->string_value ); + copy->label = AllocateAndCopyStr( symbol->label ); + + return copy; +} + static Symbol *insert_symbol( Scope *scope, char *name, SymbolClass class ) { - Symbol *sym; + Symbol *symbol; - sym = scope->symbol; - while( sym != NULL ) { - if( strcmp( sym->name, name ) == 0 ) { - return sym; + symbol = scope->symbol; + while( symbol != NULL ) { + if( strcmp( symbol->name, name ) == 0 ) { + return symbol; } - sym = sym->next; + symbol = symbol->next; } - if( sym != NULL ) { + if( symbol != NULL ) { Abort( "'%s' is already defined.", name ); } + + symbol = create_symbol( name, class ); - sym = Allocate( sizeof( Symbol ) ); - sym->class = class; - sym->name = Allocate( strlen( name ) + 1 ); - strlcpy( sym->name, name, strlen( name ) + 1 ); - sym->size = 0; - sym->offset = 0; - sym->dim = 0; - sym->next = scope->symbol; - sym->string_value = NULL; - sym->intarr_value = NULL; - sym->label = NULL; - scope->symbol = sym; + symbol->next = scope->symbol; + scope->symbol = symbol; scope->nof_symbols++; - return sym; + return symbol; } static char moduleName[MAX_IDENT_LEN+1]; @@ -1582,11 +1617,9 @@ static void parseProcedureCall( Scope *scope ) symbol = get_symbol( scope, ident ); nof_expected_params = 0; - param = symbol->scope->symbol; + param = symbol->param; while( param != NULL ) { - if( param->offset < 0 ) { - nof_expected_params++; - } + nof_expected_params++; param = param->next; } @@ -1609,14 +1642,12 @@ static void parseProcedureCall( Scope *scope ) /* check types */ if( nof_expected_params > 0 ) { node = head; - param = symbol->scope->symbol; + param = symbol->param; while( param != NULL ) { - if( param->offset < 0 ) { - param = param->next; - continue; + if( !is_compatible_type( node->actual_type, param->type ) ) { + Abort( "Incompatible parameter type for parameter '%s' in procedure '%s', expecting type '%s', got '%s'", + param->name, symbol->name, param->type->name, node->actual_type->name ); } - fprintf( stderr, "%s %s\n", node->actual_type->name, - symbol->scope->symbol->type->name ); node = node->next; param = param->next; } @@ -2105,13 +2136,9 @@ static void parseParameterDeclaration( Scope *scope ) symbol = insert_symbol( scope, ident, SYMBOL_CLASS_VARIABLE ); sym = getSym( ); - /* TODO: allocate size for parameters on stack, make sure they - * are allocated on the other side of the stack - */ - Expect( S_colon ); - symbol->type = parseType( scope ); + symbol->type = parseType( scope ); } static void parseParameterDeclarationList( Scope *scope ) @@ -2160,7 +2187,7 @@ static void parseProcedureDeclaration( Scope *scope ) size_params = 0; } else if( sym == S_lparen ) { - Symbol *param; + Symbol *param, *copy; int offset; parseParameterDeclarationList( symbol->scope ); @@ -2171,6 +2198,9 @@ static void parseProcedureDeclaration( Scope *scope ) param = symbol->scope->symbol; + /* compute size and offsets of parameter on the stack, + * also remember the types of the parameters for type + * checking when generating a produre call */ size_params = 0; offset = -4; while( param != NULL ) { @@ -2182,6 +2212,12 @@ static void parseProcedureDeclaration( Scope *scope ) param->name, param->offset, size ); offset -= size; } + + copy = copy_symbol( param ); + copy->scope = NULL; + copy->next = symbol->param; + symbol->param = copy; + param = param->next; } } diff --git a/ecomp-c/tests/procedure_call_value_parameters_wrong_types.easm b/ecomp-c/tests/procedure_call_value_parameters_wrong_types.easm new file mode 100644 index 0000000..d7fb8b4 --- /dev/null +++ b/ecomp-c/tests/procedure_call_value_parameters_wrong_types.easm @@ -0,0 +1,48 @@ +format binary +use32 +org $1000000 +jmp __global_0 +; DECL i -> integer, 1 +; param x, offset: -8, size: 4 +; PROC proc +__global_proc: +push ebp +push esp +pop ebp +; DECL l -> integer, 0 +; local l, offset: 4, size: 4 +mov eax, 4 +sub esp, eax +push ebp +pop ebx +mov eax, 4 +sub ebx, eax +mov eax, 0 +mov [ebx], eax +; LET l <- x +push ebp +pop ebx +mov eax, -8 +sub ebx, eax +mov eax, [ebx] +push eax +push ebp +pop ebx +mov eax, 4 +sub ebx, eax +pop eax +mov [ebx], eax +; LET i <- l +push ebp +pop ebx +mov eax, 4 +sub ebx, eax +mov eax, [ebx] +push eax +pop eax +mov [i], eax +mov eax, 4 +add esp, eax +pop ebp +ret 4 +__global_0: diff --git a/ecomp-c/tests/procedure_call_value_parameters_wrong_types.ecomp_err b/ecomp-c/tests/procedure_call_value_parameters_wrong_types.ecomp_err new file mode 100644 index 0000000..3ce59a7 --- /dev/null +++ b/ecomp-c/tests/procedure_call_value_parameters_wrong_types.ecomp_err @@ -0,0 +1 @@ +Error line 20, pos 1: Incompatible parameter type for parameter 'x' in procedure 'proc', expecting type 'integer', got 'boolean' -- cgit v1.2.3-54-g00ecf