Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

winch: Add saturating conversion instructions #7909

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ fn ignore(testsuite: &str, testname: &str, strategy: &str) -> bool {
if testsuite == "spec_testsuite" {
let denylist = [
"br_table",
"conversions",
"global",
"table_fill",
"table_get",
Expand Down
497 changes: 0 additions & 497 deletions tests/misc_testsuite/winch/conversions.wast

This file was deleted.

4 changes: 3 additions & 1 deletion winch/codegen/src/isa/aarch64/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
masm::{
CalleeKind, DivKind, ExtendKind, FloatCmpKind, Imm as I, IntCmpKind,
MacroAssembler as Masm, OperandSize, RegImm, RemKind, RoundingMode, SPOffset, ShiftKind,
StackSlot, TrapCode,
StackSlot, TrapCode, TruncKind,
},
};
use cranelift_codegen::{settings, Final, MachBufferFinalized, MachLabel};
Expand Down Expand Up @@ -379,6 +379,7 @@ impl Masm for MacroAssembler {
_dst: Reg,
_src_size: OperandSize,
_dst_size: OperandSize,
_kind: TruncKind,
) {
todo!()
}
Expand All @@ -390,6 +391,7 @@ impl Masm for MacroAssembler {
_tmp_fpr: Reg,
_src_size: OperandSize,
_dst_size: OperandSize,
_kind: TruncKind,
) {
todo!()
}
Expand Down
6 changes: 4 additions & 2 deletions winch/codegen/src/isa/x64/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,11 +615,12 @@ impl Assembler {
tmp_xmm: Reg,
src_size: OperandSize,
dst_size: OperandSize,
saturating: bool,
) {
self.emit(Inst::CvtFloatToSintSeq {
dst_size: dst_size.into(),
src_size: src_size.into(),
is_saturating: false,
is_saturating: saturating,
src: src.into(),
dst: dst.into(),
tmp_gpr: tmp_gpr.into(),
Expand All @@ -637,11 +638,12 @@ impl Assembler {
tmp_xmm2: Reg,
src_size: OperandSize,
dst_size: OperandSize,
saturating: bool,
) {
self.emit(Inst::CvtFloatToUintSeq {
dst_size: dst_size.into(),
src_size: src_size.into(),
is_saturating: false,
is_saturating: saturating,
src: src.into(),
dst: dst.into(),
tmp_gpr: tmp_gpr.into(),
Expand Down
6 changes: 5 additions & 1 deletion winch/codegen/src/isa/x64/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{

use crate::masm::{
DivKind, ExtendKind, FloatCmpKind, Imm as I, IntCmpKind, MacroAssembler as Masm, OperandSize,
RegImm, RemKind, RoundingMode, ShiftKind, TrapCode, TRUSTED_FLAGS, UNTRUSTED_FLAGS,
RegImm, RemKind, RoundingMode, ShiftKind, TrapCode, TruncKind, TRUSTED_FLAGS, UNTRUSTED_FLAGS,
};
use crate::{
abi::ABI,
Expand Down Expand Up @@ -1021,6 +1021,7 @@ impl Masm for MacroAssembler {
dst: Reg,
src_size: OperandSize,
dst_size: OperandSize,
kind: TruncKind,
) {
self.asm.cvt_float_to_sint_seq(
src,
Expand All @@ -1029,6 +1030,7 @@ impl Masm for MacroAssembler {
regs::scratch_xmm(),
src_size,
dst_size,
kind.is_checked(),
);
}

Expand All @@ -1039,6 +1041,7 @@ impl Masm for MacroAssembler {
tmp_fpr: Reg,
src_size: OperandSize,
dst_size: OperandSize,
kind: TruncKind,
) {
self.asm.cvt_float_to_uint_seq(
src,
Expand All @@ -1048,6 +1051,7 @@ impl Masm for MacroAssembler {
tmp_fpr,
src_size,
dst_size,
kind.is_checked(),
);
}

Expand Down
29 changes: 28 additions & 1 deletion winch/codegen/src/masm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,25 @@ pub(crate) enum MemMoveDirection {
LowToHigh,
}

/// Classifies how to treat float-to-int conversions.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub(crate) enum TruncKind {
/// Saturating conversion. If the source value is greater than the maximum
/// value of the destination type, the result is clamped to the
/// destination maximum value.
Checked,
/// An exception is raised if the source value is greater than the maximum
/// value of the destination type.
Unchecked,
}

impl TruncKind {
/// Returns true if the truncation kind is checked.
pub(crate) fn is_checked(&self) -> bool {
*self == TruncKind::Checked
}
}

/// Representation of the stack pointer offset.
#[derive(Copy, Clone, Eq, PartialEq, Debug, PartialOrd, Ord, Default)]
pub struct SPOffset(u32);
Expand Down Expand Up @@ -676,7 +695,14 @@ pub(crate) trait MacroAssembler {

/// Emits one or more instructions to perform a signed truncation of a
/// float into an integer.
fn signed_truncate(&mut self, src: Reg, dst: Reg, src_size: OperandSize, dst_size: OperandSize);
fn signed_truncate(
&mut self,
src: Reg,
dst: Reg,
src_size: OperandSize,
dst_size: OperandSize,
kind: TruncKind,
);

/// Emits one or more instructions to perform an unsigned truncation of a
/// float into an integer.
Expand All @@ -687,6 +713,7 @@ pub(crate) trait MacroAssembler {
tmp_fpr: Reg,
src_size: OperandSize,
dst_size: OperandSize,
kind: TruncKind,
);

/// Emits one or more instructions to perform a signed convert of an
Expand Down
115 changes: 106 additions & 9 deletions winch/codegen/src/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::abi::{RetArea, ABI};
use crate::codegen::{control_index, Callee, CodeGen, ControlStackFrame, FnCall};
use crate::masm::{
DivKind, ExtendKind, FloatCmpKind, IntCmpKind, MacroAssembler, MemMoveDirection, OperandSize,
RegImm, RemKind, RoundingMode, SPOffset, ShiftKind,
RegImm, RemKind, RoundingMode, SPOffset, ShiftKind, TruncKind,
};
use crate::stack::{TypedReg, Val};
use cranelift_codegen::ir::TrapCode;
Expand Down Expand Up @@ -231,6 +231,15 @@ macro_rules! def_unsupported {
(emit F32Store $($rest:tt)*) => {};
(emit F64Load $($rest:tt)*) => {};
(emit F64Store $($rest:tt)*) => {};
(emit I32TruncSatF32S $($rest:tt)*) => {};
(emit I32TruncSatF32U $($rest:tt)*) => {};
(emit I32TruncSatF64S $($rest:tt)*) => {};
(emit I32TruncSatF64U $($rest:tt)*) => {};
(emit I64TruncSatF32S $($rest:tt)*) => {};
(emit I64TruncSatF32U $($rest:tt)*) => {};
(emit I64TruncSatF64S $($rest:tt)*) => {};
(emit I64TruncSatF64U $($rest:tt)*) => {};


(emit $unsupported:tt $($rest:tt)*) => {$($rest)*};
}
Expand Down Expand Up @@ -1162,7 +1171,7 @@ where

self.context
.convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
masm.signed_truncate(src, dst, S32, dst_size);
masm.signed_truncate(src, dst, S32, dst_size, TruncKind::Unchecked);
});
}

Expand All @@ -1174,7 +1183,7 @@ where
WasmValType::I32,
RegClass::Float,
|masm, dst, src, tmp_fpr, dst_size| {
masm.unsigned_truncate(src, dst, tmp_fpr, S32, dst_size);
masm.unsigned_truncate(src, dst, tmp_fpr, S32, dst_size, TruncKind::Unchecked);
},
);
}
Expand All @@ -1184,7 +1193,7 @@ where

self.context
.convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
masm.signed_truncate(src, dst, S64, dst_size);
masm.signed_truncate(src, dst, S64, dst_size, TruncKind::Unchecked);
});
}

Expand All @@ -1196,7 +1205,7 @@ where
WasmValType::I32,
RegClass::Float,
|masm, dst, src, tmp_fpr, dst_size| {
masm.unsigned_truncate(src, dst, tmp_fpr, S64, dst_size);
masm.unsigned_truncate(src, dst, tmp_fpr, S64, dst_size, TruncKind::Unchecked);
},
);
}
Expand All @@ -1206,7 +1215,7 @@ where

self.context
.convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
masm.signed_truncate(src, dst, S32, dst_size);
masm.signed_truncate(src, dst, S32, dst_size, TruncKind::Unchecked);
});
}

Expand All @@ -1218,7 +1227,7 @@ where
WasmValType::I64,
RegClass::Float,
|masm, dst, src, tmp_fpr, dst_size| {
masm.unsigned_truncate(src, dst, tmp_fpr, S32, dst_size);
masm.unsigned_truncate(src, dst, tmp_fpr, S32, dst_size, TruncKind::Unchecked);
},
);
}
Expand All @@ -1228,7 +1237,7 @@ where

self.context
.convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
masm.signed_truncate(src, dst, S64, dst_size);
masm.signed_truncate(src, dst, S64, dst_size, TruncKind::Unchecked);
});
}

Expand All @@ -1240,7 +1249,7 @@ where
WasmValType::I64,
RegClass::Float,
|masm, dst, src, tmp_fpr, dst_size| {
masm.unsigned_truncate(src, dst, tmp_fpr, S64, dst_size);
masm.unsigned_truncate(src, dst, tmp_fpr, S64, dst_size, TruncKind::Unchecked);
},
);
}
Expand Down Expand Up @@ -1944,6 +1953,94 @@ where
self.emit_wasm_store(&memarg, OperandSize::S64)
}

fn visit_i32_trunc_sat_f32_s(&mut self) {
use OperandSize::*;

self.context
.convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
masm.signed_truncate(src, dst, S32, dst_size, TruncKind::Checked);
});
}

fn visit_i32_trunc_sat_f32_u(&mut self) {
use OperandSize::*;

self.context.convert_op_with_tmp_reg(
self.masm,
WasmValType::I32,
RegClass::Float,
|masm, dst, src, tmp_fpr, dst_size| {
masm.unsigned_truncate(src, dst, tmp_fpr, S32, dst_size, TruncKind::Checked);
},
);
}

fn visit_i32_trunc_sat_f64_s(&mut self) {
use OperandSize::*;

self.context
.convert_op(self.masm, WasmValType::I32, |masm, dst, src, dst_size| {
masm.signed_truncate(src, dst, S64, dst_size, TruncKind::Checked);
});
}

fn visit_i32_trunc_sat_f64_u(&mut self) {
use OperandSize::*;

self.context.convert_op_with_tmp_reg(
self.masm,
WasmValType::I32,
RegClass::Float,
|masm, dst, src, tmp_fpr, dst_size| {
masm.unsigned_truncate(src, dst, tmp_fpr, S64, dst_size, TruncKind::Checked);
},
);
}

fn visit_i64_trunc_sat_f32_s(&mut self) {
use OperandSize::*;

self.context
.convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
masm.signed_truncate(src, dst, S32, dst_size, TruncKind::Checked);
});
}

fn visit_i64_trunc_sat_f32_u(&mut self) {
use OperandSize::*;

self.context.convert_op_with_tmp_reg(
self.masm,
WasmValType::I64,
RegClass::Float,
|masm, dst, src, tmp_fpr, dst_size| {
masm.unsigned_truncate(src, dst, tmp_fpr, S32, dst_size, TruncKind::Checked);
},
);
}

fn visit_i64_trunc_sat_f64_s(&mut self) {
use OperandSize::*;

self.context
.convert_op(self.masm, WasmValType::I64, |masm, dst, src, dst_size| {
masm.signed_truncate(src, dst, S64, dst_size, TruncKind::Checked);
});
}

fn visit_i64_trunc_sat_f64_u(&mut self) {
use OperandSize::*;

self.context.convert_op_with_tmp_reg(
self.masm,
WasmValType::I64,
RegClass::Float,
|masm, dst, src, tmp_fpr, dst_size| {
masm.unsigned_truncate(src, dst, tmp_fpr, S64, dst_size, TruncKind::Checked);
},
);
}

wasmparser::for_each_operator!(def_unsupported);
}

Expand Down