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.rs | 80 |
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(_))); |