diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 04e39954..99059e78 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -613,8 +613,7 @@ pub(crate) fn codegen_drop<'tcx>( // (data, vtable) // an equivalent Rust `*mut dyn Trait` // // SO THEN WE CAN USE THE ABOVE CODE. - let dyn_star = drop_place.to_cvalue(fx); - let (data, vtable) = dyn_star.load_scalar_pair(fx); + let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx); let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable); let virtual_drop = Instance { diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 88d7fc2f..75f968f3 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -107,6 +107,50 @@ impl<'tcx> CValue<'tcx> { } } + // FIXME remove + // Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the + // vtable pointer. + pub(crate) fn dyn_star_force_data_on_stack( + self, + fx: &mut FunctionCx<'_, '_, 'tcx>, + ) -> (Value, Value) { + assert!(self.1.ty.is_dyn_star()); + + match self.0 { + CValueInner::ByRef(ptr, None) => { + let (a_scalar, b_scalar) = match self.1.abi { + Abi::ScalarPair(a, b) => (a, b), + _ => unreachable!("dyn_star_force_data_on_stack({:?})", self), + }; + let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar); + let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar); + let mut flags = MemFlags::new(); + flags.set_notrap(); + let vtable = ptr.offset(fx, b_offset).load(fx, clif_ty2, flags); + (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); + + (data_ptr.get_addr(fx), vtable) + } + CValueInner::ByRef(_, Some(_)) | CValueInner::ByVal(_) => { + unreachable!("dyn_star_force_data_on_stack({:?})", self) + } + } + } + pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option)> { match self.0 { CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),