Skip to content

Commit e98897e

Browse files
committed
Auto merge of rust-lang#86475 - crlf0710:miri_vtable_refactor, r=bjorn3
Change vtable memory representation to use tcx allocated allocations. This fixes rust-lang#86324. However i suspect there's more to change before it can land. r? `@bjorn3` cc `@rust-lang/miri`
2 parents 8971fff + 97772bb commit e98897e

File tree

21 files changed

+150
-249
lines changed

21 files changed

+150
-249
lines changed

compiler/rustc_codegen_cranelift/src/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
233233
pub(crate) module: &'m mut dyn Module,
234234
pub(crate) tcx: TyCtxt<'tcx>,
235235
pub(crate) pointer_type: Type, // Cached from module
236-
pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
236+
pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Pointer>,
237237
pub(crate) constants_cx: ConstantCx,
238238

239239
pub(crate) instance: Instance<'tcx>,

compiler/rustc_codegen_cranelift/src/constant.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ pub(crate) fn codegen_const_value<'tcx>(
249249
}
250250
}
251251

252-
fn pointer_for_allocation<'tcx>(
252+
pub(crate) fn pointer_for_allocation<'tcx>(
253253
fx: &mut FunctionCx<'_, '_, 'tcx>,
254254
alloc: &'tcx Allocation,
255255
) -> crate::pointer::Pointer {

compiler/rustc_codegen_cranelift/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ mod prelude {
9898
pub(crate) use cranelift_codegen::isa::{self, CallConv};
9999
pub(crate) use cranelift_codegen::Context;
100100
pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
101-
pub(crate) use cranelift_module::{self, DataContext, DataId, FuncId, Linkage, Module};
101+
pub(crate) use cranelift_module::{self, DataContext, FuncId, Linkage, Module};
102102

103103
pub(crate) use crate::abi::*;
104104
pub(crate) use crate::base::{codegen_operand, codegen_place};

compiler/rustc_codegen_cranelift/src/unsize.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,7 @@ pub(crate) fn unsized_info<'tcx>(
3131
// change to the vtable.
3232
old_info.expect("unsized_info: missing old info for trait upcast")
3333
}
34-
(_, &ty::Dynamic(ref data, ..)) => {
35-
crate::vtable::get_vtable(fx, fx.layout_of(source), data.principal())
36-
}
34+
(_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()),
3735
_ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target),
3836
}
3937
}

compiler/rustc_codegen_cranelift/src/vtable.rs

+10-96
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// FIXME dedup this logic between miri, cg_llvm and cg_clif
55

66
use crate::prelude::*;
7-
use ty::VtblEntry;
7+
use super::constant::pointer_for_allocation;
88

99
fn vtable_memflags() -> MemFlags {
1010
let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap.
@@ -66,105 +66,19 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
6666

6767
pub(crate) fn get_vtable<'tcx>(
6868
fx: &mut FunctionCx<'_, '_, 'tcx>,
69-
layout: TyAndLayout<'tcx>,
69+
ty: Ty<'tcx>,
7070
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
7171
) -> Value {
72-
let data_id = if let Some(data_id) = fx.vtables.get(&(layout.ty, trait_ref)) {
73-
*data_id
72+
let vtable_ptr = if let Some(vtable_ptr) = fx.vtables.get(&(ty, trait_ref)) {
73+
*vtable_ptr
7474
} else {
75-
let data_id = build_vtable(fx, layout, trait_ref);
76-
fx.vtables.insert((layout.ty, trait_ref), data_id);
77-
data_id
78-
};
79-
80-
let local_data_id = fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
81-
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
82-
}
83-
84-
fn build_vtable<'tcx>(
85-
fx: &mut FunctionCx<'_, '_, 'tcx>,
86-
layout: TyAndLayout<'tcx>,
87-
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
88-
) -> DataId {
89-
let tcx = fx.tcx;
90-
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes() as usize;
75+
let vtable_alloc_id = fx.tcx.vtable_allocation(ty, trait_ref);
76+
let vtable_allocation = fx.tcx.global_alloc(vtable_alloc_id).unwrap_memory();
77+
let vtable_ptr = pointer_for_allocation(fx, vtable_allocation);
9178

92-
let drop_in_place_fn = import_function(
93-
tcx,
94-
fx.module,
95-
Instance::resolve_drop_in_place(tcx, layout.ty).polymorphize(fx.tcx),
96-
);
97-
98-
let vtable_entries = if let Some(trait_ref) = trait_ref {
99-
tcx.vtable_entries(trait_ref.with_self_ty(tcx, layout.ty))
100-
} else {
101-
ty::COMMON_VTABLE_ENTRIES
79+
fx.vtables.insert((ty, trait_ref), vtable_ptr);
80+
vtable_ptr
10281
};
10382

104-
let mut data_ctx = DataContext::new();
105-
let mut data = ::std::iter::repeat(0u8)
106-
.take(vtable_entries.len() * usize_size)
107-
.collect::<Vec<u8>>()
108-
.into_boxed_slice();
109-
110-
for (idx, entry) in vtable_entries.iter().enumerate() {
111-
match entry {
112-
VtblEntry::MetadataSize => {
113-
write_usize(fx.tcx, &mut data, idx, layout.size.bytes());
114-
}
115-
VtblEntry::MetadataAlign => {
116-
write_usize(fx.tcx, &mut data, idx, layout.align.abi.bytes());
117-
}
118-
VtblEntry::MetadataDropInPlace | VtblEntry::Vacant | VtblEntry::Method(_, _) => {}
119-
}
120-
}
121-
data_ctx.define(data);
122-
123-
for (idx, entry) in vtable_entries.iter().enumerate() {
124-
match entry {
125-
VtblEntry::MetadataDropInPlace => {
126-
let func_ref = fx.module.declare_func_in_data(drop_in_place_fn, &mut data_ctx);
127-
data_ctx.write_function_addr((idx * usize_size) as u32, func_ref);
128-
}
129-
VtblEntry::Method(def_id, substs) => {
130-
let func_id = import_function(
131-
tcx,
132-
fx.module,
133-
Instance::resolve_for_vtable(tcx, ParamEnv::reveal_all(), *def_id, substs)
134-
.unwrap()
135-
.polymorphize(fx.tcx),
136-
);
137-
let func_ref = fx.module.declare_func_in_data(func_id, &mut data_ctx);
138-
data_ctx.write_function_addr((idx * usize_size) as u32, func_ref);
139-
}
140-
VtblEntry::MetadataSize | VtblEntry::MetadataAlign | VtblEntry::Vacant => {}
141-
}
142-
}
143-
144-
data_ctx.set_align(fx.tcx.data_layout.pointer_align.pref.bytes());
145-
146-
let data_id = fx.module.declare_anonymous_data(false, false).unwrap();
147-
148-
fx.module.define_data(data_id, &data_ctx).unwrap();
149-
150-
data_id
151-
}
152-
153-
fn write_usize(tcx: TyCtxt<'_>, buf: &mut [u8], idx: usize, num: u64) {
154-
let pointer_size =
155-
tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.usize)).unwrap().size.bytes() as usize;
156-
let target = &mut buf[idx * pointer_size..(idx + 1) * pointer_size];
157-
158-
match tcx.data_layout.endian {
159-
rustc_target::abi::Endian::Little => match pointer_size {
160-
4 => target.copy_from_slice(&(num as u32).to_le_bytes()),
161-
8 => target.copy_from_slice(&(num as u64).to_le_bytes()),
162-
_ => todo!("pointer size {} is not yet supported", pointer_size),
163-
},
164-
rustc_target::abi::Endian::Big => match pointer_size {
165-
4 => target.copy_from_slice(&(num as u32).to_be_bytes()),
166-
8 => target.copy_from_slice(&(num as u64).to_be_bytes()),
167-
_ => todo!("pointer size {} is not yet supported", pointer_size),
168-
},
169-
}
83+
vtable_ptr.get_addr(fx)
17084
}

compiler/rustc_codegen_llvm/src/common.rs

+4
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
282282
}
283283
}
284284

285+
fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value {
286+
const_alloc_to_llvm(self, alloc)
287+
}
288+
285289
fn from_const_alloc(
286290
&self,
287291
layout: TyAndLayout<'tcx>,

compiler/rustc_codegen_ssa/src/meth.rs

+4-39
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::traits::*;
22

3-
use rustc_middle::ty::{self, Instance, Ty, VtblEntry, COMMON_VTABLE_ENTRIES};
3+
use rustc_middle::ty::{self, Ty};
44
use rustc_target::abi::call::FnAbi;
55

66
#[derive(Copy, Clone, Debug)]
@@ -70,48 +70,13 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
7070
return val;
7171
}
7272

73-
// Not in the cache; build it.
74-
let nullptr = cx.const_null(cx.type_i8p_ext(cx.data_layout().instruction_address_space));
75-
76-
let vtable_entries = if let Some(trait_ref) = trait_ref {
77-
tcx.vtable_entries(trait_ref.with_self_ty(tcx, ty))
78-
} else {
79-
COMMON_VTABLE_ENTRIES
80-
};
81-
82-
let layout = cx.layout_of(ty);
83-
// /////////////////////////////////////////////////////////////////////////////////////////////
84-
// If you touch this code, be sure to also make the corresponding changes to
85-
// `get_vtable` in `rust_mir/interpret/traits.rs`.
86-
// /////////////////////////////////////////////////////////////////////////////////////////////
87-
let components: Vec<_> = vtable_entries
88-
.iter()
89-
.map(|entry| match entry {
90-
VtblEntry::MetadataDropInPlace => {
91-
cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty))
92-
}
93-
VtblEntry::MetadataSize => cx.const_usize(layout.size.bytes()),
94-
VtblEntry::MetadataAlign => cx.const_usize(layout.align.abi.bytes()),
95-
VtblEntry::Vacant => nullptr,
96-
VtblEntry::Method(def_id, substs) => cx.get_fn_addr(
97-
ty::Instance::resolve_for_vtable(
98-
cx.tcx(),
99-
ty::ParamEnv::reveal_all(),
100-
*def_id,
101-
substs,
102-
)
103-
.unwrap()
104-
.polymorphize(cx.tcx()),
105-
),
106-
})
107-
.collect();
108-
109-
let vtable_const = cx.const_struct(&components, false);
73+
let vtable_alloc_id = tcx.vtable_allocation(ty, trait_ref);
74+
let vtable_allocation = tcx.global_alloc(vtable_alloc_id).unwrap_memory();
75+
let vtable_const = cx.const_data_from_alloc(vtable_allocation);
11076
let align = cx.data_layout().pointer_align.abi;
11177
let vtable = cx.static_addr_of(vtable_const, align, Some("vtable"));
11278

11379
cx.create_vtable_metadata(ty, vtable);
114-
11580
cx.vtables().borrow_mut().insert((ty, trait_ref), vtable);
11681
vtable
11782
}

compiler/rustc_codegen_ssa/src/traits/consts.rs

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ pub trait ConstMethods<'tcx>: BackendTypes {
2626
fn const_to_opt_uint(&self, v: Self::Value) -> Option<u64>;
2727
fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option<u128>;
2828

29+
fn const_data_from_alloc(&self, alloc: &Allocation) -> Self::Value;
30+
2931
fn scalar_to_backend(&self, cv: Scalar, layout: &abi::Scalar, llty: Self::Type) -> Self::Value;
3032
fn from_const_alloc(
3133
&self,

compiler/rustc_middle/src/ty/context.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::middle;
1111
use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata};
1212
use crate::middle::resolve_lifetime::{self, LifetimeScopeForPath, ObjectLifetimeDefault};
1313
use crate::middle::stability;
14-
use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
14+
use crate::mir::interpret::{self, AllocId, Allocation, ConstValue, Scalar};
1515
use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted};
1616
use crate::thir::Thir;
1717
use crate::traits;
@@ -1044,6 +1044,9 @@ pub struct GlobalCtxt<'tcx> {
10441044
output_filenames: Arc<OutputFilenames>,
10451045

10461046
pub main_def: Option<MainDefinition>,
1047+
1048+
pub(super) vtables_cache:
1049+
Lock<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), AllocId>>,
10471050
}
10481051

10491052
impl<'tcx> TyCtxt<'tcx> {
@@ -1201,6 +1204,7 @@ impl<'tcx> TyCtxt<'tcx> {
12011204
alloc_map: Lock::new(interpret::AllocMap::new()),
12021205
output_filenames: Arc::new(output_filenames),
12031206
main_def: resolutions.main_def,
1207+
vtables_cache: Default::default(),
12041208
}
12051209
}
12061210

compiler/rustc_middle/src/ty/mod.rs

+2-16
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub use adt::*;
1818
pub use assoc::*;
1919
pub use closure::*;
2020
pub use generics::*;
21+
pub use vtable::*;
2122

2223
use crate::hir::exports::ExportMap;
2324
use crate::ich::StableHashingContext;
@@ -94,6 +95,7 @@ pub mod relate;
9495
pub mod subst;
9596
pub mod trait_def;
9697
pub mod util;
98+
pub mod vtable;
9799
pub mod walk;
98100

99101
mod adt;
@@ -2009,19 +2011,3 @@ impl<'tcx> fmt::Debug for SymbolName<'tcx> {
20092011
fmt::Display::fmt(&self.name, fmt)
20102012
}
20112013
}
2012-
2013-
#[derive(Clone, Copy, Debug, PartialEq, HashStable)]
2014-
pub enum VtblEntry<'tcx> {
2015-
MetadataDropInPlace,
2016-
MetadataSize,
2017-
MetadataAlign,
2018-
Vacant,
2019-
Method(DefId, SubstsRef<'tcx>),
2020-
}
2021-
2022-
pub const COMMON_VTABLE_ENTRIES: &[VtblEntry<'_>] =
2023-
&[VtblEntry::MetadataDropInPlace, VtblEntry::MetadataSize, VtblEntry::MetadataAlign];
2024-
2025-
pub const COMMON_VTABLE_ENTRIES_DROPINPLACE: usize = 0;
2026-
pub const COMMON_VTABLE_ENTRIES_SIZE: usize = 1;
2027-
pub const COMMON_VTABLE_ENTRIES_ALIGN: usize = 2;

0 commit comments

Comments
 (0)