int values_in_mode(const ir_mode *sm, const ir_mode *lm) { assert(sm != NULL); assert(lm != NULL); if (sm == lm) return true; if (sm == mode_b) return mode_is_int(lm) || mode_is_float(lm); ir_mode_arithmetic larith = get_mode_arithmetic(lm); ir_mode_arithmetic sarith = get_mode_arithmetic(sm); switch (larith) { case irma_x86_extended_float: case irma_ieee754: if (sarith == irma_ieee754 || sarith == irma_x86_extended_float) { return get_mode_size_bits(sm) <= get_mode_size_bits(lm); } else if (sarith == irma_twos_complement) { unsigned int_mantissa = get_mode_size_bits(sm) - (mode_is_signed(sm) ? 1 : 0); unsigned float_mantissa = get_mode_mantissa_size(lm) + 1; return int_mantissa <= float_mantissa; } break; case irma_twos_complement: if (sarith == irma_twos_complement) return get_mode_size_bits(sm) <= get_mode_size_bits(lm); break; case irma_none: break; } return false; }
int smaller_mode(const ir_mode *sm, const ir_mode *lm) { assert(sm != NULL); assert(lm != NULL); if (sm == lm) return true; switch (get_mode_sort(sm)) { case irms_int_number: switch (get_mode_sort(lm)) { case irms_int_number: if (get_mode_arithmetic(sm) != get_mode_arithmetic(lm)) return false; /* only two complement implemented */ assert(get_mode_arithmetic(sm) == irma_twos_complement); /* integers are convertable if * - both have the same sign and lm is the larger one * - lm is signed and is at least one bit larger (the sign) */ unsigned sm_bits = get_mode_size_bits(sm); unsigned lm_bits = get_mode_size_bits(lm); if (mode_is_signed(sm)) { if (!mode_is_signed(lm)) return false; } else { if (mode_is_signed(lm)) return sm_bits < lm_bits; } return sm_bits <= lm_bits; case irms_auxiliary: case irms_data: case irms_internal_boolean: case irms_reference: case irms_float_number: /* int to float works if the float is large enough */ return false; } panic("invalid mode_sort"); case irms_float_number: return get_mode_arithmetic(sm) == get_mode_arithmetic(lm) && mode_is_float(lm) && get_mode_size_bits(lm) >= get_mode_size_bits(sm); case irms_auxiliary: case irms_data: case irms_internal_boolean: case irms_reference: /* do exist machines out there with different pointer lengths ?*/ return false; } panic("invalid mode_sort"); }
int is_reinterpret_cast(const ir_mode *src, const ir_mode *dst) { if (src == dst) return true; if (get_mode_size_bits(src) != get_mode_size_bits(dst)) return false; ir_mode_arithmetic ma = get_mode_arithmetic(src); if (ma != get_mode_arithmetic(dst)) return false; return ma == irma_twos_complement; }
bool x86_match_immediate(x86_imm32_t *immediate, const ir_node *node, char const constraint) { ir_mode *const mode = get_irn_mode(node); if (get_mode_arithmetic(mode) != irma_twos_complement) return false; ir_tarval *offset; ir_entity *entity; if (!be_match_immediate(node, &offset, &entity)) return false; long val = 0; if (offset) { if (!tarval_is_long(offset)) { be_warningf(node, "tarval is not long"); return false; } val = get_tarval_long(offset); if (!check_immediate_constraint(val, constraint)) return false; } if (entity != NULL) { /* we need full 32bits for entities */ if (constraint != 'i' && constraint != 'g') return false; } /* we are fine */ immediate->entity = entity; immediate->offset = (int32_t)val; return true; }
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 void handle_intrinsic(ir_node *node, void *data) { (void)data; if (is_Div(node)) { ir_mode *mode = get_Div_resmode(node); if (get_mode_arithmetic(mode) == irma_twos_complement) { ir_entity *entity = mode_is_signed(mode) ? divsi3 : udivsi3; be_map_exc_node_to_runtime_call(node, mode, entity, pn_Div_M, pn_Div_X_regular, pn_Div_X_except, pn_Div_res); } } else if (is_Mod(node)) { ir_mode *mode = get_Mod_resmode(node); assert(get_mode_arithmetic(mode) == irma_twos_complement); ir_entity *entity = mode_is_signed(mode) ? modsi3 : umodsi3; be_map_exc_node_to_runtime_call(node, mode, entity, pn_Mod_M, pn_Mod_X_regular, pn_Mod_X_except, pn_Mod_res); } }
/** * lower 64bit conversions */ static void ia32_lower_conv64(ir_node *node, ir_mode *mode) { dbg_info *dbg = get_irn_dbg_info(node); ir_node *op = get_Conv_op(node); ir_mode *mode_from = get_irn_mode(op); ir_mode *mode_to = get_irn_mode(node); if (mode_is_float(mode_from) && get_mode_size_bits(mode_to) == 64 && get_mode_arithmetic(mode_to) == irma_twos_complement) { /* We have a Conv float -> long long here */ ir_node *float_to_ll; ir_node *l_res; ir_node *h_res; if (mode_is_signed(mode)) { /* convert from float to signed 64bit */ ir_node *block = get_nodes_block(node); float_to_ll = new_bd_ia32_l_FloattoLL(dbg, block, op); l_res = new_r_Proj(float_to_ll, ia32_mode_gp, pn_ia32_l_FloattoLL_res_low); h_res = new_r_Proj(float_to_ll, mode, pn_ia32_l_FloattoLL_res_high); } else { /* Convert from float to unsigned 64bit. */ ir_graph *irg = get_irn_irg(node); ir_tarval *flt_tv = new_tarval_from_str("9223372036854775808", 19, x86_mode_E); ir_node *flt_corr = new_r_Const(irg, flt_tv); ir_node *lower_blk = part_block_dw(node); ir_node *upper_blk = get_nodes_block(node); set_dw_control_flow_changed(); ir_node *opc = new_rd_Conv(dbg, upper_blk, op, x86_mode_E); ir_node *cmp = new_rd_Cmp(dbg, upper_blk, opc, flt_corr, ir_relation_less); ir_node *cond = new_rd_Cond(dbg, upper_blk, cmp); ir_node *in[] = { new_r_Proj(cond, mode_X, pn_Cond_true), new_r_Proj(cond, mode_X, pn_Cond_false) }; ir_node *blk = new_r_Block(irg, 1, &in[1]); in[1] = new_r_Jmp(blk); set_irn_in(lower_blk, 2, in); /* create to Phis */ ir_node *phi_in[] = { new_r_Const_null(irg, mode), new_r_Const_long(irg, mode, 0x80000000) }; ir_node *int_phi = new_r_Phi(lower_blk, ARRAY_SIZE(phi_in), phi_in, mode); ir_node *fphi_in[] = { opc, new_rd_Sub(dbg, upper_blk, opc, flt_corr, x86_mode_E) }; ir_node *flt_phi = new_r_Phi(lower_blk, ARRAY_SIZE(fphi_in), fphi_in, x86_mode_E); /* fix Phi links for next part_block() */ if (is_Phi(int_phi)) add_Block_phi(lower_blk, int_phi); if (is_Phi(flt_phi)) add_Block_phi(lower_blk, flt_phi); float_to_ll = new_bd_ia32_l_FloattoLL(dbg, lower_blk, flt_phi); l_res = new_r_Proj(float_to_ll, ia32_mode_gp, pn_ia32_l_FloattoLL_res_low); h_res = new_r_Proj(float_to_ll, mode, pn_ia32_l_FloattoLL_res_high); h_res = new_rd_Add(dbg, lower_blk, h_res, int_phi, mode); /* move the call and its Proj's to the lower block */ set_nodes_block(node, lower_blk); for (ir_node *proj = (ir_node*)get_irn_link(node); proj != NULL; proj = (ir_node*)get_irn_link(proj)) { set_nodes_block(proj, lower_blk); } } ir_set_dw_lowered(node, l_res, h_res); } else if (get_mode_size_bits(mode_from) == 64 && get_mode_arithmetic(mode_from) == irma_twos_complement && mode_is_float(mode_to)) { /* We have a Conv long long -> float here */ ir_node *op_low = get_lowered_low(op); ir_node *op_high = get_lowered_high(op); ir_node *block = get_nodes_block(node); ir_node *ll_to_float = new_bd_ia32_l_LLtoFloat(dbg, block, op_high, op_low, mode_to); exchange(node, ll_to_float); } else { ir_default_lower_dw_Conv(node, mode); } }
/** * @return The type of the function replacing the given node. */ static ir_type *get_softfloat_type(const ir_node *n) { ir_node *operand = get_irn_n(n, 0); ir_mode *operand_mode = get_irn_mode(operand); switch (get_irn_opcode(n)) { case iro_Div: operand_mode = get_irn_mode(get_Div_left(n)); /* fall through */ case iro_Add: case iro_Mul: case iro_Sub: if (operand_mode == mode_F) return binop_tp_f; else if (operand_mode == mode_D) return binop_tp_d; break; case iro_Cmp: if (operand_mode == mode_F) return cmp_tp_f; else if (operand_mode == mode_D) return cmp_tp_d; break; case iro_Conv: { ir_mode *const mode = get_irn_mode(n); if (operand_mode == mode_D) { if (mode == mode_F) return unop_tp_d_f; else if (get_mode_arithmetic(mode) == irma_twos_complement) { if (get_mode_size_bits(mode) <= 32) return mode_is_signed(mode) ? unop_tp_d_is : unop_tp_d_iu; else if (get_mode_size_bits(mode) == 64) return mode_is_signed(mode) ? unop_tp_d_ls : unop_tp_d_lu; } } else if (operand_mode == mode_F) { if (mode == mode_D) return unop_tp_f_d; else if (get_mode_arithmetic(mode) == irma_twos_complement) { if (get_mode_size_bits(mode) <= 32) return mode_is_signed(mode) ? unop_tp_f_is : unop_tp_f_iu; else if (get_mode_size_bits(mode) == 64) return mode_is_signed(mode) ? unop_tp_f_ls : unop_tp_f_lu; } } else if (get_mode_arithmetic(operand_mode) == irma_twos_complement) { if (mode_is_signed(operand_mode)) { if (get_mode_size_bits(operand_mode) <= 32) { if (mode == mode_D) return unop_tp_is_d; else if (mode == mode_F) return unop_tp_is_f; } else if (get_mode_size_bits(operand_mode) == 64) { if (mode == mode_D) return unop_tp_ls_d; else if (mode == mode_F) return unop_tp_ls_f; } } else { if (get_mode_size_bits(operand_mode) <= 32) { if (mode == mode_D) return unop_tp_iu_d; else if (mode == mode_F) return unop_tp_iu_f; } else if (get_mode_size_bits(operand_mode) == 64) { if (mode == mode_D) return unop_tp_lu_d; else if (mode == mode_F) return unop_tp_lu_f; } } } break; } case iro_Minus: if (operand_mode == mode_F) return unop_tp_f; else if (operand_mode == mode_D) return unop_tp_d; break; default: break; } panic("could not determine a suitable type"); }
int smaller_mode(const ir_mode *sm, const ir_mode *lm) { int sm_bits, lm_bits; assert(sm); assert(lm); if (sm == lm) return 1; sm_bits = get_mode_size_bits(sm); lm_bits = get_mode_size_bits(lm); switch (get_mode_sort(sm)) { case irms_int_number: switch (get_mode_sort(lm)) { case irms_int_number: if (get_mode_arithmetic(sm) != get_mode_arithmetic(lm)) return 0; /* only two complement implemented */ assert(get_mode_arithmetic(sm) == irma_twos_complement); /* integers are convertable if * - both have the same sign and lm is the larger one * - lm is the signed one and is at least two bits larger * (one for the sign, one for the highest bit of sm) * - sm & lm are two_complement and lm has greater or equal number of bits */ if (mode_is_signed(sm)) { if (!mode_is_signed(lm)) return 0; return sm_bits <= lm_bits; } else { if (mode_is_signed(lm)) { return sm_bits < lm_bits; } return sm_bits <= lm_bits; } case irms_float_number: /* int to float works if the float is large enough */ return 0; default: break; } break; case irms_float_number: if (get_mode_arithmetic(sm) == get_mode_arithmetic(lm)) { if ( (get_mode_sort(lm) == irms_float_number) && (get_mode_size_bits(lm) >= get_mode_size_bits(sm)) ) return 1; } break; case irms_reference: /* do exist machines out there with different pointer lengths ?*/ return 0; case irms_internal_boolean: return mode_is_int(lm); default: break; } /* else */ return 0; }