Skip to content

Commit b7266c6

Browse files
wildarchsaleemjaffer
authored andcommitted
Move pointee_info_at to TyLayoutMethods.
The original implementation is still present at librustc_codegen_llvm/abi.rs, should be removed later to prevent code duplication.
1 parent e232636 commit b7266c6

File tree

2 files changed

+154
-0
lines changed

2 files changed

+154
-0
lines changed

src/librustc/ty/layout.rs

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::iter;
1212
use std::mem;
1313
use std::ops::Bound;
1414

15+
use hir;
1516
use crate::ich::StableHashingContext;
1617
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
1718
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -1545,6 +1546,7 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
15451546
pub trait MaybeResult<T> {
15461547
fn from_ok(x: T) -> Self;
15471548
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self;
1549+
fn ok(self) -> Option<T>;
15481550
}
15491551

15501552
impl<T> MaybeResult<T> for T {
@@ -1554,6 +1556,9 @@ impl<T> MaybeResult<T> for T {
15541556
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
15551557
f(self)
15561558
}
1559+
fn ok(self) -> Option<T> {
1560+
Some(self)
1561+
}
15571562
}
15581563

15591564
impl<T, E> MaybeResult<T> for Result<T, E> {
@@ -1563,6 +1568,9 @@ impl<T, E> MaybeResult<T> for Result<T, E> {
15631568
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
15641569
self.map(f)
15651570
}
1571+
fn ok(self) -> Option<T> {
1572+
self.ok()
1573+
}
15661574
}
15671575

15681576
pub type TyLayout<'tcx> = ::rustc_target::abi::TyLayout<'tcx, Ty<'tcx>>;
@@ -1824,6 +1832,125 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
18241832
}
18251833
})
18261834
}
1835+
1836+
fn pointee_info_at(this: TyLayout<'tcx>, cx: &C, offset: Size
1837+
) -> Option<PointeeInfo> {
1838+
let mut result = None;
1839+
match this.ty.sty {
1840+
ty::RawPtr(mt) if offset.bytes() == 0 => {
1841+
result = cx.layout_of(mt.ty).ok()
1842+
.map(|layout| PointeeInfo {
1843+
size: layout.size,
1844+
align: layout.align.abi,
1845+
safe: None,
1846+
});
1847+
}
1848+
1849+
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
1850+
let tcx = cx.tcx();
1851+
let is_freeze = ty.is_freeze(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP);
1852+
let kind = match mt {
1853+
hir::MutImmutable => if is_freeze {
1854+
PointerKind::Frozen
1855+
} else {
1856+
PointerKind::Shared
1857+
},
1858+
hir::MutMutable => {
1859+
// Previously we would only emit noalias annotations for LLVM >= 6 or in
1860+
// panic=abort mode. That was deemed right, as prior versions had many bugs
1861+
// in conjunction with unwinding, but later versions didn’t seem to have
1862+
// said issues. See issue #31681.
1863+
//
1864+
// Alas, later on we encountered a case where noalias would generate wrong
1865+
// code altogether even with recent versions of LLVM in *safe* code with no
1866+
// unwinding involved. See #54462.
1867+
//
1868+
// For now, do not enable mutable_noalias by default at all, while the
1869+
// issue is being figured out.
1870+
let mutable_noalias = tcx.sess.opts.debugging_opts.mutable_noalias
1871+
.unwrap_or(false);
1872+
if mutable_noalias {
1873+
PointerKind::UniqueBorrowed
1874+
} else {
1875+
PointerKind::Shared
1876+
}
1877+
}
1878+
};
1879+
1880+
result = cx.layout_of(ty).ok()
1881+
.map(|layout| PointeeInfo {
1882+
size: layout.size,
1883+
align: layout.align.abi,
1884+
safe: Some(kind),
1885+
});
1886+
}
1887+
1888+
_ => {
1889+
let mut data_variant = match this.variants {
1890+
Variants::NicheFilling { dataful_variant, .. } => {
1891+
// Only the niche itthis is always initialized,
1892+
// so only check for a pointer at its offset.
1893+
//
1894+
// If the niche is a pointer, it's either valid
1895+
// (according to its type), or null (which the
1896+
// niche field's scalar validity range encodes).
1897+
// This allows using `dereferenceable_or_null`
1898+
// for e.g., `Option<&T>`, and this will continue
1899+
// to work as long as we don't start using more
1900+
// niches than just null (e.g., the first page
1901+
// of the address space, or unaligned pointers).
1902+
if this.fields.offset(0) == offset {
1903+
Some(this.for_variant(cx, dataful_variant))
1904+
} else {
1905+
None
1906+
}
1907+
}
1908+
_ => Some(this)
1909+
};
1910+
1911+
if let Some(variant) = data_variant {
1912+
// We're not interested in any unions.
1913+
if let FieldPlacement::Union(_) = variant.fields {
1914+
data_variant = None;
1915+
}
1916+
}
1917+
1918+
if let Some(variant) = data_variant {
1919+
let ptr_end = offset + Pointer.size(cx);
1920+
for i in 0..variant.fields.count() {
1921+
let field_start = variant.fields.offset(i);
1922+
if field_start <= offset {
1923+
let field = variant.field(cx, i);
1924+
result = field.ok()
1925+
.and_then(|field| {
1926+
if ptr_end <= field_start + field.size {
1927+
// We found the right field, look inside it.
1928+
Self::pointee_info_at(field, cx, offset - field_start)
1929+
} else {
1930+
None
1931+
}
1932+
});
1933+
if result.is_some() {
1934+
break;
1935+
}
1936+
}
1937+
}
1938+
}
1939+
1940+
// FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
1941+
if let Some(ref mut pointee) = result {
1942+
if let ty::Adt(def, _) = this.ty.sty {
1943+
if def.is_box() && offset.bytes() == 0 {
1944+
pointee.safe = Some(PointerKind::UniqueOwned);
1945+
}
1946+
}
1947+
}
1948+
}
1949+
}
1950+
1951+
result
1952+
}
1953+
18271954
}
18281955

18291956
struct Niche {

src/librustc_target/abi/mod.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -910,13 +910,40 @@ pub trait LayoutOf {
910910
fn layout_of(&self, ty: Self::Ty) -> Self::TyLayout;
911911
}
912912

913+
#[derive(Copy, Clone, PartialEq, Eq)]
914+
pub enum PointerKind {
915+
/// Most general case, we know no restrictions to tell LLVM.
916+
Shared,
917+
918+
/// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`.
919+
Frozen,
920+
921+
/// `&mut T`, when we know `noalias` is safe for LLVM.
922+
UniqueBorrowed,
923+
924+
/// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns.
925+
UniqueOwned
926+
}
927+
928+
#[derive(Copy, Clone)]
929+
pub struct PointeeInfo {
930+
pub size: Size,
931+
pub align: Align,
932+
pub safe: Option<PointerKind>,
933+
}
934+
913935
pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
914936
fn for_variant(
915937
this: TyLayout<'a, Self>,
916938
cx: &C,
917939
variant_index: VariantIdx,
918940
) -> TyLayout<'a, Self>;
919941
fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout;
942+
fn pointee_info_at(
943+
this: TyLayout<'a, Self>,
944+
cx: &C,
945+
offset: Size
946+
) -> Option<PointeeInfo>;
920947
}
921948

922949
impl<'a, Ty> TyLayout<'a, Ty> {

0 commit comments

Comments
 (0)