Implement dyn* support
This commit is contained in:
parent
f68742a03c
commit
879c86ff30
@ -465,7 +465,7 @@ enum CallTarget {
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
|
||||
(CallTarget::Indirect(sig, method), Some(ptr))
|
||||
(CallTarget::Indirect(sig, method), Some(ptr.get_addr(fx)))
|
||||
}
|
||||
|
||||
// Normal call
|
||||
@ -560,7 +560,19 @@ pub(crate) fn codegen_drop<'tcx>(
|
||||
// we don't actually need to drop anything
|
||||
} else {
|
||||
match ty.kind() {
|
||||
ty::Dynamic(..) => {
|
||||
ty::Dynamic(_, _, ty::Dyn) => {
|
||||
// IN THIS ARM, WE HAVE:
|
||||
// ty = *mut (dyn Trait)
|
||||
// which is: exists<T> ( *mut T, Vtable<T: Trait> )
|
||||
// args[0] args[1]
|
||||
//
|
||||
// args = ( Data, Vtable )
|
||||
// |
|
||||
// v
|
||||
// /-------\
|
||||
// | ... |
|
||||
// \-------/
|
||||
//
|
||||
let (ptr, vtable) = drop_place.to_ptr_maybe_unsized();
|
||||
let ptr = ptr.get_addr(fx);
|
||||
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
|
||||
@ -578,6 +590,44 @@ pub(crate) fn codegen_drop<'tcx>(
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
|
||||
}
|
||||
ty::Dynamic(_, _, ty::DynStar) => {
|
||||
// IN THIS ARM, WE HAVE:
|
||||
// ty = *mut (dyn* Trait)
|
||||
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
|
||||
//
|
||||
// args = [ * ]
|
||||
// |
|
||||
// v
|
||||
// ( Data, Vtable )
|
||||
// |
|
||||
// v
|
||||
// /-------\
|
||||
// | ... |
|
||||
// \-------/
|
||||
//
|
||||
//
|
||||
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
|
||||
//
|
||||
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
|
||||
// vtable = (*args[0]).1 // loads the vtable out
|
||||
// (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 drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
|
||||
|
||||
let virtual_drop = Instance {
|
||||
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
|
||||
substs: drop_instance.substs,
|
||||
};
|
||||
let fn_abi =
|
||||
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
|
||||
|
||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
|
||||
let sig = fx.bcx.import_signature(sig);
|
||||
fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
|
||||
}
|
||||
_ => {
|
||||
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
|
||||
|
||||
|
@ -701,9 +701,9 @@ fn is_fat_ptr<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||
let operand = codegen_operand(fx, operand);
|
||||
operand.unsize_value(fx, lval);
|
||||
}
|
||||
Rvalue::Cast(CastKind::DynStar, _, _) => {
|
||||
// FIXME(dyn-star)
|
||||
unimplemented!()
|
||||
Rvalue::Cast(CastKind::DynStar, ref operand, _) => {
|
||||
let operand = codegen_operand(fx, operand);
|
||||
operand.coerce_dyn_star(fx, lval);
|
||||
}
|
||||
Rvalue::Discriminant(place) => {
|
||||
let place = codegen_place(fx, place);
|
||||
|
@ -147,6 +147,22 @@ pub(crate) fn coerce_unsized_into<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn coerce_dyn_star<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
src: CValue<'tcx>,
|
||||
dst: CPlace<'tcx>,
|
||||
) {
|
||||
let data = src.load_scalar(fx);
|
||||
|
||||
let vtable = if let ty::Dynamic(data, _, ty::DynStar) = dst.layout().ty.kind() {
|
||||
crate::vtable::get_vtable(fx, src.layout().ty, data.principal())
|
||||
} else {
|
||||
bug!("Only valid to do a DynStar cast into a DynStar type")
|
||||
};
|
||||
|
||||
dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout()));
|
||||
}
|
||||
|
||||
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
|
||||
|
||||
pub(crate) fn size_and_align_of_dst<'tcx>(
|
||||
|
@ -236,6 +236,10 @@ pub(crate) fn unsize_value(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace
|
||||
crate::unsize::coerce_unsized_into(fx, self, dest);
|
||||
}
|
||||
|
||||
pub(crate) fn coerce_dyn_star(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) {
|
||||
crate::unsize::coerce_dyn_star(fx, self, dest);
|
||||
}
|
||||
|
||||
/// If `ty` is signed, `const_val` must already be sign extended.
|
||||
pub(crate) fn const_val(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
|
@ -45,12 +45,26 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
arg: CValue<'tcx>,
|
||||
idx: usize,
|
||||
) -> (Value, Value) {
|
||||
let (ptr, vtable) = if let Abi::ScalarPair(_, _) = arg.layout().abi {
|
||||
arg.load_scalar_pair(fx)
|
||||
) -> (Pointer, Value) {
|
||||
let (ptr, vtable) = 'block: {
|
||||
if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
|
||||
if ty.is_dyn_star() {
|
||||
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
|
||||
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
|
||||
let ptr = dyn_star.place_field(fx, mir::Field::new(0)).to_ptr();
|
||||
let vtable =
|
||||
dyn_star.place_field(fx, mir::Field::new(1)).to_cvalue(fx).load_scalar(fx);
|
||||
break 'block (ptr, vtable);
|
||||
}
|
||||
}
|
||||
|
||||
if let Abi::ScalarPair(_, _) = arg.layout().abi {
|
||||
let (ptr, vtable) = arg.load_scalar_pair(fx);
|
||||
(Pointer::new(ptr), vtable)
|
||||
} else {
|
||||
let (ptr, vtable) = arg.try_to_ptr().unwrap();
|
||||
(ptr.get_addr(fx), vtable.unwrap())
|
||||
(ptr, vtable.unwrap())
|
||||
}
|
||||
};
|
||||
|
||||
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
|
||||
|
Loading…
Reference in New Issue
Block a user