Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/mir/eval.rs')
-rw-r--r--crates/hir-ty/src/mir/eval.rs80
1 files changed, 80 insertions, 0 deletions
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index 4ee96a66a3..2d9c221b73 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -18,6 +18,10 @@ use hir_expand::{mod_path::ModPath, HirFileIdExt, InFile};
use intern::Interned;
use la_arena::ArenaMap;
use rustc_abi::TargetDataLayout;
+use rustc_apfloat::{
+ ieee::{Half as f16, Quad as f128},
+ Float,
+};
use rustc_hash::{FxHashMap, FxHashSet};
use stdx::never;
use syntax::{SyntaxNodePtr, TextRange};
@@ -55,6 +59,13 @@ macro_rules! from_bytes {
Err(_) => return Err(MirEvalError::InternalError(stringify!(mismatched size in constructing $ty).into())),
}))
};
+ ($apfloat:tt, $bits:tt, $value:expr) => {
+ // FIXME(#17451): Switch to builtin `f16` and `f128` once they are stable.
+ $apfloat::from_bits($bits::from_le_bytes(match ($value).try_into() {
+ Ok(it) => it,
+ Err(_) => return Err(MirEvalError::InternalError(stringify!(mismatched size in constructing $apfloat).into())),
+ }).into())
+ };
}
macro_rules! not_supported {
@@ -1110,6 +1121,10 @@ impl Evaluator<'_> {
}
if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) {
match f {
+ chalk_ir::FloatTy::F16 => {
+ let c = -from_bytes!(f16, u16, c);
+ Owned(u16::try_from(c.to_bits()).unwrap().to_le_bytes().into())
+ }
chalk_ir::FloatTy::F32 => {
let c = -from_bytes!(f32, c);
Owned(c.to_le_bytes().into())
@@ -1118,6 +1133,10 @@ impl Evaluator<'_> {
let c = -from_bytes!(f64, c);
Owned(c.to_le_bytes().into())
}
+ chalk_ir::FloatTy::F128 => {
+ let c = -from_bytes!(f128, u128, c);
+ Owned(c.to_bits().to_le_bytes().into())
+ }
}
} else {
let mut c = c.to_vec();
@@ -1169,6 +1188,39 @@ impl Evaluator<'_> {
}
if let TyKind::Scalar(chalk_ir::Scalar::Float(f)) = ty.kind(Interner) {
match f {
+ chalk_ir::FloatTy::F16 => {
+ let l = from_bytes!(f16, u16, lc);
+ let r = from_bytes!(f16, u16, rc);
+ match op {
+ BinOp::Ge
+ | BinOp::Gt
+ | BinOp::Le
+ | BinOp::Lt
+ | BinOp::Eq
+ | BinOp::Ne => {
+ let r = op.run_compare(l, r) as u8;
+ Owned(vec![r])
+ }
+ BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div => {
+ let r = match op {
+ BinOp::Add => l + r,
+ BinOp::Sub => l - r,
+ BinOp::Mul => l * r,
+ BinOp::Div => l / r,
+ _ => unreachable!(),
+ };
+ Owned(
+ u16::try_from(r.value.to_bits())
+ .unwrap()
+ .to_le_bytes()
+ .into(),
+ )
+ }
+ it => not_supported!(
+ "invalid binop {it:?} on floating point operators"
+ ),
+ }
+ }
chalk_ir::FloatTy::F32 => {
let l = from_bytes!(f32, lc);
let r = from_bytes!(f32, rc);
@@ -1225,6 +1277,34 @@ impl Evaluator<'_> {
),
}
}
+ chalk_ir::FloatTy::F128 => {
+ let l = from_bytes!(f128, u128, lc);
+ let r = from_bytes!(f128, u128, rc);
+ match op {
+ BinOp::Ge
+ | BinOp::Gt
+ | BinOp::Le
+ | BinOp::Lt
+ | BinOp::Eq
+ | BinOp::Ne => {
+ let r = op.run_compare(l, r) as u8;
+ Owned(vec![r])
+ }
+ BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div => {
+ let r = match op {
+ BinOp::Add => l + r,
+ BinOp::Sub => l - r,
+ BinOp::Mul => l * r,
+ BinOp::Div => l / r,
+ _ => unreachable!(),
+ };
+ Owned(r.value.to_bits().to_le_bytes().into())
+ }
+ it => not_supported!(
+ "invalid binop {it:?} on floating point operators"
+ ),
+ }
+ }
}
} else {
let is_signed = matches!(ty.as_builtin(), Some(BuiltinType::Int(_)));