Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/eval/shim.rs')
| -rw-r--r-- | crates/hir-ty/src/mir/eval/shim.rs | 144 |
1 files changed, 57 insertions, 87 deletions
diff --git a/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs index 0cdad74a4f..0a78f4a5b2 100644 --- a/crates/hir-ty/src/mir/eval/shim.rs +++ b/crates/hir-ty/src/mir/eval/shim.rs @@ -9,7 +9,7 @@ use hir_def::{ resolver::HasResolver, }; use hir_expand::name::Name; -use intern::sym; +use intern::{sym, Symbol}; use crate::{ error_lifetime, @@ -54,49 +54,32 @@ impl Evaluator<'_> { } let function_data = self.db.function_data(def); - let is_intrinsic = match &function_data.abi { - Some(abi) => *abi == sym::rust_dash_intrinsic, - None => match def.lookup(self.db.upcast()).container { - hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(self.db.upcast()).id; - id.item_tree(self.db.upcast())[id.value].abi.as_ref() - == Some(&sym::rust_dash_intrinsic) - } - _ => false, - }, - }; + let attrs = self.db.attrs(def.into()); + let is_intrinsic = attrs.by_key(&sym::rustc_intrinsic).exists() + // Keep this around for a bit until extern "rustc-intrinsic" abis are no longer used + || (match &function_data.abi { + Some(abi) => *abi == sym::rust_dash_intrinsic, + None => match def.lookup(self.db.upcast()).container { + hir_def::ItemContainerId::ExternBlockId(block) => { + let id = block.lookup(self.db.upcast()).id; + id.item_tree(self.db.upcast())[id.value].abi.as_ref() + == Some(&sym::rust_dash_intrinsic) + } + _ => false, + }, + }); + if is_intrinsic { - self.exec_intrinsic( + return self.exec_intrinsic( function_data.name.as_str(), args, generic_args, destination, locals, span, - )?; - return Ok(true); - } - let is_platform_intrinsic = match &function_data.abi { - Some(abi) => *abi == sym::platform_dash_intrinsic, - None => match def.lookup(self.db.upcast()).container { - hir_def::ItemContainerId::ExternBlockId(block) => { - let id = block.lookup(self.db.upcast()).id; - id.item_tree(self.db.upcast())[id.value].abi.as_ref() - == Some(&sym::platform_dash_intrinsic) - } - _ => false, - }, - }; - if is_platform_intrinsic { - self.exec_platform_intrinsic( - function_data.name.as_str(), - args, - generic_args, - destination, - locals, - span, - )?; - return Ok(true); + !function_data.has_body() + || attrs.by_key(&sym::rustc_intrinsic_must_be_overridden).exists(), + ); } let is_extern_c = match def.lookup(self.db.upcast()).container { hir_def::ItemContainerId::ExternBlockId(block) => { @@ -106,27 +89,25 @@ impl Evaluator<'_> { _ => false, }; if is_extern_c { - self.exec_extern_c( - function_data.name.as_str(), - args, - generic_args, - destination, - locals, - span, - )?; - return Ok(true); + return self + .exec_extern_c( + function_data.name.as_str(), + args, + generic_args, + destination, + locals, + span, + ) + .map(|()| true); } - let alloc_fn = function_data - .attrs - .iter() - .filter_map(|it| it.path().as_ident()) - .map(|it| it.as_str()) - .find(|it| { + + let alloc_fn = + attrs.iter().filter_map(|it| it.path().as_ident()).map(|it| it.symbol()).find(|it| { [ - "rustc_allocator", - "rustc_deallocator", - "rustc_reallocator", - "rustc_allocator_zeroed", + &sym::rustc_allocator, + &sym::rustc_deallocator, + &sym::rustc_reallocator, + &sym::rustc_allocator_zeroed, ] .contains(it) }); @@ -270,12 +251,12 @@ impl Evaluator<'_> { fn exec_alloc_fn( &mut self, - alloc_fn: &str, + alloc_fn: &Symbol, args: &[IntervalAndTy], destination: Interval, ) -> Result<()> { match alloc_fn { - "rustc_allocator_zeroed" | "rustc_allocator" => { + _ if *alloc_fn == sym::rustc_allocator_zeroed || *alloc_fn == sym::rustc_allocator => { let [size, align] = args else { return Err(MirEvalError::InternalError( "rustc_allocator args are not provided".into(), @@ -286,8 +267,8 @@ impl Evaluator<'_> { let result = self.heap_allocate(size, align)?; destination.write_from_bytes(self, &result.to_bytes())?; } - "rustc_deallocator" => { /* no-op for now */ } - "rustc_reallocator" => { + _ if *alloc_fn == sym::rustc_deallocator => { /* no-op for now */ } + _ if *alloc_fn == sym::rustc_reallocator => { let [ptr, old_size, align, new_size] = args else { return Err(MirEvalError::InternalError( "rustc_allocator args are not provided".into(), @@ -603,21 +584,6 @@ impl Evaluator<'_> { } } - fn exec_platform_intrinsic( - &mut self, - name: &str, - args: &[IntervalAndTy], - generic_args: &Substitution, - destination: Interval, - locals: &Locals, - span: MirSpan, - ) -> Result<()> { - if let Some(name) = name.strip_prefix("simd_") { - return self.exec_simd_intrinsic(name, args, generic_args, destination, locals, span); - } - not_supported!("unknown platform intrinsic {name}"); - } - fn exec_intrinsic( &mut self, name: &str, @@ -626,9 +592,17 @@ impl Evaluator<'_> { destination: Interval, locals: &Locals, span: MirSpan, - ) -> Result<()> { + needs_override: bool, + ) -> Result<bool> { if let Some(name) = name.strip_prefix("atomic_") { - return self.exec_atomic_intrinsic(name, args, generic_args, destination, locals, span); + return self + .exec_atomic_intrinsic(name, args, generic_args, destination, locals, span) + .map(|()| true); + } + if let Some(name) = name.strip_prefix("simd_") { + return self + .exec_simd_intrinsic(name, args, generic_args, destination, locals, span) + .map(|()| true); } // FIXME(#17451): Add `f16` and `f128` intrinsics. if let Some(name) = name.strip_suffix("f64") { @@ -701,7 +675,7 @@ impl Evaluator<'_> { } _ => not_supported!("unknown f64 intrinsic {name}"), }; - return destination.write_from_bytes(self, &result.to_le_bytes()); + return destination.write_from_bytes(self, &result.to_le_bytes()).map(|()| true); } if let Some(name) = name.strip_suffix("f32") { let result = match name { @@ -773,7 +747,7 @@ impl Evaluator<'_> { } _ => not_supported!("unknown f32 intrinsic {name}"), }; - return destination.write_from_bytes(self, &result.to_le_bytes()); + return destination.write_from_bytes(self, &result.to_le_bytes()).map(|()| true); } match name { "size_of" => { @@ -1146,12 +1120,6 @@ impl Evaluator<'_> { }; destination.write_from_interval(self, arg.interval) } - "likely" | "unlikely" => { - let [arg] = args else { - return Err(MirEvalError::InternalError("likely arg is not provided".into())); - }; - destination.write_from_interval(self, arg.interval) - } "ctpop" => { let [arg] = args else { return Err(MirEvalError::InternalError("ctpop arg is not provided".into())); @@ -1296,7 +1264,7 @@ impl Evaluator<'_> { None, span, )?; - return Ok(()); + return Ok(true); } } not_supported!("FnOnce was not available for executing const_eval_select"); @@ -1349,8 +1317,10 @@ impl Evaluator<'_> { self.write_memory_using_ref(dst, size)?.fill(val); Ok(()) } - _ => not_supported!("unknown intrinsic {name}"), + _ if needs_override => not_supported!("intrinsic {name} is not implemented"), + _ => return Ok(false), } + .map(|()| true) } fn size_align_of_unsized( |