mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-07-07 21:25:37 +00:00
Fix some mir eval/lowerings
This commit is contained in:
parent
465844c3be
commit
d6645d11da
5 changed files with 87 additions and 6 deletions
|
@ -14,3 +14,4 @@ f247090558c9ba3c551566eae5882b7ca865225f
|
||||||
b2f6fd4f961fc7e4fbfdb80cae2e6065f8436f15
|
b2f6fd4f961fc7e4fbfdb80cae2e6065f8436f15
|
||||||
c48062fe2ab9a2d913d1985a6b0aec4bf936bfc1
|
c48062fe2ab9a2d913d1985a6b0aec4bf936bfc1
|
||||||
f532576ac53ddcc666bc8d59e0b6437065e2f599
|
f532576ac53ddcc666bc8d59e0b6437065e2f599
|
||||||
|
4704881b641884de50645637108b6b6f5b68aaf9
|
||||||
|
|
|
@ -501,4 +501,5 @@ language_item_table! {
|
||||||
|
|
||||||
String, sym::String, string, Target::Struct, GenericRequirement::None;
|
String, sym::String, string, Target::Struct, GenericRequirement::None;
|
||||||
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
|
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
|
||||||
|
Ordering, sym::Ordering, ordering, Target::Enum, GenericRequirement::None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1644,14 +1644,15 @@ impl Evaluator<'_> {
|
||||||
Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
Variants::Multiple { tag, tag_encoding, variants, .. } => {
|
||||||
let size = tag.size(&*self.target_data_layout).bytes_usize();
|
let size = tag.size(&*self.target_data_layout).bytes_usize();
|
||||||
let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field
|
let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field
|
||||||
|
let is_signed = tag.is_signed();
|
||||||
match tag_encoding {
|
match tag_encoding {
|
||||||
TagEncoding::Direct => {
|
TagEncoding::Direct => {
|
||||||
let tag = &bytes[offset..offset + size];
|
let tag = &bytes[offset..offset + size];
|
||||||
Ok(i128::from_le_bytes(pad16(tag, false)))
|
Ok(i128::from_le_bytes(pad16(tag, is_signed)))
|
||||||
}
|
}
|
||||||
TagEncoding::Niche { untagged_variant, niche_start, .. } => {
|
TagEncoding::Niche { untagged_variant, niche_start, .. } => {
|
||||||
let tag = &bytes[offset..offset + size];
|
let tag = &bytes[offset..offset + size];
|
||||||
let candidate_tag = i128::from_le_bytes(pad16(tag, false))
|
let candidate_tag = i128::from_le_bytes(pad16(tag, is_signed))
|
||||||
.wrapping_sub(*niche_start as i128)
|
.wrapping_sub(*niche_start as i128)
|
||||||
as usize;
|
as usize;
|
||||||
let idx = variants
|
let idx = variants
|
||||||
|
@ -2943,10 +2944,10 @@ pub fn render_const_using_debug_impl(
|
||||||
// a3 = ::core::fmt::Arguments::new_v1(a1, a2)
|
// a3 = ::core::fmt::Arguments::new_v1(a1, a2)
|
||||||
// FIXME: similarly, we should call function here, not directly working with memory.
|
// FIXME: similarly, we should call function here, not directly working with memory.
|
||||||
let a3 = evaluator.heap_allocate(evaluator.ptr_size() * 6, evaluator.ptr_size())?;
|
let a3 = evaluator.heap_allocate(evaluator.ptr_size() * 6, evaluator.ptr_size())?;
|
||||||
evaluator.write_memory(a3.offset(2 * evaluator.ptr_size()), &a1.to_bytes())?;
|
evaluator.write_memory(a3, &a1.to_bytes())?;
|
||||||
|
evaluator.write_memory(a3.offset(evaluator.ptr_size()), &[1])?;
|
||||||
|
evaluator.write_memory(a3.offset(2 * evaluator.ptr_size()), &a2.to_bytes())?;
|
||||||
evaluator.write_memory(a3.offset(3 * evaluator.ptr_size()), &[1])?;
|
evaluator.write_memory(a3.offset(3 * evaluator.ptr_size()), &[1])?;
|
||||||
evaluator.write_memory(a3.offset(4 * evaluator.ptr_size()), &a2.to_bytes())?;
|
|
||||||
evaluator.write_memory(a3.offset(5 * evaluator.ptr_size()), &[1])?;
|
|
||||||
let Some(ValueNs::FunctionId(format_fn)) = resolver.resolve_path_in_value_ns_fully(
|
let Some(ValueNs::FunctionId(format_fn)) = resolver.resolve_path_in_value_ns_fully(
|
||||||
db.upcast(),
|
db.upcast(),
|
||||||
&hir_def::path::Path::from_known_path_with_no_generic(path![std::fmt::format]),
|
&hir_def::path::Path::from_known_path_with_no_generic(path![std::fmt::format]),
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
//! Interpret intrinsics, lang items and `extern "C"` wellknown functions which their implementation
|
//! Interpret intrinsics, lang items and `extern "C"` wellknown functions which their implementation
|
||||||
//! is not available.
|
//! is not available.
|
||||||
//!
|
//!
|
||||||
use std::cmp;
|
use std::cmp::{self, Ordering};
|
||||||
|
|
||||||
use chalk_ir::TyKind;
|
use chalk_ir::TyKind;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
builtin_type::{BuiltinInt, BuiltinUint},
|
builtin_type::{BuiltinInt, BuiltinUint},
|
||||||
|
lang_item::LangItemTarget,
|
||||||
resolver::HasResolver,
|
resolver::HasResolver,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
|
@ -1317,6 +1318,82 @@ impl Evaluator<'_> {
|
||||||
self.write_memory_using_ref(dst, size)?.fill(val);
|
self.write_memory_using_ref(dst, size)?.fill(val);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
"ptr_metadata" => {
|
||||||
|
let [ptr] = args else {
|
||||||
|
return Err(MirEvalError::InternalError(
|
||||||
|
"ptr_metadata args are not provided".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let arg = ptr.interval.get(self)?.to_owned();
|
||||||
|
let metadata = &arg[self.ptr_size()..];
|
||||||
|
destination.write_from_bytes(self, metadata)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
"three_way_compare" => {
|
||||||
|
let [lhs, rhs] = args else {
|
||||||
|
return Err(MirEvalError::InternalError(
|
||||||
|
"three_way_compare args are not provided".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let Some(ty) =
|
||||||
|
generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
|
||||||
|
else {
|
||||||
|
return Err(MirEvalError::InternalError(
|
||||||
|
"three_way_compare generic arg is not provided".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
let signed = match ty.as_builtin().unwrap() {
|
||||||
|
BuiltinType::Int(_) => true,
|
||||||
|
BuiltinType::Uint(_) => false,
|
||||||
|
_ => {
|
||||||
|
return Err(MirEvalError::InternalError(
|
||||||
|
"three_way_compare expects an integral type".into(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let rhs = rhs.get(self)?;
|
||||||
|
let lhs = lhs.get(self)?;
|
||||||
|
let mut result = Ordering::Equal;
|
||||||
|
for (l, r) in lhs.iter().zip(rhs).rev() {
|
||||||
|
let it = l.cmp(r);
|
||||||
|
if it != Ordering::Equal {
|
||||||
|
result = it;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if signed {
|
||||||
|
if let Some((&l, &r)) = lhs.iter().zip(rhs).next_back() {
|
||||||
|
if l != r {
|
||||||
|
result = (l as i8).cmp(&(r as i8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(LangItemTarget::EnumId(e)) =
|
||||||
|
self.db.lang_item(self.crate_id, LangItem::Ordering)
|
||||||
|
{
|
||||||
|
let ty = self.db.ty(e.into());
|
||||||
|
let r = self
|
||||||
|
.compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?;
|
||||||
|
destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(MirEvalError::InternalError("Ordering enum not found".into()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"aggregate_raw_ptr" => {
|
||||||
|
let [data, meta] = args else {
|
||||||
|
return Err(MirEvalError::InternalError(
|
||||||
|
"aggregate_raw_ptr args are not provided".into(),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
destination.write_from_interval(self, data.interval)?;
|
||||||
|
Interval {
|
||||||
|
addr: destination.addr.offset(data.interval.size),
|
||||||
|
size: destination.size - data.interval.size,
|
||||||
|
}
|
||||||
|
.write_from_interval(self, meta.interval)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
_ if needs_override => not_supported!("intrinsic {name} is not implemented"),
|
_ if needs_override => not_supported!("intrinsic {name} is not implemented"),
|
||||||
_ => return Ok(false),
|
_ => return Ok(false),
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,6 +347,7 @@ define_symbols! {
|
||||||
option,
|
option,
|
||||||
Option,
|
Option,
|
||||||
Ord,
|
Ord,
|
||||||
|
Ordering,
|
||||||
Output,
|
Output,
|
||||||
CallRefFuture,
|
CallRefFuture,
|
||||||
CallOnceFuture,
|
CallOnceFuture,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue