Fix local.set and local.tee types for SIMD
Because Wasm SIMD vectors store their type as `v128`, there is a mismatch between the more specific types Cranelift uses and Wasm SIMD. Because of this mismatch, Wasm SIMD translates to the default Cranelift type `I8X16`, causing issues when more specific type information is available (e.g. `I32x4`). To fix this, all incoming values to SIMD instructions are checked during translation (not runtime) and if necessary cast from `I8X16` to the appropriate type by functions like `optionally_bitcast_vector`, `pop1_with_bitcast` and `pop2_with_bitcast`. However, there are times when we must also cast to `I8X16` for outgoing values, as with `local.set` and `local.tee`. There are other ways of resolving this (e.g., see adding a new vector type, https://github.com/bytecodealliance/cranelift/pull/1251) but we discussed staying with this casting approach in https://github.com/bytecodealliance/wasmtime/issues/1147.
This commit is contained in:
@@ -73,13 +73,27 @@ pub fn translate_operator<FE: FuncEnvironment + ?Sized>(
|
|||||||
builder.set_val_label(val, label);
|
builder.set_val_label(val, label);
|
||||||
}
|
}
|
||||||
Operator::LocalSet { local_index } => {
|
Operator::LocalSet { local_index } => {
|
||||||
let val = state.pop1();
|
let mut val = state.pop1();
|
||||||
|
|
||||||
|
// Ensure SIMD values are cast to their default Cranelift type, I8x16.
|
||||||
|
let ty = builder.func.dfg.value_type(val);
|
||||||
|
if ty.is_vector() {
|
||||||
|
val = optionally_bitcast_vector(val, I8X16, builder);
|
||||||
|
}
|
||||||
|
|
||||||
builder.def_var(Variable::with_u32(*local_index), val);
|
builder.def_var(Variable::with_u32(*local_index), val);
|
||||||
let label = ValueLabel::from_u32(*local_index);
|
let label = ValueLabel::from_u32(*local_index);
|
||||||
builder.set_val_label(val, label);
|
builder.set_val_label(val, label);
|
||||||
}
|
}
|
||||||
Operator::LocalTee { local_index } => {
|
Operator::LocalTee { local_index } => {
|
||||||
let val = state.peek1();
|
let mut val = state.peek1();
|
||||||
|
|
||||||
|
// Ensure SIMD values are cast to their default Cranelift type, I8x16.
|
||||||
|
let ty = builder.func.dfg.value_type(val);
|
||||||
|
if ty.is_vector() {
|
||||||
|
val = optionally_bitcast_vector(val, I8X16, builder);
|
||||||
|
}
|
||||||
|
|
||||||
builder.def_var(Variable::with_u32(*local_index), val);
|
builder.def_var(Variable::with_u32(*local_index), val);
|
||||||
let label = ValueLabel::from_u32(*local_index);
|
let label = ValueLabel::from_u32(*local_index);
|
||||||
builder.set_val_label(val, label);
|
builder.set_val_label(val, label);
|
||||||
|
|||||||
@@ -17,6 +17,12 @@
|
|||||||
i32x4.extract_lane 3
|
i32x4.extract_lane 3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(func $test_locals (local i32 v128)
|
||||||
|
local.get 0
|
||||||
|
i32x4.splat
|
||||||
|
local.set 1
|
||||||
|
)
|
||||||
|
|
||||||
(export "test_splat" (func $test_splat))
|
(export "test_splat" (func $test_splat))
|
||||||
(export "test_insert_lane" (func $test_insert_lane))
|
(export "test_insert_lane" (func $test_insert_lane))
|
||||||
(export "test_const" (func $test_const))
|
(export "test_const" (func $test_const))
|
||||||
|
|||||||
Reference in New Issue
Block a user