Skip to content

Commit d628c2e

Browse files
committed
Auto merge of #60237 - saleemjaffer:issue-56166-miri-fntype-arg-passing, r=eddyb
Move pointee_info_at from rustc_codegen_llvm to rustc_target. Makes progress towards #56166. This is a continuation of #57150. @oli-obk Should I close the older PR?
2 parents c6b1698 + 968eb7f commit d628c2e

File tree

10 files changed

+233
-154
lines changed

10 files changed

+233
-154
lines changed

src/librustc/ty/layout.rs

+160-18
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 crate::hir;
1516
use crate::ich::StableHashingContext;
1617
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
1718
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -1518,6 +1519,10 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout {
15181519
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
15191520
}
15201521

1522+
pub trait HasParamEnv<'tcx> {
1523+
fn param_env(&self) -> ty::ParamEnv<'tcx>;
1524+
}
1525+
15211526
impl<'a, 'gcx, 'tcx> HasDataLayout for TyCtxt<'a, 'gcx, 'tcx> {
15221527
fn data_layout(&self) -> &TargetDataLayout {
15231528
&self.data_layout
@@ -1530,6 +1535,12 @@ impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> {
15301535
}
15311536
}
15321537

1538+
impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> {
1539+
fn param_env(&self) -> ty::ParamEnv<'tcx> {
1540+
self.param_env
1541+
}
1542+
}
1543+
15331544
impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> {
15341545
fn data_layout(&self) -> &TargetDataLayout {
15351546
self.tcx.data_layout()
@@ -1543,25 +1554,32 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
15431554
}
15441555

15451556
pub trait MaybeResult<T> {
1546-
fn from_ok(x: T) -> Self;
1547-
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self;
1557+
type Error;
1558+
1559+
fn from(x: Result<T, Self::Error>) -> Self;
1560+
fn to_result(self) -> Result<T, Self::Error>;
15481561
}
15491562

15501563
impl<T> MaybeResult<T> for T {
1551-
fn from_ok(x: T) -> Self {
1564+
type Error = !;
1565+
1566+
fn from(x: Result<T, Self::Error>) -> Self {
1567+
let Ok(x) = x;
15521568
x
15531569
}
1554-
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
1555-
f(self)
1570+
fn to_result(self) -> Result<T, Self::Error> {
1571+
Ok(self)
15561572
}
15571573
}
15581574

15591575
impl<T, E> MaybeResult<T> for Result<T, E> {
1560-
fn from_ok(x: T) -> Self {
1561-
Ok(x)
1576+
type Error = E;
1577+
1578+
fn from(x: Result<T, Self::Error>) -> Self {
1579+
x
15621580
}
1563-
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
1564-
self.map(f)
1581+
fn to_result(self) -> Result<T, Self::Error> {
1582+
self
15651583
}
15661584
}
15671585

@@ -1656,18 +1674,18 @@ impl ty::query::TyCtxtAt<'a, 'tcx, '_> {
16561674

16571675
impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
16581676
where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
1659-
C::TyLayout: MaybeResult<TyLayout<'tcx>>
1677+
C::TyLayout: MaybeResult<TyLayout<'tcx>>,
1678+
C: HasParamEnv<'tcx>
16601679
{
16611680
fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
16621681
let details = match this.variants {
16631682
Variants::Single { index } if index == variant_index => this.details,
16641683

16651684
Variants::Single { index } => {
16661685
// Deny calling for_variant more than once for non-Single enums.
1667-
cx.layout_of(this.ty).map_same(|layout| {
1686+
if let Ok(layout) = cx.layout_of(this.ty).to_result() {
16681687
assert_eq!(layout.variants, Variants::Single { index });
1669-
layout
1670-
});
1688+
}
16711689

16721690
let fields = match this.ty.sty {
16731691
ty::Adt(def, _) => def.variants[variant_index].fields.len(),
@@ -1700,10 +1718,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
17001718
let tcx = cx.tcx();
17011719
let discr_layout = |discr: &Scalar| -> C::TyLayout {
17021720
let layout = LayoutDetails::scalar(cx, discr.clone());
1703-
MaybeResult::from_ok(TyLayout {
1721+
MaybeResult::from(Ok(TyLayout {
17041722
details: tcx.intern_layout(layout),
1705-
ty: discr.value.to_ty(tcx)
1706-
})
1723+
ty: discr.value.to_ty(tcx),
1724+
}))
17071725
};
17081726

17091727
cx.layout_of(match this.ty.sty {
@@ -1737,10 +1755,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
17371755
} else {
17381756
tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
17391757
};
1740-
return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
1758+
return MaybeResult::from(cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| {
17411759
ptr_layout.ty = this.ty;
17421760
ptr_layout
1743-
});
1761+
}));
17441762
}
17451763

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

18291971
struct Niche {

src/librustc_codegen_llvm/abi.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::llvm::{self, AttributePlace};
22
use crate::builder::Builder;
33
use crate::context::CodegenCx;
44
use crate::type_::Type;
5-
use crate::type_of::{LayoutLlvmExt, PointerKind};
65
use crate::value::Value;
6+
use crate::type_of::{LayoutLlvmExt};
77
use rustc_codegen_ssa::MemFlags;
88
use rustc_codegen_ssa::mir::place::PlaceRef;
99
use rustc_codegen_ssa::mir::operand::OperandValue;
@@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*;
1313

1414
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
1515
use rustc::ty::{self, Ty, Instance};
16-
use rustc::ty::layout;
16+
use rustc::ty::layout::{self, PointerKind};
1717

1818
use libc::c_uint;
1919

src/librustc_codegen_llvm/builder.rs

+6
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
6666
}
6767
}
6868

69+
impl ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
70+
fn param_env(&self) -> ty::ParamEnv<'tcx> {
71+
self.cx.param_env()
72+
}
73+
}
74+
6975
impl ty::layout::LayoutOf for Builder<'_, '_, 'tcx> {
7076
type Ty = Ty<'tcx>;
7177
type TyLayout = TyLayout<'tcx>;

src/librustc_codegen_llvm/context.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ use rustc::hir;
88

99
use crate::monomorphize::partitioning::CodegenUnit;
1010
use crate::type_::Type;
11-
use crate::type_of::PointeeInfo;
1211
use rustc_codegen_ssa::traits::*;
1312

1413
use rustc_data_structures::base_n;
1514
use rustc_data_structures::small_c_str::SmallCStr;
1615
use rustc::mir::mono::Stats;
1716
use rustc::session::config::{self, DebugInfo};
1817
use rustc::session::Session;
19-
use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout, VariantIdx};
18+
use rustc::ty::layout::{
19+
LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv
20+
};
2021
use rustc::ty::{self, Ty, TyCtxt};
2122
use rustc::util::nodemap::FxHashMap;
2223
use rustc_target::spec::{HasTargetSpec, Target};
@@ -862,3 +863,9 @@ impl LayoutOf for CodegenCx<'ll, 'tcx> {
862863
})
863864
}
864865
}
866+
867+
impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
868+
fn param_env(&self) -> ty::ParamEnv<'tcx> {
869+
ty::ParamEnv::reveal_all()
870+
}
871+
}

0 commit comments

Comments
 (0)