summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-06-14 20:56:02 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2020-06-14 20:56:02 +0200
commit8d53bd7c238aa60cd8050a1972cfbfec338aebbd (patch)
treee743920e68d69350522b395a488f760635fae5c8
parent4be5f1a89e1368c9a4c98eeb2c05f5b3f06714a5 (diff)
downloadcompilertests-8d53bd7c238aa60cd8050a1972cfbfec338aebbd.tar.gz
compilertests-8d53bd7c238aa60cd8050a1972cfbfec338aebbd.tar.bz2
libc-freestanding
- added a memcpy asm-i386: - fixed address calculation for dd and multiple operands - added support for register indirect moved (writing only at the moment, needed for array assignments) ec: - added support for array assignments - removed "variable not initialized" check, too hard to implement correctly and besides we initialize static variables always)
-rw-r--r--ecomp-c/asm-i386.c75
-rw-r--r--ecomp-c/ec.c124
-rw-r--r--ecomp-c/emul.c2
-rw-r--r--ecomp-c/libc-freestanding.c14
-rwxr-xr-xecomp-c/test.sh1
-rw-r--r--ecomp-c/test1.e11
-rw-r--r--ecomp-c/tests/asm-i386/mov.asm5
-rw-r--r--ecomp-c/tests/variable_assign_from_type.easm1
-rw-r--r--ecomp-c/tests/variable_not_initialized.e13
-rw-r--r--ecomp-c/tests/variable_not_initialized.easm6
-rw-r--r--ecomp-c/tests/variable_not_initialized.ecomp_err1
11 files changed, 185 insertions, 68 deletions
diff --git a/ecomp-c/asm-i386.c b/ecomp-c/asm-i386.c
index ba62fc8..ab463a1 100644
--- a/ecomp-c/asm-i386.c
+++ b/ecomp-c/asm-i386.c
@@ -13,6 +13,8 @@
* A2 XX XX XX XX mov moffs8, al
* A1 XX XX XX XX mov eax, moffs32
* A0 XX XX XX XX mov al, moffs8
+ * 88 rr mov [r32], al
+ * 89 rr mov [r32], eax
* 01 XX add r32, r32
* 29 XX sub r32, r32
* F7 E3 mul ebx
@@ -28,7 +30,7 @@
* E9 XX XX XX XX jmp rel32
* F4 hlt
*
- * r32
+ * r32/rr
* eax 000
* ecx 001
* edx 010
@@ -709,7 +711,8 @@ typedef enum {
OPERAND_ABSOLUTE = 1,
OPERAND_REGISTER = 2,
OPERAND_MEMORY_DIRECT = 4,
- OPERAND_MEMORY_INDIRECT = 8
+ OPERAND_MEMORY_INDIRECT = 8,
+ OPERAND_REGISTER_INDIRECT = 16
} OperandType;
typedef enum {
@@ -971,11 +974,18 @@ static OperandInfo *parseOperand( OpcodeInfo *opcode_info )
opcode_info->size = strlen( str );
sym = getSym( );
} else if( sym == S_lbrak ) {
- /* pointer indirection as [a] */
+ /* pointer indirection as [a] - memory indirect and
+ * register indirect as [ebx]
+ */
Expect( S_lbrak );
Expect( S_ident );
- operand_info->type = OPERAND_MEMORY_INDIRECT;
- assign_label( operand_info, ident );
+ if( isRegister( ident ) ) {
+ operand_info->type = OPERAND_REGISTER_INDIRECT;
+ operand_info->reg = getRegister( ident );
+ } else {
+ operand_info->type = OPERAND_MEMORY_INDIRECT;
+ assign_label( operand_info, ident );
+ }
Expect( S_rbrak );
}
@@ -1021,19 +1031,50 @@ static void parseOperands( OpcodeInfo *opcode_info )
switch( opcode_info->opcode ) {
case OPCODE_HLT:
case OPCODE_PSEUDO_DD:
- case OPCODE_PSEUDO_DB:
break;
+ case OPCODE_PSEUDO_DB: {
+ OperandInfo *operand_info;
+ int i = 0;
+ int size = 0;
+
+ operand_info = opcode_info->operand;
+ while( operand_info != NULL ) {
+ if( operand_info->str != NULL ) {
+ size += strlen( operand_info->str );
+ } else {
+ size += 1;
+ }
+ i++;
+ operand_info = operand_info->next;
+ }
+ opcode_info->nof_operands = i;
+ opcode_info->size = size;
+ } break;
case OPCODE_MOV:
if( opcode_info->operand->type == OPERAND_REGISTER &&
opcode_info->operand->next->type == OPERAND_ABSOLUTE ) {
+ /* mov eax, $22, load absolute value */
} else if( opcode_info->operand->type == OPERAND_MEMORY_INDIRECT &&
opcode_info->operand->next->type == OPERAND_REGISTER &&
( opcode_info->operand->next->reg == REGISTER_EAX ||
opcode_info->operand->next->reg == REGISTER_AL ) ) {
+ /* mov [mem], eax, storing to memory */
} else if( opcode_info->operand->type == OPERAND_REGISTER &&
( opcode_info->operand->reg == REGISTER_EAX ||
opcode_info->operand->reg == REGISTER_AL ) &&
opcode_info->operand->next->type == OPERAND_MEMORY_INDIRECT ) {
+ /* mov eax, [mem], reading variables or parts of it */
+ } else if( opcode_info->operand->type == OPERAND_REGISTER &&
+ opcode_info->operand->reg == REGISTER_EAX &&
+ opcode_info->operand->next->type == OPERAND_MEMORY_DIRECT ) {
+ /* mov eax, mem, for address calculations (arrays, records) */
+ } else if( opcode_info->operand->type == OPERAND_REGISTER_INDIRECT &&
+ opcode_info->operand->reg == REGISTER_EBX &&
+ opcode_info->operand->next->type == OPERAND_REGISTER &&
+ ( opcode_info->operand->next->reg == REGISTER_EAX ||
+ opcode_info->operand->next->reg == REGISTER_AL ) ) {
+ /* mov [ebx], eax, indirect addressing array/record elementss */
+ opcode_info->size = 2;
} else {
Abort( "Unsupported operand combination in 'mov'" );
}
@@ -1317,6 +1358,9 @@ static void print_opcodes( OpcodeInfo *opcode_info )
( operand->symbol != NULL ) ? operand->symbol->name : "NULL",
operand->addr );
break;
+ case OPERAND_REGISTER_INDIRECT:
+ fprintf( stderr, "%s[%s]", indent, registername[operand->reg] );
+ break;
}
if( first ) {
first = 0;
@@ -1508,6 +1552,25 @@ static void emit_opcode( OpcodeInfo *opcode_info )
Abort( "mov is only allowed with EAX or AL register" );
}
Emit_double_little_endian( opcode_info->operand->next->addr );
+
+ } else if( opcode_info->operand->type == OPERAND_REGISTER &&
+ opcode_info->operand->reg == REGISTER_EAX &&
+ opcode_info->operand->next->type == OPERAND_MEMORY_DIRECT ) {
+ Emit( "%c", 0xB8 );
+ Emit_double_little_endian( opcode_info->operand->next->addr );
+ } else if( opcode_info->operand->type == OPERAND_REGISTER_INDIRECT &&
+ opcode_info->operand->reg == REGISTER_EBX &&
+ opcode_info->operand->next->type == OPERAND_REGISTER &&
+ ( opcode_info->operand->next->reg == REGISTER_EAX ||
+ opcode_info->operand->next->reg == REGISTER_AL ) ) {
+ if( opcode_info->operand->next->reg == REGISTER_EAX ) {
+ Emit( "%c", 0x89 );
+ } else if( opcode_info->operand->next->reg == REGISTER_AL ) {
+ Emit( "%c", 0x88 );
+ }
+ Emit( "%c", 0x03 );
+ } else {
+ Abort( "Unhandled opcode generation case in 'mov'" );
}
break;
case OPCODE_PUSH:
diff --git a/ecomp-c/ec.c b/ecomp-c/ec.c
index 42d6203..737db92 100644
--- a/ecomp-c/ec.c
+++ b/ecomp-c/ec.c
@@ -651,8 +651,8 @@ typedef struct Symbol {
int boolean_value;
char character_value;
char *string_value;
+ int *intarr_value;
/* variable */
- int initialized;
int size;
/* array type */
int dim;
@@ -690,6 +690,9 @@ static void free_symbol( Symbol *sym )
if( sym->string_value != NULL ) {
free( sym->string_value );
}
+ if( sym->intarr_value != NULL ) {
+ free( sym->intarr_value );
+ }
free( sym->name );
free( sym );
}
@@ -758,11 +761,11 @@ static Symbol *insert_symbol( Scope *scope, char *name, SymbolClass class )
sym->class = class;
sym->name = Allocate( strlen( name ) + 1 );
strlcpy( sym->name, name, strlen( name ) + 1 );
- sym->initialized = 0;
sym->size = 0;
sym->dim = 0;
sym->next = scope->symbol;
sym->string_value = NULL;
+ sym->intarr_value = NULL;
scope->symbol = sym;
return sym;
@@ -793,6 +796,7 @@ typedef struct ExpressionNode {
int boolean_value;
char character_value;
char *string_value;
+ int *intarr_value;
Symbol *symbol;
Symbol *actual_type;
} ExpressionNode;
@@ -803,6 +807,7 @@ static ExpressionNode *create_expression_node( void )
node->left = NULL;
node->right = NULL;
node->string_value = NULL;
+ node->intarr_value = NULL;
return node;
}
@@ -818,6 +823,9 @@ static void free_expression_node( ExpressionNode *node )
if( node->string_value != NULL ) {
free( node->string_value );
}
+ if( node->intarr_value != NULL ) {
+ free( node->intarr_value );
+ }
free( node );
}
@@ -925,6 +933,7 @@ static int get_size( Symbol *symbol )
case SYMBOL_CLASS_SIMPLE_TYPE:
return symbol->size;
case SYMBOL_CLASS_ARRAY_TYPE:
+ return symbol->dim * symbol->size;
default:
Abort( "No size for class '%d", symbol->class );
}
@@ -1111,9 +1120,6 @@ static ExpressionNode *parseFactor( void )
Abort( "Unhandled expression assignment from identifier with type '%s'", node->actual_type->name );
}
} else if( symbol->class == SYMBOL_CLASS_VARIABLE ) {
- if( !symbol->initialized ) {
- Abort( "Variable '%s' has not been initialized yet", ident );
- }
node = create_expression_node( );
node->type = EXPRESSION_NODE_TYPE_VAR;
node->symbol = symbol;
@@ -1232,7 +1238,7 @@ static ExpressionNode *parseExpression( void )
static void parseAssignment( Scope *scope )
{
Symbol *symbol;
- ExpressionNode *node;
+ ExpressionNode *node, *lhs, *rhs;
symbol = get_symbol( current_scope, ident );
if( symbol == NULL ) {
@@ -1246,49 +1252,89 @@ static void parseAssignment( Scope *scope )
Abort( "'%s' is a constant and can not be changed", ident );
}
- symbol->initialized = 1;
-
if( sym == S_assign ) {
Expect( S_assign );
+
+ node = parseExpression( );
+
Emit( "; LET %s <- ", symbol->name );
+ if( !is_compatible_type( symbol->type, node->actual_type ) ) {
+ Abort( "Incompatible assignment of expression of type '%s' to variable '%s' of type '%s'",
+ node->actual_type->name, symbol->name, symbol->type->name );
+ }
+ generate_expression_comment( node );
+ Emit( "\n" );
+
+ emit_expression_code( node, scope );
+ Emit( "pop eax\n" );
+
+ switch( get_size( symbol ) ) {
+ case 4:
+ Emit( "mov [%s], eax\n", symbol->name );
+ break;
+ case 1:
+ Emit( "mov [%s], al\n", symbol->name );
+ break;
+ default:
+ Abort( "Unhandled size %d when storing register immediately to memory", symbol->size );
+ }
+
+ free_expression_node( node );
+
} else if( sym == S_lbracket ) {
Expect( S_lbracket );
if( symbol->type->class != SYMBOL_CLASS_ARRAY_TYPE ) {
Abort( "array index not allowed on '%s' (not an array)", symbol->name );
}
Emit( "; LET %s[", symbol->name );
- node = parseExpression( );
- generate_expression_comment( node );
+ lhs = parseExpression( );
+ Expect( S_rbracket );
+
+ generate_expression_comment( lhs );
Emit( "] <- " );
+
+ Expect( S_assign );
+
+ rhs = parseExpression( );
+
+ generate_expression_comment( rhs );
Emit( "\n" );
- emit_expression_code( node, scope );
+
+ emit_expression_code( lhs, scope );
+
+ Emit( "pop eax\n" );
+ Emit( "mov ebx, %d\n", get_size( symbol->type->type ) );
+ Emit( "mul ebx\n" );
+ Emit( "push eax\n" );
+ Emit( "mov eax, %s\n", symbol->name );
Emit( "pop ebx\n" );
- Expect( S_rbracket );
- Expect( S_assign );
- }
-
- node = parseExpression( );
-
- if( !is_compatible_type( symbol->type, node->actual_type ) ) {
- Abort( "Incompatible assignment of expression of type '%s' to variable '%s' of type '%s'",
- node->actual_type->name, symbol->name, symbol->type->name );
- }
-
- generate_expression_comment( node );
- Emit( "\n" );
- emit_expression_code( node, scope );
- Emit( "pop eax\n" );
- switch( get_size( symbol ) ) {
- case 4:
- Emit( "mov [%s], eax\n", symbol->name );
- break;
- case 1:
- Emit( "mov [%s], al\n", symbol->name );
- break;
- default:
- Abort( "Unhandled size %d when storing register to memory", symbol->size );
- }
- free_expression_node( node );
+ Emit( "add eax, ebx\n" );
+ Emit( "push eax\n" );
+
+ if( !is_compatible_type( symbol->type->type, rhs->actual_type ) ) {
+ Abort( "Incompatible assignment of expression of type '%s' to variable '%s' of type '%s'",
+ rhs->actual_type->name, symbol->name, symbol->type->name );
+ }
+
+ emit_expression_code( rhs, scope );
+ Emit( "pop eax\n" );
+
+ Emit( "pop ebx\n" );
+
+ switch( get_size( symbol->type->type ) ) {
+ case 4:
+ Emit( "mov [ebx], eax\n", symbol->name );
+ break;
+ case 1:
+ Emit( "mov [ebx], al\n", symbol->name );
+ break;
+ default:
+ Abort( "Unhandled size %d when storing register indirectly to memory", symbol->size );
+ }
+
+ free_expression_node( rhs );
+ free_expression_node( lhs );
+ }
}
static void parseStatementSequence( Scope *scope );
@@ -1502,6 +1548,8 @@ static void symbol_copy( Symbol *from, Symbol *to )
if( from->type->type == character_type ) {
/* type remains, initializer is smaller than dimensioned string */
to->string_value = AllocateAndCopyStr( from->string_value );
+ } else if( from->type->type == integer_type ) {
+ memcpy( to->intarr_value, from->intarr_value, to->dim * sizeof( int ) );
} else {
Abort( "Unhandled case for array type '%s' when copying value of symbol", from->type->name );
}
@@ -1530,6 +1578,8 @@ static void symbol_copy_node( ExpressionNode *from, Symbol *to )
if( from->actual_type->type == character_type ) {
/* type remains, initializer is smaller than dimensioned string */
to->string_value = AllocateAndCopyStr( from->string_value );
+ } else if( from->actual_type->type == integer_type ) {
+ memcpy( to->intarr_value, from->intarr_value, to->dim * sizeof( int ) );
} else {
Abort( "Unhandled case for array type '%s' when copying value of symbol from expression node", from->actual_type->name );
}
diff --git a/ecomp-c/emul.c b/ecomp-c/emul.c
index 929caa6..682b5a0 100644
--- a/ecomp-c/emul.c
+++ b/ecomp-c/emul.c
@@ -331,7 +331,7 @@ int main( int argc, char *argv[] )
printf( "%s %s\n", instrs[n].mnemonic, instrs[n].op_str );
- uerr = uc_emu_start( uc, addr, CODE_START + CODE_SIZE, 0, 1 );
+ uerr = uc_emu_start( uc, addr, CODE_START + code_size, 0, 1 );
if( uerr != UC_ERR_OK ) {
fprintf( stderr, "ERROR: failed to call uc_emu_start( ): %s\n", uc_strerror( uerr ) );
cs_close( &cs );
diff --git a/ecomp-c/libc-freestanding.c b/ecomp-c/libc-freestanding.c
index 495436e..ca41ae7 100644
--- a/ecomp-c/libc-freestanding.c
+++ b/ecomp-c/libc-freestanding.c
@@ -76,6 +76,20 @@ int strlcat( char *d, const char *s, int n )
return len;
}
+void *memcpy( void *d, const void *s, int len )
+{
+ const char *p = s;
+ char *q = d;
+
+ while( len-- ) {
+ *q = *p;
+ q++;
+ p++;
+ }
+
+ return d;
+}
+
/* errno */
int errno;
diff --git a/ecomp-c/test.sh b/ecomp-c/test.sh
index a17d78e..96f0d42 100755
--- a/ecomp-c/test.sh
+++ b/ecomp-c/test.sh
@@ -4,7 +4,6 @@ TESTS="
empty_module
unknown_variable
variable_name_as_type
-variable_not_initialized
variable_initialization
unknown_type
const_assignment_error
diff --git a/ecomp-c/test1.e b/ecomp-c/test1.e
index 83090ec..656d634 100644
--- a/ecomp-c/test1.e
+++ b/ecomp-c/test1.e
@@ -28,6 +28,7 @@ var
i : integer;
j : character := C;
s : array 10 of character := S;
+ s1 : array 10 of character;
s2 : array 10 of character := "hello";
a1 : array 10 of integer;
@@ -60,7 +61,13 @@ begin
end;
j := 'B';
- a1[0] := 'c';
+ a1[4] := 42;
+ s1[0] := 'a';
s[0] := 'H';
- j := s2[1];
+ i := 0;
+ while i < 10 do
+ a1[i] := i;
+ i := i + 1;
+ end;
+ //j := s2[1];
end
diff --git a/ecomp-c/tests/asm-i386/mov.asm b/ecomp-c/tests/asm-i386/mov.asm
index b823bf6..2db4f1d 100644
--- a/ecomp-c/tests/asm-i386/mov.asm
+++ b/ecomp-c/tests/asm-i386/mov.asm
@@ -4,6 +4,11 @@ org $1000000
mov al, [flag1]
mov eax, $ffffffff
mov [flag2], al
+mov eax, flag1
+push eax
+pop ebx
+mov [ebx], eax
+mov [ebx], al
hlt
db "The"
flag1: db $1
diff --git a/ecomp-c/tests/variable_assign_from_type.easm b/ecomp-c/tests/variable_assign_from_type.easm
index 6a1629f..c89a9c2 100644
--- a/ecomp-c/tests/variable_assign_from_type.easm
+++ b/ecomp-c/tests/variable_assign_from_type.easm
@@ -3,4 +3,3 @@ use32
org $1000000
; CONST N -> integer, 20
; DECL a -> integer, 0
-; LET a <- \ No newline at end of file
diff --git a/ecomp-c/tests/variable_not_initialized.e b/ecomp-c/tests/variable_not_initialized.e
deleted file mode 100644
index bff8933..0000000
--- a/ecomp-c/tests/variable_not_initialized.e
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * assign variable from another uninitialized variable
- */
-
-module variable_not_initialized;
-
-var
- a : integer;
- b : integer;
-
-begin
- a := b; // should error out as we assign from an unitialized variable
-end
diff --git a/ecomp-c/tests/variable_not_initialized.easm b/ecomp-c/tests/variable_not_initialized.easm
deleted file mode 100644
index 23665ea..0000000
--- a/ecomp-c/tests/variable_not_initialized.easm
+++ /dev/null
@@ -1,6 +0,0 @@
-format binary
-use32
-org $1000000
-; DECL a -> integer, 0
-; DECL b -> integer, 0
-; LET a <- \ No newline at end of file
diff --git a/ecomp-c/tests/variable_not_initialized.ecomp_err b/ecomp-c/tests/variable_not_initialized.ecomp_err
deleted file mode 100644
index 8202b94..0000000
--- a/ecomp-c/tests/variable_not_initialized.ecomp_err
+++ /dev/null
@@ -1 +0,0 @@
-Error line 12, pos 9: Variable 'b' has not been initialized yet