Skip to content

Commit 879c86f

Browse files
committed
Implement dyn* support
1 parent f68742a commit 879c86f

File tree

5 files changed

+95
-11
lines changed

5 files changed

+95
-11
lines changed

src/abi/mod.rs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
465465
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
466466
let sig = fx.bcx.import_signature(sig);
467467

468-
(CallTarget::Indirect(sig, method), Some(ptr))
468+
(CallTarget::Indirect(sig, method), Some(ptr.get_addr(fx)))
469469
}
470470

471471
// Normal call
@@ -560,7 +560,19 @@ pub(crate) fn codegen_drop<'tcx>(
560560
// we don't actually need to drop anything
561561
} else {
562562
match ty.kind() {
563-
ty::Dynamic(..) => {
563+
ty::Dynamic(_, _, ty::Dyn) => {
564+
// IN THIS ARM, WE HAVE:
565+
// ty = *mut (dyn Trait)
566+
// which is: exists<T> ( *mut T, Vtable<T: Trait> )
567+
// args[0] args[1]
568+
//
569+
// args = ( Data, Vtable )
570+
// |
571+
// v
572+
// /-------\
573+
// | ... |
574+
// \-------/
575+
//
564576
let (ptr, vtable) = drop_place.to_ptr_maybe_unsized();
565577
let ptr = ptr.get_addr(fx);
566578
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable.unwrap());
@@ -578,6 +590,44 @@ pub(crate) fn codegen_drop<'tcx>(
578590
let sig = fx.bcx.import_signature(sig);
579591
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
580592
}
593+
ty::Dynamic(_, _, ty::DynStar) => {
594+
// IN THIS ARM, WE HAVE:
595+
// ty = *mut (dyn* Trait)
596+
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
597+
//
598+
// args = [ * ]
599+
// |
600+
// v
601+
// ( Data, Vtable )
602+
// |
603+
// v
604+
// /-------\
605+
// | ... |
606+
// \-------/
607+
//
608+
//
609+
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
610+
//
611+
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
612+
// vtable = (*args[0]).1 // loads the vtable out
613+
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
614+
//
615+
// SO THEN WE CAN USE THE ABOVE CODE.
616+
let dyn_star = drop_place.to_cvalue(fx);
617+
let (data, vtable) = dyn_star.load_scalar_pair(fx);
618+
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
619+
620+
let virtual_drop = Instance {
621+
def: ty::InstanceDef::Virtual(drop_instance.def_id(), 0),
622+
substs: drop_instance.substs,
623+
};
624+
let fn_abi =
625+
RevealAllLayoutCx(fx.tcx).fn_abi_of_instance(virtual_drop, ty::List::empty());
626+
627+
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
628+
let sig = fx.bcx.import_signature(sig);
629+
fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
630+
}
581631
_ => {
582632
assert!(!matches!(drop_instance.def, InstanceDef::Virtual(_, _)));
583633

src/base.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -701,9 +701,9 @@ fn codegen_stmt<'tcx>(
701701
let operand = codegen_operand(fx, operand);
702702
operand.unsize_value(fx, lval);
703703
}
704-
Rvalue::Cast(CastKind::DynStar, _, _) => {
705-
// FIXME(dyn-star)
706-
unimplemented!()
704+
Rvalue::Cast(CastKind::DynStar, ref operand, _) => {
705+
let operand = codegen_operand(fx, operand);
706+
operand.coerce_dyn_star(fx, lval);
707707
}
708708
Rvalue::Discriminant(place) => {
709709
let place = codegen_place(fx, place);

src/unsize.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,22 @@ pub(crate) fn coerce_unsized_into<'tcx>(
147147
}
148148
}
149149

150+
pub(crate) fn coerce_dyn_star<'tcx>(
151+
fx: &mut FunctionCx<'_, '_, 'tcx>,
152+
src: CValue<'tcx>,
153+
dst: CPlace<'tcx>,
154+
) {
155+
let data = src.load_scalar(fx);
156+
157+
let vtable = if let ty::Dynamic(data, _, ty::DynStar) = dst.layout().ty.kind() {
158+
crate::vtable::get_vtable(fx, src.layout().ty, data.principal())
159+
} else {
160+
bug!("Only valid to do a DynStar cast into a DynStar type")
161+
};
162+
163+
dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout()));
164+
}
165+
150166
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
151167

152168
pub(crate) fn size_and_align_of_dst<'tcx>(

src/value_and_place.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@ impl<'tcx> CValue<'tcx> {
236236
crate::unsize::coerce_unsized_into(fx, self, dest);
237237
}
238238

239+
pub(crate) fn coerce_dyn_star(self, fx: &mut FunctionCx<'_, '_, 'tcx>, dest: CPlace<'tcx>) {
240+
crate::unsize::coerce_dyn_star(fx, self, dest);
241+
}
242+
239243
/// If `ty` is signed, `const_val` must already be sign extended.
240244
pub(crate) fn const_val(
241245
fx: &mut FunctionCx<'_, '_, 'tcx>,

src/vtable.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,26 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
4545
fx: &mut FunctionCx<'_, '_, 'tcx>,
4646
arg: CValue<'tcx>,
4747
idx: usize,
48-
) -> (Value, Value) {
49-
let (ptr, vtable) = if let Abi::ScalarPair(_, _) = arg.layout().abi {
50-
arg.load_scalar_pair(fx)
51-
} else {
52-
let (ptr, vtable) = arg.try_to_ptr().unwrap();
53-
(ptr.get_addr(fx), vtable.unwrap())
48+
) -> (Pointer, Value) {
49+
let (ptr, vtable) = 'block: {
50+
if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
51+
if ty.is_dyn_star() {
52+
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap().ty);
53+
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
54+
let ptr = dyn_star.place_field(fx, mir::Field::new(0)).to_ptr();
55+
let vtable =
56+
dyn_star.place_field(fx, mir::Field::new(1)).to_cvalue(fx).load_scalar(fx);
57+
break 'block (ptr, vtable);
58+
}
59+
}
60+
61+
if let Abi::ScalarPair(_, _) = arg.layout().abi {
62+
let (ptr, vtable) = arg.load_scalar_pair(fx);
63+
(Pointer::new(ptr), vtable)
64+
} else {
65+
let (ptr, vtable) = arg.try_to_ptr().unwrap();
66+
(ptr, vtable.unwrap())
67+
}
5468
};
5569

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

0 commit comments

Comments
 (0)