+ ir_node *res;
+
+ switch(expression->type) {
+ case BINEXPR_SHIFTLEFT_ASSIGN:
+ case BINEXPR_SHIFTLEFT:
+ res = new_d_Shl(dbgi, left, right, mode);
+ break;
+ case BINEXPR_SHIFTRIGHT_ASSIGN:
+ case BINEXPR_SHIFTRIGHT: {
+ expression_t *expr_left = expression->left;
+ type_t *type_left = skip_typeref(expr_left->base.datatype);
+
+ 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->expression.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.datatype;
+ ir_mode *mode = get_ir_mode(type);
+ left = create_conv(dbgi, left, mode);
+ ir_node *op;
+ ir_node *res;
+
+ switch (expression->type) {
+ case BINEXPR_DIV:
+ case BINEXPR_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 BINEXPR_MOD:
+ case BINEXPR_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->expression.source_position);
+ type_t *const type = expression->expression.datatype;
+ ir_mode *const mode = get_ir_mode(type);
+
+ assert(type->type != 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->expression.source_position);
+ type_t *const type = expression->expression.datatype;
+ 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)
+{
+ binary_expression_type_t type = expression->type;
+ switch(type) {
+ case BINEXPR_EQUAL:
+ case BINEXPR_NOTEQUAL:
+ case BINEXPR_LESS:
+ case BINEXPR_LESSEQUAL:
+ case BINEXPR_GREATER:
+ case BINEXPR_GREATEREQUAL: {
+ 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);
+ ir_node *cmp = new_d_Cmp(dbgi, left, right);
+ long pnc = get_pnc(type);
+ ir_node *proj = new_d_Proj(dbgi, cmp, mode_b, pnc);
+ return proj;
+ }
+ case BINEXPR_ASSIGN: {
+ ir_node *right = expression_to_firm(expression->right);
+ set_value_for_expression(expression->left, right);
+
+ return right;
+ }
+ case BINEXPR_ADD:
+ return create_add(expression);
+ case BINEXPR_SUB:
+ return create_sub(expression);
+ case BINEXPR_MUL:
+ return create_arithmetic_binop(expression, new_d_Mul);
+ case BINEXPR_BITWISE_AND:
+ return create_arithmetic_binop(expression, new_d_And);
+ case BINEXPR_BITWISE_OR:
+ return create_arithmetic_binop(expression, new_d_Or);
+ case BINEXPR_BITWISE_XOR:
+ return create_arithmetic_binop(expression, new_d_Eor);
+ case BINEXPR_SHIFTLEFT:
+ case BINEXPR_SHIFTRIGHT:
+ return create_shift(expression);
+ case BINEXPR_DIV:
+ case BINEXPR_MOD:
+ return create_divmod(expression);
+ case BINEXPR_LOGICAL_AND:
+ case BINEXPR_LOGICAL_OR:
+ return create_lazy_op(expression);
+ case BINEXPR_COMMA:
+ expression_to_firm(expression->left);
+ return expression_to_firm(expression->right);
+ case BINEXPR_ADD_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Add);
+ case BINEXPR_SUB_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Sub);
+ case BINEXPR_MUL_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Mul);
+ case BINEXPR_DIV_ASSIGN:
+ return create_arithmetic_assign_divmod(expression);
+ case BINEXPR_BITWISE_AND_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_And);
+ case BINEXPR_BITWISE_OR_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Or);
+ case BINEXPR_BITWISE_XOR_ASSIGN:
+ return create_arithmetic_assign_binop(expression, new_d_Eor);
+ case BINEXPR_SHIFTLEFT_ASSIGN:
+ case BINEXPR_SHIFTRIGHT_ASSIGN:
+ return create_arithmetic_assign_shift(expression);
+ default:
+ panic("TODO binexpr type");
+ }
+}
+
+static ir_node *array_access_addr(const array_access_expression_t *expression)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+ ir_node *base_addr = expression_to_firm(expression->array_ref);
+ ir_node *offset = expression_to_firm(expression->index);
+ offset = create_conv(dbgi, offset, mode_Iu);
+
+ type_t *ref_type = skip_typeref(expression->array_ref->base.datatype);
+ assert(is_type_pointer(ref_type));
+ pointer_type_t *pointer_type = (pointer_type_t*) ref_type;
+
+ unsigned elem_size = get_type_size(pointer_type->points_to);
+ ir_node *elem_size_const = new_Const_long(mode_Iu, elem_size);
+ ir_node *real_offset = new_d_Mul(dbgi, offset, elem_size_const,
+ mode_Iu);
+ ir_node *result = new_d_Add(dbgi, base_addr, real_offset, mode_P);
+
+ return result;
+}
+
+static ir_node *array_access_to_firm(
+ const array_access_expression_t *expression)
+{
+ dbg_info *dbgi = get_dbg_info(&expression->expression.source_position);
+ ir_node *addr = array_access_addr(expression);
+ type_t *type = revert_automatic_type_conversion(
+ (const expression_t*) expression);
+ type = skip_typeref(type);
+ ir_type *irtype = get_ir_type(type);
+
+ return deref_address(irtype, addr, dbgi);