summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2020-07-23 15:53:46 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2020-07-23 15:53:46 +0200
commitc3c7f10a4f6b55abbc5e577930ed59d94577cb59 (patch)
treeb5d5d865c21b7f55d3bcc34596efc99a45ef0011
parent8a42e9b49b2f3b3521d9158a7df4b056eac43a9b (diff)
downloadcompilertests-c3c7f10a4f6b55abbc5e577930ed59d94577cb59.tar.gz
compilertests-c3c7f10a4f6b55abbc5e577930ed59d94577cb59.tar.bz2
asm-i386: started to work on const expressions, works again for pure integer/hex constants
-rw-r--r--ecomp-c/asm-i386.c130
1 files changed, 127 insertions, 3 deletions
diff --git a/ecomp-c/asm-i386.c b/ecomp-c/asm-i386.c
index fc91130..3cb6ff1 100644
--- a/ecomp-c/asm-i386.c
+++ b/ecomp-c/asm-i386.c
@@ -90,6 +90,8 @@ typedef enum {
S_rbrak,
S_plus,
S_minus,
+ S_star,
+ S_slash,
S_eof
} S_Symbol;
@@ -108,6 +110,8 @@ static char *symname[S_eof+1] = {
"]",
"+",
"-",
+ "*",
+ "/",
"eof"
};
@@ -395,6 +399,12 @@ static S_Symbol getSym( void )
case '+':
s = S_plus;
break;
+ case '*':
+ s = S_star;
+ break;
+ case '/':
+ s = S_slash;
+ break;
case 'f':
identifier( );
if( strcmp( ident, "format" ) == 0 ) {
@@ -761,6 +771,7 @@ typedef struct OperandInfo {
int addr;
Symbol *symbol;
struct OperandInfo *next;
+ struct ExpressionNode *node;
} OperandInfo;
typedef struct OpcodeInfo {
@@ -997,6 +1008,116 @@ static void assign_label( OperandInfo *operand_info, char *label )
}
}
+typedef enum ExpressionNodeType {
+ EXPRESSION_NODE_TYPE_CONST,
+ EXPRESSION_NODE_TYPE_VAR,
+ EXPRESSION_NODE_TYPE_OP
+} ExpressionNodeType;
+
+typedef struct ExpressionNode {
+ ExpressionNodeType type;
+ S_Symbol op;
+ struct ExpressionNode *left, *right;
+ int integer_value;
+ Symbol *symbol;
+} ExpressionNode;
+
+static ExpressionNode *create_expression_node( void )
+{
+ ExpressionNode *node = Allocate( sizeof( ExpressionNode ) );
+ node->left = NULL;
+ node->right = NULL;
+
+ return node;
+}
+
+static void free_expression_node( ExpressionNode *node )
+{
+ if( node->left != NULL ) {
+ free_expression_node( node->left );
+ }
+ if( node->right != NULL ) {
+ free_expression_node( node->right );
+ }
+ free( node );
+}
+
+static ExpressionNode *parseFactor( void )
+{
+ Symbol *symbol;
+ ExpressionNode *node = NULL;
+
+ if( sym == S_number ) {
+ node = create_expression_node( );
+ node->type = EXPRESSION_NODE_TYPE_CONST;
+ node->integer_value = num;
+ sym = getSym( );
+ } else if( sym == S_ident ) {
+ symbol = get_symbol( ident );
+ if( symbol == NULL ) {
+ Abort( "Unknown identifier '%s'", ident );
+ }
+ node = create_expression_node( );
+ node->type = EXPRESSION_NODE_TYPE_VAR;
+ node->symbol = symbol;
+ sym = getSym( );
+ } else {
+ Abort( "Expected a literal, a variable or a constant." );
+ }
+
+ return node;
+}
+
+static ExpressionNode *parseTerm( void )
+{
+ ExpressionNode *node, *tmp;
+
+ node = parseFactor( );
+
+ while( sym == S_star || sym == S_slash ) {
+ tmp = node;
+ node = create_expression_node( );
+ node->type = EXPRESSION_NODE_TYPE_OP;
+ node->op = sym;
+ sym = getSym( );
+ node->left = tmp;
+ node->right = parseFactor( );
+ }
+
+ return node;
+}
+
+static ExpressionNode *parseExpression( void )
+{
+ ExpressionNode *node, *tmp;
+
+ node = parseTerm( );
+ while( sym == S_plus || sym == S_minus ) {
+ tmp = node;
+ node = create_expression_node( );
+ node->type = EXPRESSION_NODE_TYPE_OP;
+ node->op = sym;
+ sym = getSym( );
+ node->left = tmp;
+ node->right = parseTerm( );
+ }
+
+ return node;
+}
+
+static int evaluate_const_expression_as_integer( ExpressionNode *node )
+{
+ switch( node->type ) {
+ case EXPRESSION_NODE_TYPE_CONST:
+ return node->integer_value;
+ case EXPRESSION_NODE_TYPE_VAR:
+ case EXPRESSION_NODE_TYPE_OP:
+ Abort( "Const node expression node not implemented yet" );
+ }
+
+ return 0;
+}
+
static OperandInfo *parseOperand( OpcodeInfo *opcode_info )
{
OperandInfo *operand_info;
@@ -1018,10 +1139,13 @@ static OperandInfo *parseOperand( OpcodeInfo *opcode_info )
}
sym = getSym( );
} else if( sym == S_number ) {
- /* absolute operand, like in mov eax, $1 */
+ /* absolute operand, like in mov eax, $1,
+ * we have assemble-time expressions here
+ */
operand_info->type = OPERAND_ABSOLUTE;
- operand_info->num = num;
- sym = getSym( );
+ operand_info->node = parseExpression( );
+ operand_info->num = evaluate_const_expression_as_integer( operand_info->node );
+ free_expression_node( operand_info->node );
} else if( sym == S_string ) {
operand_info->type = OPERAND_ABSOLUTE;
operand_info->str = AllocateAndCopyStr( str );