Skip to content

Commit 4d289db

Browse files
committed
Update other codegens to use tcx managed vtable allocations.
1 parent e475efb commit 4d289db

File tree

5 files changed

+14
-102
lines changed

5 files changed

+14
-102
lines changed

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>,

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 {

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};

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
}

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
}

0 commit comments

Comments
 (0)