Skip to content

Commit

Permalink
Implement dyn* support
Browse files Browse the repository at this point in the history
  • Loading branch information
bjorn3 committed Sep 15, 2022
1 parent f68742a commit 879c86f
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 11 deletions.
54 changes: 52 additions & 2 deletions src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
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
Expand Down Expand Up @@ -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());
Expand All @@ -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(_, _)));

Expand Down
6 changes: 3 additions & 3 deletions src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -701,9 +701,9 @@ fn codegen_stmt<'tcx>(
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);
Expand Down
16 changes: 16 additions & 0 deletions src/unsize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>(
Expand Down
4 changes: 4 additions & 0 deletions src/value_and_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ impl<'tcx> CValue<'tcx> {
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>,
Expand Down
26 changes: 20 additions & 6 deletions src/vtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
} else {
let (ptr, vtable) = arg.try_to_ptr().unwrap();
(ptr.get_addr(fx), vtable.unwrap())
) -> (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, vtable.unwrap())
}
};

let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
Expand Down

0 comments on commit 879c86f

Please sign in to comment.