Skip to content

Commit d6645d1

Browse files
committed
Fix some mir eval/lowerings
1 parent 465844c commit d6645d1

File tree

5 files changed

+87
-6
lines changed

5 files changed

+87
-6
lines changed

.git-blame-ignore-revs

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ f247090558c9ba3c551566eae5882b7ca865225f
1414
b2f6fd4f961fc7e4fbfdb80cae2e6065f8436f15
1515
c48062fe2ab9a2d913d1985a6b0aec4bf936bfc1
1616
f532576ac53ddcc666bc8d59e0b6437065e2f599
17+
4704881b641884de50645637108b6b6f5b68aaf9

crates/hir-def/src/lang_item.rs

+1
Original file line numberDiff line numberDiff line change
@@ -501,4 +501,5 @@ language_item_table! {
501501

502502
String, sym::String, string, Target::Struct, GenericRequirement::None;
503503
CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
504+
Ordering, sym::Ordering, ordering, Target::Enum, GenericRequirement::None;
504505
}

crates/hir-ty/src/mir/eval.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -1644,14 +1644,15 @@ impl Evaluator<'_> {
16441644
Variants::Multiple { tag, tag_encoding, variants, .. } => {
16451645
let size = tag.size(&*self.target_data_layout).bytes_usize();
16461646
let offset = layout.fields.offset(0).bytes_usize(); // The only field on enum variants is the tag field
1647+
let is_signed = tag.is_signed();
16471648
match tag_encoding {
16481649
TagEncoding::Direct => {
16491650
let tag = &bytes[offset..offset + size];
1650-
Ok(i128::from_le_bytes(pad16(tag, false)))
1651+
Ok(i128::from_le_bytes(pad16(tag, is_signed)))
16511652
}
16521653
TagEncoding::Niche { untagged_variant, niche_start, .. } => {
16531654
let tag = &bytes[offset..offset + size];
1654-
let candidate_tag = i128::from_le_bytes(pad16(tag, false))
1655+
let candidate_tag = i128::from_le_bytes(pad16(tag, is_signed))
16551656
.wrapping_sub(*niche_start as i128)
16561657
as usize;
16571658
let idx = variants
@@ -2943,10 +2944,10 @@ pub fn render_const_using_debug_impl(
29432944
// a3 = ::core::fmt::Arguments::new_v1(a1, a2)
29442945
// FIXME: similarly, we should call function here, not directly working with memory.
29452946
let a3 = evaluator.heap_allocate(evaluator.ptr_size() * 6, evaluator.ptr_size())?;
2946-
evaluator.write_memory(a3.offset(2 * evaluator.ptr_size()), &a1.to_bytes())?;
2947+
evaluator.write_memory(a3, &a1.to_bytes())?;
2948+
evaluator.write_memory(a3.offset(evaluator.ptr_size()), &[1])?;
2949+
evaluator.write_memory(a3.offset(2 * evaluator.ptr_size()), &a2.to_bytes())?;
29472950
evaluator.write_memory(a3.offset(3 * evaluator.ptr_size()), &[1])?;
2948-
evaluator.write_memory(a3.offset(4 * evaluator.ptr_size()), &a2.to_bytes())?;
2949-
evaluator.write_memory(a3.offset(5 * evaluator.ptr_size()), &[1])?;
29502951
let Some(ValueNs::FunctionId(format_fn)) = resolver.resolve_path_in_value_ns_fully(
29512952
db.upcast(),
29522953
&hir_def::path::Path::from_known_path_with_no_generic(path![std::fmt::format]),

crates/hir-ty/src/mir/eval/shim.rs

+78-1
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
//! Interpret intrinsics, lang items and `extern "C"` wellknown functions which their implementation
22
//! is not available.
33
//!
4-
use std::cmp;
4+
use std::cmp::{self, Ordering};
55

66
use chalk_ir::TyKind;
77
use hir_def::{
88
builtin_type::{BuiltinInt, BuiltinUint},
9+
lang_item::LangItemTarget,
910
resolver::HasResolver,
1011
};
1112
use hir_expand::name::Name;
@@ -1317,6 +1318,82 @@ impl Evaluator<'_> {
13171318
self.write_memory_using_ref(dst, size)?.fill(val);
13181319
Ok(())
13191320
}
1321+
"ptr_metadata" => {
1322+
let [ptr] = args else {
1323+
return Err(MirEvalError::InternalError(
1324+
"ptr_metadata args are not provided".into(),
1325+
));
1326+
};
1327+
let arg = ptr.interval.get(self)?.to_owned();
1328+
let metadata = &arg[self.ptr_size()..];
1329+
destination.write_from_bytes(self, metadata)?;
1330+
Ok(())
1331+
}
1332+
"three_way_compare" => {
1333+
let [lhs, rhs] = args else {
1334+
return Err(MirEvalError::InternalError(
1335+
"three_way_compare args are not provided".into(),
1336+
));
1337+
};
1338+
let Some(ty) =
1339+
generic_args.as_slice(Interner).first().and_then(|it| it.ty(Interner))
1340+
else {
1341+
return Err(MirEvalError::InternalError(
1342+
"three_way_compare generic arg is not provided".into(),
1343+
));
1344+
};
1345+
let signed = match ty.as_builtin().unwrap() {
1346+
BuiltinType::Int(_) => true,
1347+
BuiltinType::Uint(_) => false,
1348+
_ => {
1349+
return Err(MirEvalError::InternalError(
1350+
"three_way_compare expects an integral type".into(),
1351+
))
1352+
}
1353+
};
1354+
let rhs = rhs.get(self)?;
1355+
let lhs = lhs.get(self)?;
1356+
let mut result = Ordering::Equal;
1357+
for (l, r) in lhs.iter().zip(rhs).rev() {
1358+
let it = l.cmp(r);
1359+
if it != Ordering::Equal {
1360+
result = it;
1361+
break;
1362+
}
1363+
}
1364+
if signed {
1365+
if let Some((&l, &r)) = lhs.iter().zip(rhs).next_back() {
1366+
if l != r {
1367+
result = (l as i8).cmp(&(r as i8));
1368+
}
1369+
}
1370+
}
1371+
if let Some(LangItemTarget::EnumId(e)) =
1372+
self.db.lang_item(self.crate_id, LangItem::Ordering)
1373+
{
1374+
let ty = self.db.ty(e.into());
1375+
let r = self
1376+
.compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?;
1377+
destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])?;
1378+
Ok(())
1379+
} else {
1380+
Err(MirEvalError::InternalError("Ordering enum not found".into()))
1381+
}
1382+
}
1383+
"aggregate_raw_ptr" => {
1384+
let [data, meta] = args else {
1385+
return Err(MirEvalError::InternalError(
1386+
"aggregate_raw_ptr args are not provided".into(),
1387+
));
1388+
};
1389+
destination.write_from_interval(self, data.interval)?;
1390+
Interval {
1391+
addr: destination.addr.offset(data.interval.size),
1392+
size: destination.size - data.interval.size,
1393+
}
1394+
.write_from_interval(self, meta.interval)?;
1395+
Ok(())
1396+
}
13201397
_ if needs_override => not_supported!("intrinsic {name} is not implemented"),
13211398
_ => return Ok(false),
13221399
}

crates/intern/src/symbol/symbols.rs

+1
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,7 @@ define_symbols! {
347347
option,
348348
Option,
349349
Ord,
350+
Ordering,
350351
Output,
351352
CallRefFuture,
352353
CallOnceFuture,

0 commit comments

Comments
 (0)