]>
git.proxmox.com Git - rustc.git/blob - src/librustc_codegen_ssa/meth.rs
3 use rustc_middle
::ty
::{self, Instance, Ty}
;
4 use rustc_target
::abi
::call
::FnAbi
;
6 #[derive(Copy, Clone, Debug)]
7 pub struct VirtualIndex(u64);
9 pub const DESTRUCTOR
: VirtualIndex
= VirtualIndex(0);
10 pub const SIZE
: VirtualIndex
= VirtualIndex(1);
11 pub const ALIGN
: VirtualIndex
= VirtualIndex(2);
13 impl<'a
, 'tcx
> VirtualIndex
{
14 pub fn from_index(index
: usize) -> Self {
15 VirtualIndex(index
as u64 + 3)
18 pub fn get_fn
<Bx
: BuilderMethods
<'a
, 'tcx
>>(
22 fn_abi
: &FnAbi
<'tcx
, Ty
<'tcx
>>,
24 // Load the data pointer from the object.
25 debug
!("get_fn({:?}, {:?})", llvtable
, self);
27 let llvtable
= bx
.pointercast(llvtable
, bx
.type_ptr_to(bx
.fn_ptr_backend_type(fn_abi
)));
28 let ptr_align
= bx
.tcx().data_layout
.pointer_align
.abi
;
29 let gep
= bx
.inbounds_gep(llvtable
, &[bx
.const_usize(self.0)]);
30 let ptr
= bx
.load(gep
, ptr_align
);
31 bx
.nonnull_metadata(ptr
);
32 // Vtable loads are invariant.
33 bx
.set_invariant_load(ptr
);
37 pub fn get_usize
<Bx
: BuilderMethods
<'a
, 'tcx
>>(
42 // Load the data pointer from the object.
43 debug
!("get_int({:?}, {:?})", llvtable
, self);
45 let llvtable
= bx
.pointercast(llvtable
, bx
.type_ptr_to(bx
.type_isize()));
46 let usize_align
= bx
.tcx().data_layout
.pointer_align
.abi
;
47 let gep
= bx
.inbounds_gep(llvtable
, &[bx
.const_usize(self.0)]);
48 let ptr
= bx
.load(gep
, usize_align
);
49 // Vtable loads are invariant.
50 bx
.set_invariant_load(ptr
);
55 /// Creates a dynamic vtable for the given type and vtable origin.
56 /// This is used only for objects.
58 /// The vtables are cached instead of created on every call.
60 /// The `trait_ref` encodes the erased self type. Hence if we are
61 /// making an object `Foo<dyn Trait>` from a value of type `Foo<T>`, then
62 /// `trait_ref` would map `T: Trait`.
63 pub fn get_vtable
<'tcx
, Cx
: CodegenMethods
<'tcx
>>(
66 trait_ref
: Option
<ty
::PolyExistentialTraitRef
<'tcx
>>,
70 debug
!("get_vtable(ty={:?}, trait_ref={:?})", ty
, trait_ref
);
73 if let Some(&val
) = cx
.vtables().borrow().get(&(ty
, trait_ref
)) {
77 // Not in the cache; build it.
78 let nullptr
= cx
.const_null(cx
.type_i8p());
81 let methods
= if let Some(trait_ref
) = trait_ref
{
82 methods_root
= tcx
.vtable_methods(trait_ref
.with_self_ty(tcx
, ty
));
88 let methods
= methods
.cloned().map(|opt_mth
| {
89 opt_mth
.map_or(nullptr
, |(def_id
, substs
)| {
91 ty
::Instance
::resolve_for_vtable(
93 ty
::ParamEnv
::reveal_all(),
102 let layout
= cx
.layout_of(ty
);
103 // /////////////////////////////////////////////////////////////////////////////////////////////
104 // If you touch this code, be sure to also make the corresponding changes to
105 // `get_vtable` in `rust_mir/interpret/traits.rs`.
106 // /////////////////////////////////////////////////////////////////////////////////////////////
107 let components
: Vec
<_
> = [
108 cx
.get_fn_addr(Instance
::resolve_drop_in_place(cx
.tcx(), ty
)),
109 cx
.const_usize(layout
.size
.bytes()),
110 cx
.const_usize(layout
.align
.abi
.bytes()),
117 let vtable_const
= cx
.const_struct(&components
, false);
118 let align
= cx
.data_layout().pointer_align
.abi
;
119 let vtable
= cx
.static_addr_of(vtable_const
, align
, Some("vtable"));
121 cx
.create_vtable_metadata(ty
, vtable
);
123 cx
.vtables().borrow_mut().insert((ty
, trait_ref
), vtable
);