From 8b9307bfa89b9669aebbee853e7cabeaedbc5afe Mon Sep 17 00:00:00 2001 From: Jan-Justin van Tonder Date: Mon, 15 May 2023 20:41:16 +0200 Subject: [PATCH] cranelift-interpreter: Fix panic when bitcasting SIMD values Fixes #5915 --- .../filetests/runtests/simd-bitcast.clif | 16 +++++++++++++++ cranelift/interpreter/src/step.rs | 20 ++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/cranelift/filetests/filetests/runtests/simd-bitcast.clif b/cranelift/filetests/filetests/runtests/simd-bitcast.clif index fdc3454b7a11..a8d1f9c3b110 100644 --- a/cranelift/filetests/filetests/runtests/simd-bitcast.clif +++ b/cranelift/filetests/filetests/runtests/simd-bitcast.clif @@ -35,3 +35,19 @@ block0(v0: f64x2): } ; run: %bitcast_fi64x2([0x0.0 -NaN:0x7ffffffffffff]) == [0 18446744073709551615] ; run: %bitcast_fi64x2([-NaN:0x7ffffffffffff 0x0.000000000007fp-1022]) == [-1 127] + +function %bitcast_more_lanes(i64x2) -> i32x4 { +block0(v0: i64x2): + v1 = bitcast.i32x4 little v0 + return v1 +} +; run: %bitcast_more_lanes(0x00000000000000000000000000000000) == 0x00000000000000000000000000000000 +; run: %bitcast_more_lanes(0x00000000000000ff00000000000000ff) == 0x00000000000000ff00000000000000ff + +function %bitcast_fewer_lanes(i16x8) -> i64x2 { +block0(v0: i16x8): + v1 = bitcast.i64x2 little v0 + return v1 +} +; run: %bitcast_fewer_lanes(0x00000000000000000000000000000000) == 0x00000000000000000000000000000000 +; run: %bitcast_fewer_lanes(0x00ff0000000000000000000000000000) == 0x00ff0000000000000000000000000000 diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 1022ae175d47..e5be56c44f3e 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -904,11 +904,21 @@ where Opcode::IsInvalid => unimplemented!("IsInvalid"), Opcode::Bitcast | Opcode::ScalarToVector => { let input_ty = inst_context.type_of(inst_context.args()[0]).unwrap(); - let arg0 = extractlanes(&arg(0), input_ty)?; - let lanes = &arg0 - .into_iter() - .map(|x| DataValue::convert(x, ValueConversionKind::Exact(ctrl_ty.lane_type()))) - .collect::>>()?; + let out_lane_ty = ctrl_ty.lane_type(); + let nr_in_lane_bytes = input_ty.lane_type().bytes() as usize; + let nr_out_lane_bytes = out_lane_ty.bytes() as usize; + let lanes = &if nr_in_lane_bytes == nr_out_lane_bytes { + extractlanes(&arg(0), input_ty)? + .into_iter() + .map(|lane| DataValue::convert(lane, ValueConversionKind::Exact(out_lane_ty))) + .collect::>>()? + } else { + arg(0) + .into_array()? + .chunks(nr_out_lane_bytes) + .map(|bytes| DataValue::read_from_slice_ne(&bytes, out_lane_ty)) + .collect::>() + }; assign(match inst.opcode() { Opcode::Bitcast => vectorizelanes(lanes, ctrl_ty)?, Opcode::ScalarToVector => vectorizelanes_all(lanes, ctrl_ty)?,