From 62960ad0396cef884afa2970238db902fc6c06f1 Mon Sep 17 00:00:00 2001 From: Christoph Mallon Date: Sat, 17 Nov 2007 19:14:03 +0000 Subject: [PATCH] Implement pointer arithmetic for += and -=. (Hopefully) fix pointer arithmetic for -. [r18456] --- ast2firm.c | 112 ++++++++++++++++++++++++----------------------------- parser.c | 38 +++++++++++++++++- 2 files changed, 86 insertions(+), 64 deletions(-) diff --git a/ast2firm.c b/ast2firm.c index 6947b74..2ec9b96 100644 --- a/ast2firm.c +++ b/ast2firm.c @@ -973,16 +973,44 @@ static ir_node *create_arithmetic_binop(const binary_expression_t *expression, return res; } +static ir_node *pointer_arithmetic(ir_node *const pointer, + ir_node * integer, + type_t *const type, + dbg_info *const dbgi, + const create_arithmetic_func func) +{ + pointer_type_t *const pointer_type = (pointer_type_t*)type; + type_t *const points_to = pointer_type->points_to; + const unsigned elem_size = get_type_size(points_to); + + assert(elem_size >= 1); + if (elem_size > 1) { + integer = create_conv(dbgi, integer, mode_Is); + ir_node *const cnst = new_Const_long(mode_Is, (long)elem_size); + ir_node *const mul = new_d_Mul(dbgi, integer, cnst, mode_Is); + integer = mul; + } + + ir_mode *const mode = get_ir_mode(type); + return func(dbgi, pointer, integer, mode); +} + static ir_node *create_arithmetic_assign_binop( const binary_expression_t *expression, create_arithmetic_func func) { - dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); - ir_node *value = create_arithmetic_binop(expression, func); - type_t *type = expression->expression.datatype; - ir_mode *mode = get_ir_mode(type); + dbg_info *const dbgi = get_dbg_info(&expression->expression.source_position); + type_t *const type = expression->expression.datatype; + ir_node *value; - assert(type->type != TYPE_POINTER); + if (type->type == TYPE_POINTER) { + ir_node *const pointer = expression_to_firm(expression->left); + ir_node * integer = expression_to_firm(expression->right); + value = pointer_arithmetic(pointer, integer, type, dbgi, func); + } else { + value = create_arithmetic_binop(expression, func); + } + ir_mode *const mode = get_ir_mode(type); value = create_conv(dbgi, value, mode); set_value_for_expression(expression->left, value); @@ -995,7 +1023,6 @@ static ir_node *create_add(const binary_expression_t *expression) ir_node *left = expression_to_firm(expression->left); ir_node *right = expression_to_firm(expression->right); type_t *type = expression->expression.datatype; - ir_mode *mode = get_ir_mode(type); expression_t *expr_left = expression->left; expression_t *expr_right = expression->right; @@ -1003,76 +1030,37 @@ static ir_node *create_add(const binary_expression_t *expression) type_t *type_right = skip_typeref(expr_right->datatype); if(is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { + ir_mode *const mode = get_ir_mode(type); return new_d_Add(dbgi, left, right, mode); } - ir_node *pointer; - ir_node *integer; - pointer_type_t *pointer_type; if(type_left->type == TYPE_POINTER) { - pointer = left; - integer = right; - pointer_type = (pointer_type_t*) type_left; + return pointer_arithmetic(left, right, type_left, dbgi, new_d_Add); } else { assert(type_right->type == TYPE_POINTER); - pointer = right; - integer = left; - pointer_type = (pointer_type_t*) type_right; + return pointer_arithmetic(right, left, type_right, dbgi, new_d_Add); } - - type_t *points_to = pointer_type->points_to; - unsigned elem_size = get_type_size(points_to); - - assert(elem_size >= 1); - if(elem_size > 1) { - integer = create_conv(dbgi, integer, mode_Is); - ir_node *cnst = new_Const_long(mode_Is, (int) elem_size); - ir_node *mul = new_d_Mul(dbgi, integer, cnst, mode_Is); - integer = mul; - } - - ir_node *res = new_d_Add(dbgi, pointer, integer, mode); - - return res; } static ir_node *create_sub(const binary_expression_t *expression) { - dbg_info *dbgi = get_dbg_info(&expression->expression.source_position); - ir_node *left = expression_to_firm(expression->left); - ir_node *right = expression_to_firm(expression->right); - type_t *type = expression->expression.datatype; - ir_mode *mode = get_ir_mode(type); - - expression_t *expr_left = expression->left; - expression_t *expr_right = expression->right; - type_t *type_left = skip_typeref(expr_left->datatype); - type_t *type_right = skip_typeref(expr_right->datatype); - - if((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) - || (type_left->type == TYPE_POINTER - && type_right->type == TYPE_POINTER)) { + dbg_info *const dbgi = get_dbg_info(&expression->expression.source_position); + expression_t *const expr_left = expression->left; + expression_t *const expr_right = expression->right; + ir_node *const left = expression_to_firm(expr_left); + ir_node *const right = expression_to_firm(expr_right); + type_t *const type = expression->expression.datatype; + type_t *const type_left = skip_typeref(expr_left->datatype); + type_t *const type_right = skip_typeref(expr_right->datatype); + + if ((is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) || + (type_left->type == TYPE_POINTER && type_right->type == TYPE_POINTER)) { + ir_mode *const mode = get_ir_mode(type); return new_d_Sub(dbgi, left, right, mode); } - assert(type_right->type == TYPE_POINTER); - ir_node *pointer = left; - ir_node *integer = right; - pointer_type_t *pointer_type = (pointer_type_t*) type_right; - - type_t *points_to = pointer_type->points_to; - unsigned elem_size = get_type_size(points_to); - - assert(elem_size >= 1); - if(elem_size > 1) { - ir_node *cnst = new_Const_long(mode_Iu, elem_size); - ir_node *mul = new_d_Mul(dbgi, integer, cnst, mode_Iu); - integer = mul; - } - - ir_node *res = new_d_Sub(dbgi, pointer, integer, mode); - - return res; + assert(type_left->type == TYPE_POINTER); + return pointer_arithmetic(left, right, type_left, dbgi, new_d_Sub); } static ir_node *create_shift(const binary_expression_t *expression) diff --git a/parser.c b/parser.c index 4c4208c..dbc6630 100644 --- a/parser.c +++ b/parser.c @@ -3173,6 +3173,40 @@ static void semantic_arithmetic_assign(binary_expression_t *expression) expression->expression.datatype = type_left; } +static void semantic_arithmetic_addsubb_assign(binary_expression_t *expression) +{ + expression_t *left = expression->left; + expression_t *right = expression->right; + type_t *orig_type_left = left->datatype; + type_t *orig_type_right = right->datatype; + + if(orig_type_left == NULL || orig_type_right == NULL) + return; + + type_t *type_left = skip_typeref(orig_type_left); + type_t *type_right = skip_typeref(orig_type_right); + + if (is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) { + /* combined instructions are tricky. We can't create an implicit cast on + * the left side, because we need the uncasted form for the store. + * The ast2firm pass has to know that left_type must be right_type + * for the arithmeitc operation and create a cast by itself */ + type_t *const arithmetic_type = semantic_arithmetic(type_left, type_right); + expression->right = create_implicit_cast(right, arithmetic_type); + expression->expression.datatype = type_left; + } else if (type_left->type == TYPE_POINTER && is_type_integer(type_right)) { + expression->expression.datatype = type_left; + } else { + parser_print_error_prefix(); + fputs("Incompatible types ", stderr); + print_type_quoted(orig_type_left); + fputs(" and ", stderr); + print_type_quoted(orig_type_right); + fputs(" in assignment\n", stderr); + return; + } +} + static void semantic_logical_op(binary_expression_t *expression) { expression_t *left = expression->left; @@ -3260,9 +3294,9 @@ CREATE_BINEXPR_PARSER(T_LESSLESS, BINEXPR_SHIFTLEFT, CREATE_BINEXPR_PARSER(T_GREATERGREATER, BINEXPR_SHIFTRIGHT, semantic_shift_op, 1) CREATE_BINEXPR_PARSER(T_PLUSEQUAL, BINEXPR_ADD_ASSIGN, - semantic_arithmetic_assign, 0) + semantic_arithmetic_addsubb_assign, 0) CREATE_BINEXPR_PARSER(T_MINUSEQUAL, BINEXPR_SUB_ASSIGN, - semantic_arithmetic_assign, 0) + semantic_arithmetic_addsubb_assign, 0) CREATE_BINEXPR_PARSER(T_ASTERISKEQUAL, BINEXPR_MUL_ASSIGN, semantic_arithmetic_assign, 0) CREATE_BINEXPR_PARSER(T_SLASHEQUAL, BINEXPR_DIV_ASSIGN, -- 2.20.1