about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-06-16 07:20:27 +0000
committerbors <bors@rust-lang.org>2021-06-16 07:20:27 +0000
commit9be7ca00f1ca2425e97da90d65575ac48aa7803c (patch)
treee0e5c1be21ba111197aac1350865940573693a04 /src
parent8923e42a05b59022ffcc163d9e9b13c9de1189c9 (diff)
parentd3e123fc4f8c2907db8a88e851ecb5149fa7670f (diff)
downloadrust-9be7ca00f1ca2425e97da90d65575ac48aa7803c.tar.gz
rust-9be7ca00f1ca2425e97da90d65575ac48aa7803c.zip
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`
Diffstat (limited to 'src')
-rw-r--r--src/vtable.rs72
1 files changed, 38 insertions, 34 deletions
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::<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 => {}
         }
     }