Prepend instructions to inst to avoid traps
(pos: &mut FuncCursor, inst: Inst)
| 65 | |
| 66 | /// Prepend instructions to inst to avoid traps |
| 67 | fn insert_fcvt_sequence(pos: &mut FuncCursor, inst: Inst) { |
| 68 | let dfg = &pos.func.dfg; |
| 69 | let opcode = dfg.insts[inst].opcode(); |
| 70 | let arg = dfg.inst_args(inst)[0]; |
| 71 | let float_ty = dfg.value_type(arg); |
| 72 | let int_ty = dfg.value_type(dfg.first_result(inst)); |
| 73 | |
| 74 | // These instructions trap on NaN |
| 75 | let is_nan = pos.ins().fcmp(FloatCC::NotEqual, arg, arg); |
| 76 | |
| 77 | // They also trap if the value is larger or smaller than what the integer type can represent. So |
| 78 | // we generate the maximum and minimum float value that would make this trap, and compare against |
| 79 | // those limits. |
| 80 | let is_signed = opcode == Opcode::FcvtToSint; |
| 81 | let (min, max) = float_limits(pos, float_ty, int_ty, is_signed); |
| 82 | let underflows = pos.ins().fcmp(FloatCC::LessThanOrEqual, arg, min); |
| 83 | let overflows = pos.ins().fcmp(FloatCC::GreaterThanOrEqual, arg, max); |
| 84 | |
| 85 | // Check the previous conditions and replace with a 1.0 if this instruction would trap |
| 86 | let overflows_int = pos.ins().bor(underflows, overflows); |
| 87 | let is_invalid = pos.ins().bor(is_nan, overflows_int); |
| 88 | |
| 89 | let one = if float_ty == F32 { |
| 90 | pos.ins().f32const(1.0) |
| 91 | } else { |
| 92 | pos.ins().f64const(1.0) |
| 93 | }; |
| 94 | let new_arg = pos.ins().select(is_invalid, one, arg); |
| 95 | |
| 96 | // Replace the previous arg with the new one |
| 97 | pos.func.dfg.inst_args_mut(inst)[0] = new_arg; |
| 98 | } |
no test coverage detected