Skip to content

Commit 71feb9e

Browse files
feat(wasm-encoder, wasmparser): replace f32 / f64 with Ieee32 / Ieee64 (#2157)
1 parent 9558e44 commit 71feb9e

File tree

14 files changed

+172
-82
lines changed

14 files changed

+172
-82
lines changed

crates/wasm-encoder/src/core/code.rs

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,76 @@ impl Encode for Function {
294294
}
295295
}
296296

297+
/// An IEEE binary32 immediate floating point value, represented as a u32
298+
/// containing the bit pattern.
299+
///
300+
/// All bit patterns are allowed.
301+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
302+
pub struct Ieee32(pub(crate) u32);
303+
304+
impl Ieee32 {
305+
/// Gets the underlying bits of the 32-bit float.
306+
pub fn bits(self) -> u32 {
307+
self.0
308+
}
309+
}
310+
311+
impl From<f32> for Ieee32 {
312+
fn from(value: f32) -> Self {
313+
Ieee32 {
314+
0: u32::from_le_bytes(value.to_le_bytes()),
315+
}
316+
}
317+
}
318+
319+
impl From<Ieee32> for f32 {
320+
fn from(bits: Ieee32) -> f32 {
321+
f32::from_bits(bits.bits())
322+
}
323+
}
324+
325+
impl Encode for Ieee32 {
326+
fn encode(&self, sink: &mut Vec<u8>) {
327+
let bits = self.bits();
328+
sink.extend(bits.to_le_bytes())
329+
}
330+
}
331+
332+
/// An IEEE binary64 immediate floating point value, represented as a u64
333+
/// containing the bit pattern.
334+
///
335+
/// All bit patterns are allowed.
336+
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
337+
pub struct Ieee64(pub(crate) u64);
338+
339+
impl Ieee64 {
340+
/// Gets the underlying bits of the 64-bit float.
341+
pub fn bits(self) -> u64 {
342+
self.0
343+
}
344+
}
345+
346+
impl From<f64> for Ieee64 {
347+
fn from(value: f64) -> Self {
348+
Ieee64 {
349+
0: u64::from_le_bytes(value.to_le_bytes()),
350+
}
351+
}
352+
}
353+
354+
impl From<Ieee64> for f64 {
355+
fn from(bits: Ieee64) -> f64 {
356+
f64::from_bits(bits.bits())
357+
}
358+
}
359+
360+
impl Encode for Ieee64 {
361+
fn encode(&self, sink: &mut Vec<u8>) {
362+
let bits = self.bits();
363+
sink.extend(bits.to_le_bytes())
364+
}
365+
}
366+
297367
/// The immediate for a memory instruction.
298368
#[derive(Clone, Copy, Debug)]
299369
pub struct MemArg {
@@ -471,8 +541,8 @@ pub enum Instruction<'a> {
471541
// Numeric instructions.
472542
I32Const(i32),
473543
I64Const(i64),
474-
F32Const(f32),
475-
F64Const(f64),
544+
F32Const(Ieee32),
545+
F64Const(Ieee64),
476546
I32Eqz,
477547
I32Eq,
478548
I32Ne,
@@ -2202,12 +2272,12 @@ impl ConstExpr {
22022272
}
22032273

22042274
/// Create a constant expression containing a single `f32.const` instruction.
2205-
pub fn f32_const(value: f32) -> Self {
2275+
pub fn f32_const(value: Ieee32) -> Self {
22062276
Self::new(|insn| insn.f32_const(value))
22072277
}
22082278

22092279
/// Create a constant expression containing a single `f64.const` instruction.
2210-
pub fn f64_const(value: f64) -> Self {
2280+
pub fn f64_const(value: Ieee64) -> Self {
22112281
Self::new(|insn| insn.f64_const(value))
22122282
}
22132283

@@ -2242,12 +2312,12 @@ impl ConstExpr {
22422312
}
22432313

22442314
/// Add a `f32.const` instruction to this constant expression.
2245-
pub fn with_f32_const(self, value: f32) -> Self {
2315+
pub fn with_f32_const(self, value: Ieee32) -> Self {
22462316
self.with(|insn| insn.f32_const(value))
22472317
}
22482318

22492319
/// Add a `f64.const` instruction to this constant expression.
2250-
pub fn with_f64_const(self, value: f64) -> Self {
2320+
pub fn with_f64_const(self, value: Ieee64) -> Self {
22512321
self.with(|insn| insn.f64_const(value))
22522322
}
22532323

crates/wasm-encoder/src/core/dump.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{CustomSection, Encode, Section};
1+
use crate::{CustomSection, Encode, Ieee32, Ieee64, Section};
22
use alloc::borrow::Cow;
33
use alloc::string::String;
44
use alloc::vec;
@@ -305,9 +305,9 @@ pub enum CoreDumpValue {
305305
/// An i64 value
306306
I64(i64),
307307
/// An f32 value
308-
F32(f32),
308+
F32(Ieee32),
309309
/// An f64 value
310-
F64(f64),
310+
F64(Ieee64),
311311
}
312312

313313
impl Encode for CoreDumpValue {

crates/wasm-encoder/src/core/instructions.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#[allow(unused_imports)]
22
use crate::Instruction;
33
use crate::{
4-
encode_vec, BlockType, Catch, Encode, Handle, HeapType, Lane, MemArg, Ordering, RefType,
5-
ValType,
4+
encode_vec, BlockType, Catch, Encode, Handle, HeapType, Ieee32, Ieee64, Lane, MemArg, Ordering,
5+
RefType, ValType,
66
};
77
use alloc::vec::Vec;
88

@@ -505,17 +505,17 @@ impl<'a> InstructionSink<'a> {
505505
}
506506

507507
/// Encode [`Instruction::F32Const`].
508-
pub fn f32_const(&mut self, x: f32) -> &mut Self {
508+
pub fn f32_const(&mut self, x: Ieee32) -> &mut Self {
509509
self.sink.push(0x43);
510-
let x = x.to_bits();
510+
let x = x.bits();
511511
self.sink.extend(x.to_le_bytes().iter().copied());
512512
self
513513
}
514514

515515
/// Encode [`Instruction::F64Const`].
516-
pub fn f64_const(&mut self, x: f64) -> &mut Self {
516+
pub fn f64_const(&mut self, x: Ieee64) -> &mut Self {
517517
self.sink.push(0x44);
518-
let x = x.to_bits();
518+
let x = x.bits();
519519
self.sink.extend(x.to_le_bytes().iter().copied());
520520
self
521521
}

crates/wasm-encoder/src/lib.rs

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -162,20 +162,6 @@ impl Encode for i64 {
162162
}
163163
}
164164

165-
impl Encode for f32 {
166-
fn encode(&self, sink: &mut Vec<u8>) {
167-
let bits = self.to_bits();
168-
sink.extend(bits.to_le_bytes())
169-
}
170-
}
171-
172-
impl Encode for f64 {
173-
fn encode(&self, sink: &mut Vec<u8>) {
174-
let bits = self.to_bits();
175-
sink.extend(bits.to_le_bytes())
176-
}
177-
}
178-
179165
fn encode_vec<T, V>(elements: V, sink: &mut Vec<u8>)
180166
where
181167
T: Encode,

crates/wasm-encoder/src/reencode.rs

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ pub trait Reencode {
173173
utils::memory_type(self, memory_ty)
174174
}
175175

176+
fn ieee32_arg(&mut self, arg: wasmparser::Ieee32) -> crate::Ieee32 {
177+
utils::ieee32_arg(self, arg)
178+
}
179+
180+
fn ieee64_arg(&mut self, arg: wasmparser::Ieee64) -> crate::Ieee64 {
181+
utils::ieee64_arg(self, arg)
182+
}
183+
176184
fn mem_arg(&mut self, arg: wasmparser::MemArg) -> crate::MemArg {
177185
utils::mem_arg(self, arg)
178186
}
@@ -885,6 +893,20 @@ pub mod utils {
885893
memory
886894
}
887895

896+
pub fn ieee32_arg<T: ?Sized + Reencode>(
897+
_reencoder: &mut T,
898+
arg: wasmparser::Ieee32,
899+
) -> crate::Ieee32 {
900+
crate::Ieee32(arg.bits())
901+
}
902+
903+
pub fn ieee64_arg<T: ?Sized + Reencode>(
904+
_reencoder: &mut T,
905+
arg: wasmparser::Ieee64,
906+
) -> crate::Ieee64 {
907+
crate::Ieee64(arg.bits())
908+
}
909+
888910
pub fn mem_arg<T: ?Sized + Reencode>(
889911
reencoder: &mut T,
890912
arg: wasmparser::MemArg,
@@ -1649,8 +1671,8 @@ pub mod utils {
16491671
(build TypedSelectMulti $arg:ident) => (Instruction::TypedSelectMulti(Cow::from($arg)));
16501672
(build I32Const $arg:ident) => (Instruction::I32Const($arg));
16511673
(build I64Const $arg:ident) => (Instruction::I64Const($arg));
1652-
(build F32Const $arg:ident) => (Instruction::F32Const(f32::from_bits($arg.bits())));
1653-
(build F64Const $arg:ident) => (Instruction::F64Const(f64::from_bits($arg.bits())));
1674+
(build F32Const $arg:ident) => (Instruction::F32Const($arg.into()));
1675+
(build F64Const $arg:ident) => (Instruction::F64Const($arg.into()));
16541676
(build V128Const $arg:ident) => (Instruction::V128Const($arg.i128()));
16551677
(build TryTable $table:ident) => (Instruction::TryTable(reencoder.block_type($table.ty)?, {
16561678
$table.catches.into_iter().map(|c| reencoder.catch(c)).collect::<Vec<_>>().into()
@@ -1808,6 +1830,18 @@ pub mod utils {
18081830
}
18091831
}
18101832

1833+
impl From<wasmparser::Ieee32> for crate::Ieee32 {
1834+
fn from(arg: wasmparser::Ieee32) -> Self {
1835+
RoundtripReencoder.ieee32_arg(arg)
1836+
}
1837+
}
1838+
1839+
impl From<wasmparser::Ieee64> for crate::Ieee64 {
1840+
fn from(arg: wasmparser::Ieee64) -> Self {
1841+
RoundtripReencoder.ieee64_arg(arg)
1842+
}
1843+
}
1844+
18111845
impl From<wasmparser::MemArg> for crate::MemArg {
18121846
fn from(arg: wasmparser::MemArg) -> Self {
18131847
RoundtripReencoder.mem_arg(arg)

crates/wasm-mutate/src/mutators/add_function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ impl Mutator for AddFunctionMutator {
5353
func.instructions().i64_const(0);
5454
}
5555
PrimitiveTypeInfo::F32 => {
56-
func.instructions().f32_const(0.0);
56+
func.instructions().f32_const(0.0.into());
5757
}
5858
PrimitiveTypeInfo::F64 => {
59-
func.instructions().f64_const(0.0);
59+
func.instructions().f64_const(0.0.into());
6060
}
6161
PrimitiveTypeInfo::V128 => {
6262
func.instructions().v128_const(0);

crates/wasm-mutate/src/mutators/modify_const_exprs.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ impl<'cfg, 'wasm> Reencode for InitTranslator<'cfg, 'wasm> {
117117
T::I32 if should_zero => CE::i32_const(0),
118118
T::I64 if should_zero => CE::i64_const(0),
119119
T::V128 if should_zero => CE::v128_const(0),
120-
T::F32 if should_zero => CE::f32_const(0.0),
121-
T::F64 if should_zero => CE::f64_const(0.0),
120+
T::F32 if should_zero => CE::f32_const(0.0.into()),
121+
T::F64 if should_zero => CE::f64_const(0.0.into()),
122122
T::I32 => CE::i32_const(if let O::I32Const { value } = op {
123123
let range = if value < 0 { value..0 } else { 0..value };
124124
self.config.rng().gen_range(range)
@@ -137,14 +137,14 @@ impl<'cfg, 'wasm> Reencode for InitTranslator<'cfg, 'wasm> {
137137
self.config.rng().r#gen()
138138
}),
139139
T::F32 => CE::f32_const(if let O::F32Const { value } = op {
140-
f32::from_bits(value.bits()) / 2.0
140+
(f32::from_bits(value.bits()) / 2.0).into()
141141
} else {
142-
f32::from_bits(self.config.rng().r#gen())
142+
f32::from_bits(self.config.rng().r#gen()).into()
143143
}),
144144
T::F64 => CE::f64_const(if let O::F64Const { value } = op {
145-
f64::from_bits(value.bits()) / 2.0
145+
(f64::from_bits(value.bits()) / 2.0).into()
146146
} else {
147-
f64::from_bits(self.config.rng().r#gen())
147+
f64::from_bits(self.config.rng().r#gen()).into()
148148
}),
149149
T::FuncRef => CE::ref_null(wasm_encoder::HeapType::FUNC),
150150
T::ExternRef => CE::ref_null(wasm_encoder::HeapType::EXTERN),

crates/wasm-mutate/src/mutators/peephole.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,10 @@ impl PeepholeMutator {
316316
(ConstExpr::i64_const(0), ValType::I64)
317317
}
318318
PrimitiveTypeInfo::F32 => {
319-
(ConstExpr::f32_const(0.0), ValType::F32)
319+
(ConstExpr::f32_const(0.0.into()), ValType::F32)
320320
}
321321
PrimitiveTypeInfo::F64 => {
322-
(ConstExpr::f64_const(0.0), ValType::F64)
322+
(ConstExpr::f64_const(0.0.into()), ValType::F64)
323323
}
324324
PrimitiveTypeInfo::V128 => {
325325
(ConstExpr::v128_const(0), ValType::V128)

crates/wasm-mutate/src/mutators/peephole/eggsy/encoder/expr2wasm.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ pub fn expr2wasm(
116116
Lang::I64Load32S(memarg, _) => insn.i64_load32_s(memarg.into()),
117117
Lang::RandI32 => insn.i32_const(config.rng().r#gen()),
118118
Lang::RandI64 => insn.i64_const(config.rng().r#gen()),
119-
Lang::RandF32 => insn.f32_const(f32::from_bits(config.rng().r#gen())),
120-
Lang::RandF64 => insn.f64_const(f64::from_bits(config.rng().r#gen())),
119+
Lang::RandF32 => insn.f32_const(f32::from_bits(config.rng().r#gen()).into()),
120+
Lang::RandF64 => insn.f64_const(f64::from_bits(config.rng().r#gen()).into()),
121121
Lang::Undef => {
122122
// Do nothing
123123
insn
@@ -164,8 +164,8 @@ pub fn expr2wasm(
164164
}
165165
Lang::I32(v) => insn.i32_const(*v),
166166
Lang::I64(v) => insn.i64_const(*v),
167-
Lang::F32(v) => insn.f32_const(v.to_f32()),
168-
Lang::F64(v) => insn.f64_const(v.to_f64()),
167+
Lang::F32(v) => insn.f32_const(v.to_f32().into()),
168+
Lang::F64(v) => insn.f64_const(v.to_f64().into()),
169169
Lang::V128(v) => insn.v128_const(*v),
170170
Lang::I32Add(_) => insn.i32_add(),
171171
Lang::I64Add(_) => insn.i64_add(),

crates/wasm-mutate/src/mutators/snip_function.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ impl Mutator for SnipMutator {
5252
f.instructions().i64_const(0);
5353
}
5454
PrimitiveTypeInfo::F32 => {
55-
f.instructions().f32_const(0.0);
55+
f.instructions().f32_const(0.0.into());
5656
}
5757
PrimitiveTypeInfo::F64 => {
58-
f.instructions().f64_const(0.0);
58+
f.instructions().f64_const(0.0.into());
5959
}
6060
PrimitiveTypeInfo::V128 => {
6161
f.instructions().v128_const(0);

0 commit comments

Comments
 (0)