Remove ConstFloat
This commit is contained in:
parent
f45d0f3783
commit
40b118cf47
@ -11,11 +11,6 @@
|
||||
//! This module contains `HashStable` implementations for various data types
|
||||
//! from `rustc_const_math` in no particular order.
|
||||
|
||||
impl_stable_hash_for!(struct ::rustc_const_math::ConstFloat {
|
||||
ty,
|
||||
bits
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum ::rustc_const_math::ConstMathErr {
|
||||
Overflow(op),
|
||||
DivisionByZero,
|
||||
|
@ -43,6 +43,8 @@ use std::vec::IntoIter;
|
||||
use syntax::ast::{self, Name};
|
||||
use syntax::symbol::InternedString;
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use rustc_apfloat::ieee::{Single, Double};
|
||||
use rustc_apfloat::Float;
|
||||
|
||||
mod cache;
|
||||
pub mod tcx;
|
||||
@ -1915,12 +1917,13 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ty::Const) -> fmt::Result {
|
||||
|
||||
pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Result {
|
||||
use ty::TypeVariants::*;
|
||||
use rustc_const_math::ConstFloat;
|
||||
match (value, &ty.sty) {
|
||||
(Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"),
|
||||
(Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"),
|
||||
(Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(fty)) =>
|
||||
write!(f, "{}", ConstFloat { bits, ty: fty }),
|
||||
(Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F32)) =>
|
||||
write!(f, "{}", Single::from_bits(bits)),
|
||||
(Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) =>
|
||||
write!(f, "{}", Double::from_bits(bits)),
|
||||
(Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui),
|
||||
(Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i),
|
||||
(Value::ByVal(PrimVal::Bytes(n)), &TyChar) =>
|
||||
|
@ -1,217 +0,0 @@
|
||||
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::num::ParseFloatError;
|
||||
|
||||
use syntax::ast;
|
||||
|
||||
use rustc_apfloat::{Float, FloatConvert, Status};
|
||||
use rustc_apfloat::ieee::{Single, Double};
|
||||
|
||||
// Note that equality for `ConstFloat` means that the it is the same
|
||||
// constant, not that the rust values are equal. In particular, `NaN
|
||||
// == NaN` (at least if it's the same NaN; distinct encodings for NaN
|
||||
// are considering unequal).
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||
pub struct ConstFloat {
|
||||
pub ty: ast::FloatTy,
|
||||
|
||||
// This is a bit inefficient but it makes conversions below more
|
||||
// ergonomic, and all of this will go away once `miri` is merged.
|
||||
pub bits: u128,
|
||||
}
|
||||
|
||||
impl PartialOrd<ConstFloat> for ConstFloat {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
self.try_cmp(*other)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConstFloat {
|
||||
/// Description of the type, not the value
|
||||
pub fn description(&self) -> &'static str {
|
||||
self.ty.ty_to_string()
|
||||
}
|
||||
|
||||
/// Compares the values if they are of the same type
|
||||
fn try_cmp(self, rhs: Self) -> Option<Ordering> {
|
||||
match (self.ty, rhs.ty) {
|
||||
(ast::FloatTy::F64, ast::FloatTy::F64) => {
|
||||
let a = Double::from_bits(self.bits);
|
||||
let b = Double::from_bits(rhs.bits);
|
||||
// This is pretty bad but it is the existing behavior.
|
||||
Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater))
|
||||
}
|
||||
|
||||
(ast::FloatTy::F32, ast::FloatTy::F32) => {
|
||||
let a = Single::from_bits(self.bits);
|
||||
let b = Single::from_bits(rhs.bits);
|
||||
Some(a.partial_cmp(&b).unwrap_or(Ordering::Greater))
|
||||
}
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_i128(input: i128, ty: ast::FloatTy) -> Self {
|
||||
let bits = match ty {
|
||||
ast::FloatTy::F32 => Single::from_i128(input).value.to_bits(),
|
||||
ast::FloatTy::F64 => Double::from_i128(input).value.to_bits()
|
||||
};
|
||||
ConstFloat { bits, ty }
|
||||
}
|
||||
|
||||
pub fn from_u128(input: u128, ty: ast::FloatTy) -> Self {
|
||||
let bits = match ty {
|
||||
ast::FloatTy::F32 => Single::from_u128(input).value.to_bits(),
|
||||
ast::FloatTy::F64 => Double::from_u128(input).value.to_bits()
|
||||
};
|
||||
ConstFloat { bits, ty }
|
||||
}
|
||||
|
||||
pub fn from_str(num: &str, ty: ast::FloatTy) -> Result<Self, ParseFloatError> {
|
||||
let bits = match ty {
|
||||
ast::FloatTy::F32 => {
|
||||
let rust_bits = num.parse::<f32>()?.to_bits() as u128;
|
||||
let apfloat = num.parse::<Single>().unwrap_or_else(|e| {
|
||||
panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e);
|
||||
});
|
||||
let apfloat_bits = apfloat.to_bits();
|
||||
assert!(rust_bits == apfloat_bits,
|
||||
"apfloat::ieee::Single gave different result for `{}`: \
|
||||
{}({:#x}) vs Rust's {}({:#x})",
|
||||
num, apfloat, apfloat_bits,
|
||||
Single::from_bits(rust_bits), rust_bits);
|
||||
apfloat_bits
|
||||
}
|
||||
ast::FloatTy::F64 => {
|
||||
let rust_bits = num.parse::<f64>()?.to_bits() as u128;
|
||||
let apfloat = num.parse::<Double>().unwrap_or_else(|e| {
|
||||
panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e);
|
||||
});
|
||||
let apfloat_bits = apfloat.to_bits();
|
||||
assert!(rust_bits == apfloat_bits,
|
||||
"apfloat::ieee::Double gave different result for `{}`: \
|
||||
{}({:#x}) vs Rust's {}({:#x})",
|
||||
num, apfloat, apfloat_bits,
|
||||
Double::from_bits(rust_bits), rust_bits);
|
||||
apfloat_bits
|
||||
}
|
||||
};
|
||||
Ok(ConstFloat { bits, ty })
|
||||
}
|
||||
|
||||
pub fn to_i128(self, width: usize) -> Option<i128> {
|
||||
assert!(width <= 128);
|
||||
let r = match self.ty {
|
||||
ast::FloatTy::F32 => Single::from_bits(self.bits).to_i128(width),
|
||||
ast::FloatTy::F64 => Double::from_bits(self.bits).to_i128(width)
|
||||
};
|
||||
if r.status.intersects(Status::INVALID_OP) {
|
||||
None
|
||||
} else {
|
||||
Some(r.value)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_u128(self, width: usize) -> Option<u128> {
|
||||
assert!(width <= 128);
|
||||
let r = match self.ty {
|
||||
ast::FloatTy::F32 => Single::from_bits(self.bits).to_u128(width),
|
||||
ast::FloatTy::F64 => Double::from_bits(self.bits).to_u128(width)
|
||||
};
|
||||
if r.status.intersects(Status::INVALID_OP) {
|
||||
None
|
||||
} else {
|
||||
Some(r.value)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn convert(self, to: ast::FloatTy) -> Self {
|
||||
let bits = match (self.ty, to) {
|
||||
(ast::FloatTy::F32, ast::FloatTy::F32) |
|
||||
(ast::FloatTy::F64, ast::FloatTy::F64) => return self,
|
||||
|
||||
(ast::FloatTy::F32, ast::FloatTy::F64) => {
|
||||
Double::to_bits(Single::from_bits(self.bits).convert(&mut false).value)
|
||||
}
|
||||
(ast::FloatTy::F64, ast::FloatTy::F32) => {
|
||||
Single::to_bits(Double::from_bits(self.bits).convert(&mut false).value)
|
||||
}
|
||||
};
|
||||
ConstFloat { bits, ty: to }
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Display for ConstFloat {
|
||||
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||
match self.ty {
|
||||
ast::FloatTy::F32 => write!(fmt, "{:#}", Single::from_bits(self.bits))?,
|
||||
ast::FloatTy::F64 => write!(fmt, "{:#}", Double::from_bits(self.bits))?,
|
||||
}
|
||||
write!(fmt, "{}", self.ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for ConstFloat {
|
||||
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
|
||||
::std::fmt::Display::fmt(self, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! derive_binop {
|
||||
($op:ident, $func:ident) => {
|
||||
impl ::std::ops::$op for ConstFloat {
|
||||
type Output = Option<Self>;
|
||||
fn $func(self, rhs: Self) -> Option<Self> {
|
||||
let bits = match (self.ty, rhs.ty) {
|
||||
(ast::FloatTy::F32, ast::FloatTy::F32) =>{
|
||||
let a = Single::from_bits(self.bits);
|
||||
let b = Single::from_bits(rhs.bits);
|
||||
a.$func(b).value.to_bits()
|
||||
}
|
||||
(ast::FloatTy::F64, ast::FloatTy::F64) => {
|
||||
let a = Double::from_bits(self.bits);
|
||||
let b = Double::from_bits(rhs.bits);
|
||||
a.$func(b).value.to_bits()
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
Some(ConstFloat { bits, ty: self.ty })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
derive_binop!(Add, add);
|
||||
derive_binop!(Sub, sub);
|
||||
derive_binop!(Mul, mul);
|
||||
derive_binop!(Div, div);
|
||||
derive_binop!(Rem, rem);
|
||||
|
||||
impl ::std::ops::Neg for ConstFloat {
|
||||
type Output = Self;
|
||||
fn neg(self) -> Self {
|
||||
let bits = match self.ty {
|
||||
ast::FloatTy::F32 => (-Single::from_bits(self.bits)).to_bits(),
|
||||
ast::FloatTy::F64 => (-Double::from_bits(self.bits)).to_bits(),
|
||||
};
|
||||
ConstFloat { bits, ty: self.ty }
|
||||
}
|
||||
}
|
||||
|
||||
/// This is `f32::MAX + (0.5 ULP)` as an integer. Numbers greater or equal to this
|
||||
/// are rounded to infinity when converted to `f32`.
|
||||
///
|
||||
/// NB: Computed as maximum significand with an extra 1 bit added (for the half ULP)
|
||||
/// shifted by the maximum exponent (accounting for normalization).
|
||||
pub const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
|
||||
<< (Single::MAX_EXP - Single::PRECISION as i16);
|
@ -18,14 +18,9 @@
|
||||
html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
|
||||
extern crate rustc_apfloat;
|
||||
|
||||
extern crate syntax;
|
||||
|
||||
extern crate serialize as rustc_serialize; // used by deriving
|
||||
|
||||
mod float;
|
||||
mod err;
|
||||
|
||||
pub use float::*;
|
||||
pub use err::{ConstMathErr, Op};
|
||||
|
@ -30,9 +30,9 @@ use syntax::ast::{self, LitKind};
|
||||
use syntax::attr;
|
||||
use syntax::symbol::Symbol;
|
||||
use rustc::hir;
|
||||
use rustc_const_math::ConstFloat;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc::mir::interpret::{Value, PrimVal};
|
||||
use hair::pattern::parse_float;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Cx<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
||||
@ -170,14 +170,6 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
neg: bool,
|
||||
) -> Literal<'tcx> {
|
||||
trace!("const_eval_literal: {:#?}, {:?}, {:?}, {:?}", lit, ty, sp, neg);
|
||||
let tcx = self.tcx.global_tcx();
|
||||
|
||||
let parse_float = |num: &str, fty| -> ConstFloat {
|
||||
ConstFloat::from_str(num, fty).unwrap_or_else(|_| {
|
||||
// FIXME(#31407) this is only necessary because float parsing is buggy
|
||||
tcx.sess.span_fatal(sp, "could not evaluate float literal (see issue #31407)");
|
||||
})
|
||||
};
|
||||
|
||||
let clamp = |n| {
|
||||
let size = self.integer_bit_width(ty);
|
||||
@ -214,12 +206,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(clamp(n))),
|
||||
LitKind::Float(n, fty) => {
|
||||
let n = n.as_str();
|
||||
let mut f = parse_float(&n, fty);
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
let bits = f.bits;
|
||||
Value::ByVal(PrimVal::Bytes(bits))
|
||||
parse_float(&n, fty, neg).expect("apfloat parsing failed")
|
||||
}
|
||||
LitKind::FloatUnsuffixed(n) => {
|
||||
let fty = match ty.sty {
|
||||
@ -227,12 +214,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
|
||||
_ => bug!()
|
||||
};
|
||||
let n = n.as_str();
|
||||
let mut f = parse_float(&n, fty);
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
let bits = f.bits;
|
||||
Value::ByVal(PrimVal::Bytes(bits))
|
||||
parse_float(&n, fty, neg).expect("apfloat parsing failed")
|
||||
}
|
||||
LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
|
||||
LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
|
||||
|
@ -28,7 +28,6 @@ use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::pat_util::EnumerateAndAdjustIterator;
|
||||
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_const_math::ConstFloat;
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
@ -1053,22 +1052,21 @@ pub fn compare_const_vals<'a, 'tcx>(
|
||||
b: &ConstVal,
|
||||
ty: Ty<'tcx>,
|
||||
) -> Option<Ordering> {
|
||||
use rustc_const_math::ConstFloat;
|
||||
trace!("compare_const_vals: {:?}, {:?}", a, b);
|
||||
use rustc::mir::interpret::{Value, PrimVal};
|
||||
match (a, b) {
|
||||
(&ConstVal::Value(Value::ByVal(PrimVal::Bytes(a))),
|
||||
&ConstVal::Value(Value::ByVal(PrimVal::Bytes(b)))) => {
|
||||
use ::rustc_apfloat::Float;
|
||||
match ty.sty {
|
||||
ty::TyFloat(ty) => {
|
||||
let l = ConstFloat {
|
||||
bits: a,
|
||||
ty,
|
||||
};
|
||||
let r = ConstFloat {
|
||||
bits: b,
|
||||
ty,
|
||||
};
|
||||
ty::TyFloat(ast::FloatTy::F32) => {
|
||||
let l = ::rustc_apfloat::ieee::Single::from_bits(a);
|
||||
let r = ::rustc_apfloat::ieee::Single::from_bits(b);
|
||||
l.partial_cmp(&r)
|
||||
},
|
||||
ty::TyFloat(ast::FloatTy::F64) => {
|
||||
let l = ::rustc_apfloat::ieee::Double::from_bits(a);
|
||||
let r = ::rustc_apfloat::ieee::Double::from_bits(b);
|
||||
l.partial_cmp(&r)
|
||||
},
|
||||
ty::TyInt(_) => {
|
||||
@ -1148,12 +1146,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
|
||||
},
|
||||
LitKind::Float(n, fty) => {
|
||||
let n = n.as_str();
|
||||
let mut f = parse_float(&n, fty)?;
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
let bits = f.bits;
|
||||
Value::ByVal(PrimVal::Bytes(bits))
|
||||
parse_float(&n, fty, neg).map_err(|_| ())?
|
||||
}
|
||||
LitKind::FloatUnsuffixed(n) => {
|
||||
let fty = match ty.sty {
|
||||
@ -1161,12 +1154,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
|
||||
_ => bug!()
|
||||
};
|
||||
let n = n.as_str();
|
||||
let mut f = parse_float(&n, fty)?;
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
let bits = f.bits;
|
||||
Value::ByVal(PrimVal::Bytes(bits))
|
||||
parse_float(&n, fty, neg).map_err(|_| ())?
|
||||
}
|
||||
LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
|
||||
LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
|
||||
@ -1174,7 +1162,33 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
|
||||
Ok(ConstVal::Value(lit))
|
||||
}
|
||||
|
||||
fn parse_float<'tcx>(num: &str, fty: ast::FloatTy)
|
||||
-> Result<ConstFloat, ()> {
|
||||
ConstFloat::from_str(num, fty).map_err(|_| ())
|
||||
pub fn parse_float(
|
||||
num: &str,
|
||||
fty: ast::FloatTy,
|
||||
neg: bool,
|
||||
) -> Result<Value, String> {
|
||||
use rustc_apfloat::ieee::{Single, Double};
|
||||
use rustc_apfloat::Float;
|
||||
let bits = match fty {
|
||||
ast::FloatTy::F32 => {
|
||||
let mut f = num.parse::<Single>().map_err(|e| {
|
||||
format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
|
||||
})?;
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
f.to_bits()
|
||||
}
|
||||
ast::FloatTy::F64 => {
|
||||
let mut f = num.parse::<Double>().map_err(|e| {
|
||||
format!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e)
|
||||
})?;
|
||||
if neg {
|
||||
f = -f;
|
||||
}
|
||||
f.to_bits()
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Value::ByVal(PrimVal::Bytes(bits)))
|
||||
}
|
||||
|
@ -2,10 +2,9 @@ use rustc::ty::Ty;
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use syntax::ast::{FloatTy, IntTy, UintTy};
|
||||
|
||||
use rustc_const_math::ConstFloat;
|
||||
use rustc_apfloat::ieee::{Single, Double};
|
||||
use super::{EvalContext, Machine};
|
||||
use rustc::mir::interpret::{PrimVal, EvalResult, MemoryPointer, PointerArithmetic};
|
||||
use rustc_apfloat::ieee::{Single, Double};
|
||||
use rustc_apfloat::Float;
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
@ -50,8 +49,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
Ok(PrimVal::Bytes(v))
|
||||
}
|
||||
|
||||
TyFloat(fty) if signed => Ok(PrimVal::Bytes(ConstFloat::from_i128(v as i128, fty).bits)),
|
||||
TyFloat(fty) => Ok(PrimVal::Bytes(ConstFloat::from_u128(v, fty).bits)),
|
||||
TyFloat(FloatTy::F32) if signed => Ok(PrimVal::Bytes(Single::from_i128(v as i128).value.to_bits())),
|
||||
TyFloat(FloatTy::F64) if signed => Ok(PrimVal::Bytes(Double::from_i128(v as i128).value.to_bits())),
|
||||
TyFloat(FloatTy::F32) => Ok(PrimVal::Bytes(Single::from_u128(v).value.to_bits())),
|
||||
TyFloat(FloatTy::F64) => Ok(PrimVal::Bytes(Double::from_u128(v).value.to_bits())),
|
||||
|
||||
TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)),
|
||||
TyChar => err!(InvalidChar(v)),
|
||||
|
@ -1,9 +1,10 @@
|
||||
use rustc::mir;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc_const_math::ConstFloat;
|
||||
use syntax::ast::FloatTy;
|
||||
use std::cmp::Ordering;
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use rustc_apfloat::ieee::{Double, Single};
|
||||
use rustc_apfloat::Float;
|
||||
|
||||
use super::{EvalContext, Place, Machine, ValTy};
|
||||
|
||||
@ -125,31 +126,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
return err!(Unimplemented(msg));
|
||||
}
|
||||
|
||||
let float_op = |op, l, r, ty| {
|
||||
let l = ConstFloat {
|
||||
bits: l,
|
||||
ty,
|
||||
};
|
||||
let r = ConstFloat {
|
||||
bits: r,
|
||||
ty,
|
||||
};
|
||||
match op {
|
||||
Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Equal),
|
||||
Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Equal),
|
||||
Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Less),
|
||||
Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Greater),
|
||||
Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap() == Ordering::Greater),
|
||||
Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap() != Ordering::Less),
|
||||
Add => PrimVal::Bytes((l + r).unwrap().bits),
|
||||
Sub => PrimVal::Bytes((l - r).unwrap().bits),
|
||||
Mul => PrimVal::Bytes((l * r).unwrap().bits),
|
||||
Div => PrimVal::Bytes((l / r).unwrap().bits),
|
||||
Rem => PrimVal::Bytes((l % r).unwrap().bits),
|
||||
_ => bug!("invalid float op: `{:?}`", op),
|
||||
}
|
||||
};
|
||||
|
||||
if left_layout.abi.is_signed() {
|
||||
let op: Option<fn(&i128, &i128) -> bool> = match bin_op {
|
||||
Lt => Some(i128::lt),
|
||||
@ -199,7 +175,31 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
}
|
||||
|
||||
if let ty::TyFloat(fty) = left_ty.sty {
|
||||
return Ok((float_op(bin_op, l, r, fty), false));
|
||||
macro_rules! float_math {
|
||||
($ty:path) => {{
|
||||
let l = <$ty>::from_bits(l);
|
||||
let r = <$ty>::from_bits(r);
|
||||
let val = match bin_op {
|
||||
Eq => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Equal),
|
||||
Ne => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Equal),
|
||||
Lt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Less),
|
||||
Le => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Greater),
|
||||
Gt => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) == Ordering::Greater),
|
||||
Ge => PrimVal::from_bool(l.partial_cmp(&r).unwrap_or(Ordering::Greater) != Ordering::Less),
|
||||
Add => PrimVal::Bytes((l + r).value.to_bits()),
|
||||
Sub => PrimVal::Bytes((l - r).value.to_bits()),
|
||||
Mul => PrimVal::Bytes((l * r).value.to_bits()),
|
||||
Div => PrimVal::Bytes((l / r).value.to_bits()),
|
||||
Rem => PrimVal::Bytes((l % r).value.to_bits()),
|
||||
_ => bug!("invalid float op: `{:?}`", bin_op),
|
||||
};
|
||||
return Ok((val, false));
|
||||
}};
|
||||
}
|
||||
match fty {
|
||||
FloatTy::F32 => float_math!(Single),
|
||||
FloatTy::F64 => float_math!(Double),
|
||||
}
|
||||
}
|
||||
|
||||
// only ints left
|
||||
|
@ -15,7 +15,6 @@ use rustc::ty::layout::{self, LayoutOf};
|
||||
use rustc::mir;
|
||||
use rustc::middle::lang_items::ExchangeMallocFnLangItem;
|
||||
use rustc_apfloat::{ieee, Float, Status, Round};
|
||||
use rustc_const_math::MAX_F32_PLUS_HALF_ULP;
|
||||
use std::{u128, i128};
|
||||
|
||||
use base;
|
||||
@ -805,6 +804,10 @@ fn cast_int_to_float(bx: &Builder,
|
||||
if is_u128_to_f32 {
|
||||
// All inputs greater or equal to (f32::MAX + 0.5 ULP) are rounded to infinity,
|
||||
// and for everything else LLVM's uitofp works just fine.
|
||||
use rustc_apfloat::ieee::Single;
|
||||
use rustc_apfloat::Float;
|
||||
const MAX_F32_PLUS_HALF_ULP: u128 = ((1 << (Single::PRECISION + 1)) - 1)
|
||||
<< (Single::MAX_EXP - Single::PRECISION as i16);
|
||||
let max = C_uint_big(int_ty, MAX_F32_PLUS_HALF_ULP);
|
||||
let overflow = bx.icmp(llvm::IntUGE, x, max);
|
||||
let infinity_bits = C_u32(bx.cx, ieee::Single::INFINITY.to_bits() as u32);
|
||||
|
Loading…
x
Reference in New Issue
Block a user