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);
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_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)
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;
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,