Skip to content

Commit 3778fa0

Browse files
committed
Switch DataValue to use Ieee32/Ieee64
As discussed in #2251, in order to be very confident that NaN signaling bits are correctly handled by the compiler, this switches `DataValue` to use Cranelift's `Ieee32` and `Ieee64` structures. This makes it a bit more inconvenient to interpreter Cranelift FP operations but this should change to something like `rustc_apfloat` in the future.
1 parent ce44719 commit 3778fa0

File tree

5 files changed

+22
-28
lines changed

5 files changed

+22
-28
lines changed

cranelift/codegen/src/data_value.rs

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ pub enum DataValue {
1818
I16(i16),
1919
I32(i32),
2020
I64(i64),
21-
F32(f32),
22-
F64(f64),
21+
F32(Ieee32),
22+
F64(Ieee64),
2323
V128([u8; 16]),
2424
}
2525

@@ -97,19 +97,9 @@ build_conversion_impl!(i8, I8, I8);
9797
build_conversion_impl!(i16, I16, I16);
9898
build_conversion_impl!(i32, I32, I32);
9999
build_conversion_impl!(i64, I64, I64);
100-
build_conversion_impl!(f32, F32, F32);
101-
build_conversion_impl!(f64, F64, F64);
100+
build_conversion_impl!(Ieee32, F32, F32);
101+
build_conversion_impl!(Ieee64, F64, F64);
102102
build_conversion_impl!([u8; 16], V128, I8X16);
103-
impl From<Ieee64> for DataValue {
104-
fn from(f: Ieee64) -> Self {
105-
DataValue::from(f64::from_bits(f.bits()))
106-
}
107-
}
108-
impl From<Ieee32> for DataValue {
109-
fn from(f: Ieee32) -> Self {
110-
DataValue::from(f32::from_bits(f.bits()))
111-
}
112-
}
113103
impl From<Offset32> for DataValue {
114104
fn from(o: Offset32) -> Self {
115105
DataValue::from(Into::<i32>::into(o))
@@ -124,9 +114,9 @@ impl Display for DataValue {
124114
DataValue::I16(dv) => write!(f, "{}", dv),
125115
DataValue::I32(dv) => write!(f, "{}", dv),
126116
DataValue::I64(dv) => write!(f, "{}", dv),
127-
// Use the Ieee* wrappers here to maintain a consistent syntax.
128-
DataValue::F32(dv) => write!(f, "{}", Ieee32::from(*dv)),
129-
DataValue::F64(dv) => write!(f, "{}", Ieee64::from(*dv)),
117+
// The Ieee* wrappers here print the expected syntax.
118+
DataValue::F32(dv) => write!(f, "{}", dv),
119+
DataValue::F64(dv) => write!(f, "{}", dv),
130120
// Again, for syntax consistency, use ConstantData, which in this case displays as hex.
131121
DataValue::V128(dv) => write!(f, "{}", ConstantData::from(&dv[..])),
132122
}

cranelift/codegen/src/ir/immediates.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,13 +450,15 @@ impl FromStr for Offset32 {
450450
///
451451
/// All bit patterns are allowed.
452452
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
453+
#[repr(C)]
453454
pub struct Ieee32(u32);
454455

455456
/// An IEEE binary64 immediate floating point value, represented as a u64
456457
/// containing the bit pattern.
457458
///
458459
/// All bit patterns are allowed.
459460
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
461+
#[repr(C)]
460462
pub struct Ieee64(u64);
461463

462464
/// Format a floating point number in a way that is reasonably human-readable, and that can be

cranelift/filetests/src/function_runner.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
use core::{mem, ptr};
33
use cranelift_codegen::binemit::{NullRelocSink, NullStackMapSink, NullTrapSink};
44
use cranelift_codegen::data_value::DataValue;
5+
use cranelift_codegen::ir::immediates::{Ieee32, Ieee64};
56
use cranelift_codegen::ir::{condcodes::IntCC, Function, InstBuilder, Signature, Type};
67
use cranelift_codegen::isa::TargetIsa;
78
use cranelift_codegen::{ir, settings, CodegenError, Context};
@@ -233,8 +234,8 @@ impl UnboxedValues {
233234
DataValue::I16(i) => ptr::write(p as *mut i16, *i),
234235
DataValue::I32(i) => ptr::write(p as *mut i32, *i),
235236
DataValue::I64(i) => ptr::write(p as *mut i64, *i),
236-
DataValue::F32(f) => ptr::write(p as *mut f32, *f),
237-
DataValue::F64(f) => ptr::write(p as *mut f64, *f),
237+
DataValue::F32(f) => ptr::write(p as *mut Ieee32, *f),
238+
DataValue::F64(f) => ptr::write(p as *mut Ieee64, *f),
238239
DataValue::V128(b) => ptr::write(p as *mut [u8; 16], *b),
239240
}
240241
}
@@ -246,8 +247,8 @@ impl UnboxedValues {
246247
ir::types::I16 => DataValue::I16(ptr::read(p as *const i16)),
247248
ir::types::I32 => DataValue::I32(ptr::read(p as *const i32)),
248249
ir::types::I64 => DataValue::I64(ptr::read(p as *const i64)),
249-
ir::types::F32 => DataValue::F32(ptr::read(p as *const f32)),
250-
ir::types::F64 => DataValue::F64(ptr::read(p as *const f64)),
250+
ir::types::F32 => DataValue::F32(ptr::read(p as *const Ieee32)),
251+
ir::types::F64 => DataValue::F64(ptr::read(p as *const Ieee64)),
251252
_ if ty.is_bool() => DataValue::B(ptr::read(p as *const bool)),
252253
_ if ty.is_vector() && ty.bytes() == 16 => {
253254
DataValue::V128(ptr::read(p as *const [u8; 16]))

cranelift/interpreter/src/interpreter.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use cranelift_codegen::ir::{
1212
Value as ValueRef, ValueList,
1313
};
1414
use log::trace;
15-
use std::ops::{Add, Div, Mul, Sub};
15+
use std::ops::{Add, Mul, Sub};
1616
use thiserror::Error;
1717

1818
/// The valid control flow states.
@@ -153,10 +153,11 @@ impl Interpreter {
153153
Iadd => binary_op!(Add::add[arg1, arg2]; [I8, I16, I32, I64]; inst),
154154
Isub => binary_op!(Sub::sub[arg1, arg2]; [I8, I16, I32, I64]; inst),
155155
Imul => binary_op!(Mul::mul[arg1, arg2]; [I8, I16, I32, I64]; inst),
156-
Fadd => binary_op!(Add::add[arg1, arg2]; [F32, F64]; inst),
157-
Fsub => binary_op!(Sub::sub[arg1, arg2]; [F32, F64]; inst),
158-
Fmul => binary_op!(Mul::mul[arg1, arg2]; [F32, F64]; inst),
159-
Fdiv => binary_op!(Div::div[arg1, arg2]; [F32, F64]; inst),
156+
// TODO re-enable by importing something like rustc_apfloat for correctness.
157+
// Fadd => binary_op!(Add::add[arg1, arg2]; [F32, F64]; inst),
158+
// Fsub => binary_op!(Sub::sub[arg1, arg2]; [F32, F64]; inst),
159+
// Fmul => binary_op!(Mul::mul[arg1, arg2]; [F32, F64]; inst),
160+
// Fdiv => binary_op!(Div::div[arg1, arg2]; [F32, F64]; inst),
160161
_ => unimplemented!("interpreter does not support opcode yet: {}", opcode),
161162
}?;
162163
frame.set(first_result(frame.function, inst), result);

cranelift/reader/src/parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2700,8 +2700,8 @@ impl<'a> Parser<'a> {
27002700
I16 => DataValue::from(self.match_imm16("expected an i16")?),
27012701
I32 => DataValue::from(self.match_imm32("expected an i32")?),
27022702
I64 => DataValue::from(Into::<i64>::into(self.match_imm64("expected an i64")?)),
2703-
F32 => DataValue::from(f32::from_bits(self.match_ieee32("expected an f32")?.bits())),
2704-
F64 => DataValue::from(f64::from_bits(self.match_ieee64("expected an f64")?.bits())),
2703+
F32 => DataValue::from(self.match_ieee32("expected an f32")?),
2704+
F64 => DataValue::from(self.match_ieee64("expected an f64")?),
27052705
_ if ty.is_vector() => {
27062706
let as_vec = self.match_uimm128(ty)?.into_vec();
27072707
if as_vec.len() == 16 {

0 commit comments

Comments
 (0)