static ir_tarval *fold_expression_to_address(expression_t const *const expr) { switch (expr->kind) { case EXPR_SELECT: { select_expression_t const *const sel = &expr->select; type_t *const type = skip_typeref(sel->compound->base.type); ir_tarval *const base_addr = is_type_pointer(type) ? fold_expression(sel->compound) : fold_expression_to_address(sel->compound); ir_mode *const mode = get_tarval_mode(base_addr); ir_mode *const mode_offset = get_reference_offset_mode(mode); ir_tarval *const offset = new_tarval_from_long(sel->compound_entry->compound_member.offset, mode_offset); return tarval_add(base_addr, offset); } case EXPR_ARRAY_ACCESS: { ir_tarval *const base_addr = fold_expression_to_address(expr->array_access.array_ref); ir_tarval *const idx = fold_expression(expr->array_access.index); ir_mode *const mode = get_ir_mode_arithmetic(type_size_t); ir_tarval *const idx_conv = tarval_convert_to(idx, mode); type_t *const elem_type = skip_typeref(expr->array_access.array_ref->base.type); ir_tarval *const elem_size = get_type_size_tarval(elem_type, mode); return tarval_add(base_addr, tarval_mul(idx_conv, elem_size)); } case EXPR_UNARY_DEREFERENCE: return fold_expression(expr->unary.value); default: panic("unexpected expression kind"); } }
static carry_result lower_add_carry(ir_node *left, ir_node *right, ir_mode *mode) { assert(!mode_is_signed(mode)); bitinfo *bi_left = get_bitinfo(left); if (!bi_left) { return can_carry; } bitinfo *bi_right = get_bitinfo(right); // If we have bitinfo for one node, we should also have it for // the other assert(bi_right); ir_tarval *lmin = tarval_convert_to(bitinfo_min(bi_left), mode); ir_tarval *rmin = tarval_convert_to(bitinfo_min(bi_right), mode); ir_tarval *lmax = tarval_convert_to(bitinfo_max(bi_left), mode); ir_tarval *rmax = tarval_convert_to(bitinfo_max(bi_right), mode); carry_result result = no_carry; int old_wrap_on_overflow = tarval_get_wrap_on_overflow(); tarval_set_wrap_on_overflow(false); if (tarval_add(lmax, rmax) == tarval_bad) { result = can_carry; if (tarval_add(lmin, rmin) == tarval_bad) { result = must_carry; } } tarval_set_wrap_on_overflow(old_wrap_on_overflow); return result; }
static complex_constant fold_complex_add(complex_constant const left, complex_constant const right) { return (complex_constant) { tarval_add(left.real, right.real), tarval_add(left.imag, right.imag) }; }
static ir_tarval *fold_binary_add(binary_expression_t const *const binexpr) { ir_tarval *const l = fold_expression(binexpr->left); ir_tarval *const r = fold_expression(binexpr->right); ir_tarval *ll = l; ir_tarval *rr = r; type_t *const typel = skip_typeref(binexpr->left->base.type); type_t *const typer = skip_typeref(binexpr->right->base.type); if (is_type_pointer(typel)) { type_t *const elem = skip_typeref(typel->pointer.points_to); ir_mode *const mode = get_ir_mode_arithmetic(typer); ir_tarval *const size = get_type_size_tarval(elem, mode); rr = tarval_mul(rr, size); } else if (is_type_pointer(typer)) { type_t *const elem = skip_typeref(typer->pointer.points_to); ir_mode *const mode = get_ir_mode_arithmetic(typel); ir_tarval *const size = get_type_size_tarval(elem, mode); ll = tarval_mul(ll, size); } else { type_t *const type = skip_typeref(binexpr->base.type); ir_mode *const mode = get_ir_mode_arithmetic(type); ll = tarval_convert_to(l, mode); rr = tarval_convert_to(r, mode); } return tarval_add(ll, rr); }
static complex_constant fold_complex_div(complex_constant const left, complex_constant const right) { ir_tarval *const op1 = tarval_mul(left.real, right.real); ir_tarval *const op2 = tarval_mul(left.imag, right.imag); ir_tarval *const op3 = tarval_mul(left.imag, right.real); ir_tarval *const op4 = tarval_mul(left.real, right.imag); ir_tarval *const op5 = tarval_mul(right.real, right.real); ir_tarval *const op6 = tarval_mul(right.imag, right.imag); ir_tarval *const real_dividend = tarval_add(op1, op2); ir_tarval *const real_divisor = tarval_add(op5, op6); ir_tarval *const imag_dividend = tarval_sub(op3, op4); ir_tarval *const imag_divisor = tarval_add(op5, op6); return (complex_constant) { tarval_div(real_dividend, real_divisor), tarval_div(imag_dividend, imag_divisor) }; }
static complex_constant fold_complex_mul(complex_constant const left, complex_constant const right) { ir_tarval *const op1 = tarval_mul(left.real, right.real); ir_tarval *const op2 = tarval_mul(left.imag, right.imag); ir_tarval *const op3 = tarval_mul(left.real, right.imag); ir_tarval *const op4 = tarval_mul(left.imag, right.real); return (complex_constant) { tarval_sub(op1, op2), tarval_add(op3, op4) }; }
/** * creates a tarval from a condensed representation. */ static ir_tarval *condensed_to_value(mul_env *env, unsigned char *R, int r) { ir_tarval *tv = get_mode_one(env->mode); ir_tarval *res = NULL; for (int i = 0; i < r; ++i) { int j = R[i]; if (j != 0) tv = tarval_shl_unsigned(tv, j); res = res ? tarval_add(res, tv) : tv; } return res; }
void determine_enum_values(enum_t *const enume) { if (enume->error) return; ir_mode *const mode = atomic_modes[enume->akind]; ir_tarval *const one = get_mode_one(mode); ir_tarval * tv_next = get_mode_null(mode); for (entity_t *entry = enume->first_value; entry != NULL && entry->kind == ENTITY_ENUM_VALUE; entry = entry->base.next) { expression_t *const init = entry->enum_value.value; if (init != NULL) { type_t *const init_type = skip_typeref(init->base.type); if (!is_type_valid(init_type)) continue; tv_next = fold_expression(init); } assert(entry->enum_value.tv == NULL || entry->enum_value.tv == tv_next); entry->enum_value.tv = tv_next; tv_next = tarval_add(tv_next, one); } }