mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-27 02:06:57 +00:00
Support new #[rustc_intrinsic] attribute and fallback bodies
This commit is contained in:
parent
78f3112626
commit
36d68c5d0f
9 changed files with 143 additions and 174 deletions
|
|
@ -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(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue