diff --git a/src/vtable.rs b/src/vtable.rs index bbf07ffc85d..4d1ee47b41e 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -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::>() .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 => {} } }