diff --git a/cranelift/codegen/src/ir/types.rs b/cranelift/codegen/src/ir/types.rs index bb2056926b..59e6a871b9 100644 --- a/cranelift/codegen/src/ir/types.rs +++ b/cranelift/codegen/src/ir/types.rs @@ -104,6 +104,8 @@ impl Type { } /// Get an integer type with the requested number of bits. + /// + /// For the same thing but in *bytes*, use [`Self::int_with_byte_size`]. pub fn int(bits: u16) -> Option { match bits { 8 => Some(I8), @@ -115,6 +117,13 @@ impl Type { } } + /// Get an integer type with the requested number of bytes. + /// + /// For the same thing but in *bits*, use [`Self::int`]. + pub fn int_with_byte_size(bytes: u16) -> Option { + Self::int(bytes.checked_mul(8)?) + } + /// Get a type with the same number of lanes as `self`, but using `lane` as the lane type. fn replace_lanes(self, lane: Self) -> Self { debug_assert!(lane.is_lane() && !self.is_special()); @@ -595,4 +604,22 @@ mod tests { assert_eq!(B8.as_int(), I8); assert_eq!(B128.as_int(), I128); } + + #[test] + fn int_from_size() { + assert_eq!(Type::int(0), None); + assert_eq!(Type::int(8), Some(I8)); + assert_eq!(Type::int(33), None); + assert_eq!(Type::int(64), Some(I64)); + + assert_eq!(Type::int_with_byte_size(0), None); + assert_eq!(Type::int_with_byte_size(2), Some(I16)); + assert_eq!(Type::int_with_byte_size(6), None); + assert_eq!(Type::int_with_byte_size(16), Some(I128)); + + // Ensure `int_with_byte_size` handles overflow properly + let evil = 0xE001_u16; + assert_eq!(evil.wrapping_mul(8), 8, "check the constant is correct"); + assert_eq!(Type::int_with_byte_size(evil), None); + } } diff --git a/cranelift/frontend/src/frontend.rs b/cranelift/frontend/src/frontend.rs index eb87cb0e66..7611e69c0a 100644 --- a/cranelift/frontend/src/frontend.rs +++ b/cranelift/frontend/src/frontend.rs @@ -13,6 +13,7 @@ use cranelift_codegen::ir::{ }; use cranelift_codegen::isa::TargetFrontendConfig; use cranelift_codegen::packed_option::PackedOption; +use std::convert::TryInto; // FIXME: Remove in edition2021 /// Structure used for translating a series of functions into Cranelift IR. /// @@ -892,13 +893,7 @@ impl<'a> FunctionBuilder<'a> { } // Future work could consider expanding this to handle more-complex scenarios. - fn type_from_byte_size(size: u64) -> Option { - if size > 16 { - return None; - } - Type::int(size as u16 * 8) - } - if let Some(small_type) = type_from_byte_size(size) { + if let Some(small_type) = size.try_into().ok().and_then(Type::int_with_byte_size) { if let Equal | NotEqual = zero_cc { let mut left_flags = flags; if size == left_align.get().into() {