Skip to content

Commit c170c94

Browse files
committed
[WIP] Bunch of hacks to make vectors smaller than 128bit work with the new Rust ABI
1 parent c969356 commit c170c94

File tree

4 files changed

+83
-9
lines changed

4 files changed

+83
-9
lines changed

src/abi/pass_mode.rs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ fn reg_to_abi_param(reg: Reg) -> AbiParam {
2424
(RegKind::Integer, 9..=16) => types::I128,
2525
(RegKind::Float, 4) => types::F32,
2626
(RegKind::Float, 8) => types::F64,
27-
(RegKind::Vector, size) => types::I8.by(u32::try_from(size).unwrap()).unwrap(),
27+
// FIXME(bytecodealliance/wasmtime#10254): Increasing vector size to 128bit to workaround
28+
// load and store for smaller vectors not being supported.
29+
(RegKind::Vector, size) => types::I8.by(u32::try_from(size.max(128)).unwrap()).unwrap(),
2830
_ => unreachable!("{:?}", reg),
2931
};
3032
AbiParam::new(clif_ty)
@@ -222,7 +224,36 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
222224
assert_assignable(fx, arg.layout().ty, arg_abi.layout.ty, 16);
223225
match arg_abi.mode {
224226
PassMode::Ignore => smallvec![],
225-
PassMode::Direct(_) => smallvec![arg.load_scalar(fx)],
227+
PassMode::Direct(_) => match arg_abi.layout.backend_repr {
228+
BackendRepr::Scalar(_) => smallvec![arg.load_scalar(fx)],
229+
BackendRepr::Vector { .. } => {
230+
let vector_ty = crate::intrinsics::clif_vector_type(fx.tcx, arg_abi.layout);
231+
if u64::from(vector_ty.bytes()) > arg_abi.layout.size.bytes() {
232+
// FIXME(bytecodealliance/wasmtime#10254): In reg_to_abi_param we increased the
233+
// vector size to 128bit to workaround load and store for smaller vectors not
234+
// being supported. As such we need to truncate the vector.
235+
// FIXME(bytecodealliance/wasmtime#6104) do something more efficient for
236+
// transmutes between vectors and integers.
237+
let tmp_ptr = fx.create_stack_slot(vector_ty.bytes(), vector_ty.bytes());
238+
let tmp_ptr_addr = tmp_ptr.get_addr(fx);
239+
let val_ptr = arg.force_stack(fx).0.get_addr(fx);
240+
fx.bcx.emit_small_memory_copy(
241+
fx.target_config,
242+
tmp_ptr_addr,
243+
val_ptr,
244+
arg_abi.layout.size.bytes(),
245+
vector_ty.bytes().try_into().unwrap(),
246+
arg_abi.layout.align.abi.bytes().try_into().unwrap(),
247+
true,
248+
MemFlags::trusted(),
249+
);
250+
smallvec![tmp_ptr.load(fx, vector_ty, MemFlags::trusted())]
251+
} else {
252+
smallvec![arg.load_scalar(fx)]
253+
}
254+
}
255+
_ => unreachable!("{:?}", arg_abi.layout.backend_repr),
256+
},
226257
PassMode::Pair(_, _) => {
227258
let (a, b) = arg.load_scalar_pair(fx);
228259
smallvec![a, b]

src/abi/returning.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,45 @@ pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) {
111111
unreachable!("unsized return value")
112112
}
113113
PassMode::Direct(_) => {
114-
let place = fx.get_local_place(RETURN_PLACE);
115-
let ret_val = place.to_cvalue(fx).load_scalar(fx);
116-
fx.bcx.ins().return_(&[ret_val]);
114+
match fx.fn_abi.ret.layout.backend_repr {
115+
BackendRepr::Scalar(_) => {
116+
let place = fx.get_local_place(RETURN_PLACE);
117+
let ret_val = place.to_cvalue(fx).load_scalar(fx);
118+
fx.bcx.ins().return_(&[ret_val]);
119+
}
120+
BackendRepr::Vector { .. } => {
121+
let vector_ty =
122+
crate::intrinsics::clif_vector_type(fx.tcx, fx.fn_abi.ret.layout);
123+
if u64::from(vector_ty.bytes()) > fx.fn_abi.ret.layout.size.bytes() {
124+
// FIXME(bytecodealliance/wasmtime#10254): In reg_to_abi_param we increased the
125+
// vector size to 128bit to workaround load and store for smaller vectors not
126+
// being supported. As such we need to truncate the vector.
127+
// FIXME(bytecodealliance/wasmtime#6104) do something more efficient for
128+
// transmutes between vectors and integers.
129+
let tmp_ptr = fx.create_stack_slot(vector_ty.bytes(), vector_ty.bytes());
130+
let tmp_ptr_addr = tmp_ptr.get_addr(fx);
131+
let place = fx.get_local_place(RETURN_PLACE);
132+
let ret_ptr = place.to_cvalue(fx).force_stack(fx).0.get_addr(fx);
133+
fx.bcx.emit_small_memory_copy(
134+
fx.target_config,
135+
tmp_ptr_addr,
136+
ret_ptr,
137+
vector_ty.bytes().try_into().unwrap(),
138+
vector_ty.bytes().try_into().unwrap(),
139+
fx.fn_abi.ret.layout.align.abi.bytes().try_into().unwrap(),
140+
true,
141+
MemFlags::trusted(),
142+
);
143+
let ret_val = tmp_ptr.load(fx, vector_ty, MemFlags::trusted());
144+
fx.bcx.ins().return_(&[ret_val]);
145+
} else {
146+
let place = fx.get_local_place(RETURN_PLACE);
147+
let ret_val = place.to_cvalue(fx).load_scalar(fx);
148+
fx.bcx.ins().return_(&[ret_val]);
149+
}
150+
}
151+
_ => unreachable!("{:?}", fx.fn_abi.ret.layout.backend_repr),
152+
}
117153
}
118154
PassMode::Pair(_, _) => {
119155
let place = fx.get_local_place(RETURN_PLACE);

src/intrinsics/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,10 @@ pub(crate) fn clif_vector_type<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx
5757
_ => unreachable!(),
5858
};
5959

60-
scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()).unwrap()
60+
// FIXME(bytecodealliance/wasmtime#10254): Increasing vector size to 128bit to workaround
61+
// load and store for smaller vectors not being supported.
62+
let scalar = scalar_to_clif_type(tcx, element);
63+
scalar.by(u32::try_from(count.max((128 / scalar.bits()).try_into().unwrap())).unwrap()).unwrap()
6164
}
6265

6366
fn simd_for_each_lane<'tcx>(

src/value_and_place.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,13 @@ impl<'tcx> CValue<'tcx> {
173173
CValueInner::ByRef(ptr, None) => {
174174
let clif_ty = match layout.backend_repr {
175175
BackendRepr::Scalar(scalar) => scalar_to_clif_type(fx.tcx, scalar),
176-
BackendRepr::Vector { element, count } => scalar_to_clif_type(fx.tcx, element)
177-
.by(u32::try_from(count).unwrap())
178-
.unwrap(),
176+
BackendRepr::Vector { element, count } => {
177+
let ty = scalar_to_clif_type(fx.tcx, element)
178+
.by(u32::try_from(count).unwrap())
179+
.unwrap();
180+
assert!(ty.bits() >= 128);
181+
ty
182+
}
179183
_ => unreachable!("{:?}", layout.ty),
180184
};
181185
let mut flags = MemFlags::new();

0 commit comments

Comments
 (0)