incorporate some review feedback
This commit is contained in:
parent
8affef2ccb
commit
5e840c5c8c
6 changed files with 18 additions and 38 deletions
|
@ -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_") => {
|
||||||
|
|
|
@ -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, _)) => {
|
||||||
|
|
|
@ -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))?;
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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))]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue