summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-08-14 21:31:06 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2020-08-14 21:31:06 +0200
commit3d41b8813db0ebe45ce7d0c54604554812ddb484 (patch)
treed0ec0e457b848a5834cfb56c669fc05ac69421d1
parent3e51c4b9c32425a435d090636ea04dce25c3bf24 (diff)
downloadcompilertests-3d41b8813db0ebe45ce7d0c54604554812ddb484.tar.gz
compilertests-3d41b8813db0ebe45ce7d0c54604554812ddb484.tar.bz2
started handling value parameters for procedures
- asm386 handles also negative numbers (for negative offsets for parameters on stack) - parameter handling in stdcall style (procedure handles all of the stack operations)
-rw-r--r--ecomp-c/asm-i386.c17
-rw-r--r--ecomp-c/ec.c170
-rw-r--r--ecomp-c/minie.ebnf9
-rw-r--r--ecomp-c/test1.e19
-rw-r--r--ecomp-c/tests/procedure_call_value_parameters.e20
5 files changed, 187 insertions, 48 deletions
diff --git a/ecomp-c/asm-i386.c b/ecomp-c/asm-i386.c
index 25a1e86..c9de15a 100644
--- a/ecomp-c/asm-i386.c
+++ b/ecomp-c/asm-i386.c
@@ -262,7 +262,12 @@ static void skipWhite( void )
static void number( void )
{
int n = 0;
+ int negative = 0;
+ if( look == '-' ) {
+ negative = 1;
+ look = getChar( );
+ }
if( isDigit( look ) ) {
num = look - '0';
look = getChar( );
@@ -276,6 +281,9 @@ static void number( void )
}
sym = S_number;
}
+ if( negative ) {
+ num = ~num + 1;
+ }
}
static void hexnumber( void )
@@ -418,7 +426,14 @@ static S_Symbol getSym( void )
break;
case '-':
look = getChar( );
- s = S_minus;
+ if( look >= '0' && look <= '9' ) {
+ ungetChar( look );
+ s = S_number;
+ look = '-';
+ number( );
+ } else {
+ s = S_minus;
+ }
break;
case '+':
look = getChar( );
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c
index 5b72bfc..5d42355 100644
--- a/ecomp-c/ec.c
+++ b/ecomp-c/ec.c
@@ -692,7 +692,7 @@ typedef struct Scope {
int label_no;
struct Symbol *symbol;
struct Scope *parent;
- int size_locals;
+ int nof_symbols;
} Scope;
static Scope *global_scope;
@@ -706,6 +706,7 @@ static Scope *create_scope( Scope *parent, char *name )
scope->symbol = NULL;
scope->parent = parent;
scope->label_no = 0;
+ scope->nof_symbols = 0;
return scope;
}
@@ -805,6 +806,7 @@ static Symbol *insert_symbol( Scope *scope, char *name, SymbolClass class )
sym->intarr_value = NULL;
sym->label = NULL;
scope->symbol = sym;
+ scope->nof_symbols++;
return sym;
}
@@ -1541,6 +1543,22 @@ static void parseWhileStatement( Scope *scope )
free( jump_label1 );
}
+static void parseParameterList( Scope *scope )
+{
+ ExpressionNode *node;
+
+ Expect( S_lparen );
+ do {
+ node = parseExpression( scope );
+ if( sym == S_comma ) {
+ sym = getSym( );
+ }
+ } while( sym != S_rparen );
+ Expect( S_rparen );
+
+ (void)node;
+}
+
static void parseStatement( Scope *scope )
{
Symbol *symbol;
@@ -1558,6 +1576,9 @@ static void parseStatement( Scope *scope )
Abort( "Unknown indentifier '%s'", ident );
}
if( symbol->class == SYMBOL_CLASS_PROCEDURE_TYPE ) {
+ if( sym == S_lparen ) {
+ parseParameterList( scope );
+ }
Emit( "call %s\n", symbol->label );
} else {
parseAssignment( scope );
@@ -1990,10 +2011,42 @@ static void parseProcedureDeclarationBlock( Scope *scope )
}
}
-static void parseProcedureBlock( Scope *scope )
+static void parseParameterDeclaration( Scope *scope )
+{
+ Symbol *symbol;
+
+ Expect( S_ident );
+ symbol = insert_symbol( scope, ident, SYMBOL_CLASS_VARIABLE );
+
+ /* 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 );
+}
+
+static void parseParameterDeclarationList( Scope *scope )
+{
+ Expect( S_lparen );
+ do {
+ if( sym == S_ident ) {
+ parseParameterDeclaration( scope );
+ if( sym == S_comma ) {
+ sym = getSym( );
+ }
+ }
+ } while( sym != S_rparen );
+ Expect( S_rparen );
+}
+
+static void parseProcedureDeclaration( Scope *scope )
{
char *procedure_label;
Symbol *symbol;
+ int size_locals;
+ int size_params;
Expect( S_procedure );
Expect( S_ident );
@@ -2008,11 +2061,45 @@ static void parseProcedureBlock( Scope *scope )
/* TODO: check, if parameter lists and return values match */
}
- Expect( S_semicolon );
+ /* local scope holding all local defitions */
+ symbol->scope = create_scope( scope, symbol->name );
+ if( sym == S_semicolon ) {
+ /* no parameters */
+ sym = getSym( );
+ size_params = 0;
+ } else if( sym == S_lparen ) {
+
+ Symbol *param;
+ int offset;
+
+ parseParameterDeclarationList( symbol->scope );
+ if( sym == S_semicolon ) {
+ /* forward declaration */
+ sym = getSym( );
+ }
+
+ param = symbol->scope->symbol;
+
+ size_params = 0;
+ offset = 0;
+ while( param != NULL ) {
+ if( param->class == SYMBOL_CLASS_VARIABLE ) {
+ int size = get_size( param );
+ size_params += size;
+ param->offset = offset - size;
+ Emit( "; param %s, offset: %d, size: %d\n",
+ param->name, param->offset, size );
+ offset -= size;
+ }
+ param = param->next;
+ }
+ }
+
+ /* procedure body */
if( sym == S_const || sym == S_var || sym == S_begin ) {
- Symbol *sym;
+ Symbol *local, *param_or_local;
int offset;
Emit( "; PROC %s\n", symbol->name );
@@ -2023,9 +2110,6 @@ static void parseProcedureBlock( Scope *scope )
Emit( "push ebp\n" );
Emit( "push esp\n" );
Emit( "pop ebp\n" );
-
- /* local scope holding all local defitions */
- symbol->scope = create_scope( scope, symbol->name );
/* TODO: parse parameters, assign parameter values to
* local variables (when passed by value) or set
@@ -2034,66 +2118,66 @@ static void parseProcedureBlock( Scope *scope )
parseProcedureDeclarationBlock( symbol->scope );
/* compute sizes of all locals */
+ size_locals = 0;
offset = 0;
- scope->size_locals = 0;
- sym = symbol->scope->symbol;
- while( sym != NULL ) {
- if( sym->class == SYMBOL_CLASS_VARIABLE ) {
- int size = get_size( sym );
- scope->size_locals += size;
- sym->offset = offset + size;
+ local = symbol->scope->symbol;
+ while( local != NULL ) {
+ if( local->class == SYMBOL_CLASS_VARIABLE && local->offset == 0 ) {
+ int size = get_size( local );
+ size_locals += size;
+ local->offset = offset + size;
Emit( "; local %s, offset: %d, size: %d\n",
- sym->name, sym->offset, size );
+ local->name, local->offset, size );
offset += size;
}
- sym = sym->next;
+ local = local->next;
}
- /* reserve space on stack */
- if( scope->size_locals > 0 ) {
- Emit( "mov eax, %d\n", scope->size_locals );
+ /* reserve space on stack for locals */
+ if( size_locals > 0 ) {
+ Emit( "mov eax, %d\n", 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 ) {
+ param_or_local = symbol->scope->symbol;
+ while( param_or_local != NULL ) {
+ if( param_or_local->class == SYMBOL_CLASS_VARIABLE ) {
/* TODO: use type here! */
- int size = get_size( sym );
- if( sym->type == integer_type || sym->type == boolean_type ) {
+ int size = get_size( param_or_local );
+ if( param_or_local->type == integer_type || param_or_local->type == boolean_type ) {
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( "mov eax, %d\n", param_or_local->offset );
Emit( "sub ebx, eax\n" );
- Emit( "mov eax, %d\n", sym->integer_value );
+ Emit( "mov eax, %d\n", param_or_local->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( "mov eax, %d\n", param_or_local->offset );
Emit( "sub ebx, eax\n" );
- Emit( "mov eax, %d\n", sym->boolean_value );
+ Emit( "mov eax, %d\n", param_or_local->boolean_value );
Emit( "mov [ebx], al\n" );
break;
default:
- Abort( "Unhandled case when initializing local variable '%s' of primitive type on stack", sym->name );
+ Abort( "Unhandled case when initializing local variable '%s' of primitive type on stack", param_or_local->name );
}
- } else if( sym->type->class == SYMBOL_CLASS_ARRAY_TYPE ) {
+ } else if( param_or_local->type->class == SYMBOL_CLASS_ARRAY_TYPE ) {
/* TODO: we would need an internal memset here
* memset( ebp + offset, get_size, 0 )
*/
} else {
- Abort( "Unhandled case when initializing local variable '%s' of complex type on stack", sym->name );
+ Abort( "Unhandled case when initializing local variable '%s' of complex type on stack", param_or_local->name );
}
}
- sym = sym->next;
+ param_or_local = param_or_local->next;
}
/* TODO: allocate space on stack for local variables (and
@@ -2103,19 +2187,25 @@ static void parseProcedureBlock( Scope *scope )
parseStatementBlock( symbol->scope );
- /* discard locals, reset base pointer */
-
- if( scope->size_locals > 0 ) {
- Emit( "mov eax, %d\n", scope->size_locals );
+ /* discard locals, discard params, reset base pointer */
+ if( size_locals + size_params > 0 ) {
+ Emit( "mov eax, %d\n", size_locals + size_params );
Emit( "add esp, eax\n" );
}
- free_scope( symbol->scope );
-
Emit( "pop ebp\n" );
Emit( "ret\n" );
}
+
+ free_scope( symbol->scope );
+}
+
+static void parseProcedureBlock( Scope *scope )
+{
+ while( sym == S_procedure ) {
+ parseProcedureDeclaration( scope );
+ }
}
static void parseDeclarationBlock( Scope *scope )
@@ -2126,10 +2216,10 @@ static void parseDeclarationBlock( Scope *scope )
if( sym == S_var ) {
parseVariableBlock( scope );
}
- while( sym == S_procedure ) {
+ if( sym == S_procedure ) {
parseProcedureBlock( scope );
}
-}
+}
static void parseModule( Scope *scope )
{
diff --git a/ecomp-c/minie.ebnf b/ecomp-c/minie.ebnf
index 484572d..be68ba8 100644
--- a/ecomp-c/minie.ebnf
+++ b/ecomp-c/minie.ebnf
@@ -17,7 +17,8 @@ Expression = SimpleExpression [ RelationalOperator SimpleExpression ] .
Assignment = Identifier [ "[" Expression "]" ] ":=" Expression .
IfStatement = "if" Expression "do" StatementSequence "else" StatementSequence "end" .
WhileStatement = "while" Expression "do" StatementSequence "end" .
-ProcedureCall = Identifier .
+ParameterList = "(" Expression { "," Expression } ")" .
+ProcedureCall = Identifier [ ParameterList ] .
Statement = Assignment | IfStatement | WhileStatement | ProcedureCall .
StatementSequence = Statement { ";" Statement } .
StatementBlock = "begin" StatementSequence "end" .
@@ -29,8 +30,10 @@ ConstDeclaration = Identifier { "," Identifier } ":" Type "=" ConstExpression .
ConstBlock = "const" { ConstDeclaration ";" } .
VariableDeclaration = Identifier { "," Identifier } ":" Type [ ":=" ConstExpression ] .
VariableBlock = "var" { VariableDeclaration ";" } .
-ProcedureDeclaration = "procedure" Identifier ";" ProcedureDeclarationBlock StatementBlock .
-ProcedureBlock = { ProcedureDeclaration } .
+ParameterDeclaration = Identifier ":" Type .
+ParamaterDeclarationList = "(" ParameterDeclaration { "," ParameterDeclaration } ")" .
+ProcedureDeclaration = "procedure" Identifier [ ParamaterDeclarationList ] ";" ProcedureDeclarationBlock StatementBlock .
ProcedureDeclarationBlock = [ ConstBlock ] [ VariableBlock ] .
+ProcedureBlock = { ProcedureDeclaration } .
DeclarationBlock = [ ConstBlock ] [ VariableBlock ] [ ProcedureBlock ] .
Module = "module" Identifier ";" DeclarationBlock StatementBlock .
diff --git a/ecomp-c/test1.e b/ecomp-c/test1.e
index 49418db..59ec90a 100644
--- a/ecomp-c/test1.e
+++ b/ecomp-c/test1.e
@@ -32,17 +32,28 @@ var
s2 : array 10 of character := "hello";
a1 : array 10 of integer;
-procedure B;
+procedure B( n : integer, m : integer );
procedure A;
+const
+ N : integer = 10;
+ S : array N of character = "local";
+var
+ s : array N of character := S;
+
begin
a1[5] := 43;
- B;
+ s[0] := 'L';
+ B( a1[5], 7 );
end
-procedure B;
+procedure B( n : integer, m : integer );
+var
+ x : integer;
+
begin
- a1[4] := 44;
+ x := n + m;
+ a1[4] := x;
end
begin
diff --git a/ecomp-c/tests/procedure_call_value_parameters.e b/ecomp-c/tests/procedure_call_value_parameters.e
new file mode 100644
index 0000000..3b100ed
--- /dev/null
+++ b/ecomp-c/tests/procedure_call_value_parameters.e
@@ -0,0 +1,20 @@
+/*
+ * procedure call with value parameters
+ */
+
+module procedure_call_value_parameters;
+
+var
+ i : integer := 0;
+
+procedure proc( x : integer );
+var
+ l : integer;
+begin
+ l := x;
+ i := x;
+end
+
+begin
+ proc( 42 );
+end