diff --git a/src/builder.rs b/src/builder.rs index 6347a3fb19b4..8dac76f01d10 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1873,32 +1873,33 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // On the other hand, f_max works even if int_ty::MAX is greater than float_ty::MAX. Because // we're rounding towards zero, we just get float_ty::MAX (which is always an integer). // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX. - let int_max = |signed: bool, int_width: u64| -> u128 { + fn int_max(signed: bool, int_width: u64) -> u128 { let shift_amount = 128 - int_width; if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount } - }; - let int_min = |signed: bool, int_width: u64| -> i128 { + } + fn int_min(signed: bool, int_width: u64) -> i128 { if signed { i128::MIN >> (128 - int_width) } else { 0 } - }; + } - let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) { + // TODO: rewrite using a generic function with . + let compute_clamp_bounds_half = |signed: bool, int_width: u64| -> (u128, u128) { let rounded_min = - ieee::Single::from_i128_r(int_min(signed, int_width), Round::TowardZero); - assert_eq!(rounded_min.status, Status::OK); + ieee::Half::from_i128_r(int_min(signed, int_width), Round::TowardZero); + //assert_eq!(rounded_min.status, Status::OK); let rounded_max = - ieee::Single::from_u128_r(int_max(signed, int_width), Round::TowardZero); + ieee::Half::from_u128_r(int_max(signed, int_width), Round::TowardZero); assert!(rounded_max.value.is_finite()); (rounded_min.value.to_bits(), rounded_max.value.to_bits()) }; - let compute_clamp_bounds_double = |signed: bool, int_width: u64| -> (u128, u128) { + fn compute_clamp_bounds(signed: bool, int_width: u64) -> (u128, u128) { let rounded_min = - ieee::Double::from_i128_r(int_min(signed, int_width), Round::TowardZero); + F::from_i128_r(int_min(signed, int_width), Round::TowardZero); assert_eq!(rounded_min.status, Status::OK); let rounded_max = - ieee::Double::from_u128_r(int_max(signed, int_width), Round::TowardZero); + F::from_u128_r(int_max(signed, int_width), Round::TowardZero); assert!(rounded_max.value.is_finite()); (rounded_min.value.to_bits(), rounded_max.value.to_bits()) - }; + } // To implement saturation, we perform the following steps: // // 1. Cast val to an integer with fpto[su]i. This may result in undef. @@ -1928,15 +1929,19 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let float_bits_to_llval = |bx: &mut Self, bits| { let bits_llval = match float_width { + 16 => bx.cx().const_u16(bits as u16), 32 => bx.cx().const_u32(bits as u32), 64 => bx.cx().const_u64(bits as u64), + 128 => bx.cx().const_u128(bits), n => bug!("unsupported float width {}", n), }; bx.bitcast(bits_llval, float_ty) }; let (f_min, f_max) = match float_width { - 32 => compute_clamp_bounds_single(signed, int_width), - 64 => compute_clamp_bounds_double(signed, int_width), + 16 => compute_clamp_bounds_half(signed, int_width), + 32 => compute_clamp_bounds::(signed, int_width), + 64 => compute_clamp_bounds::(signed, int_width), + 128 => compute_clamp_bounds::(signed, int_width), n => bug!("unsupported float width {}", n), }; let f_min = float_bits_to_llval(self, f_min); diff --git a/src/common.rs b/src/common.rs index 1f133fa0c1b7..86a4eeac89d5 100644 --- a/src/common.rs +++ b/src/common.rs @@ -20,6 +20,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { bytes_in_context(self, bytes) } + pub fn const_u16(&self, i: u16) -> RValue<'gcc> { + self.const_uint(self.type_u16(), i as u64) + } + fn global_string(&self, string: &str) -> LValue<'gcc> { // TODO(antoyo): handle non-null-terminated strings. let string = self.context.new_string_literal(string);