2019-02-09 08:31:47 -06:00
|
|
|
use crate::traits::*;
|
2018-08-07 10:14:40 -05:00
|
|
|
|
2021-06-20 04:43:25 -05:00
|
|
|
use rustc_middle::ty::{self, Ty};
|
2019-05-16 20:20:14 -05:00
|
|
|
use rustc_target::abi::call::FnAbi;
|
2012-08-28 17:54:45 -05:00
|
|
|
|
2017-03-13 18:08:21 -05:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
2017-06-25 04:41:24 -05:00
|
|
|
pub struct VirtualIndex(u64);
|
2017-03-13 18:08:21 -05:00
|
|
|
|
2019-06-14 11:39:39 -05:00
|
|
|
impl<'a, 'tcx> VirtualIndex {
|
2017-03-13 18:08:21 -05:00
|
|
|
pub fn from_index(index: usize) -> Self {
|
2021-06-14 05:02:53 -05:00
|
|
|
VirtualIndex(index as u64)
|
2017-03-13 18:08:21 -05:00
|
|
|
}
|
|
|
|
|
2018-09-20 08:47:22 -05:00
|
|
|
pub fn get_fn<Bx: BuilderMethods<'a, 'tcx>>(
|
|
|
|
self,
|
2018-10-05 08:08:49 -05:00
|
|
|
bx: &mut Bx,
|
2018-09-20 08:47:22 -05:00
|
|
|
llvtable: Bx::Value,
|
2019-05-16 20:20:14 -05:00
|
|
|
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
2018-09-20 08:47:22 -05:00
|
|
|
) -> Bx::Value {
|
2017-03-13 18:08:21 -05:00
|
|
|
// Load the data pointer from the object.
|
2018-07-10 05:28:39 -05:00
|
|
|
debug!("get_fn({:?}, {:?})", llvtable, self);
|
2017-03-13 18:08:21 -05:00
|
|
|
|
2021-07-04 11:53:04 -05:00
|
|
|
let llty = bx.fn_ptr_backend_type(fn_abi);
|
|
|
|
let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
|
2018-09-08 17:16:45 -05:00
|
|
|
let ptr_align = bx.tcx().data_layout.pointer_align.abi;
|
2021-07-31 19:00:00 -05:00
|
|
|
let gep = bx.inbounds_gep(llty, llvtable, &[bx.const_usize(self.0)]);
|
2021-07-04 11:53:04 -05:00
|
|
|
let ptr = bx.load(llty, gep, ptr_align);
|
2018-01-04 23:12:32 -06:00
|
|
|
bx.nonnull_metadata(ptr);
|
2019-05-16 20:20:14 -05:00
|
|
|
// Vtable loads are invariant.
|
2018-01-04 23:12:32 -06:00
|
|
|
bx.set_invariant_load(ptr);
|
2017-03-13 18:08:21 -05:00
|
|
|
ptr
|
|
|
|
}
|
|
|
|
|
2018-09-14 10:48:57 -05:00
|
|
|
pub fn get_usize<Bx: BuilderMethods<'a, 'tcx>>(
|
2018-08-07 10:14:40 -05:00
|
|
|
self,
|
2018-10-05 08:08:49 -05:00
|
|
|
bx: &mut Bx,
|
2019-05-16 20:20:14 -05:00
|
|
|
llvtable: Bx::Value,
|
2018-09-14 10:48:57 -05:00
|
|
|
) -> Bx::Value {
|
2017-03-13 18:08:21 -05:00
|
|
|
// Load the data pointer from the object.
|
2018-07-10 05:28:39 -05:00
|
|
|
debug!("get_int({:?}, {:?})", llvtable, self);
|
2017-03-13 18:08:21 -05:00
|
|
|
|
2021-07-04 11:53:04 -05:00
|
|
|
let llty = bx.type_isize();
|
|
|
|
let llvtable = bx.pointercast(llvtable, bx.type_ptr_to(llty));
|
2018-09-08 17:16:45 -05:00
|
|
|
let usize_align = bx.tcx().data_layout.pointer_align.abi;
|
2021-07-31 19:00:00 -05:00
|
|
|
let gep = bx.inbounds_gep(llty, llvtable, &[bx.const_usize(self.0)]);
|
2021-07-04 11:53:04 -05:00
|
|
|
let ptr = bx.load(llty, gep, usize_align);
|
2019-05-16 20:20:14 -05:00
|
|
|
// Vtable loads are invariant.
|
2018-01-04 23:12:32 -06:00
|
|
|
bx.set_invariant_load(ptr);
|
2017-03-13 18:08:21 -05:00
|
|
|
ptr
|
|
|
|
}
|
2012-01-07 15:44:14 -06:00
|
|
|
}
|
|
|
|
|
2016-09-08 05:58:05 -05:00
|
|
|
/// Creates a dynamic vtable for the given type and vtable origin.
|
2013-05-15 19:38:52 -05:00
|
|
|
/// This is used only for objects.
|
2014-09-12 10:42:58 -05:00
|
|
|
///
|
2016-09-08 05:58:05 -05:00
|
|
|
/// The vtables are cached instead of created on every call.
|
|
|
|
///
|
2014-09-12 10:42:58 -05:00
|
|
|
/// The `trait_ref` encodes the erased self type. Hence if we are
|
2018-11-20 08:34:15 -06:00
|
|
|
/// making an object `Foo<dyn Trait>` from a value of type `Foo<T>`, then
|
2019-05-16 20:20:14 -05:00
|
|
|
/// `trait_ref` would map `T: Trait`.
|
2018-09-13 07:58:19 -05:00
|
|
|
pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
|
|
|
|
cx: &Cx,
|
2018-07-10 05:28:39 -05:00
|
|
|
ty: Ty<'tcx>,
|
2018-12-04 05:28:06 -06:00
|
|
|
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
2018-09-13 07:58:19 -05:00
|
|
|
) -> Cx::Value {
|
|
|
|
let tcx = cx.tcx();
|
2013-08-13 15:22:58 -05:00
|
|
|
|
2016-11-16 10:21:49 -06:00
|
|
|
debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref);
|
2015-01-29 06:03:34 -06:00
|
|
|
|
2013-08-13 15:22:58 -05:00
|
|
|
// Check the cache.
|
2018-09-13 07:58:19 -05:00
|
|
|
if let Some(&val) = cx.vtables().borrow().get(&(ty, trait_ref)) {
|
2016-10-17 21:00:20 -05:00
|
|
|
return val;
|
2013-08-13 15:22:58 -05:00
|
|
|
}
|
|
|
|
|
2021-10-07 04:29:01 -05:00
|
|
|
let vtable_alloc_id = tcx.vtable_allocation((ty, trait_ref));
|
2021-06-20 04:43:25 -05:00
|
|
|
let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
|
|
|
|
let vtable_const = cx.const_data_from_alloc(vtable_allocation);
|
2018-09-08 17:16:45 -05:00
|
|
|
let align = cx.data_layout().pointer_align.abi;
|
2018-09-10 09:28:47 -05:00
|
|
|
let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
|
2013-12-18 19:00:56 -06:00
|
|
|
|
2021-10-06 07:26:50 -05:00
|
|
|
cx.create_vtable_metadata(ty, trait_ref, vtable);
|
2018-09-13 07:58:19 -05:00
|
|
|
cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
|
2014-04-10 06:04:45 -05:00
|
|
|
vtable
|
2012-01-12 09:57:30 -06:00
|
|
|
}
|