]> git.lizzy.rs Git - rust.git/blob - src/vtable.rs
Auto merge of #86475 - crlf0710:miri_vtable_refactor, r=bjorn3
[rust.git] / src / vtable.rs
1 //! Codegen vtables and vtable accesses.
2 //!
3 //! See `rustc_codegen_ssa/src/meth.rs` for reference.
4 // FIXME dedup this logic between miri, cg_llvm and cg_clif
5
6 use crate::prelude::*;
7 use super::constant::pointer_for_allocation;
8
9 fn vtable_memflags() -> MemFlags {
10     let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap.
11     flags.set_readonly(); // A vtable is always read-only.
12     flags
13 }
14
15 pub(crate) fn drop_fn_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value {
16     let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
17     fx.bcx.ins().load(
18         pointer_ty(fx.tcx),
19         vtable_memflags(),
20         vtable,
21         (ty::COMMON_VTABLE_ENTRIES_DROPINPLACE * usize_size) as i32,
22     )
23 }
24
25 pub(crate) fn size_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value {
26     let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
27     fx.bcx.ins().load(
28         pointer_ty(fx.tcx),
29         vtable_memflags(),
30         vtable,
31         (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32,
32     )
33 }
34
35 pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Value {
36     let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
37     fx.bcx.ins().load(
38         pointer_ty(fx.tcx),
39         vtable_memflags(),
40         vtable,
41         (ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32,
42     )
43 }
44
45 pub(crate) fn get_ptr_and_method_ref<'tcx>(
46     fx: &mut FunctionCx<'_, '_, 'tcx>,
47     arg: CValue<'tcx>,
48     idx: usize,
49 ) -> (Value, Value) {
50     let (ptr, vtable) = if let Abi::ScalarPair(_, _) = arg.layout().abi {
51         arg.load_scalar_pair(fx)
52     } else {
53         let (ptr, vtable) = arg.try_to_ptr().unwrap();
54         (ptr.get_addr(fx), vtable.unwrap())
55     };
56
57     let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
58     let func_ref = fx.bcx.ins().load(
59         pointer_ty(fx.tcx),
60         vtable_memflags(),
61         vtable,
62         (idx * usize_size as usize) as i32,
63     );
64     (ptr, func_ref)
65 }
66
67 pub(crate) fn get_vtable<'tcx>(
68     fx: &mut FunctionCx<'_, '_, 'tcx>,
69     ty: Ty<'tcx>,
70     trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
71 ) -> Value {
72     let vtable_ptr = if let Some(vtable_ptr) = fx.vtables.get(&(ty, trait_ref)) {
73         *vtable_ptr
74     } else {
75         let vtable_alloc_id = fx.tcx.vtable_allocation(ty, trait_ref);
76         let vtable_allocation = fx.tcx.global_alloc(vtable_alloc_id).unwrap_memory();
77         let vtable_ptr = pointer_for_allocation(fx, vtable_allocation);
78
79         fx.vtables.insert((ty, trait_ref), vtable_ptr);
80         vtable_ptr
81     };
82
83     vtable_ptr.get_addr(fx)
84 }