1
Fork 0

incorporate some review feedback

This commit is contained in:
Ralf Jung 2022-07-19 19:50:04 -04:00
parent 8affef2ccb
commit 5e840c5c8c
6 changed files with 18 additions and 38 deletions

View file

@ -10,6 +10,7 @@ use crate::value::Value;
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh}; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::meth;
use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::traits::*;
@ -364,17 +365,13 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
} }
sym::vtable_size | sym::vtable_align => { sym::vtable_size | sym::vtable_align => {
let ptr = args[0].immediate(); let vtable = args[0].immediate();
let layout = self.layout_of(self.tcx.types.usize); let idx = match name {
let type_ = self.backend_type(layout); sym::vtable_size => ty::COMMON_VTABLE_ENTRIES_SIZE,
let offset = match name { sym::vtable_align => ty::COMMON_VTABLE_ENTRIES_ALIGN,
sym::vtable_size => 1,
sym::vtable_align => 2,
_ => bug!(), _ => bug!(),
}; };
let offset = self.const_int(type_, offset); meth::VirtualIndex::from_index(idx).get_usize(self, vtable)
let vtable_field_ptr = self.inbounds_gep(type_, ptr, &[offset]);
self.load(type_, vtable_field_ptr, layout.align.abi)
} }
_ if name.as_str().starts_with("simd_") => { _ if name.as_str().starts_with("simd_") => {

View file

@ -297,32 +297,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self); Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
self.write_immediate(val, dest) self.write_immediate(val, dest)
} }
(&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { (&ty::Dynamic(ref _data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
let val = self.read_immediate(src)?; let (old_data, old_vptr) = self.read_immediate(src)?.to_scalar_pair()?;
let (old_data, old_vptr) = val.to_scalar_pair()?;
let old_vptr = self.scalar_to_ptr(old_vptr)?; let old_vptr = self.scalar_to_ptr(old_vptr)?;
if data_a.principal_def_id() == data_b.principal_def_id() {
return self.write_immediate(*val, dest);
}
// trait upcasting coercion
let Some(vptr_entry_idx) = self.tcx.vtable_trait_upcasting_coercion_new_vptr_slot((
src_pointee_ty,
dest_pointee_ty,
)) else {
return self.write_immediate(*val, dest);
};
let (ty, _) = self.get_ptr_vtable(old_vptr)?; let (ty, _) = self.get_ptr_vtable(old_vptr)?;
let Some(ty::VtblEntry::TraitVPtr(new_trait)) = self.get_vtable_entries(old_vptr)?.get(vptr_entry_idx) else { let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
throw_ub_format!(
"upcasting to index {vptr_entry_idx} of vtable {old_vptr} but \
that vtable is too small or does not have an upcast-vtable at that index"
)
};
let new_trait = new_trait.map_bound(|trait_ref| {
ty::ExistentialTraitRef::erase_self_ty(*self.tcx, trait_ref)
});
let new_vptr = self.get_vtable_ptr(ty, Some(new_trait))?;
self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest) self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
} }
(_, &ty::Dynamic(ref data, _)) => { (_, &ty::Dynamic(ref data, _)) => {

View file

@ -875,7 +875,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
write!(fmt, " (vtable: impl {trait_ref} for {ty})")?; write!(fmt, " (vtable: impl {trait_ref} for {ty})")?;
} }
Some(GlobalAlloc::Vtable(ty, None)) => { Some(GlobalAlloc::Vtable(ty, None)) => {
write!(fmt, " (vtable: impl ? for {ty})")?; write!(fmt, " (vtable: impl <auto trait> for {ty})")?;
} }
Some(GlobalAlloc::Static(did)) => { Some(GlobalAlloc::Static(did)) => {
write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?; write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?;

View file

@ -10,9 +10,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
/// objects. /// objects.
/// ///
/// The `trait_ref` encodes the erased self type. Hence, if we are /// The `trait_ref` encodes the erased self type. Hence, if we are making an object `Foo<Trait>`
/// making an object `Foo<Trait>` from a value of type `Foo<T>`, then /// from a value of type `Foo<T>`, then `trait_ref` would map `T: Trait`. `None` here means that
/// `trait_ref` would map `T: Trait`. /// this is an auto trait without any methods, so we only need the basic vtable (drop, size,
/// align).
pub fn get_vtable_ptr( pub fn get_vtable_ptr(
&self, &self,
ty: Ty<'tcx>, ty: Ty<'tcx>,

View file

@ -728,7 +728,7 @@ pub fn write_allocations<'tcx>(
Some(GlobalAlloc::Vtable(ty, Some(trait_ref))) => { Some(GlobalAlloc::Vtable(ty, Some(trait_ref))) => {
write!(w, " (vtable: impl {trait_ref} for {ty})")? write!(w, " (vtable: impl {trait_ref} for {ty})")?
} }
Some(GlobalAlloc::Vtable(ty, None)) => write!(w, " (vtable: impl ? for {ty})")?, Some(GlobalAlloc::Vtable(ty, None)) => write!(w, " (vtable: impl <auto trait> for {ty})")?,
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => { Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
match tcx.eval_static_initializer(did) { match tcx.eval_static_initializer(did) {
Ok(alloc) => { Ok(alloc) => {

View file

@ -204,6 +204,9 @@ impl<Dyn: ?Sized> DynMetadata<Dyn> {
/// Returns the size of the type associated with this vtable. /// Returns the size of the type associated with this vtable.
#[inline] #[inline]
pub fn size_of(self) -> usize { pub fn size_of(self) -> usize {
// Note that "size stored in vtable" is *not* the same as "result of size_of_val_raw".
// Consider a reference like `&(i32, dyn Send)`: the vtable will only store the size of the
// `Send` part!
#[cfg(bootstrap)] #[cfg(bootstrap)]
return self.vtable_ptr.size_of; return self.vtable_ptr.size_of;
#[cfg(not(bootstrap))] #[cfg(not(bootstrap))]