restrict the valid range of references if -Z reference-niches
is set
Note that this doesn't actually work at all, as many places in rustc assume that references only have the null niche.
This commit is contained in:
parent
8b847ef734
commit
3c05276866
2 changed files with 64 additions and 11 deletions
|
@ -354,6 +354,31 @@ impl TargetDataLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the theoretical maximum address.
|
||||||
|
///
|
||||||
|
/// Note that this doesn't take into account target-specific limitations.
|
||||||
|
#[inline]
|
||||||
|
pub fn max_address(&self) -> u64 {
|
||||||
|
match self.pointer_size.bits() {
|
||||||
|
16 => u16::MAX.into(),
|
||||||
|
32 => u32::MAX.into(),
|
||||||
|
64 => u64::MAX,
|
||||||
|
bits => panic!("max_address: unknown pointer bit size {}", bits),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the (inclusive) range of possible addresses for an allocation with
|
||||||
|
/// the given size and alignment.
|
||||||
|
///
|
||||||
|
/// Note that this doesn't take into account target-specific limitations.
|
||||||
|
#[inline]
|
||||||
|
pub fn address_range_for(&self, size: Size, align: Align) -> (u64, u64) {
|
||||||
|
let end = Size::from_bytes(self.max_address());
|
||||||
|
let min = align.bytes();
|
||||||
|
let max = (end - size).align_down_to(align).bytes();
|
||||||
|
(min, max)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
|
pub fn vector_align(&self, vec_size: Size) -> AbiAndPrefAlign {
|
||||||
for &(size, align) in &self.vector_align {
|
for &(size, align) in &self.vector_align {
|
||||||
|
@ -481,6 +506,12 @@ impl Size {
|
||||||
Size::from_bytes((self.bytes() + mask) & !mask)
|
Size::from_bytes((self.bytes() + mask) & !mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn align_down_to(self, align: Align) -> Size {
|
||||||
|
let mask = align.bytes() - 1;
|
||||||
|
Size::from_bytes(self.bytes() & !mask)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_aligned(self, align: Align) -> bool {
|
pub fn is_aligned(self, align: Align) -> bool {
|
||||||
let mask = align.bytes() - 1;
|
let mask = align.bytes() - 1;
|
||||||
|
|
|
@ -30,11 +30,13 @@ pub fn provide(providers: &mut Providers) {
|
||||||
|
|
||||||
#[instrument(skip(tcx), level = "debug")]
|
#[instrument(skip(tcx), level = "debug")]
|
||||||
fn reference_niches_policy<'tcx>(tcx: TyCtxt<'tcx>, _: LocalCrate) -> ReferenceNichePolicy {
|
fn reference_niches_policy<'tcx>(tcx: TyCtxt<'tcx>, _: LocalCrate) -> ReferenceNichePolicy {
|
||||||
const DEFAULT: ReferenceNichePolicy = ReferenceNichePolicy { size: false, align: false };
|
tcx.sess.opts.unstable_opts.reference_niches.unwrap_or(DEFAULT_REF_NICHES)
|
||||||
|
|
||||||
tcx.sess.opts.unstable_opts.reference_niches.unwrap_or(DEFAULT)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The reference niche policy for builtin types, and for types in
|
||||||
|
/// crates not specifying `-Z reference-niches`.
|
||||||
|
const DEFAULT_REF_NICHES: ReferenceNichePolicy = ReferenceNichePolicy { size: false, align: false };
|
||||||
|
|
||||||
#[instrument(skip(tcx, query), level = "debug")]
|
#[instrument(skip(tcx, query), level = "debug")]
|
||||||
fn naive_layout_of<'tcx>(
|
fn naive_layout_of<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
@ -163,7 +165,6 @@ fn naive_layout_of_uncached<'tcx>(
|
||||||
// Potentially-wide pointers.
|
// Potentially-wide pointers.
|
||||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||||
let data_ptr = scalar(Pointer(AddressSpace::DATA));
|
let data_ptr = scalar(Pointer(AddressSpace::DATA));
|
||||||
|
|
||||||
if let Some(metadata) = ptr_metadata_scalar(cx, pointee)? {
|
if let Some(metadata) = ptr_metadata_scalar(cx, pointee)? {
|
||||||
// Effectively a (ptr, meta) tuple.
|
// Effectively a (ptr, meta) tuple.
|
||||||
data_ptr
|
data_ptr
|
||||||
|
@ -322,15 +323,36 @@ fn layout_of_uncached<'tcx>(
|
||||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||||
let mut data_ptr = scalar_unit(Pointer(AddressSpace::DATA));
|
let mut data_ptr = scalar_unit(Pointer(AddressSpace::DATA));
|
||||||
if !ty.is_unsafe_ptr() {
|
if !ty.is_unsafe_ptr() {
|
||||||
match cx.naive_layout_of(pointee) {
|
// Calling `layout_of` here would cause a query cycle for recursive types;
|
||||||
// TODO(reference_niches): actually use the naive layout to set
|
// so use a conservative estimate that doesn't look past references.
|
||||||
// reference niches; the query is still kept to for testing purposes.
|
let naive = match cx.naive_layout_of(pointee) {
|
||||||
Ok(_) => (),
|
Ok(n) => n.layout,
|
||||||
// This can happen when computing the `SizeSkeleton` of a generic type.
|
// This can happen when computing the `SizeSkeleton` of a generic type.
|
||||||
Err(LayoutError::Unknown(_)) => (),
|
Err(LayoutError::Unknown(_)) => {
|
||||||
|
// TODO(reference_niches): this is *very* incorrect, but we can't
|
||||||
|
// return an error here; this would break transmute checks.
|
||||||
|
// We need some other solution.
|
||||||
|
NaiveLayout::EMPTY
|
||||||
|
}
|
||||||
Err(err) => return Err(err),
|
Err(err) => return Err(err),
|
||||||
}
|
};
|
||||||
data_ptr.valid_range_mut().start = 1;
|
|
||||||
|
let niches = match *pointee.kind() {
|
||||||
|
ty::FnDef(def, ..)
|
||||||
|
| ty::Foreign(def)
|
||||||
|
| ty::Generator(def, ..)
|
||||||
|
| ty::Closure(def, ..) => tcx.reference_niches_policy(def.krate),
|
||||||
|
ty::Adt(def, _) => tcx.reference_niches_policy(def.did().krate),
|
||||||
|
_ => DEFAULT_REF_NICHES,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (min_addr, max_addr) = dl.address_range_for(
|
||||||
|
if niches.size { naive.min_size } else { Size::ZERO },
|
||||||
|
if niches.align { naive.min_align } else { Align::ONE },
|
||||||
|
);
|
||||||
|
|
||||||
|
*data_ptr.valid_range_mut() =
|
||||||
|
WrappingRange { start: min_addr.into(), end: max_addr.into() };
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(metadata) = ptr_metadata_scalar(cx, pointee)? {
|
if let Some(metadata) = ptr_metadata_scalar(cx, pointee)? {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue