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.rs144
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(