From 274e8301c1218f8506d6c20a83b316f8b99c7b9f Mon Sep 17 00:00:00 2001 From: hkalbasi Date: Wed, 12 Jul 2023 01:14:49 +0330 Subject: [PATCH] Add write_bytes and ctlz intrinsics --- crates/hir-ty/src/consteval/tests.rs | 12 +++++++ .../hir-ty/src/consteval/tests/intrinsics.rs | 32 +++++++++++++++++++ crates/hir-ty/src/mir/eval.rs | 22 +++++++------ crates/hir-ty/src/mir/eval/shim.rs | 32 +++++++++++++++++-- crates/hir-ty/src/mir/eval/shim/simd.rs | 7 +++- crates/hir-ty/src/mir/lower.rs | 1 + 6 files changed, 93 insertions(+), 13 deletions(-) diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs index 8e21272e14a..4ca1d8a2394 100644 --- a/crates/hir-ty/src/consteval/tests.rs +++ b/crates/hir-ty/src/consteval/tests.rs @@ -1724,6 +1724,18 @@ fn function_pointer() { "#, 5, ); + check_number( + r#" + fn add2(x: u8) -> u8 { + x + 2 + } + const GOAL: u8 = { + let plus2 = add2 as fn(u8) -> u8; + plus2(3) + }; + "#, + 5, + ); check_number( r#" //- minicore: coerce_unsized, index, slice diff --git a/crates/hir-ty/src/consteval/tests/intrinsics.rs b/crates/hir-ty/src/consteval/tests/intrinsics.rs index cb8f1b55575..30e87661abc 100644 --- a/crates/hir-ty/src/consteval/tests/intrinsics.rs +++ b/crates/hir-ty/src/consteval/tests/intrinsics.rs @@ -510,6 +510,24 @@ fn copy_nonoverlapping() { ); } +#[test] +fn write_bytes() { + check_number( + r#" + extern "rust-intrinsic" { + fn write_bytes(dst: *mut T, val: u8, count: usize); + } + + const GOAL: i32 = unsafe { + let mut x = 2; + write_bytes(&mut x, 5, 1); + x + }; + "#, + 0x05050505, + ); +} + #[test] fn copy() { check_number( @@ -545,6 +563,20 @@ fn ctpop() { ); } +#[test] +fn ctlz() { + check_number( + r#" + extern "rust-intrinsic" { + pub fn ctlz(x: T) -> T; + } + + const GOAL: u8 = ctlz(0b0001_1100_u8); + "#, + 3, + ); +} + #[test] fn cttz() { check_number( diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs index a1bab097951..47c93547683 100644 --- a/crates/hir-ty/src/mir/eval.rs +++ b/crates/hir-ty/src/mir/eval.rs @@ -1627,24 +1627,26 @@ impl Evaluator<'_> { .ok_or_else(|| MirEvalError::UndefinedBehavior("out of bound memory read".to_string())) } - fn write_memory(&mut self, addr: Address, r: &[u8]) -> Result<()> { - if r.is_empty() { - return Ok(()); - } + fn write_memory_using_ref(&mut self, addr: Address, size: usize) -> Result<&mut [u8]> { let (mem, pos) = match addr { Stack(it) => (&mut self.stack, it), Heap(it) => (&mut self.heap, it), Invalid(it) => { return Err(MirEvalError::UndefinedBehavior(format!( - "write invalid memory address {it} with content {r:?}" + "write invalid memory address {it} with size {size}" ))); } }; - mem.get_mut(pos..pos + r.len()) - .ok_or_else(|| { - MirEvalError::UndefinedBehavior("out of bound memory write".to_string()) - })? - .copy_from_slice(r); + Ok(mem.get_mut(pos..pos + size).ok_or_else(|| { + MirEvalError::UndefinedBehavior("out of bound memory write".to_string()) + })?) + } + + fn write_memory(&mut self, addr: Address, r: &[u8]) -> Result<()> { + if r.is_empty() { + return Ok(()); + } + self.write_memory_using_ref(addr, r.len())?.copy_from_slice(r); Ok(()) } diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index 3b8b7201223..cedc4538037 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -800,15 +800,25 @@ impl Evaluator<'_> { } "ctpop" => { let [arg] = args else { - return Err(MirEvalError::TypeError("likely arg is not provided")); + return Err(MirEvalError::TypeError("ctpop arg is not provided")); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).count_ones(); destination .write_from_bytes(self, &(result as u128).to_le_bytes()[0..destination.size]) } + "ctlz" | "ctlz_nonzero" => { + let [arg] = args else { + return Err(MirEvalError::TypeError("cttz arg is not provided")); + }; + let result = + u128::from_le_bytes(pad16(arg.get(self)?, false)).leading_zeros() as usize; + let result = result - (128 - arg.interval.size * 8); + destination + .write_from_bytes(self, &(result as u128).to_le_bytes()[0..destination.size]) + } "cttz" | "cttz_nonzero" => { let [arg] = args else { - return Err(MirEvalError::TypeError("likely arg is not provided")); + return Err(MirEvalError::TypeError("cttz arg is not provided")); }; let result = u128::from_le_bytes(pad16(arg.get(self)?, false)).trailing_zeros(); destination @@ -932,6 +942,24 @@ impl Evaluator<'_> { let addr = Address::from_bytes(arg.interval.get(self)?)?; destination.write_from_interval(self, Interval { addr, size: destination.size }) } + "write_bytes" => { + let [dst, val, count] = args else { + return Err(MirEvalError::TypeError("write_bytes args are not provided")); + }; + let count = from_bytes!(usize, count.get(self)?); + let val = from_bytes!(u8, val.get(self)?); + let Some(ty) = generic_args.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) + else { + return Err(MirEvalError::TypeError( + "write_bytes generic arg is not provided", + )); + }; + let dst = Address::from_bytes(dst.get(self)?)?; + let size = self.size_of_sized(ty, locals, "copy_nonoverlapping ptr type")?; + let size = count * size; + self.write_memory_using_ref(dst, size)?.fill(val); + Ok(()) + } _ => not_supported!("unknown intrinsic {name}"), } } diff --git a/crates/hir-ty/src/mir/eval/shim/simd.rs b/crates/hir-ty/src/mir/eval/shim/simd.rs index bc9529d38f4..ec746310487 100644 --- a/crates/hir-ty/src/mir/eval/shim/simd.rs +++ b/crates/hir-ty/src/mir/eval/shim/simd.rs @@ -44,7 +44,12 @@ impl Evaluator<'_> { } }; match try_const_usize(self.db, len) { - Some(_) => not_supported!("array like simd type"), + Some(len) => { + let Some(ty) = subst.as_slice(Interner).get(0).and_then(|it| it.ty(Interner)) else { + return Err(MirEvalError::TypeError("simd type with no ty param")); + }; + Ok((len as usize, ty.clone())) + } None => Err(MirEvalError::TypeError("simd type with unevaluatable len param")), } } diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs index d8fa8cf01a9..36108587904 100644 --- a/crates/hir-ty/src/mir/lower.rs +++ b/crates/hir-ty/src/mir/lower.rs @@ -1880,6 +1880,7 @@ impl<'ctx> MirLowerCtx<'ctx> { fn cast_kind(source_ty: &Ty, target_ty: &Ty) -> Result { Ok(match (source_ty.kind(Interner), target_ty.kind(Interner)) { + (TyKind::FnDef(..), TyKind::Function(_)) => CastKind::Pointer(PointerCast::ReifyFnPointer), (TyKind::Scalar(s), TyKind::Scalar(t)) => match (s, t) { (chalk_ir::Scalar::Float(_), chalk_ir::Scalar::Float(_)) => CastKind::FloatToFloat, (chalk_ir::Scalar::Float(_), _) => CastKind::FloatToInt,