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 https://github.com/rust-lang/rust/pull/57150. @oli-obk Should I close the older PR?
This commit is contained in:
commit
d628c2e642
@ -12,6 +12,7 @@ use std::iter;
|
||||
use std::mem;
|
||||
use std::ops::Bound;
|
||||
|
||||
use crate::hir;
|
||||
use crate::ich::StableHashingContext;
|
||||
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
||||
@ -1518,6 +1519,10 @@ pub trait HasTyCtxt<'tcx>: HasDataLayout {
|
||||
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
|
||||
}
|
||||
|
||||
pub trait HasParamEnv<'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> HasDataLayout for TyCtxt<'a, 'gcx, 'tcx> {
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
&self.data_layout
|
||||
@ -1530,6 +1535,12 @@ impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> {
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
self.tcx.data_layout()
|
||||
@ -1543,25 +1554,32 @@ impl<'gcx, 'tcx, T: HasTyCtxt<'gcx>> HasTyCtxt<'gcx> for LayoutCx<'tcx, T> {
|
||||
}
|
||||
|
||||
pub trait MaybeResult<T> {
|
||||
fn from_ok(x: T) -> Self;
|
||||
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self;
|
||||
type Error;
|
||||
|
||||
fn from(x: Result<T, Self::Error>) -> Self;
|
||||
fn to_result(self) -> Result<T, Self::Error>;
|
||||
}
|
||||
|
||||
impl<T> MaybeResult<T> for T {
|
||||
fn from_ok(x: T) -> Self {
|
||||
type Error = !;
|
||||
|
||||
fn from(x: Result<T, Self::Error>) -> Self {
|
||||
let Ok(x) = x;
|
||||
x
|
||||
}
|
||||
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
|
||||
f(self)
|
||||
fn to_result(self) -> Result<T, Self::Error> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, E> MaybeResult<T> for Result<T, E> {
|
||||
fn from_ok(x: T) -> Self {
|
||||
Ok(x)
|
||||
type Error = E;
|
||||
|
||||
fn from(x: Result<T, Self::Error>) -> Self {
|
||||
x
|
||||
}
|
||||
fn map_same<F: FnOnce(T) -> T>(self, f: F) -> Self {
|
||||
self.map(f)
|
||||
fn to_result(self) -> Result<T, Self::Error> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
@ -1656,7 +1674,8 @@ impl ty::query::TyCtxtAt<'a, 'tcx, '_> {
|
||||
|
||||
impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
|
||||
where C: LayoutOf<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>,
|
||||
C::TyLayout: MaybeResult<TyLayout<'tcx>>
|
||||
C::TyLayout: MaybeResult<TyLayout<'tcx>>,
|
||||
C: HasParamEnv<'tcx>
|
||||
{
|
||||
fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> {
|
||||
let details = match this.variants {
|
||||
@ -1664,10 +1683,9 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
|
||||
|
||||
Variants::Single { index } => {
|
||||
// Deny calling for_variant more than once for non-Single enums.
|
||||
cx.layout_of(this.ty).map_same(|layout| {
|
||||
if let Ok(layout) = cx.layout_of(this.ty).to_result() {
|
||||
assert_eq!(layout.variants, Variants::Single { index });
|
||||
layout
|
||||
});
|
||||
}
|
||||
|
||||
let fields = match this.ty.sty {
|
||||
ty::Adt(def, _) => def.variants[variant_index].fields.len(),
|
||||
@ -1700,10 +1718,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
|
||||
let tcx = cx.tcx();
|
||||
let discr_layout = |discr: &Scalar| -> C::TyLayout {
|
||||
let layout = LayoutDetails::scalar(cx, discr.clone());
|
||||
MaybeResult::from_ok(TyLayout {
|
||||
MaybeResult::from(Ok(TyLayout {
|
||||
details: tcx.intern_layout(layout),
|
||||
ty: discr.value.to_ty(tcx)
|
||||
})
|
||||
ty: discr.value.to_ty(tcx),
|
||||
}))
|
||||
};
|
||||
|
||||
cx.layout_of(match this.ty.sty {
|
||||
@ -1737,10 +1755,10 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
|
||||
} else {
|
||||
tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
|
||||
};
|
||||
return cx.layout_of(ptr_ty).map_same(|mut ptr_layout| {
|
||||
return MaybeResult::from(cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| {
|
||||
ptr_layout.ty = this.ty;
|
||||
ptr_layout
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
match tcx.struct_tail(pointee).sty {
|
||||
@ -1824,6 +1842,130 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn pointee_info_at(
|
||||
this: TyLayout<'tcx>,
|
||||
cx: &C,
|
||||
offset: Size,
|
||||
) -> Option<PointeeInfo> {
|
||||
match this.ty.sty {
|
||||
ty::RawPtr(mt) if offset.bytes() == 0 => {
|
||||
cx.layout_of(mt.ty).to_result().ok()
|
||||
.map(|layout| PointeeInfo {
|
||||
size: layout.size,
|
||||
align: layout.align.abi,
|
||||
safe: None,
|
||||
})
|
||||
}
|
||||
|
||||
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
|
||||
let tcx = cx.tcx();
|
||||
let is_freeze = ty.is_freeze(tcx, cx.param_env(), DUMMY_SP);
|
||||
let kind = match mt {
|
||||
hir::MutImmutable => if is_freeze {
|
||||
PointerKind::Frozen
|
||||
} else {
|
||||
PointerKind::Shared
|
||||
},
|
||||
hir::MutMutable => {
|
||||
// Previously we would only emit noalias annotations for LLVM >= 6 or in
|
||||
// panic=abort mode. That was deemed right, as prior versions had many bugs
|
||||
// in conjunction with unwinding, but later versions didn’t seem to have
|
||||
// said issues. See issue #31681.
|
||||
//
|
||||
// Alas, later on we encountered a case where noalias would generate wrong
|
||||
// code altogether even with recent versions of LLVM in *safe* code with no
|
||||
// unwinding involved. See #54462.
|
||||
//
|
||||
// For now, do not enable mutable_noalias by default at all, while the
|
||||
// issue is being figured out.
|
||||
let mutable_noalias = tcx.sess.opts.debugging_opts.mutable_noalias
|
||||
.unwrap_or(false);
|
||||
if mutable_noalias {
|
||||
PointerKind::UniqueBorrowed
|
||||
} else {
|
||||
PointerKind::Shared
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
cx.layout_of(ty).to_result().ok()
|
||||
.map(|layout| PointeeInfo {
|
||||
size: layout.size,
|
||||
align: layout.align.abi,
|
||||
safe: Some(kind),
|
||||
})
|
||||
}
|
||||
|
||||
_ => {
|
||||
let mut data_variant = match this.variants {
|
||||
// Within the discriminant field, only the niche itself is
|
||||
// always initialized, so we only check for a pointer at its
|
||||
// offset.
|
||||
//
|
||||
// If the niche is a pointer, it's either valid (according
|
||||
// to its type), or null (which the niche field's scalar
|
||||
// validity range encodes). This allows using
|
||||
// `dereferenceable_or_null` for e.g., `Option<&T>`, and
|
||||
// this will continue to work as long as we don't start
|
||||
// using more niches than just null (e.g., the first page of
|
||||
// the address space, or unaligned pointers).
|
||||
Variants::Multiple {
|
||||
discr_kind: DiscriminantKind::Niche {
|
||||
dataful_variant,
|
||||
..
|
||||
},
|
||||
discr_index,
|
||||
..
|
||||
} if this.fields.offset(discr_index) == offset =>
|
||||
Some(this.for_variant(cx, dataful_variant)),
|
||||
_ => Some(this),
|
||||
};
|
||||
|
||||
if let Some(variant) = data_variant {
|
||||
// We're not interested in any unions.
|
||||
if let FieldPlacement::Union(_) = variant.fields {
|
||||
data_variant = None;
|
||||
}
|
||||
}
|
||||
|
||||
let mut result = None;
|
||||
|
||||
if let Some(variant) = data_variant {
|
||||
let ptr_end = offset + Pointer.size(cx);
|
||||
for i in 0..variant.fields.count() {
|
||||
let field_start = variant.fields.offset(i);
|
||||
if field_start <= offset {
|
||||
let field = variant.field(cx, i);
|
||||
result = field.to_result().ok()
|
||||
.and_then(|field| {
|
||||
if ptr_end <= field_start + field.size {
|
||||
// We found the right field, look inside it.
|
||||
field.pointee_info_at(cx, offset - field_start)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
if result.is_some() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
|
||||
if let Some(ref mut pointee) = result {
|
||||
if let ty::Adt(def, _) = this.ty.sty {
|
||||
if def.is_box() && offset.bytes() == 0 {
|
||||
pointee.safe = Some(PointerKind::UniqueOwned);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Niche {
|
||||
|
@ -2,8 +2,8 @@ use crate::llvm::{self, AttributePlace};
|
||||
use crate::builder::Builder;
|
||||
use crate::context::CodegenCx;
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::{LayoutLlvmExt, PointerKind};
|
||||
use crate::value::Value;
|
||||
use crate::type_of::{LayoutLlvmExt};
|
||||
use rustc_codegen_ssa::MemFlags;
|
||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||
use rustc_codegen_ssa::mir::operand::OperandValue;
|
||||
@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*;
|
||||
|
||||
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TyLayout, Abi as LayoutAbi};
|
||||
use rustc::ty::{self, Ty, Instance};
|
||||
use rustc::ty::layout;
|
||||
use rustc::ty::layout::{self, PointerKind};
|
||||
|
||||
use libc::c_uint;
|
||||
|
||||
|
@ -66,6 +66,12 @@ impl ty::layout::HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl ty::layout::HasParamEnv<'tcx> for Builder<'_, '_, 'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.cx.param_env()
|
||||
}
|
||||
}
|
||||
|
||||
impl ty::layout::LayoutOf for Builder<'_, '_, 'tcx> {
|
||||
type Ty = Ty<'tcx>;
|
||||
type TyLayout = TyLayout<'tcx>;
|
||||
|
@ -8,7 +8,6 @@ use rustc::hir;
|
||||
|
||||
use crate::monomorphize::partitioning::CodegenUnit;
|
||||
use crate::type_::Type;
|
||||
use crate::type_of::PointeeInfo;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
||||
use rustc_data_structures::base_n;
|
||||
@ -16,7 +15,9 @@ use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc::mir::mono::Stats;
|
||||
use rustc::session::config::{self, DebugInfo};
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout, VariantIdx};
|
||||
use rustc::ty::layout::{
|
||||
LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, HasParamEnv
|
||||
};
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc_target::spec::{HasTargetSpec, Target};
|
||||
@ -862,3 +863,9 @@ impl LayoutOf for CodegenCx<'ll, 'tcx> {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
ty::ParamEnv::reveal_all()
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,9 @@
|
||||
use crate::abi::{FnType, FnTypeExt};
|
||||
use crate::common::*;
|
||||
use crate::type_::Type;
|
||||
use rustc::hir;
|
||||
use rustc::ty::{self, Ty, TypeFoldable};
|
||||
use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
|
||||
use rustc_target::abi::FloatTy;
|
||||
use rustc::ty::layout::{self, Align, LayoutOf, PointeeInfo, Size, TyLayout};
|
||||
use rustc_target::abi::{FloatTy, TyLayoutMethods};
|
||||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
|
||||
@ -174,28 +173,6 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum PointerKind {
|
||||
/// Most general case, we know no restrictions to tell LLVM.
|
||||
Shared,
|
||||
|
||||
/// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`.
|
||||
Frozen,
|
||||
|
||||
/// `&mut T`, when we know `noalias` is safe for LLVM.
|
||||
UniqueBorrowed,
|
||||
|
||||
/// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns.
|
||||
UniqueOwned
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct PointeeInfo {
|
||||
pub size: Size,
|
||||
pub align: Align,
|
||||
pub safe: Option<PointerKind>,
|
||||
}
|
||||
|
||||
pub trait LayoutLlvmExt<'tcx> {
|
||||
fn is_llvm_immediate(&self) -> bool;
|
||||
fn is_llvm_scalar_pair<'a>(&self) -> bool;
|
||||
@ -406,112 +383,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
|
||||
return pointee;
|
||||
}
|
||||
|
||||
let mut result = None;
|
||||
match self.ty.sty {
|
||||
ty::RawPtr(mt) if offset.bytes() == 0 => {
|
||||
let (size, align) = cx.size_and_align_of(mt.ty);
|
||||
result = Some(PointeeInfo {
|
||||
size,
|
||||
align,
|
||||
safe: None
|
||||
});
|
||||
}
|
||||
|
||||
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
|
||||
let (size, align) = cx.size_and_align_of(ty);
|
||||
|
||||
let kind = match mt {
|
||||
hir::MutImmutable => if cx.type_is_freeze(ty) {
|
||||
PointerKind::Frozen
|
||||
} else {
|
||||
PointerKind::Shared
|
||||
},
|
||||
hir::MutMutable => {
|
||||
// Previously we would only emit noalias annotations for LLVM >= 6 or in
|
||||
// panic=abort mode. That was deemed right, as prior versions had many bugs
|
||||
// in conjunction with unwinding, but later versions didn’t seem to have
|
||||
// said issues. See issue #31681.
|
||||
//
|
||||
// Alas, later on we encountered a case where noalias would generate wrong
|
||||
// code altogether even with recent versions of LLVM in *safe* code with no
|
||||
// unwinding involved. See #54462.
|
||||
//
|
||||
// For now, do not enable mutable_noalias by default at all, while the
|
||||
// issue is being figured out.
|
||||
let mutable_noalias = cx.tcx.sess.opts.debugging_opts.mutable_noalias
|
||||
.unwrap_or(false);
|
||||
if mutable_noalias {
|
||||
PointerKind::UniqueBorrowed
|
||||
} else {
|
||||
PointerKind::Shared
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
result = Some(PointeeInfo {
|
||||
size,
|
||||
align,
|
||||
safe: Some(kind)
|
||||
});
|
||||
}
|
||||
|
||||
_ => {
|
||||
let mut data_variant = match self.variants {
|
||||
// Within the discriminant field, only the niche itself is
|
||||
// always initialized, so we only check for a pointer at its
|
||||
// offset.
|
||||
//
|
||||
// If the niche is a pointer, it's either valid (according
|
||||
// to its type), or null (which the niche field's scalar
|
||||
// validity range encodes). This allows using
|
||||
// `dereferenceable_or_null` for e.g., `Option<&T>`, and
|
||||
// this will continue to work as long as we don't start
|
||||
// using more niches than just null (e.g., the first page of
|
||||
// the address space, or unaligned pointers).
|
||||
layout::Variants::Multiple {
|
||||
discr_kind: layout::DiscriminantKind::Niche {
|
||||
dataful_variant,
|
||||
..
|
||||
},
|
||||
discr_index,
|
||||
..
|
||||
} if self.fields.offset(discr_index) == offset =>
|
||||
Some(self.for_variant(cx, dataful_variant)),
|
||||
_ => Some(*self),
|
||||
};
|
||||
|
||||
if let Some(variant) = data_variant {
|
||||
// We're not interested in any unions.
|
||||
if let layout::FieldPlacement::Union(_) = variant.fields {
|
||||
data_variant = None;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(variant) = data_variant {
|
||||
let ptr_end = offset + layout::Pointer.size(cx);
|
||||
for i in 0..variant.fields.count() {
|
||||
let field_start = variant.fields.offset(i);
|
||||
if field_start <= offset {
|
||||
let field = variant.field(cx, i);
|
||||
if ptr_end <= field_start + field.size {
|
||||
// We found the right field, look inside it.
|
||||
result = field.pointee_info_at(cx, offset - field_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
|
||||
if let Some(ref mut pointee) = result {
|
||||
if let ty::Adt(def, _) = self.ty.sty {
|
||||
if def.is_box() && offset.bytes() == 0 {
|
||||
pointee.safe = Some(PointerKind::UniqueOwned);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let result = Ty::pointee_info_at(*self, cx, offset);
|
||||
|
||||
cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
|
||||
result
|
||||
|
@ -10,7 +10,7 @@ use crate::mir::operand::OperandRef;
|
||||
use crate::mir::place::PlaceRef;
|
||||
use crate::MemFlags;
|
||||
use rustc::ty::Ty;
|
||||
use rustc::ty::layout::{Align, Size};
|
||||
use rustc::ty::layout::{Align, Size, HasParamEnv};
|
||||
use std::ops::Range;
|
||||
use std::iter::TrustedLen;
|
||||
|
||||
@ -29,6 +29,8 @@ pub trait BuilderMethods<'a, 'tcx: 'a>:
|
||||
+ IntrinsicCallMethods<'tcx>
|
||||
+ AsmBuilderMethods<'tcx>
|
||||
+ StaticBuilderMethods<'tcx>
|
||||
+ HasParamEnv<'tcx>
|
||||
|
||||
{
|
||||
fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self;
|
||||
fn with_cx(cx: &'a Self::CodegenCx) -> Self;
|
||||
|
@ -41,6 +41,8 @@ pub use self::type_::{
|
||||
ArgTypeMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMethods,
|
||||
};
|
||||
pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
|
||||
use rustc::ty::layout::{HasParamEnv};
|
||||
|
||||
|
||||
use std::fmt;
|
||||
|
||||
@ -58,6 +60,7 @@ pub trait CodegenMethods<'tcx>:
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods<'tcx>
|
||||
+ PreDefineMethods<'tcx>
|
||||
+ HasParamEnv<'tcx>
|
||||
{
|
||||
}
|
||||
|
||||
@ -72,6 +75,7 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods<'tcx>
|
||||
+ PreDefineMethods<'tcx>
|
||||
+ HasParamEnv<'tcx>
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -175,6 +175,14 @@ impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpretCx<'a, 'mir, 'tcx,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M> layout::HasParamEnv<'tcx> for InterpretCx<'a, 'mir, 'tcx, M>
|
||||
where M: Machine<'a, 'mir, 'tcx>
|
||||
{
|
||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> LayoutOf
|
||||
for InterpretCx<'a, 'mir, 'tcx, M>
|
||||
{
|
||||
|
@ -7,6 +7,7 @@ use rustc::ty::layout::HasTyCtxt;
|
||||
use rustc::ty::layout::LayoutOf;
|
||||
use rustc::ty::layout::TargetDataLayout;
|
||||
use rustc::ty::layout::TyLayout;
|
||||
use rustc::ty::layout::HasParamEnv;
|
||||
use rustc::ty::ParamEnv;
|
||||
use rustc::ty::Ty;
|
||||
use rustc::ty::TyCtxt;
|
||||
@ -122,6 +123,12 @@ impl<'me, 'tcx> HasTyCtxt<'tcx> for UnwrapLayoutCx<'me, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'me, 'tcx> HasParamEnv<'tcx> for UnwrapLayoutCx<'me, 'tcx> {
|
||||
fn param_env(&self) -> ParamEnv<'tcx> {
|
||||
self.param_env
|
||||
}
|
||||
}
|
||||
|
||||
impl<'me, 'tcx> HasDataLayout for UnwrapLayoutCx<'me, 'tcx> {
|
||||
fn data_layout(&self) -> &TargetDataLayout {
|
||||
self.tcx.data_layout()
|
||||
|
@ -910,6 +910,28 @@ pub trait LayoutOf {
|
||||
fn layout_of(&self, ty: Self::Ty) -> Self::TyLayout;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum PointerKind {
|
||||
/// Most general case, we know no restrictions to tell LLVM.
|
||||
Shared,
|
||||
|
||||
/// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`.
|
||||
Frozen,
|
||||
|
||||
/// `&mut T`, when we know `noalias` is safe for LLVM.
|
||||
UniqueBorrowed,
|
||||
|
||||
/// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns.
|
||||
UniqueOwned
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct PointeeInfo {
|
||||
pub size: Size,
|
||||
pub align: Align,
|
||||
pub safe: Option<PointerKind>,
|
||||
}
|
||||
|
||||
pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
|
||||
fn for_variant(
|
||||
this: TyLayout<'a, Self>,
|
||||
@ -917,6 +939,11 @@ pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
|
||||
variant_index: VariantIdx,
|
||||
) -> TyLayout<'a, Self>;
|
||||
fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout;
|
||||
fn pointee_info_at(
|
||||
this: TyLayout<'a, Self>,
|
||||
cx: &C,
|
||||
offset: Size,
|
||||
) -> Option<PointeeInfo>;
|
||||
}
|
||||
|
||||
impl<'a, Ty> TyLayout<'a, Ty> {
|
||||
@ -928,6 +955,10 @@ impl<'a, Ty> TyLayout<'a, Ty> {
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
|
||||
Ty::field(self, cx, i)
|
||||
}
|
||||
pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
|
||||
where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> {
|
||||
Ty::pointee_info_at(self, cx, offset)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Ty> TyLayout<'a, Ty> {
|
||||
|
Loading…
Reference in New Issue
Block a user