]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
1 | //! Codegen vtables and vtable accesses. |
2 | //! | |
cdc7bbd5 | 3 | //! See `rustc_codegen_ssa/src/meth.rs` for reference. |
29967ef6 | 4 | |
136023e0 | 5 | use crate::constant::data_id_for_alloc_id; |
29967ef6 XL |
6 | use crate::prelude::*; |
7 | ||
94222f64 | 8 | pub(crate) fn vtable_memflags() -> MemFlags { |
29967ef6 XL |
9 | let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap. |
10 | flags.set_readonly(); // A vtable is always read-only. | |
11 | flags | |
12 | } | |
13 | ||
6a06907d | 14 | pub(crate) fn drop_fn_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value { |
29967ef6 XL |
15 | let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; |
16 | fx.bcx.ins().load( | |
94222f64 | 17 | fx.pointer_type, |
29967ef6 XL |
18 | vtable_memflags(), |
19 | vtable, | |
136023e0 | 20 | (ty::COMMON_VTABLE_ENTRIES_DROPINPLACE * usize_size) as i32, |
29967ef6 XL |
21 | ) |
22 | } | |
23 | ||
6a06907d | 24 | pub(crate) fn size_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value { |
29967ef6 XL |
25 | let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; |
26 | fx.bcx.ins().load( | |
94222f64 | 27 | fx.pointer_type, |
29967ef6 XL |
28 | vtable_memflags(), |
29 | vtable, | |
136023e0 | 30 | (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32, |
29967ef6 XL |
31 | ) |
32 | } | |
33 | ||
6a06907d | 34 | pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value { |
29967ef6 XL |
35 | let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize; |
36 | fx.bcx.ins().load( | |
94222f64 | 37 | fx.pointer_type, |
29967ef6 XL |
38 | vtable_memflags(), |
39 | vtable, | |
136023e0 | 40 | (ty::COMMON_VTABLE_ENTRIES_ALIGN * usize_size) as i32, |
29967ef6 XL |
41 | ) |
42 | } | |
43 | ||
44 | pub(crate) fn get_ptr_and_method_ref<'tcx>( | |
6a06907d | 45 | fx: &mut FunctionCx<'_, '_, 'tcx>, |
29967ef6 XL |
46 | arg: CValue<'tcx>, |
47 | idx: usize, | |
2b03887a FG |
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 | } | |
29967ef6 XL |
68 | }; |
69 | ||
70 | let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes(); | |
71 | let func_ref = fx.bcx.ins().load( | |
94222f64 | 72 | fx.pointer_type, |
29967ef6 XL |
73 | vtable_memflags(), |
74 | vtable, | |
136023e0 | 75 | (idx * usize_size as usize) as i32, |
29967ef6 XL |
76 | ); |
77 | (ptr, func_ref) | |
78 | } | |
79 | ||
80 | pub(crate) fn get_vtable<'tcx>( | |
6a06907d | 81 | fx: &mut FunctionCx<'_, '_, 'tcx>, |
136023e0 | 82 | ty: Ty<'tcx>, |
29967ef6 XL |
83 | trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>, |
84 | ) -> Value { | |
dc3f5686 | 85 | let alloc_id = fx.tcx.vtable_allocation((ty, trait_ref)); |
136023e0 XL |
86 | let data_id = |
87 | data_id_for_alloc_id(&mut fx.constants_cx, &mut *fx.module, alloc_id, Mutability::Not); | |
17df50a5 | 88 | let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); |
136023e0 XL |
89 | if fx.clif_comments.enabled() { |
90 | fx.add_comment(local_data_id, format!("vtable: {:?}", alloc_id)); | |
29967ef6 | 91 | } |
136023e0 | 92 | fx.bcx.ins().global_value(fx.pointer_type, local_data_id) |
29967ef6 | 93 | } |