static ir_tarval *fold_binary_sub(binary_expression_t const *const binexpr) { ir_tarval *const l = fold_expression(binexpr->left); ir_tarval *const r = fold_expression(binexpr->right); type_t *const type = skip_typeref(binexpr->base.type); ir_mode *const res_mode = get_ir_mode_arithmetic(type); type_t *const typel = skip_typeref(binexpr->left->base.type); if (is_type_pointer(typel)) { type_t *const elem = skip_typeref(typel->pointer.points_to); type_t *const typer = skip_typeref(binexpr->right->base.type); if (is_type_pointer(typer)) { ir_tarval *const size = get_type_size_tarval(elem, res_mode); ir_tarval *const diff = tarval_sub(l, r); return tarval_div(diff, size); } else { ir_mode *const mode = get_tarval_mode(r); ir_tarval *const size = get_type_size_tarval(elem, mode); ir_tarval *const rr = tarval_mul(r, size); return tarval_sub(l, rr); } } else { ir_tarval *const conv_l = tarval_convert_to(l, res_mode); ir_tarval *const conv_r = tarval_convert_to(r, res_mode); return tarval_sub(conv_l, conv_r); } }
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 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 unsigned get_address_alignment(expression_t const *const expr) { if (expr->kind == EXPR_UNARY_TAKE_ADDRESS) { return get_object_alignment(expr->unary.value); } else { type_t *const type = skip_typeref(expr->base.type); assert(is_type_pointer(type)); return get_type_alignment(type->pointer.points_to); } }
type_t *handle_attribute_mode(const attribute_t *attribute, type_t *orig_type) { type_t *type = skip_typeref(orig_type); /* at least: byte, word, pointer, list of machine modes * __XXX___ is interpreted as XXX */ /* This isn't really correct, the backend should provide a list of machine * specific modes (according to gcc philosophy that is...) */ attribute_argument_t *arg = attribute->a.arguments; if (arg == NULL) { errorf(&attribute->pos, "__attribute__((mode(X))) misses argument"); return orig_type; } const char *symbol_str = arg->v.symbol->string; bool sign = is_type_signed(type); atomic_type_kind_t akind; if (streq_underscore("QI", symbol_str) || streq_underscore("byte", symbol_str)) { akind = sign ? ATOMIC_TYPE_CHAR : ATOMIC_TYPE_UCHAR; } else if (streq_underscore("HI", symbol_str)) { akind = sign ? ATOMIC_TYPE_SHORT : ATOMIC_TYPE_USHORT; } else if (streq_underscore("SI", symbol_str) || streq_underscore("word", symbol_str) || streq_underscore("pointer", symbol_str)) { akind = sign ? ATOMIC_TYPE_INT : ATOMIC_TYPE_UINT; } else if (streq_underscore("DI", symbol_str)) { akind = sign ? ATOMIC_TYPE_LONGLONG : ATOMIC_TYPE_ULONGLONG; } else { warningf(WARN_OTHER, &attribute->pos, "ignoring unknown mode '%s'", symbol_str); return orig_type; } if (type->kind == TYPE_ATOMIC || type->kind == TYPE_ENUM) { type_t *copy = duplicate_type(type); copy->atomic.akind = akind; return identify_new_type(copy); } else if (is_type_pointer(type)) { warningf(WARN_OTHER, &attribute->pos, "__attribute__((mode)) on pointers not implemented yet (ignored)"); return type; } errorf(&attribute->pos, "__attribute__((mode)) only allowed on integer, enum or pointer type"); return orig_type; }
static void write_pointer_type(const pointer_type_t *type) { type_t *orig_points_to = type->points_to; type_t *points_to = skip_typeref(type->points_to); if (is_type_atomic(points_to, ATOMIC_TYPE_CHAR) && orig_points_to->kind != TYPE_TYPEDEF) { fputs("String", out); return; } if (is_type_pointer(points_to)) { /* hack... */ fputs("java.nio.Buffer", out); return; } fputs("Pointer", out); }
static ir_tarval *fold_call_builtin(call_expression_t const *const call) { expression_t const *const function = call->function; assert(function->kind == EXPR_REFERENCE); reference_expression_t const *const ref = &function->reference; assert(ref->entity->kind == ENTITY_FUNCTION); type_t *expr_type = skip_typeref(ref->base.type); assert(is_type_pointer(expr_type)); type_t *function_type = skip_typeref(expr_type->pointer.points_to); assert(is_type_function(function_type)); switch (ref->entity->function.btk) { case BUILTIN_INF: return fold_builtin_inf(function_type); case BUILTIN_NAN: return fold_builtin_nan(call, function_type); default: panic("builtin is no constant"); } }