From 966e54ee2ed1a329ae0e1fe28e9a7bcc75d96ab5 Mon Sep 17 00:00:00 2001 From: Jade <software@lfcode.ca> Date: Tue, 27 Jul 2021 16:38:13 -0700 Subject: [PATCH 1/2] rfc3052: Remove authors field from Cargo manifests Since RFC 3052 soft deprecated the authors field anyway, hiding it from crates.io, docs.rs, and making Cargo not add it by default, and it is not generally up to date/useful information, we should remove it from crates in this repo. --- Cargo.toml | 1 - build_sysroot/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef68d7ee532..6593ac738fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [package] name = "rustc_codegen_cranelift" version = "0.1.0" -authors = ["bjorn3 <bjorn3@users.noreply.github.com>"] edition = "2018" [lib] diff --git a/build_sysroot/Cargo.toml b/build_sysroot/Cargo.toml index 04748d5dbab..f25d87e60c0 100644 --- a/build_sysroot/Cargo.toml +++ b/build_sysroot/Cargo.toml @@ -1,5 +1,4 @@ [package] -authors = ["bjorn3 <bjorn3@users.noreply.github.com>"] name = "sysroot" version = "0.0.0" From 6f682236c96f7f304ffda201ef80824765a50bd8 Mon Sep 17 00:00:00 2001 From: Charles Lew <crlf0710@gmail.com> Date: Sat, 31 Jul 2021 22:46:23 +0800 Subject: [PATCH 2/2] Implement pointer casting. --- src/unsize.rs | 63 +++++++++++++++++++++++++++++++++++++++------------ src/vtable.rs | 2 +- 2 files changed, 49 insertions(+), 16 deletions(-) diff --git a/src/unsize.rs b/src/unsize.rs index b9d379c6117..d594731b4df 100644 --- a/src/unsize.rs +++ b/src/unsize.rs @@ -25,39 +25,73 @@ pub(crate) fn unsized_info<'tcx>( .bcx .ins() .iconst(fx.pointer_type, len.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64), - (&ty::Dynamic(..), &ty::Dynamic(..)) => { - // For now, upcasts are limited to changes in marker - // traits, and hence never actually require an actual - // change to the vtable. - old_info.expect("unsized_info: missing old info for trait upcast") + (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => { + let old_info = + old_info.expect("unsized_info: missing old info for trait upcasting coercion"); + if data_a.principal_def_id() == data_b.principal_def_id() { + return old_info; + } + // trait upcasting coercion + + // if both of the two `principal`s are `None`, this function would have returned early above. + // and if one of the two `principal`s is `None`, typechecking would have rejected this case. + let principal_a = data_a + .principal() + .expect("unsized_info: missing principal trait for trait upcasting coercion"); + let principal_b = data_b + .principal() + .expect("unsized_info: missing principal trait for trait upcasting coercion"); + + let vptr_entry_idx = fx.tcx.vtable_trait_upcasting_coercion_new_vptr_slot(( + principal_a.with_self_ty(fx.tcx, source), + principal_b.with_self_ty(fx.tcx, source), + )); + + if let Some(entry_idx) = vptr_entry_idx { + let entry_idx = u32::try_from(entry_idx).unwrap(); + let entry_offset = entry_idx * fx.pointer_type.bytes(); + let vptr_ptr = Pointer::new(old_info).offset_i64(fx, entry_offset.into()).load( + fx, + fx.pointer_type, + crate::vtable::vtable_memflags(), + ); + vptr_ptr + } else { + old_info + } } (_, &ty::Dynamic(ref data, ..)) => crate::vtable::get_vtable(fx, source, data.principal()), _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", source, target), } } -/// Coerce `src` to `dst_ty`. `src_ty` must be a thin pointer. -fn unsize_thin_ptr<'tcx>( +/// Coerce `src` to `dst_ty`. +fn unsize_ptr<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, src: Value, src_layout: TyAndLayout<'tcx>, dst_layout: TyAndLayout<'tcx>, + old_info: Option<Value>, ) -> (Value, Value) { match (&src_layout.ty.kind(), &dst_layout.ty.kind()) { (&ty::Ref(_, a, _), &ty::Ref(_, b, _)) | (&ty::Ref(_, a, _), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) | (&ty::RawPtr(ty::TypeAndMut { ty: a, .. }), &ty::RawPtr(ty::TypeAndMut { ty: b, .. })) => { assert!(!fx.layout_of(a).is_unsized()); - (src, unsized_info(fx, a, b, None)) + (src, unsized_info(fx, a, b, old_info)) } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { let (a, b) = (src_layout.ty.boxed_ty(), dst_layout.ty.boxed_ty()); assert!(!fx.layout_of(a).is_unsized()); - (src, unsized_info(fx, a, b, None)) + (src, unsized_info(fx, a, b, old_info)) } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); + if src_layout == dst_layout { + return (src, old_info.unwrap()); + } + let mut result = None; for i in 0..src_layout.fields.count() { let src_f = src_layout.field(fx, i); @@ -71,11 +105,11 @@ fn unsize_thin_ptr<'tcx>( let dst_f = dst_layout.field(fx, i); assert_ne!(src_f.ty, dst_f.ty); assert_eq!(result, None); - result = Some(unsize_thin_ptr(fx, src, src_f, dst_f)); + result = Some(unsize_ptr(fx, src, src_f, dst_f, old_info)); } result.unwrap() } - _ => bug!("unsize_thin_ptr: called on bad types"), + _ => bug!("unsize_ptr: called on bad types"), } } @@ -91,12 +125,11 @@ pub(crate) fn coerce_unsized_into<'tcx>( let mut coerce_ptr = || { let (base, info) = if fx.layout_of(src.layout().ty.builtin_deref(true).unwrap().ty).is_unsized() { - // fat-ptr to fat-ptr unsize preserves the vtable - // i.e., &'a fmt::Debug+Send => &'a fmt::Debug - src.load_scalar_pair(fx) + let (old_base, old_info) = src.load_scalar_pair(fx); + unsize_ptr(fx, old_base, src.layout(), dst.layout(), Some(old_info)) } else { let base = src.load_scalar(fx); - unsize_thin_ptr(fx, base, src.layout(), dst.layout()) + unsize_ptr(fx, base, src.layout(), dst.layout(), None) }; dst.write_cvalue(fx, CValue::by_val_pair(base, info, dst.layout())); }; diff --git a/src/vtable.rs b/src/vtable.rs index 4a5f9f133a2..1b315874308 100644 --- a/src/vtable.rs +++ b/src/vtable.rs @@ -5,7 +5,7 @@ use crate::constant::data_id_for_alloc_id; use crate::prelude::*; -fn vtable_memflags() -> MemFlags { +pub(crate) fn vtable_memflags() -> MemFlags { let mut flags = MemFlags::trusted(); // A vtable access is always aligned and will never trap. flags.set_readonly(); // A vtable is always read-only. flags