mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 06:41:48 +00:00
Add f16
and f128
support
This commit is contained in:
parent
da27b89ca5
commit
d5db933f9d
28 changed files with 384 additions and 73 deletions
|
@ -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(_)));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue