ir_node *gcji_allocate_array(ir_type *eltype, ir_node *count) { ir_node *jclass = gcji_get_runtime_classinfo(eltype); ir_node *res; ir_node *new_mem; if (is_Primitive_type(eltype)) { ir_node *addr = new_Address(gcj_new_prim_array_entity); ir_node *args[] = { jclass, count }; ir_type *call_type = get_entity_type(gcj_new_prim_array_entity); ir_node *mem = get_store(); ir_node *call = new_Call(mem, addr, ARRAY_SIZE(args), args, call_type); ir_node *ress = new_Proj(call, mode_T, pn_Call_T_result); new_mem = new_Proj(call, mode_M, pn_Call_M); res = new_r_Proj(ress, mode_reference, 0); } else { ir_node *addr = new_Address(gcj_new_object_array_entity); ir_node *null = new_Const(get_mode_null(mode_reference)); ir_node *args[] = { count, jclass, null }; ir_type *call_type = get_entity_type(gcj_new_object_array_entity); ir_node *mem = get_store(); ir_node *call = new_Call(mem, addr, ARRAY_SIZE(args), args, call_type); ir_node *ress = new_Proj(call, mode_T, pn_Call_T_result); new_mem = new_Proj(call, mode_M, pn_Call_M); res = new_Proj(ress, mode_reference, 0); } ir_node *assure_vptr = new_VptrIsSet(new_mem, res, type_jarray); ir_node *new_mem2 = new_Proj(assure_vptr, mode_M, pn_VptrIsSet_M); ir_node *res2 = new_Proj(assure_vptr, mode_reference, pn_VptrIsSet_res); set_store(new_mem2); return res2; }
static ir_tarval *literal_to_tarval_(const literal_expression_t *literal, ir_mode *mode) { switch (literal->base.kind) { case EXPR_LITERAL_INTEGER: assert(literal->target_value != NULL); return literal->target_value; case EXPR_LITERAL_FLOATINGPOINT: return new_tarval_from_str(literal->value->begin, literal->value->size, mode); case EXPR_LITERAL_BOOLEAN: if (literal->value->begin[0] == 't') { return get_mode_one(mode); } else { assert(literal->value->begin[0] == 'f'); case EXPR_LITERAL_MS_NOOP: return get_mode_null(mode); } default: panic("invalid literal kind"); } }
ir_node *get_atomic_ent_value(const ir_entity *entity) { ir_initializer_t *initializer = get_entity_initializer(entity); assert(is_atomic_entity(entity)); if (initializer == NULL) { ir_type *type = get_entity_type(entity); return new_r_Unknown(get_const_code_irg(), get_type_mode(type)); } switch (get_initializer_kind(initializer)) { case IR_INITIALIZER_NULL: { ir_type *type = get_entity_type(entity); ir_mode *mode = get_type_mode(type); return new_r_Const(get_const_code_irg(), get_mode_null(mode)); } case IR_INITIALIZER_TARVAL: { ir_tarval *tv = get_initializer_tarval_value(initializer); return new_r_Const(get_const_code_irg(), tv); } case IR_INITIALIZER_CONST: return get_initializer_const_value(initializer); case IR_INITIALIZER_COMPOUND: panic("compound initializer in atomic entity not allowed (%+F)", entity); } panic("invalid initializer kind (%+F)", entity); }
complex_constant fold_complex_literal(literal_expression_t const *const literal) { type_t *type = skip_typeref(literal->base.type); ir_mode *mode = get_complex_mode_storage(type); ir_tarval *litvalue = literal_to_tarval_(literal, mode); ir_tarval *zero = get_mode_null(mode); return (complex_constant) { zero, litvalue }; }
static void check_mode(ir_mode *mode) { ir_tarval *zero = get_mode_null(mode); ir_tarval *minus_zero = tarval_neg(zero); ir_tarval *min = get_mode_min(mode); ir_tarval *max = get_mode_max(mode); ir_tarval *inf = get_mode_infinite(mode); ir_tarval *minus_inf = tarval_neg(inf); ir_tarval *one = get_mode_one(mode); ir_tarval *minus_one = tarval_neg(one); /* some random arithmetics */ ir_tarval *int_zero = get_mode_null(mode_Is); ir_tarval *int_one = get_mode_one(mode_Is); ir_tarval *int_minus_one = get_mode_all_one(mode_Is); ir_tarval *int_min = get_mode_min(mode_Is); ir_tarval *int_max = get_mode_max(mode_Is); assert(tarval_convert_to(zero, mode_Is) == int_zero); assert(tarval_convert_to(minus_zero, mode_Is) == int_zero); assert(tarval_convert_to(one, mode_Is) == int_one); assert(tarval_convert_to(minus_one, mode_Is) == int_minus_one); assert(tarval_convert_to(min, mode_Is) == int_min); assert(tarval_convert_to(max, mode_Is) == int_max); assert(tarval_convert_to(inf, mode_Is) == int_max); assert(tarval_convert_to(minus_inf, mode_Is) == int_min); static const char *const ints[] = { "0", "1", "-1", "12345", "2", "4", "8", "16", "32", "64", "128", "256", "512", "1024", "2048", "127", "2047" }; for (unsigned i = 0; i < ARRAY_SIZE(ints); ++i) { const char *str = ints[i]; ir_tarval *flt = new_tarval_from_str(str, strlen(str), mode); ir_tarval *intt = new_tarval_from_str(str, strlen(str), mode_Is); assert(tarval_convert_to(flt, mode_Is) == intt); assert(tarval_convert_to(intt, mode) == flt); } }
static ir_node *gcji_get_arrayclass(ir_node *block, ir_node **mem, ir_node *array_class_ref) { ir_graph *irg = get_irn_irg(block); ir_node *addr = new_r_Address(irg, gcj_get_array_class_entity); ir_node *null = new_r_Const(irg, get_mode_null(mode_reference)); ir_node *args[] = { array_class_ref, null }; ir_type *call_type = get_entity_type(gcj_get_array_class_entity); ir_node *call = new_r_Call(block, *mem, addr, ARRAY_SIZE(args), args, call_type); ir_node *new_mem = new_Proj(call, mode_M, pn_Call_M); ir_node *ress = new_Proj(call, mode_T, pn_Call_T_result); ir_node *res = new_Proj(ress, mode_reference, 0); *mem = new_mem; return res; }
static complex_constant fold_complex_cast(const unary_expression_t *expression) { const expression_t *const value = expression->value; type_t *const from_type = skip_typeref(value->base.type); type_t *const to_type = skip_typeref(expression->base.type); ir_mode *const mode = get_complex_mode_storage(to_type); if (is_type_complex(from_type)) { complex_constant const folded = fold_complex(value); return convert_complex_constant(folded, mode); } else { ir_tarval *const folded = fold_expression(value); ir_tarval *const casted = tarval_convert_to(folded, mode); ir_tarval *const zero = get_mode_null(mode); return (complex_constant) { casted, zero }; } }
static ir_node *gcji_instanceof(ir_node *objptr, ir_type *classtype, ir_graph *irg, ir_node *block, ir_node **mem) { ir_node *jclass = gcji_get_runtime_classinfo_(block, mem, classtype); ir_node *addr = new_r_Address(irg, gcj_instanceof_entity); ir_node *args[] = { objptr, jclass }; ir_type *call_type = get_entity_type(gcj_instanceof_entity); ir_node *call = new_r_Call(block, *mem, addr, ARRAY_SIZE(args), args, call_type); ir_node *new_mem = new_r_Proj(call, mode_M, pn_Call_M); ir_node *ress = new_r_Proj(call, mode_T, pn_Call_T_result); ir_node *call_res = new_r_Proj(ress, mode_int, 0); ir_node *zero = new_r_Const(irg, get_mode_null(mode_int)); ir_node *res = new_r_Cmp(block, call_res, zero, ir_relation_less_greater); *mem = new_mem; return res; }
bool enum_bitfield_big_enough(enum_t *enume, type_t *base_type, unsigned bitfield_size) { ir_mode *mode = get_ir_mode_storage(base_type); ir_tarval *max = get_mode_max(mode); ir_tarval *min = get_mode_min(mode); bool is_signed = is_type_signed(base_type); unsigned mode_size = get_mode_size_bits(mode); unsigned shift_amount = mode_size - bitfield_size + is_signed; ir_tarval *adjusted_max; ir_tarval *adjusted_min; /* corner case: signed mode with just sign bit results in shift_amount * being as big as mode_size triggering "modulo shift" which is not what * we want here. */ if (shift_amount >= mode_size) { assert(bitfield_size == 1 && mode_is_signed(mode)); adjusted_max = get_mode_null(mode); adjusted_min = get_mode_all_one(mode); } else { adjusted_max = tarval_shr_unsigned(max, shift_amount); adjusted_min = tarval_shrs_unsigned(min, shift_amount); } for (entity_t *entry = enume->first_value; entry != NULL && entry->kind == ENTITY_ENUM_VALUE; entry = entry->base.next) { ir_tarval *tv = get_enum_value(&entry->enum_value); if (tv == NULL) continue; ir_tarval *tvc = tarval_convert_to(tv, mode); if (tarval_cmp(tvc, adjusted_min) == ir_relation_less || tarval_cmp(tvc, adjusted_max) == ir_relation_greater) { return false; } } return true; }
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); } }
/* * Check, if the value of a node is != 0. * * This is a often needed case, so we handle here Confirm * nodes too. */ int value_not_zero(const ir_node *n, const ir_node **confirm) { #define RET_ON(x) if (x) { *confirm = n; return 1; } break ir_tarval *tv; ir_mode *mode = get_irn_mode(n); ir_relation relation; *confirm = NULL; /* there might be several Confirms one after other that form an interval */ for (;;) { if (is_Minus(n)) { /* we can safely skip Minus when checking for != 0 */ n = get_Minus_op(n); continue; } if (! is_Confirm(n)) break; /* * Note: A Confirm is never after a Const. So, * we simply can check the bound for being a Const * without the fear that is might be hidden by a further Confirm. */ tv = value_of(get_Confirm_bound(n)); if (tv == tarval_bad) { n = get_Confirm_value(n); continue; } relation = tarval_cmp(tv, get_mode_null(mode)); /* * Beware: C might by a NaN. It is not clear, what we should do * than. Of course a NaN is != 0, but we might use this function * to remove up Exceptions, and NaN's might generate Exception. * So, we do NOT handle NaNs here for safety. * * Note that only the C != 0 case need additional checking. */ switch (get_Confirm_relation(n)) { case ir_relation_equal: /* n == C /\ C != 0 ==> n != 0 */ RET_ON(relation != ir_relation_equal && relation != ir_relation_unordered); case ir_relation_less_greater: /* n != C /\ C == 0 ==> n != 0 */ RET_ON(relation == ir_relation_equal); case ir_relation_less: /* n < C /\ C <= 0 ==> n != 0 */ RET_ON(relation == ir_relation_less || relation == ir_relation_equal); case ir_relation_less_equal: /* n <= C /\ C < 0 ==> n != 0 */ RET_ON(relation == ir_relation_less); case ir_relation_greater_equal: /* n >= C /\ C > 0 ==> n != 0 */ RET_ON(relation == ir_relation_greater); case ir_relation_greater: /* n > C /\ C >= 0 ==> n != 0 */ RET_ON(relation == ir_relation_greater || relation == ir_relation_equal); default: break; } n = get_Confirm_value(n); } /* global entities are never NULL */ if (is_SymConst_addr_ent(n)) return true; tv = value_of(n); if (tv == tarval_bad) return false; relation = tarval_cmp(tv, get_mode_null(mode)); /* again, need check for NaN */ return (relation != ir_relation_equal) && (relation != ir_relation_unordered); #undef RET_ON }
/* * Check, if the value of a node can be confirmed >= 0 or <= 0, * If the mode of the value did not honor signed zeros, else * check for >= 0 or < 0. */ ir_value_classify_sign classify_value_sign(ir_node *n) { ir_tarval *tv, *c; ir_mode *mode; ir_relation cmp, ncmp; int negate = 1; for (;;) { unsigned code = get_irn_opcode(n); switch (code) { case iro_Minus: negate *= -1; n = get_Minus_op(n); continue; case iro_Confirm: break; default: return value_classified_unknown; } break; } if (!is_Confirm(n)) return value_classified_unknown; tv = value_of(get_Confirm_bound(n)); if (tv == tarval_bad) return value_classified_unknown; mode = get_irn_mode(n); /* * We can handle only >=, >, <, <= cases. * We could handle == too, but this will be optimized into * a constant either. * * Note that for integer modes we have a slightly better * optimization possibilities, so we handle this * different. */ cmp = get_Confirm_relation(n); switch (cmp) { case ir_relation_less: /* * must be x < c <= 1 to be useful if integer mode and -0 = 0 * x < c <= 0 to be useful else */ case ir_relation_less_equal: /* * must be x <= c < 1 to be useful if integer mode and -0 = 0 * x <= c < 0 to be useful else */ c = mode_is_int(mode) && mode_honor_signed_zeros(mode) ? get_mode_one(mode) : get_mode_null(mode); ncmp = tarval_cmp(tv, c); if (ncmp == ir_relation_equal) ncmp = ir_relation_less_equal; if (cmp != (ncmp ^ ir_relation_equal)) return value_classified_unknown; /* yep, negative */ return value_classified_negative * negate; case ir_relation_greater_equal: /* * must be x >= c > -1 to be useful if integer mode * x >= c >= 0 to be useful else */ case ir_relation_greater: /* * must be x > c >= -1 to be useful if integer mode * x > c >= 0 to be useful else */ if (mode_is_int(mode)) { c = get_mode_minus_one(mode); ncmp = tarval_cmp(tv, c); if (ncmp == ir_relation_equal) ncmp = ir_relation_greater_equal; if (cmp != (ncmp ^ ir_relation_equal)) return value_classified_unknown; } else { c = get_mode_minus_one(mode); ncmp = tarval_cmp(tv, c); if (ncmp != ir_relation_equal && ncmp != ir_relation_greater) return value_classified_unknown; } /* yep, positive */ return value_classified_positive * negate; default: return value_classified_unknown; } }