mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-18 03:25:55 +00:00
Auto merge of #86291 - crlf0710:trait_vtbl_refactor, r=bjorn3
Refactor vtable codegen This refactor the codegen of vtables of miri interpreter, llvm, cranelift codegen backends. This is preparation for the implementation of trait upcasting feature. cc #65991 Note that aside from code reorganization, there's an internal behavior change here that now InstanceDef::Virtual's index now include the three metadata slots, and now the first method is with index 3. cc `@RalfJung` `@bjorn3`
This commit is contained in:
commit
9be7ca00f1
@ -4,10 +4,7 @@
|
||||
// FIXME dedup this logic between miri, cg_llvm and cg_clif
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
const DROP_FN_INDEX: usize = 0;
|
||||
const SIZE_INDEX: usize = 1;
|
||||
const ALIGN_INDEX: usize = 2;
|
||||
use ty::VtblEntry;
|
||||
|
||||
fn vtable_memflags() -> MemFlags {
|
||||
let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap.
|
||||
@ -21,7 +18,7 @@ pub(crate) fn drop_fn_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) ->
|
||||
pointer_ty(fx.tcx),
|
||||
vtable_memflags(),
|
||||
vtable,
|
||||
(DROP_FN_INDEX * usize_size) as i32,
|
||||
(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE * usize_size) as i32,
|
||||
)
|
||||
}
|
||||
|
||||
@ -31,7 +28,7 @@ pub(crate) fn size_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -> Val
|
||||
pointer_ty(fx.tcx),
|
||||
vtable_memflags(),
|
||||
vtable,
|
||||
(SIZE_INDEX * usize_size) as i32,
|
||||
(ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32,
|
||||
)
|
||||
}
|
||||
|
||||
@ -41,7 +38,7 @@ pub(crate) fn min_align_of_obj(fx: &mut FunctionCx<'_, '_, '_>, vtable: Value) -
|
||||
pointer_ty(fx.tcx),
|
||||
vtable_memflags(),
|
||||
vtable,
|
||||
(ALIGN_INDEX * usize_size) as i32,
|
||||
(ty::COMMON_VTABLE_ENTRIES_SIZE * usize_size) as i32,
|
||||
)
|
||||
}
|
||||
|
||||
@ -62,7 +59,7 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
|
||||
pointer_ty(fx.tcx),
|
||||
vtable_memflags(),
|
||||
vtable,
|
||||
((idx + 3) * usize_size as usize) as i32,
|
||||
(idx * usize_size as usize) as i32,
|
||||
);
|
||||
(ptr, func_ref)
|
||||
}
|
||||
@ -98,42 +95,49 @@ fn build_vtable<'tcx>(
|
||||
Instance::resolve_drop_in_place(tcx, layout.ty).polymorphize(fx.tcx),
|
||||
);
|
||||
|
||||
let mut components: Vec<_> = vec![Some(drop_in_place_fn), None, None];
|
||||
|
||||
let methods_root;
|
||||
let methods = if let Some(trait_ref) = trait_ref {
|
||||
methods_root = tcx.vtable_methods(trait_ref.with_self_ty(tcx, layout.ty));
|
||||
methods_root.iter()
|
||||
let vtable_entries = if let Some(trait_ref) = trait_ref {
|
||||
tcx.vtable_entries(trait_ref.with_self_ty(tcx, layout.ty))
|
||||
} else {
|
||||
(&[]).iter()
|
||||
ty::COMMON_VTABLE_ENTRIES
|
||||
};
|
||||
let methods = methods.cloned().map(|opt_mth| {
|
||||
opt_mth.map(|(def_id, substs)| {
|
||||
import_function(
|
||||
tcx,
|
||||
fx.module,
|
||||
Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), def_id, substs)
|
||||
.unwrap()
|
||||
.polymorphize(fx.tcx),
|
||||
)
|
||||
})
|
||||
});
|
||||
components.extend(methods);
|
||||
|
||||
let mut data_ctx = DataContext::new();
|
||||
let mut data = ::std::iter::repeat(0u8)
|
||||
.take(components.len() * usize_size)
|
||||
.take(vtable_entries.len() * usize_size)
|
||||
.collect::<Vec<u8>>()
|
||||
.into_boxed_slice();
|
||||
|
||||
write_usize(fx.tcx, &mut data, SIZE_INDEX, layout.size.bytes());
|
||||
write_usize(fx.tcx, &mut data, ALIGN_INDEX, layout.align.abi.bytes());
|
||||
for (idx, entry) in vtable_entries.iter().enumerate() {
|
||||
match entry {
|
||||
VtblEntry::MetadataSize => {
|
||||
write_usize(fx.tcx, &mut data, idx, layout.size.bytes());
|
||||
}
|
||||
VtblEntry::MetadataAlign => {
|
||||
write_usize(fx.tcx, &mut data, idx, layout.align.abi.bytes());
|
||||
}
|
||||
VtblEntry::MetadataDropInPlace | VtblEntry::Vacant | VtblEntry::Method(_, _) => {}
|
||||
}
|
||||
}
|
||||
data_ctx.define(data);
|
||||
|
||||
for (i, component) in components.into_iter().enumerate() {
|
||||
if let Some(func_id) = component {
|
||||
let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
|
||||
data_ctx.write_function_addr((i * usize_size) as u32, func_ref);
|
||||
for (idx, entry) in vtable_entries.iter().enumerate() {
|
||||
match entry {
|
||||
VtblEntry::MetadataDropInPlace => {
|
||||
let func_ref = fx.module.declare_func_in_data(drop_in_place_fn, &mut data_ctx);
|
||||
data_ctx.write_function_addr((idx * usize_size) as u32, func_ref);
|
||||
}
|
||||
VtblEntry::Method(def_id, substs) => {
|
||||
let func_id = import_function(
|
||||
tcx,
|
||||
fx.module,
|
||||
Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), *def_id, substs)
|
||||
.unwrap()
|
||||
.polymorphize(fx.tcx),
|
||||
);
|
||||
let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
|
||||
data_ctx.write_function_addr((idx * usize_size) as u32, func_ref);
|
||||
}
|
||||
VtblEntry::MetadataSize | VtblEntry::MetadataAlign | VtblEntry::Vacant => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user