diff options
author | Andreas Baumann <mail@andreasbaumann.cc> | 2020-06-14 20:56:02 +0200 |
---|---|---|
committer | Andreas Baumann <mail@andreasbaumann.cc> | 2020-06-14 20:56:02 +0200 |
commit | 8d53bd7c238aa60cd8050a1972cfbfec338aebbd (patch) | |
tree | e743920e68d69350522b395a488f760635fae5c8 | |
parent | 4be5f1a89e1368c9a4c98eeb2c05f5b3f06714a5 (diff) | |
download | compilertests-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.c | 75 | ||||
-rw-r--r-- | ecomp-c/ec.c | 124 | ||||
-rw-r--r-- | ecomp-c/emul.c | 2 | ||||
-rw-r--r-- | ecomp-c/libc-freestanding.c | 14 | ||||
-rwxr-xr-x | ecomp-c/test.sh | 1 | ||||
-rw-r--r-- | ecomp-c/test1.e | 11 | ||||
-rw-r--r-- | ecomp-c/tests/asm-i386/mov.asm | 5 | ||||
-rw-r--r-- | ecomp-c/tests/variable_assign_from_type.easm | 1 | ||||
-rw-r--r-- | ecomp-c/tests/variable_not_initialized.e | 13 | ||||
-rw-r--r-- | ecomp-c/tests/variable_not_initialized.easm | 6 | ||||
-rw-r--r-- | ecomp-c/tests/variable_not_initialized.ecomp_err | 1 |
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 |