Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/eval/shim/simd.rs')
| -rw-r--r-- | crates/hir-ty/src/mir/eval/shim/simd.rs | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs index 64fd130182..bc9529d38f 100644 --- a/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -22,7 +22,7 @@ macro_rules! not_supported { } impl Evaluator<'_> { - fn detect_simd_ty(&self, ty: &Ty) -> Result<usize> { + fn detect_simd_ty(&self, ty: &Ty) -> Result<(usize, Ty)> { match ty.kind(Interner) { TyKind::Adt(id, subst) => { let len = match subst.as_slice(Interner).get(1).and_then(|it| it.constant(Interner)) @@ -30,13 +30,21 @@ impl Evaluator<'_> { Some(len) => len, _ => { if let AdtId::StructId(id) = id.0 { - return Ok(self.db.struct_data(id).variant_data.fields().len()); + let struct_data = self.db.struct_data(id); + let fields = struct_data.variant_data.fields(); + let Some((first_field, _)) = fields.iter().next() else { + not_supported!("simd type with no field"); + }; + let field_ty = self.db.field_types(id.into())[first_field] + .clone() + .substitute(Interner, subst); + return Ok((fields.len(), field_ty)); } return Err(MirEvalError::TypeError("simd type with no len param")); } }; match try_const_usize(self.db, len) { - Some(it) => Ok(it as usize), + Some(_) => not_supported!("array like simd type"), None => Err(MirEvalError::TypeError("simd type with unevaluatable len param")), } } @@ -75,7 +83,8 @@ impl Evaluator<'_> { let [left, right] = args else { return Err(MirEvalError::TypeError("simd args are not provided")); }; - let len = self.detect_simd_ty(&left.ty)?; + let (len, ty) = self.detect_simd_ty(&left.ty)?; + let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_))); let size = left.interval.size / len; let dest_size = destination.size / len; let mut destination_bytes = vec![]; @@ -89,6 +98,13 @@ impl Evaluator<'_> { break; } } + if is_signed { + if let Some((&l, &r)) = l.iter().zip(r).rev().next() { + if l != r { + result = (l as i8).cmp(&(r as i8)); + } + } + } let result = match result { Ordering::Less => ["lt", "le", "ne"].contains(&name), Ordering::Equal => ["ge", "le", "eq"].contains(&name), @@ -102,9 +118,9 @@ impl Evaluator<'_> { } "bitmask" => { let [op] = args else { - return Err(MirEvalError::TypeError("simd_shuffle args are not provided")); + return Err(MirEvalError::TypeError("simd_bitmask args are not provided")); }; - let op_len = self.detect_simd_ty(&op.ty)?; + let (op_len, _) = self.detect_simd_ty(&op.ty)?; let op_count = op.interval.size / op_len; let mut result: u64 = 0; for (i, val) in op.get(self)?.chunks(op_count).enumerate() { @@ -131,7 +147,7 @@ impl Evaluator<'_> { )) } }; - let left_len = self.detect_simd_ty(&left.ty)?; + let (left_len, _) = self.detect_simd_ty(&left.ty)?; let left_size = left.interval.size / left_len; let vector = left.get(self)?.chunks(left_size).chain(right.get(self)?.chunks(left_size)); |