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_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 complex_constant convert_complex_constant(const complex_constant cnst, ir_mode *mode) { if (get_tarval_mode(cnst.real) == mode) return cnst; return (complex_constant) { tarval_convert_to(cnst.real, mode), tarval_convert_to(cnst.imag, mode) }; }
static ir_tarval *bitinfo_min(bitinfo *info) { ir_tarval *z = info->z; ir_tarval *o = info->o; ir_mode *mode = get_tarval_mode(z); ir_tarval *min = get_mode_min(mode); assert(get_mode_arithmetic(mode) == irma_twos_complement); return tarval_or(o, tarval_and(z, min)); }
static bool tarval_possible(ir_tarval *tv) { ir_mode *mode = get_tarval_mode(tv); if (get_mode_size_bits(mode) <= 32) { assert(tarval_is_long(tv)); return true; } if (!tarval_is_long(tv)) return false; /* immediates on x86_64 are at most 32bit and get sign extended */ long val = get_tarval_long(tv); int32_t val32 = (long)val; return val == (long)val32; }
/** * Returns the condensed representation of the tarval tv */ static unsigned char *value_to_condensed(mul_env *env, ir_tarval *tv, int *pr) { ir_mode *mode = get_tarval_mode(tv); unsigned bits = get_mode_size_bits(mode); unsigned char *R = OALLOCN(&env->obst, unsigned char, bits); int r = 0; for (unsigned i = 0, l = 0; i < bits; ++i) { if (tarval_get_bit(tv, i)) { R[r] = i - l; l = i; ++r; } } *pr = r; return R; }
/** * construct an interval from a value * * @return the filled interval or NULL if no interval * can be created (happens only on floating point */ static interval_t *get_interval_from_tv(interval_t *iv, ir_tarval *tv) { ir_mode *mode = get_tarval_mode(tv); if (tv == tarval_bad) { if (mode_is_float(mode)) { /* NaN could be included which we cannot handle */ iv->min = tarval_bad; iv->max = tarval_bad; iv->flags = MIN_EXCLUDED | MAX_EXCLUDED; return NULL; } else { /* [-oo, +oo] */ iv->min = get_mode_min(mode); iv->max = get_mode_max(mode); iv->flags = MIN_INCLUDED | MAX_INCLUDED; return iv; } } if (mode_is_float(mode)) { if (tv == get_mode_NAN(mode)) { /* arg, we cannot handle NaN's. */ iv->min = tarval_bad; iv->max = tarval_bad; iv->flags = MIN_EXCLUDED | MAX_EXCLUDED; return NULL; } } /* [tv, tv] */ iv->min = tv; iv->max = tv; iv->flags = MIN_INCLUDED | MAX_INCLUDED; return iv; }
static bool check_initializer(const ir_initializer_t *initializer, const ir_type *type, const ir_entity *context) { bool fine = true; switch (get_initializer_kind(initializer)) { case IR_INITIALIZER_NULL: return fine; case IR_INITIALIZER_TARVAL: { ir_tarval *tv = get_initializer_tarval_value(initializer); if (get_type_mode(type) != get_tarval_mode(tv)) { report_error("tarval initializer for entity %+F has wrong mode: %+F vs %+F", context, get_type_mode(type), get_tarval_mode(tv)); fine = false; } return fine; } case IR_INITIALIZER_CONST: { ir_node *value = get_initializer_const_value(initializer); if (get_type_mode(type) != get_irn_mode(value)) { report_error("const initializer for entity %+F has wrong mode: %+F vs %+F", context, get_type_mode(type), get_irn_mode(value)); fine = false; } if (!constant_on_correct_irg(value)) { report_error("initializer const value %+F for entity %+F not on const-code irg", value, context); fine = false; } return fine; } case IR_INITIALIZER_COMPOUND: { size_t n_entries = get_initializer_compound_n_entries(initializer); if (is_Array_type(type)) { ir_type *element_type = get_array_element_type(type); /* TODO: check array bounds? */ for (size_t i = 0; i < n_entries; ++i) { const ir_initializer_t *sub_initializer = get_initializer_compound_value(initializer, i); check_initializer(sub_initializer, element_type, context); } } else if (is_compound_type(type)) { size_t n_members = get_compound_n_members(type); if (n_entries > n_members) { report_error("too many values in compound initializer of %+F", context); fine = false; } for (size_t i = 0; i < n_entries; ++i) { if (i >= n_members) break; ir_entity *member = get_compound_member(type, i); ir_type *member_type = get_entity_type(member); const ir_initializer_t *sub_initializer = get_initializer_compound_value(initializer, i); check_initializer(sub_initializer, member_type, context); } } else { report_error("compound initiailizer for non-array/compound type in entity %+F", context); fine = false; } return fine; } } report_error("invalid initializer for entity %+F", context); return false; }
int check_entity(const ir_entity *entity) { bool fine = true; ir_type *tp = get_entity_type(entity); ir_linkage linkage = get_entity_linkage(entity); fine &= constants_on_wrong_irg(entity); if (is_method_entity(entity)) { ir_graph *irg = get_entity_irg(entity); if (irg != NULL) { ir_entity *irg_entity = get_irg_entity(irg); if (irg_entity != entity) { report_error("entity(%+F)->irg->entity(%+F) relation invalid", entity, irg_entity); fine = false; } } if (get_entity_peculiarity(entity) == peculiarity_existent) { ir_entity *impl = get_SymConst_entity(get_atomic_ent_value(entity)); if (impl == NULL) { report_error("inherited method entity %+F must have constant pointing to existent entity.", entity); fine = false; } } } if (linkage & IR_LINKAGE_NO_CODEGEN) { if (!is_method_entity(entity)) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not a function", entity); fine = false; } else if (get_entity_irg(entity) == NULL) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but has no ir-graph anyway", entity); fine = false; } if (get_entity_visibility(entity) != ir_visibility_external) { report_error("entity %+F has IR_LINKAGE_NO_CODEGEN but is not externally visible", entity); fine = false; } } check_external_linkage(entity, IR_LINKAGE_WEAK, "WEAK"); check_external_linkage(entity, IR_LINKAGE_GARBAGE_COLLECT, "GARBAGE_COLLECT"); check_external_linkage(entity, IR_LINKAGE_MERGE, "MERGE"); if (is_atomic_entity(entity) && entity->initializer != NULL) { ir_mode *mode = NULL; ir_initializer_t *initializer = entity->initializer; switch (initializer->kind) { case IR_INITIALIZER_CONST: mode = get_irn_mode(get_initializer_const_value(initializer)); break; case IR_INITIALIZER_TARVAL: mode = get_tarval_mode(get_initializer_tarval_value(initializer)); break; case IR_INITIALIZER_NULL: case IR_INITIALIZER_COMPOUND: break; } if (mode != NULL && mode != get_type_mode(tp)) { report_error("initializer of entity %+F has wrong mode.", entity); fine = false; } } return fine; }