- if (is_type_pointer(type)) {
- 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);
-
- return value;
-}
-
-static ir_node *create_add(const binary_expression_t *expression)
-{
- dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
- ir_node *left = expression_to_firm(expression->left);
- ir_node *right = expression_to_firm(expression->right);
- type_t *type = expression->base.type;
-
- expression_t *expr_left = expression->left;
- expression_t *expr_right = expression->right;
- type_t *type_left = skip_typeref(expr_left->base.type);
- type_t *type_right = skip_typeref(expr_right->base.type);
-
- 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);
- }
-
- if (is_type_pointer(type_left)) {
- return pointer_arithmetic(left, right, type, dbgi, new_d_Add);
- } else {
- assert(is_type_pointer(type_right));
- return pointer_arithmetic(right, left, type, dbgi, new_d_Add);
- }
-}
-
-static ir_node *create_sub(const binary_expression_t *expression)
-{
- dbg_info *const dbgi = get_dbg_info(&expression->base.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->base.type;
- type_t *const type_left = skip_typeref(expr_left->base.type);
- type_t *const type_right = skip_typeref(expr_right->base.type);
-
- if (is_type_arithmetic(type_left) && is_type_arithmetic(type_right)) {
- ir_mode *const mode = get_ir_mode(type);
- return new_d_Sub(dbgi, left, right, mode);
- } else if (is_type_pointer(type_left) && is_type_pointer(type_right)) {
- const pointer_type_t *const ptr_type = &type_left->pointer;
-
- ir_node *const elem_size = get_type_size(ptr_type->points_to);
- ir_mode *const mode = get_ir_mode(type);
- ir_node *const conv_size = new_d_Conv(dbgi, elem_size, mode);
- ir_node *const sub = new_d_Sub(dbgi, left, right, mode);
- ir_node *const no_mem = new_NoMem();
- ir_node *const div = new_d_DivRL(dbgi, no_mem, sub, conv_size, mode,
- op_pin_state_floats);
- return new_d_Proj(dbgi, div, mode, pn_Div_res);
- }
-
- assert(is_type_pointer(type_left));
- return pointer_arithmetic(left, right, type_left, dbgi, new_d_Sub);
-}
-
-static ir_node *create_shift(const binary_expression_t *expression)
-{
- dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
- ir_node *left = expression_to_firm(expression->left);
- ir_node *right = expression_to_firm(expression->right);
- type_t *type = expression->base.type;
- ir_mode *mode = get_ir_mode(type);
-
- /* firm always wants the shift count to be unsigned */
- right = create_conv(dbgi, right, mode_uint);
-
- ir_node *res;
-
- switch(expression->base.kind) {
- case EXPR_BINARY_SHIFTLEFT_ASSIGN:
- case EXPR_BINARY_SHIFTLEFT:
- res = new_d_Shl(dbgi, left, right, mode);
- break;
- case EXPR_BINARY_SHIFTRIGHT_ASSIGN:
- case EXPR_BINARY_SHIFTRIGHT: {
- expression_t *expr_left = expression->left;
- type_t *type_left = skip_typeref(expr_left->base.type);
-
- if(is_type_signed(type_left)) {
- res = new_d_Shrs(dbgi, left, right, mode);
- } else {
- res = new_d_Shr(dbgi, left, right, mode);
- }
- break;
- }
- default:
- panic("create shift op called for non-shift op");
- }
-
- return res;
-}
-
-
-static ir_node *create_divmod(const binary_expression_t *expression)
-{
- dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
- ir_node *left = expression_to_firm(expression->left);
- ir_node *right = expression_to_firm(expression->right);
- ir_node *pin = new_Pin(new_NoMem());
- /* be careful with the modes, because in arithmetic assign nodes only
- * the right operand has the mode of the arithmetic already */
- type_t *type = expression->right->base.type;
- ir_mode *mode = get_ir_mode(type);
- left = create_conv(dbgi, left, mode);
- ir_node *op;
- ir_node *res;
-
- switch (expression->base.kind) {
- case EXPR_BINARY_DIV:
- case EXPR_BINARY_DIV_ASSIGN:
- if(mode_is_float(mode)) {
- op = new_d_Quot(dbgi, pin, left, right, mode, op_pin_state_floats);
- res = new_d_Proj(dbgi, op, mode, pn_Quot_res);
- } else {
- op = new_d_Div(dbgi, pin, left, right, mode, op_pin_state_floats);
- res = new_d_Proj(dbgi, op, mode, pn_Div_res);
- }
- break;
-
- case EXPR_BINARY_MOD:
- case EXPR_BINARY_MOD_ASSIGN:
- assert(!mode_is_float(mode));
- op = new_d_Mod(dbgi, pin, left, right, mode, op_pin_state_floats);
- res = new_d_Proj(dbgi, op, mode, pn_Mod_res);
- break;
-
- default: panic("unexpected binary expression type in create_divmod()");
- }
-
- return res;
-}
-
-static ir_node *create_arithmetic_assign_divmod(
- const binary_expression_t *expression)
-{
- ir_node * value = create_divmod(expression);
- dbg_info *const dbgi = get_dbg_info(&expression->base.source_position);
- type_t *const type = expression->base.type;
- ir_mode *const mode = get_ir_mode(type);
-
- assert(type->kind != TYPE_POINTER);
-
- value = create_conv(dbgi, value, mode);
- set_value_for_expression(expression->left, value);
-
- return value;
-}
-
-static ir_node *create_arithmetic_assign_shift(
- const binary_expression_t *expression)
-{
- ir_node * value = create_shift(expression);
- dbg_info *const dbgi = get_dbg_info(&expression->base.source_position);
- type_t *const type = expression->base.type;
- ir_mode *const mode = get_ir_mode(type);
-
- value = create_conv(dbgi, value, mode);
- set_value_for_expression(expression->left, value);
-
- return value;
-}
-
-static ir_node *binary_expression_to_firm(const binary_expression_t *expression)
-{
- expression_kind_t kind = expression->base.kind;
-
- switch(kind) {
- case EXPR_BINARY_EQUAL:
- case EXPR_BINARY_NOTEQUAL:
- case EXPR_BINARY_LESS:
- case EXPR_BINARY_LESSEQUAL:
- case EXPR_BINARY_GREATER:
- case EXPR_BINARY_GREATEREQUAL:
- case EXPR_BINARY_ISGREATER:
- case EXPR_BINARY_ISGREATEREQUAL:
- case EXPR_BINARY_ISLESS:
- case EXPR_BINARY_ISLESSEQUAL:
- case EXPR_BINARY_ISLESSGREATER:
- case EXPR_BINARY_ISUNORDERED: {
- dbg_info *dbgi = get_dbg_info(&expression->base.source_position);
- ir_node *left = expression_to_firm(expression->left);
- ir_node *right = expression_to_firm(expression->right);
- ir_node *cmp = new_d_Cmp(dbgi, left, right);
- long pnc = get_pnc(kind, expression->left->base.type);
- ir_node *proj = new_d_Proj(dbgi, cmp, mode_b, pnc);
- return proj;