From 38e8be9673c5a24a5f8282a0047499071598a370 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 22 Oct 2023 16:02:02 +0000 Subject: [PATCH] Add create_stack_slot helper to FunctionCx This will allow centrally handling a workaround for the lack of stack alignment specifier in cranelift. --- src/abi/mod.rs | 35 ++++++++++++++--------------------- src/abi/pass_mode.rs | 11 ++++------- src/cast.rs | 6 +----- src/common.rs | 10 ++++++++++ src/inline_asm.rs | 22 ++++++++++++---------- src/value_and_place.rs | 37 +++++++++++-------------------------- 6 files changed, 52 insertions(+), 69 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index c75ad852f82..c4572e03525 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -120,32 +120,25 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { args: &[Value], ) -> Cow<'_, [Value]> { if self.tcx.sess.target.is_like_windows { - let (mut params, mut args): (Vec<_>, Vec<_>) = - params - .into_iter() - .zip(args) - .map(|(param, &arg)| { - if param.value_type == types::I128 { - let arg_ptr = Pointer::stack_slot(self.bcx.create_sized_stack_slot( - StackSlotData { kind: StackSlotKind::ExplicitSlot, size: 16 }, - )); - arg_ptr.store(self, arg, MemFlags::trusted()); - (AbiParam::new(self.pointer_type), arg_ptr.get_addr(self)) - } else { - (param, arg) - } - }) - .unzip(); + let (mut params, mut args): (Vec<_>, Vec<_>) = params + .into_iter() + .zip(args) + .map(|(param, &arg)| { + if param.value_type == types::I128 { + let arg_ptr = self.create_stack_slot(16, 16); + arg_ptr.store(self, arg, MemFlags::trusted()); + (AbiParam::new(self.pointer_type), arg_ptr.get_addr(self)) + } else { + (param, arg) + } + }) + .unzip(); let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128; if indirect_ret_val { params.insert(0, AbiParam::new(self.pointer_type)); - let ret_ptr = - Pointer::stack_slot(self.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: 16, - })); + let ret_ptr = self.create_stack_slot(16, 16); args.insert(0, ret_ptr.get_addr(self)); self.lib_call_unadjusted(name, params, vec![], &args); return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]); diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 7c9f8c1051c..06522670029 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -189,16 +189,13 @@ pub(super) fn from_casted_value<'tcx>( let abi_params = cast_target_to_abi_params(cast); let abi_param_size: u32 = abi_params.iter().map(|param| param.value_type.bytes()).sum(); let layout_size = u32::try_from(layout.size.bytes()).unwrap(); - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. + let ptr = fx.create_stack_slot( // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`. // It may also be smaller for example when the type is a wrapper around an integer with a // larger alignment than the integer. - size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, - }); - let ptr = Pointer::stack_slot(stack_slot); + std::cmp::max(abi_param_size, layout_size), + u32::try_from(layout.align.pref.bytes()).unwrap(), + ); let mut offset = 0; let mut block_params_iter = block_params.iter().copied(); for param in abi_params { diff --git a/src/cast.rs b/src/cast.rs index 7e027c5f1b3..0b5cb1547fc 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -104,11 +104,7 @@ pub(crate) fn clif_int_or_float_cast( &[from], )[0]; // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128 - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: 16, - }); - let ret_ptr = Pointer::stack_slot(stack_slot); + let ret_ptr = fx.create_stack_slot(16, 16); ret_ptr.store(fx, ret, MemFlags::trusted()); ret_ptr.load(fx, types::I128, MemFlags::trusted()) } else { diff --git a/src/common.rs b/src/common.rs index 7a3ae6ebf52..d306471e970 100644 --- a/src/common.rs +++ b/src/common.rs @@ -383,6 +383,16 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { }) } + pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { + let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to + // specify stack slot alignment. + size: (size + 15) / 16 * 16, + }); + Pointer::stack_slot(stack_slot) + } + pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) { if let Some(debug_context) = &mut self.cx.debug_context { let (file, line, column) = diff --git a/src/inline_asm.rs b/src/inline_asm.rs index ed077234254..0517c609337 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -878,13 +878,7 @@ fn call_inline_asm<'tcx>( inputs: Vec<(Size, Value)>, outputs: Vec<(Size, CPlace<'tcx>)>, ) { - let stack_slot = fx.bcx.func.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: u32::try_from(slot_size.bytes()).unwrap(), - }); - if fx.clif_comments.enabled() { - fx.add_comment(stack_slot, "inline asm scratch slot"); - } + let stack_slot = fx.create_stack_slot(u32::try_from(slot_size.bytes()).unwrap(), 16); let inline_asm_func = fx .module @@ -904,15 +898,23 @@ fn call_inline_asm<'tcx>( } for (offset, value) in inputs { - fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap()); + stack_slot.offset(fx, i32::try_from(offset.bytes()).unwrap().into()).store( + fx, + value, + MemFlags::trusted(), + ); } - let stack_slot_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0); + let stack_slot_addr = stack_slot.get_addr(fx); fx.bcx.ins().call(inline_asm_func, &[stack_slot_addr]); for (offset, place) in outputs { let ty = fx.clif_type(place.layout().ty).unwrap(); - let value = fx.bcx.ins().stack_load(ty, stack_slot, i32::try_from(offset.bytes()).unwrap()); + let value = stack_slot.offset(fx, i32::try_from(offset.bytes()).unwrap().into()).load( + fx, + ty, + MemFlags::trusted(), + ); place.write_cvalue(fx, CValue::by_val(value, place.layout())); } } diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 3a6a6c9e3f5..5f0aa6c5581 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -132,18 +132,11 @@ impl<'tcx> CValue<'tcx> { (ptr.get_addr(fx), vtable) } CValueInner::ByValPair(data, vtable) => { - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (u32::try_from(fx.target_config.pointer_type().bytes()).unwrap() + 15) - / 16 - * 16, - }); - let data_ptr = Pointer::stack_slot(stack_slot); - let mut flags = MemFlags::new(); - flags.set_notrap(); - data_ptr.store(fx, data, flags); + let data_ptr = fx.create_stack_slot( + u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(), + u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(), + ); + data_ptr.store(fx, data, MemFlags::trusted()); (data_ptr.get_addr(fx), vtable) } @@ -372,13 +365,11 @@ impl<'tcx> CPlace<'tcx> { .fatal(format!("values of type {} are too big to store on the stack", layout.ty)); } - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (u32::try_from(layout.size.bytes()).unwrap() + 15) / 16 * 16, - }); - CPlace { inner: CPlaceInner::Addr(Pointer::stack_slot(stack_slot), None), layout } + let stack_slot = fx.create_stack_slot( + u32::try_from(layout.size.bytes()).unwrap(), + u32::try_from(layout.align.pref.bytes()).unwrap(), + ); + CPlace { inner: CPlaceInner::Addr(stack_slot, None), layout } } pub(crate) fn new_var( @@ -543,13 +534,7 @@ impl<'tcx> CPlace<'tcx> { _ if src_ty.is_vector() && dst_ty.is_vector() => codegen_bitcast(fx, dst_ty, data), _ if src_ty.is_vector() || dst_ty.is_vector() => { // FIXME(bytecodealliance/wasmtime#6104) do something more efficient for transmutes between vectors and integers. - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (src_ty.bytes() + 15) / 16 * 16, - }); - let ptr = Pointer::stack_slot(stack_slot); + let ptr = fx.create_stack_slot(src_ty.bytes(), src_ty.bytes()); ptr.store(fx, data, MemFlags::trusted()); ptr.load(fx, dst_ty, MemFlags::trusted()) }