mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-27 07:03:45 +00:00
Auto merge of #88337 - eddyb:field-failure-is-not-an-option, r=nagisa
rustc_target: `TyAndLayout::field` should never error. This refactor (making `TyAndLayout::field` return `TyAndLayout` without any `Result` around it) is based on a simple observation, regarding `TyAndLayout::field`: If `cx.layout_of(ty)` succeeds (for some `cx` and `ty`), then `.field(cx, i)` on the resulting `TyAndLayout` should *always* succeed in computing `cx.layout_of(field_ty)` (where `field_ty` is the type of the `i`th field of `ty`). The reason for this is that no matter which field is chosen, `cx.layout_of(field_ty)` *will have already been computed*, as part of computing `cx.layout_of(ty)`, as we cannot determine the layout of *any* type without considering the layouts of *all* of its fields. And so it should be fine to turn any errors into ICEs, since they likely indicate a `cx` mismatch, or some other edge case that is due to a compiler bug (as opposed to ever being an user-facing error). <hr/> Each commit should probably be reviewed separately, though note that there's some `where` clauses (in `rustc_target::abi::call::*`) that change in most commits. cc `@nagisa` `@oli-obk`
This commit is contained in:
commit
9556d7a09a
@ -256,7 +256,7 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
|
|||||||
pub(crate) inline_asm_index: u32,
|
pub(crate) inline_asm_index: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> LayoutOf for FunctionCx<'_, '_, 'tcx> {
|
impl<'tcx> LayoutOf<'tcx> for FunctionCx<'_, '_, 'tcx> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = TyAndLayout<'tcx>;
|
type TyAndLayout = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
@ -364,7 +364,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
|||||||
|
|
||||||
pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
|
pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
|
||||||
|
|
||||||
impl<'tcx> LayoutOf for RevealAllLayoutCx<'tcx> {
|
impl<'tcx> LayoutOf<'tcx> for RevealAllLayoutCx<'tcx> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = TyAndLayout<'tcx>;
|
type TyAndLayout = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
|
@ -160,12 +160,10 @@ impl<'tcx> DebugContext<'tcx> {
|
|||||||
|
|
||||||
for (field_idx, field_def) in variant.fields.iter().enumerate() {
|
for (field_idx, field_def) in variant.fields.iter().enumerate() {
|
||||||
let field_offset = layout.fields.offset(field_idx);
|
let field_offset = layout.fields.offset(field_idx);
|
||||||
let field_layout = layout
|
let field_layout = layout.field(
|
||||||
.field(
|
&layout::LayoutCx { tcx: self.tcx, param_env: ParamEnv::reveal_all() },
|
||||||
&layout::LayoutCx { tcx: self.tcx, param_env: ParamEnv::reveal_all() },
|
field_idx,
|
||||||
field_idx,
|
);
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let field_type = self.dwarf_ty(field_layout.ty);
|
let field_type = self.dwarf_ty(field_layout.ty);
|
||||||
|
|
||||||
|
@ -789,7 +789,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if intrinsic == sym::assert_zero_valid && !layout.might_permit_raw_init(fx, /*zero:*/ true).unwrap() {
|
if intrinsic == sym::assert_zero_valid && !layout.might_permit_raw_init(fx, /*zero:*/ true) {
|
||||||
with_no_trimmed_paths(|| crate::base::codegen_panic(
|
with_no_trimmed_paths(|| crate::base::codegen_panic(
|
||||||
fx,
|
fx,
|
||||||
&format!("attempted to zero-initialize type `{}`, which is invalid", T),
|
&format!("attempted to zero-initialize type `{}`, which is invalid", T),
|
||||||
@ -798,7 +798,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if intrinsic == sym::assert_uninit_valid && !layout.might_permit_raw_init(fx, /*zero:*/ false).unwrap() {
|
if intrinsic == sym::assert_uninit_valid && !layout.might_permit_raw_init(fx, /*zero:*/ false) {
|
||||||
with_no_trimmed_paths(|| crate::base::codegen_panic(
|
with_no_trimmed_paths(|| crate::base::codegen_panic(
|
||||||
fx,
|
fx,
|
||||||
&format!("attempted to leave type `{}` uninitialized, which is invalid", T),
|
&format!("attempted to leave type `{}` uninitialized, which is invalid", T),
|
||||||
|
@ -88,7 +88,7 @@ impl HasTargetSpec for Builder<'_, '_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl abi::LayoutOf for Builder<'_, '_, 'tcx> {
|
impl abi::LayoutOf<'tcx> for Builder<'_, '_, 'tcx> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = TyAndLayout<'tcx>;
|
type TyAndLayout = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
|
@ -835,7 +835,7 @@ impl ty::layout::HasTyCtxt<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutOf for CodegenCx<'ll, 'tcx> {
|
impl LayoutOf<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = TyAndLayout<'tcx>;
|
type TyAndLayout = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
|
|||||||
use rustc_middle::ty::{self, Ty, TypeFoldable};
|
use rustc_middle::ty::{self, Ty, TypeFoldable};
|
||||||
use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
|
use rustc_target::abi::{Abi, AddressSpace, Align, FieldsShape};
|
||||||
use rustc_target::abi::{Int, Pointer, F32, F64};
|
use rustc_target::abi::{Int, Pointer, F32, F64};
|
||||||
use rustc_target::abi::{LayoutOf, PointeeInfo, Scalar, Size, TyAndLayoutMethods, Variants};
|
use rustc_target::abi::{LayoutOf, PointeeInfo, Scalar, Size, TyAbiInterface, Variants};
|
||||||
use smallvec::{smallvec, SmallVec};
|
use smallvec::{smallvec, SmallVec};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
@ -393,12 +393,15 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(eddyb) this having the same name as `TyAndLayout::pointee_info_at`
|
||||||
|
// (the inherent method, which is lacking this caching logic) can result in
|
||||||
|
// the uncached version being called - not wrong, but potentially inefficient.
|
||||||
fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo> {
|
fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo> {
|
||||||
if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) {
|
if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) {
|
||||||
return pointee;
|
return pointee;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = Ty::pointee_info_at(*self, cx, offset);
|
let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset);
|
||||||
|
|
||||||
cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
|
cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
|
||||||
result
|
result
|
||||||
|
@ -472,10 +472,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
let layout = bx.layout_of(ty);
|
let layout = bx.layout_of(ty);
|
||||||
let do_panic = match intrinsic {
|
let do_panic = match intrinsic {
|
||||||
Inhabited => layout.abi.is_uninhabited(),
|
Inhabited => layout.abi.is_uninhabited(),
|
||||||
// We unwrap as the error type is `!`.
|
ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true),
|
||||||
ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(),
|
UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false),
|
||||||
// We unwrap as the error type is `!`.
|
|
||||||
UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(),
|
|
||||||
};
|
};
|
||||||
if do_panic {
|
if do_panic {
|
||||||
let msg_str = with_no_trimmed_paths(|| {
|
let msg_str = with_no_trimmed_paths(|| {
|
||||||
|
@ -39,12 +39,17 @@ pub trait BackendTypes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Backend<'tcx>:
|
pub trait Backend<'tcx>:
|
||||||
Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
Sized
|
||||||
|
+ BackendTypes
|
||||||
|
+ HasTyCtxt<'tcx>
|
||||||
|
+ LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, T> Backend<'tcx> for T where
|
impl<'tcx, T> Backend<'tcx> for T where
|
||||||
Self: BackendTypes + HasTyCtxt<'tcx> + LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
Self: BackendTypes
|
||||||
|
+ HasTyCtxt<'tcx>
|
||||||
|
+ LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ use rustc_session::Session;
|
|||||||
use rustc_session::SessionLintStore;
|
use rustc_session::SessionLintStore;
|
||||||
use rustc_span::lev_distance::find_best_match_for_name;
|
use rustc_span::lev_distance::find_best_match_for_name;
|
||||||
use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
|
use rustc_span::{symbol::Symbol, MultiSpan, Span, DUMMY_SP};
|
||||||
use rustc_target::abi::LayoutOf;
|
use rustc_target::abi::{self, LayoutOf};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
@ -1059,7 +1059,28 @@ impl<'tcx> LateContext<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> LayoutOf for LateContext<'tcx> {
|
impl<'tcx> abi::HasDataLayout for LateContext<'tcx> {
|
||||||
|
#[inline]
|
||||||
|
fn data_layout(&self) -> &abi::TargetDataLayout {
|
||||||
|
&self.tcx.data_layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ty::layout::HasTyCtxt<'tcx> for LateContext<'tcx> {
|
||||||
|
#[inline]
|
||||||
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
|
self.tcx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ty::layout::HasParamEnv<'tcx> for LateContext<'tcx> {
|
||||||
|
#[inline]
|
||||||
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
|
self.param_env
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> LayoutOf<'tcx> for LateContext<'tcx> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
||||||
|
|
||||||
|
@ -1788,22 +1788,18 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||||||
let field_info: Vec<_> = flds
|
let field_info: Vec<_> = flds
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, &name)| match layout.field(self, i) {
|
.map(|(i, &name)| {
|
||||||
Err(err) => {
|
let field_layout = layout.field(self, i);
|
||||||
bug!("no layout found for field {}: `{:?}`", name, err);
|
let offset = layout.fields.offset(i);
|
||||||
|
let field_end = offset + field_layout.size;
|
||||||
|
if min_size < field_end {
|
||||||
|
min_size = field_end;
|
||||||
}
|
}
|
||||||
Ok(field_layout) => {
|
FieldInfo {
|
||||||
let offset = layout.fields.offset(i);
|
name: name.to_string(),
|
||||||
let field_end = offset + field_layout.size;
|
offset: offset.bytes(),
|
||||||
if min_size < field_end {
|
size: field_layout.size.bytes(),
|
||||||
min_size = field_end;
|
align: field_layout.align.abi.bytes(),
|
||||||
}
|
|
||||||
FieldInfo {
|
|
||||||
name: name.to_string(),
|
|
||||||
offset: offset.bytes(),
|
|
||||||
size: field_layout.size.bytes(),
|
|
||||||
align: field_layout.align.abi.bytes(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
@ -2034,6 +2030,20 @@ impl<'tcx> HasTyCtxt<'tcx> for TyCtxt<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> HasDataLayout for ty::query::TyCtxtAt<'tcx> {
|
||||||
|
#[inline]
|
||||||
|
fn data_layout(&self) -> &TargetDataLayout {
|
||||||
|
&self.data_layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> HasTyCtxt<'tcx> for ty::query::TyCtxtAt<'tcx> {
|
||||||
|
#[inline]
|
||||||
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
|
**self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> {
|
impl<'tcx, C> HasParamEnv<'tcx> for LayoutCx<'tcx, C> {
|
||||||
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
self.param_env
|
self.param_env
|
||||||
@ -2054,7 +2064,7 @@ impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> {
|
|||||||
|
|
||||||
pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>;
|
pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>;
|
||||||
|
|
||||||
impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
|
impl LayoutOf<'tcx> for LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
||||||
|
|
||||||
@ -2066,7 +2076,7 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
|
impl LayoutOf<'tcx> for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
||||||
|
|
||||||
@ -2078,13 +2088,11 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, C> TyAndLayoutMethods<'tcx, C> for Ty<'tcx>
|
impl<'tcx, C> TyAbiInterface<'tcx, C> for Ty<'tcx>
|
||||||
where
|
where
|
||||||
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout: MaybeResult<TyAndLayout<'tcx>>>
|
C: HasTyCtxt<'tcx> + HasParamEnv<'tcx>,
|
||||||
+ HasTyCtxt<'tcx>
|
|
||||||
+ HasParamEnv<'tcx>,
|
|
||||||
{
|
{
|
||||||
fn for_variant(
|
fn ty_and_layout_for_variant(
|
||||||
this: TyAndLayout<'tcx>,
|
this: TyAndLayout<'tcx>,
|
||||||
cx: &C,
|
cx: &C,
|
||||||
variant_index: VariantIdx,
|
variant_index: VariantIdx,
|
||||||
@ -2101,8 +2109,11 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
Variants::Single { index } => {
|
Variants::Single { index } => {
|
||||||
|
let tcx = cx.tcx();
|
||||||
|
let param_env = cx.param_env();
|
||||||
|
|
||||||
// Deny calling for_variant more than once for non-Single enums.
|
// Deny calling for_variant more than once for non-Single enums.
|
||||||
if let Ok(original_layout) = cx.layout_of(this.ty).to_result() {
|
if let Ok(original_layout) = tcx.layout_of(param_env.and(this.ty)) {
|
||||||
assert_eq!(original_layout.variants, Variants::Single { index });
|
assert_eq!(original_layout.variants, Variants::Single { index });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2112,7 +2123,6 @@ where
|
|||||||
ty::Adt(def, _) => def.variants[variant_index].fields.len(),
|
ty::Adt(def, _) => def.variants[variant_index].fields.len(),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
let tcx = cx.tcx();
|
|
||||||
tcx.intern_layout(Layout {
|
tcx.intern_layout(Layout {
|
||||||
variants: Variants::Single { index: variant_index },
|
variants: Variants::Single { index: variant_index },
|
||||||
fields: match NonZeroUsize::new(fields) {
|
fields: match NonZeroUsize::new(fields) {
|
||||||
@ -2134,32 +2144,24 @@ where
|
|||||||
TyAndLayout { ty: this.ty, layout }
|
TyAndLayout { ty: this.ty, layout }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> C::TyAndLayout {
|
fn ty_and_layout_field(this: TyAndLayout<'tcx>, cx: &C, i: usize) -> TyAndLayout<'tcx> {
|
||||||
enum TyMaybeWithLayout<C: LayoutOf> {
|
enum TyMaybeWithLayout<'tcx> {
|
||||||
Ty(C::Ty),
|
Ty(Ty<'tcx>),
|
||||||
TyAndLayout(C::TyAndLayout),
|
TyAndLayout(TyAndLayout<'tcx>),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_and_layout_kind<
|
fn field_ty_or_layout(
|
||||||
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout: MaybeResult<TyAndLayout<'tcx>>>
|
|
||||||
+ HasTyCtxt<'tcx>
|
|
||||||
+ HasParamEnv<'tcx>,
|
|
||||||
>(
|
|
||||||
this: TyAndLayout<'tcx>,
|
this: TyAndLayout<'tcx>,
|
||||||
cx: &C,
|
cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
|
||||||
i: usize,
|
i: usize,
|
||||||
ty: C::Ty,
|
) -> TyMaybeWithLayout<'tcx> {
|
||||||
) -> TyMaybeWithLayout<C> {
|
|
||||||
let tcx = cx.tcx();
|
let tcx = cx.tcx();
|
||||||
let tag_layout = |tag: &Scalar| -> C::TyAndLayout {
|
let tag_layout = |tag: &Scalar| -> TyAndLayout<'tcx> {
|
||||||
let layout = Layout::scalar(cx, tag.clone());
|
let layout = Layout::scalar(cx, tag.clone());
|
||||||
MaybeResult::from(Ok(TyAndLayout {
|
TyAndLayout { layout: tcx.intern_layout(layout), ty: tag.value.to_ty(tcx) }
|
||||||
layout: tcx.intern_layout(layout),
|
|
||||||
ty: tag.value.to_ty(tcx),
|
|
||||||
}))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match *ty.kind() {
|
match *this.ty.kind() {
|
||||||
ty::Bool
|
ty::Bool
|
||||||
| ty::Char
|
| ty::Char
|
||||||
| ty::Int(_)
|
| ty::Int(_)
|
||||||
@ -2170,7 +2172,7 @@ where
|
|||||||
| ty::FnDef(..)
|
| ty::FnDef(..)
|
||||||
| ty::GeneratorWitness(..)
|
| ty::GeneratorWitness(..)
|
||||||
| ty::Foreign(..)
|
| ty::Foreign(..)
|
||||||
| ty::Dynamic(..) => bug!("TyAndLayout::field_type({:?}): not applicable", this),
|
| ty::Dynamic(..) => bug!("TyAndLayout::field({:?}): not applicable", this),
|
||||||
|
|
||||||
// Potentially-fat pointers.
|
// Potentially-fat pointers.
|
||||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||||
@ -2182,17 +2184,19 @@ where
|
|||||||
// as the `Abi` or `FieldsShape` is checked by users.
|
// as the `Abi` or `FieldsShape` is checked by users.
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
let nil = tcx.mk_unit();
|
let nil = tcx.mk_unit();
|
||||||
let ptr_ty = if ty.is_unsafe_ptr() {
|
let unit_ptr_ty = if this.ty.is_unsafe_ptr() {
|
||||||
tcx.mk_mut_ptr(nil)
|
tcx.mk_mut_ptr(nil)
|
||||||
} else {
|
} else {
|
||||||
tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
|
tcx.mk_mut_ref(tcx.lifetimes.re_static, nil)
|
||||||
};
|
};
|
||||||
return TyMaybeWithLayout::TyAndLayout(MaybeResult::from(
|
|
||||||
cx.layout_of(ptr_ty).to_result().map(|mut ptr_layout| {
|
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing
|
||||||
ptr_layout.ty = ty;
|
// the `Result` should always work because the type is
|
||||||
ptr_layout
|
// always either `*mut ()` or `&'static mut ()`.
|
||||||
}),
|
return TyMaybeWithLayout::TyAndLayout(TyAndLayout {
|
||||||
));
|
ty: this.ty,
|
||||||
|
..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
|
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).kind() {
|
||||||
@ -2216,7 +2220,7 @@ where
|
|||||||
])
|
])
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
_ => bug!("TyAndLayout::field_type({:?}): not applicable", this),
|
_ => bug!("TyAndLayout::field({:?}): not applicable", this),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2225,9 +2229,11 @@ where
|
|||||||
ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
|
ty::Str => TyMaybeWithLayout::Ty(tcx.types.u8),
|
||||||
|
|
||||||
// Tuples, generators and closures.
|
// Tuples, generators and closures.
|
||||||
ty::Closure(_, ref substs) => {
|
ty::Closure(_, ref substs) => field_ty_or_layout(
|
||||||
ty_and_layout_kind(this, cx, i, substs.as_closure().tupled_upvars_ty())
|
TyAndLayout { ty: substs.as_closure().tupled_upvars_ty(), ..this },
|
||||||
}
|
cx,
|
||||||
|
i,
|
||||||
|
),
|
||||||
|
|
||||||
ty::Generator(def_id, ref substs, _) => match this.variants {
|
ty::Generator(def_id, ref substs, _) => match this.variants {
|
||||||
Variants::Single { index } => TyMaybeWithLayout::Ty(
|
Variants::Single { index } => TyMaybeWithLayout::Ty(
|
||||||
@ -2270,24 +2276,42 @@ where
|
|||||||
| ty::Opaque(..)
|
| ty::Opaque(..)
|
||||||
| ty::Param(_)
|
| ty::Param(_)
|
||||||
| ty::Infer(_)
|
| ty::Infer(_)
|
||||||
| ty::Error(_) => bug!("TyAndLayout::field_type: unexpected type `{}`", this.ty),
|
| ty::Error(_) => bug!("TyAndLayout::field: unexpected type `{}`", this.ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.layout_of(match ty_and_layout_kind(this, cx, i, this.ty) {
|
match field_ty_or_layout(this, cx, i) {
|
||||||
TyMaybeWithLayout::Ty(result) => result,
|
TyMaybeWithLayout::Ty(field_ty) => {
|
||||||
TyMaybeWithLayout::TyAndLayout(result) => return result,
|
cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| {
|
||||||
})
|
bug!(
|
||||||
|
"failed to get layout for `{}`: {},\n\
|
||||||
|
despite it being a field (#{}) of an existing layout: {:#?}",
|
||||||
|
field_ty,
|
||||||
|
e,
|
||||||
|
i,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
TyMaybeWithLayout::TyAndLayout(field_layout) => field_layout,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pointee_info_at(this: TyAndLayout<'tcx>, cx: &C, offset: Size) -> Option<PointeeInfo> {
|
fn ty_and_layout_pointee_info_at(
|
||||||
|
this: TyAndLayout<'tcx>,
|
||||||
|
cx: &C,
|
||||||
|
offset: Size,
|
||||||
|
) -> Option<PointeeInfo> {
|
||||||
|
let tcx = cx.tcx();
|
||||||
|
let param_env = cx.param_env();
|
||||||
|
|
||||||
let addr_space_of_ty = |ty: Ty<'tcx>| {
|
let addr_space_of_ty = |ty: Ty<'tcx>| {
|
||||||
if ty.is_fn() { cx.data_layout().instruction_address_space } else { AddressSpace::DATA }
|
if ty.is_fn() { cx.data_layout().instruction_address_space } else { AddressSpace::DATA }
|
||||||
};
|
};
|
||||||
|
|
||||||
let pointee_info = match *this.ty.kind() {
|
let pointee_info = match *this.ty.kind() {
|
||||||
ty::RawPtr(mt) if offset.bytes() == 0 => {
|
ty::RawPtr(mt) if offset.bytes() == 0 => {
|
||||||
cx.layout_of(mt.ty).to_result().ok().map(|layout| PointeeInfo {
|
tcx.layout_of(param_env.and(mt.ty)).ok().map(|layout| PointeeInfo {
|
||||||
size: layout.size,
|
size: layout.size,
|
||||||
align: layout.align.abi,
|
align: layout.align.abi,
|
||||||
safe: None,
|
safe: None,
|
||||||
@ -2295,18 +2319,15 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
|
ty::FnPtr(fn_sig) if offset.bytes() == 0 => {
|
||||||
cx.layout_of(cx.tcx().mk_fn_ptr(fn_sig)).to_result().ok().map(|layout| {
|
tcx.layout_of(param_env.and(tcx.mk_fn_ptr(fn_sig))).ok().map(|layout| PointeeInfo {
|
||||||
PointeeInfo {
|
size: layout.size,
|
||||||
size: layout.size,
|
align: layout.align.abi,
|
||||||
align: layout.align.abi,
|
safe: None,
|
||||||
safe: None,
|
address_space: cx.data_layout().instruction_address_space,
|
||||||
address_space: cx.data_layout().instruction_address_space,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
|
ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
|
||||||
let address_space = addr_space_of_ty(ty);
|
let address_space = addr_space_of_ty(ty);
|
||||||
let tcx = cx.tcx();
|
|
||||||
let kind = if tcx.sess.opts.optimize == OptLevel::No {
|
let kind = if tcx.sess.opts.optimize == OptLevel::No {
|
||||||
// Use conservative pointer kind if not optimizing. This saves us the
|
// Use conservative pointer kind if not optimizing. This saves us the
|
||||||
// Freeze/Unpin queries, and can save time in the codegen backend (noalias
|
// Freeze/Unpin queries, and can save time in the codegen backend (noalias
|
||||||
@ -2335,7 +2356,7 @@ where
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.layout_of(ty).to_result().ok().map(|layout| PointeeInfo {
|
tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
|
||||||
size: layout.size,
|
size: layout.size,
|
||||||
align: layout.align.abi,
|
align: layout.align.abi,
|
||||||
safe: Some(kind),
|
safe: Some(kind),
|
||||||
@ -2538,7 +2559,7 @@ impl<'tcx> ty::Instance<'tcx> {
|
|||||||
|
|
||||||
pub trait FnAbiExt<'tcx, C>
|
pub trait FnAbiExt<'tcx, C>
|
||||||
where
|
where
|
||||||
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
C: LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
||||||
+ HasDataLayout
|
+ HasDataLayout
|
||||||
+ HasTargetSpec
|
+ HasTargetSpec
|
||||||
+ HasTyCtxt<'tcx>
|
+ HasTyCtxt<'tcx>
|
||||||
@ -2725,7 +2746,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
|
|||||||
|
|
||||||
impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
|
impl<'tcx, C> FnAbiExt<'tcx, C> for call::FnAbi<'tcx, Ty<'tcx>>
|
||||||
where
|
where
|
||||||
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
C: LayoutOf<'tcx, Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
||||||
+ HasDataLayout
|
+ HasDataLayout
|
||||||
+ HasTargetSpec
|
+ HasTargetSpec
|
||||||
+ HasTyCtxt<'tcx>
|
+ HasTyCtxt<'tcx>
|
||||||
@ -3004,16 +3025,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_thin_self_ptr<'tcx, C>(cx: &C, mut layout: TyAndLayout<'tcx>) -> TyAndLayout<'tcx>
|
fn make_thin_self_ptr<'tcx>(
|
||||||
where
|
cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>),
|
||||||
C: LayoutOf<Ty = Ty<'tcx>, TyAndLayout = TyAndLayout<'tcx>>
|
layout: TyAndLayout<'tcx>,
|
||||||
+ HasTyCtxt<'tcx>
|
) -> TyAndLayout<'tcx> {
|
||||||
+ HasParamEnv<'tcx>,
|
let tcx = cx.tcx();
|
||||||
{
|
|
||||||
let fat_pointer_ty = if layout.is_unsized() {
|
let fat_pointer_ty = if layout.is_unsized() {
|
||||||
// unsized `self` is passed as a pointer to `self`
|
// unsized `self` is passed as a pointer to `self`
|
||||||
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
|
// FIXME (mikeyhew) change this to use &own if it is ever added to the language
|
||||||
cx.tcx().mk_mut_ptr(layout.ty)
|
tcx.mk_mut_ptr(layout.ty)
|
||||||
} else {
|
} else {
|
||||||
match layout.abi {
|
match layout.abi {
|
||||||
Abi::ScalarPair(..) => (),
|
Abi::ScalarPair(..) => (),
|
||||||
@ -3047,8 +3067,13 @@ where
|
|||||||
// we now have a type like `*mut RcBox<dyn Trait>`
|
// we now have a type like `*mut RcBox<dyn Trait>`
|
||||||
// change its layout to that of `*mut ()`, a thin pointer, but keep the same type
|
// change its layout to that of `*mut ()`, a thin pointer, but keep the same type
|
||||||
// this is understood as a special case elsewhere in the compiler
|
// this is understood as a special case elsewhere in the compiler
|
||||||
let unit_pointer_ty = cx.tcx().mk_mut_ptr(cx.tcx().mk_unit());
|
let unit_ptr_ty = tcx.mk_mut_ptr(tcx.mk_unit());
|
||||||
layout = cx.layout_of(unit_pointer_ty);
|
|
||||||
layout.ty = fat_pointer_ty;
|
TyAndLayout {
|
||||||
layout
|
ty: fat_pointer_ty,
|
||||||
|
|
||||||
|
// NOTE(eddyb) using an empty `ParamEnv`, and `unwrap`-ing the `Result`
|
||||||
|
// should always work because the type is always `*mut ()`.
|
||||||
|
..tcx.layout_of(ty::ParamEnv::reveal_all().and(unit_ptr_ty)).unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,7 +340,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
// Example: `Arc<T>` -> `Arc<Trait>`
|
// Example: `Arc<T>` -> `Arc<Trait>`
|
||||||
// here we need to increase the size of every &T thin ptr field to a fat ptr
|
// here we need to increase the size of every &T thin ptr field to a fat ptr
|
||||||
for i in 0..src.layout.fields.count() {
|
for i in 0..src.layout.fields.count() {
|
||||||
let cast_ty_field = cast_ty.field(self, i)?;
|
let cast_ty_field = cast_ty.field(self, i);
|
||||||
if cast_ty_field.is_zst() {
|
if cast_ty_field.is_zst() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
|
impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf<'tcx> for InterpCx<'mir, 'tcx, M> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>;
|
type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>;
|
||||||
|
|
||||||
@ -592,7 +592,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
// Recurse to get the size of the dynamically sized field (must be
|
// Recurse to get the size of the dynamically sized field (must be
|
||||||
// the last field). Can't have foreign types here, how would we
|
// the last field). Can't have foreign types here, how would we
|
||||||
// adjust alignment and size for them?
|
// adjust alignment and size for them?
|
||||||
let field = layout.field(self, layout.fields.count() - 1)?;
|
let field = layout.field(self, layout.fields.count() - 1);
|
||||||
let (unsized_size, unsized_align) =
|
let (unsized_size, unsized_align) =
|
||||||
match self.size_and_align_of(metadata, &field)? {
|
match self.size_and_align_of(metadata, &field)? {
|
||||||
Some(size_and_align) => size_and_align,
|
Some(size_and_align) => size_and_align,
|
||||||
@ -645,7 +645,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
|
|
||||||
ty::Slice(_) | ty::Str => {
|
ty::Slice(_) | ty::Str => {
|
||||||
let len = metadata.unwrap_meta().to_machine_usize(self)?;
|
let len = metadata.unwrap_meta().to_machine_usize(self)?;
|
||||||
let elem = layout.field(self, 0)?;
|
let elem = layout.field(self, 0);
|
||||||
|
|
||||||
// Make sure the slice is not too big.
|
// Make sure the slice is not too big.
|
||||||
let size = elem.size.checked_mul(len, self).ok_or_else(|| {
|
let size = elem.size.checked_mul(len, self).ok_or_else(|| {
|
||||||
|
@ -364,7 +364,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
Err(value) => value,
|
Err(value) => value,
|
||||||
};
|
};
|
||||||
|
|
||||||
let field_layout = op.layout.field(self, field)?;
|
let field_layout = op.layout.field(self, field);
|
||||||
if field_layout.is_zst() {
|
if field_layout.is_zst() {
|
||||||
let immediate = Scalar::ZST.into();
|
let immediate = Scalar::ZST.into();
|
||||||
return Ok(OpTy { op: Operand::Immediate(immediate), layout: field_layout });
|
return Ok(OpTy { op: Operand::Immediate(immediate), layout: field_layout });
|
||||||
|
@ -355,7 +355,7 @@ where
|
|||||||
field: usize,
|
field: usize,
|
||||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
|
||||||
let offset = base.layout.fields.offset(field);
|
let offset = base.layout.fields.offset(field);
|
||||||
let field_layout = base.layout.field(self, field)?;
|
let field_layout = base.layout.field(self, field);
|
||||||
|
|
||||||
// Offset may need adjustment for unsized fields.
|
// Offset may need adjustment for unsized fields.
|
||||||
let (meta, offset) = if field_layout.is_unsized() {
|
let (meta, offset) = if field_layout.is_unsized() {
|
||||||
@ -405,7 +405,7 @@ where
|
|||||||
}
|
}
|
||||||
let offset = stride * index; // `Size` multiplication
|
let offset = stride * index; // `Size` multiplication
|
||||||
// All fields have the same layout.
|
// All fields have the same layout.
|
||||||
let field_layout = base.layout.field(self, 0)?;
|
let field_layout = base.layout.field(self, 0);
|
||||||
|
|
||||||
assert!(!field_layout.is_unsized());
|
assert!(!field_layout.is_unsized());
|
||||||
base.offset(offset, MemPlaceMeta::None, field_layout, self)
|
base.offset(offset, MemPlaceMeta::None, field_layout, self)
|
||||||
@ -430,7 +430,7 @@ where
|
|||||||
FieldsShape::Array { stride, .. } => stride,
|
FieldsShape::Array { stride, .. } => stride,
|
||||||
_ => span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"),
|
_ => span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"),
|
||||||
};
|
};
|
||||||
let layout = base.layout.field(self, 0)?;
|
let layout = base.layout.field(self, 0);
|
||||||
let dl = &self.tcx.data_layout;
|
let dl = &self.tcx.data_layout;
|
||||||
// `Size` multiplication
|
// `Size` multiplication
|
||||||
Ok((0..len).map(move |i| base.offset(stride * i, MemPlaceMeta::None, layout, dl)))
|
Ok((0..len).map(move |i| base.offset(stride * i, MemPlaceMeta::None, layout, dl)))
|
||||||
|
@ -461,7 +461,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
// a thin pointer.
|
// a thin pointer.
|
||||||
assert!(receiver_place.layout.is_unsized());
|
assert!(receiver_place.layout.is_unsized());
|
||||||
let receiver_ptr_ty = self.tcx.mk_mut_ptr(receiver_place.layout.ty);
|
let receiver_ptr_ty = self.tcx.mk_mut_ptr(receiver_place.layout.ty);
|
||||||
let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0)?;
|
let this_receiver_ptr = self.layout_of(receiver_ptr_ty)?.field(self, 0);
|
||||||
// Adjust receiver argument.
|
// Adjust receiver argument.
|
||||||
args[0] = OpTy::from(ImmTy::from_immediate(
|
args[0] = OpTy::from(ImmTy::from_immediate(
|
||||||
Scalar::from_maybe_pointer(receiver_place.ptr, self).into(),
|
Scalar::from_maybe_pointer(receiver_place.ptr, self).into(),
|
||||||
|
@ -17,7 +17,7 @@ use rustc_middle::mir::{
|
|||||||
Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
|
Location, Operand, Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement,
|
||||||
StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
|
StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE,
|
||||||
};
|
};
|
||||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutError, TyAndLayout};
|
use rustc_middle::ty::layout::{LayoutError, TyAndLayout};
|
||||||
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
use rustc_middle::ty::subst::{InternalSubsts, Subst};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable,
|
self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable,
|
||||||
@ -330,7 +330,7 @@ struct ConstPropagator<'mir, 'tcx> {
|
|||||||
source_info: Option<SourceInfo>,
|
source_info: Option<SourceInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> {
|
impl<'mir, 'tcx> LayoutOf<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
type TyAndLayout = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
|
||||||
|
|
||||||
@ -346,13 +346,20 @@ impl<'mir, 'tcx> HasDataLayout for ConstPropagator<'mir, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> {
|
impl<'mir, 'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn tcx(&self) -> TyCtxt<'tcx> {
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
||||||
self.tcx
|
self.tcx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'mir, 'tcx> ty::layout::HasParamEnv<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||||
|
#[inline]
|
||||||
|
fn param_env(&self) -> ty::ParamEnv<'tcx> {
|
||||||
|
self.param_env
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||||
fn new(
|
fn new(
|
||||||
body: &Body<'tcx>,
|
body: &Body<'tcx>,
|
||||||
|
@ -113,7 +113,7 @@ struct UnwrapLayoutCx<'tcx> {
|
|||||||
param_env: ParamEnv<'tcx>,
|
param_env: ParamEnv<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayoutOf for UnwrapLayoutCx<'tcx> {
|
impl LayoutOf<'tcx> for UnwrapLayoutCx<'tcx> {
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type TyAndLayout = TyAndLayout<'tcx>;
|
type TyAndLayout = TyAndLayout<'tcx>;
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
|
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
|
||||||
use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{HasDataLayout, TyAbiInterface};
|
||||||
|
|
||||||
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
|
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
|
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
|
||||||
let size = arg.layout.size;
|
let size = arg.layout.size;
|
||||||
@ -26,8 +26,8 @@ where
|
|||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !ret.layout.is_aggregate() {
|
if !ret.layout.is_aggregate() {
|
||||||
ret.extend_integer_width_to(32);
|
ret.extend_integer_width_to(32);
|
||||||
@ -48,8 +48,8 @@ where
|
|||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !arg.layout.is_aggregate() {
|
if !arg.layout.is_aggregate() {
|
||||||
arg.extend_integer_width_to(32);
|
arg.extend_integer_width_to(32);
|
||||||
@ -70,8 +70,8 @@ where
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
classify_ret(cx, &mut fn_abi.ret);
|
classify_ret(cx, &mut fn_abi.ret);
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
use crate::abi::call::{ArgAbi, FnAbi};
|
use crate::abi::call::{ArgAbi, FnAbi};
|
||||||
use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{HasDataLayout, TyAbiInterface};
|
||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(_cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
fn classify_ret<'a, Ty, C>(_cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
ret.extend_integer_width_to(32);
|
ret.extend_integer_width_to(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(_cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
fn classify_arg<'a, Ty, C>(_cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
arg.extend_integer_width_to(32);
|
arg.extend_integer_width_to(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
classify_ret(cx, &mut fn_abi.ret);
|
classify_ret(cx, &mut fn_abi.ret);
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::abi::call::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform};
|
use crate::abi::call::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform};
|
||||||
use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{HasDataLayout, TyAbiInterface};
|
||||||
use crate::spec::HasTargetSpec;
|
use crate::spec::HasTargetSpec;
|
||||||
|
|
||||||
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
|
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
|
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
|
||||||
let size = arg.layout.size;
|
let size = arg.layout.size;
|
||||||
@ -27,8 +27,8 @@ where
|
|||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool)
|
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, vfp: bool)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !ret.layout.is_aggregate() {
|
if !ret.layout.is_aggregate() {
|
||||||
ret.extend_integer_width_to(32);
|
ret.extend_integer_width_to(32);
|
||||||
@ -53,8 +53,8 @@ where
|
|||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool)
|
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, vfp: bool)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !arg.layout.is_aggregate() {
|
if !arg.layout.is_aggregate() {
|
||||||
arg.extend_integer_width_to(32);
|
arg.extend_integer_width_to(32);
|
||||||
@ -75,8 +75,8 @@ where
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
|
C: HasDataLayout + HasTargetSpec,
|
||||||
{
|
{
|
||||||
// If this is a target with a hard-float ABI, and the function is not explicitly
|
// If this is a target with a hard-float ABI, and the function is not explicitly
|
||||||
// `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
|
// `extern "aapcs"`, then we must use the VFP registers for homogeneous aggregates.
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
|
use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
|
||||||
use crate::abi::{HasDataLayout, LayoutOf, Size, TyAndLayoutMethods};
|
use crate::abi::{HasDataLayout, Size};
|
||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
|
fn classify_ret<Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
C: HasDataLayout,
|
||||||
C: LayoutOf<Ty = Ty> + HasDataLayout,
|
|
||||||
{
|
{
|
||||||
if !ret.layout.is_aggregate() {
|
if !ret.layout.is_aggregate() {
|
||||||
ret.extend_integer_width_to(32);
|
ret.extend_integer_width_to(32);
|
||||||
@ -14,10 +13,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
|
fn classify_arg<Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
C: HasDataLayout,
|
||||||
C: LayoutOf<Ty = Ty> + HasDataLayout,
|
|
||||||
{
|
{
|
||||||
let dl = cx.data_layout();
|
let dl = cx.data_layout();
|
||||||
let size = arg.layout.size;
|
let size = arg.layout.size;
|
||||||
@ -35,10 +33,9 @@ where
|
|||||||
*offset = offset.align_to(align) + size.align_to(align);
|
*offset = offset.align_to(align) + size.align_to(align);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
|
pub fn compute_abi_info<Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
C: HasDataLayout,
|
||||||
C: LayoutOf<Ty = Ty> + HasDataLayout,
|
|
||||||
{
|
{
|
||||||
let mut offset = Size::ZERO;
|
let mut offset = Size::ZERO;
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
||||||
use crate::abi::{self, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
|
||||||
|
|
||||||
fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
|
fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
|
||||||
// Always sign extend u32 values on 64-bit mips
|
// Always sign extend u32 values on 64-bit mips
|
||||||
@ -19,8 +19,8 @@ fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
|
|||||||
|
|
||||||
fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
|
fn float_reg<'a, Ty, C>(cx: &C, ret: &ArgAbi<'a, Ty>, i: usize) -> Option<Reg>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
match ret.layout.field(cx, i).abi {
|
match ret.layout.field(cx, i).abi {
|
||||||
abi::Abi::Scalar(ref scalar) => match scalar.value {
|
abi::Abi::Scalar(ref scalar) => match scalar.value {
|
||||||
@ -34,8 +34,8 @@ where
|
|||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !ret.layout.is_aggregate() {
|
if !ret.layout.is_aggregate() {
|
||||||
extend_integer_width_mips(ret, 64);
|
extend_integer_width_mips(ret, 64);
|
||||||
@ -74,8 +74,8 @@ where
|
|||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !arg.layout.is_aggregate() {
|
if !arg.layout.is_aggregate() {
|
||||||
extend_integer_width_mips(arg, 64);
|
extend_integer_width_mips(arg, 64);
|
||||||
@ -144,8 +144,8 @@ where
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
classify_ret(cx, &mut fn_abi.ret);
|
classify_ret(cx, &mut fn_abi.ret);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::abi::{self, Abi, Align, FieldsShape, Size};
|
use crate::abi::{self, Abi, Align, FieldsShape, Size};
|
||||||
use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
|
||||||
use crate::spec::{self, HasTargetSpec};
|
use crate::spec::{self, HasTargetSpec};
|
||||||
|
|
||||||
mod aarch64;
|
mod aarch64;
|
||||||
@ -316,8 +316,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||||||
/// specific targets.
|
/// specific targets.
|
||||||
pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
|
pub fn homogeneous_aggregate<C>(&self, cx: &C) -> Result<HomogeneousAggregate, Heterogeneous>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = Self>,
|
|
||||||
{
|
{
|
||||||
match self.abi {
|
match self.abi {
|
||||||
Abi::Uninhabited => Err(Heterogeneous),
|
Abi::Uninhabited => Err(Heterogeneous),
|
||||||
@ -603,8 +602,8 @@ pub struct FnAbi<'a, Ty> {
|
|||||||
impl<'a, Ty> FnAbi<'a, Ty> {
|
impl<'a, Ty> FnAbi<'a, Ty> {
|
||||||
pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String>
|
pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), String>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
|
C: HasDataLayout + HasTargetSpec,
|
||||||
{
|
{
|
||||||
if abi == spec::abi::Abi::X86Interrupt {
|
if abi == spec::abi::Abi::X86Interrupt {
|
||||||
if let Some(arg) = self.args.first_mut() {
|
if let Some(arg) = self.args.first_mut() {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// need to be fixed when PowerPC vector support is added.
|
// need to be fixed when PowerPC vector support is added.
|
||||||
|
|
||||||
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
|
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
|
||||||
use crate::abi::{Endian, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{Endian, HasDataLayout, TyAbiInterface};
|
||||||
use crate::spec::HasTargetSpec;
|
use crate::spec::HasTargetSpec;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
@ -19,8 +19,8 @@ fn is_homogeneous_aggregate<'a, Ty, C>(
|
|||||||
abi: ABI,
|
abi: ABI,
|
||||||
) -> Option<Uniform>
|
) -> Option<Uniform>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
|
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
|
||||||
// ELFv1 only passes one-member aggregates transparently.
|
// ELFv1 only passes one-member aggregates transparently.
|
||||||
@ -43,8 +43,8 @@ where
|
|||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI)
|
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, abi: ABI)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !ret.layout.is_aggregate() {
|
if !ret.layout.is_aggregate() {
|
||||||
ret.extend_integer_width_to(64);
|
ret.extend_integer_width_to(64);
|
||||||
@ -86,8 +86,8 @@ where
|
|||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
|
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, abi: ABI)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !arg.layout.is_aggregate() {
|
if !arg.layout.is_aggregate() {
|
||||||
arg.extend_integer_width_to(64);
|
arg.extend_integer_width_to(64);
|
||||||
@ -116,8 +116,8 @@ where
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
|
C: HasDataLayout + HasTargetSpec,
|
||||||
{
|
{
|
||||||
let abi = if cx.target_spec().env == "musl" {
|
let abi = if cx.target_spec().env == "musl" {
|
||||||
ELFv2
|
ELFv2
|
||||||
|
@ -5,9 +5,7 @@
|
|||||||
// https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
|
// https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
|
||||||
|
|
||||||
use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
|
||||||
use crate::abi::{
|
use crate::abi::{self, Abi, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
|
||||||
self, Abi, FieldsShape, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods,
|
|
||||||
};
|
|
||||||
use crate::spec::HasTargetSpec;
|
use crate::spec::HasTargetSpec;
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@ -43,8 +41,7 @@ fn should_use_fp_conv_helper<'a, Ty, C>(
|
|||||||
field2_kind: &mut RegPassKind,
|
field2_kind: &mut RegPassKind,
|
||||||
) -> Result<(), CannotUseFpConv>
|
) -> Result<(), CannotUseFpConv>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
|
|
||||||
{
|
{
|
||||||
match arg_layout.abi {
|
match arg_layout.abi {
|
||||||
Abi::Scalar(ref scalar) => match scalar.value {
|
Abi::Scalar(ref scalar) => match scalar.value {
|
||||||
@ -130,8 +127,7 @@ fn should_use_fp_conv<'a, Ty, C>(
|
|||||||
flen: u64,
|
flen: u64,
|
||||||
) -> Option<FloatConv>
|
) -> Option<FloatConv>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
|
|
||||||
{
|
{
|
||||||
let mut field1_kind = RegPassKind::Unknown;
|
let mut field1_kind = RegPassKind::Unknown;
|
||||||
let mut field2_kind = RegPassKind::Unknown;
|
let mut field2_kind = RegPassKind::Unknown;
|
||||||
@ -149,8 +145,7 @@ where
|
|||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u64) -> bool
|
fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u64) -> bool
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
|
|
||||||
{
|
{
|
||||||
if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) {
|
if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) {
|
||||||
match conv {
|
match conv {
|
||||||
@ -212,8 +207,7 @@ fn classify_arg<'a, Ty, C>(
|
|||||||
avail_gprs: &mut u64,
|
avail_gprs: &mut u64,
|
||||||
avail_fprs: &mut u64,
|
avail_fprs: &mut u64,
|
||||||
) where
|
) where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>>,
|
|
||||||
{
|
{
|
||||||
if !is_vararg {
|
if !is_vararg {
|
||||||
match should_use_fp_conv(cx, &arg.layout, xlen, flen) {
|
match should_use_fp_conv(cx, &arg.layout, xlen, flen) {
|
||||||
@ -320,8 +314,8 @@ fn extend_integer_width<'a, Ty>(arg: &mut ArgAbi<'a, Ty>, xlen: u64) {
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
|
C: HasDataLayout + HasTargetSpec,
|
||||||
{
|
{
|
||||||
let flen = match &cx.target_spec().llvm_abiname[..] {
|
let flen = match &cx.target_spec().llvm_abiname[..] {
|
||||||
"ilp32f" | "lp64f" => 32,
|
"ilp32f" | "lp64f" => 32,
|
||||||
|
@ -2,13 +2,9 @@
|
|||||||
// for a pre-z13 machine or using -mno-vx.
|
// for a pre-z13 machine or using -mno-vx.
|
||||||
|
|
||||||
use crate::abi::call::{ArgAbi, FnAbi, Reg};
|
use crate::abi::call::{ArgAbi, FnAbi, Reg};
|
||||||
use crate::abi::{self, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{self, HasDataLayout, TyAbiInterface, TyAndLayout};
|
||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(ret: &mut ArgAbi<'_, Ty>)
|
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
|
||||||
where
|
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
|
||||||
C: LayoutOf<Ty = Ty> + HasDataLayout,
|
|
||||||
{
|
|
||||||
if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
|
if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 {
|
||||||
ret.extend_integer_width_to(64);
|
ret.extend_integer_width_to(64);
|
||||||
} else {
|
} else {
|
||||||
@ -18,8 +14,8 @@ where
|
|||||||
|
|
||||||
fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
|
fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
Ty: TyAbiInterface<'a, C>,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
match layout.abi {
|
match layout.abi {
|
||||||
abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
|
abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
|
||||||
@ -36,8 +32,8 @@ where
|
|||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
|
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
|
||||||
arg.extend_integer_width_to(64);
|
arg.extend_integer_width_to(64);
|
||||||
@ -63,8 +59,8 @@ where
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
classify_ret(&mut fn_abi.ret);
|
classify_ret(&mut fn_abi.ret);
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
|
use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
|
||||||
use crate::abi::{HasDataLayout, LayoutOf, Size, TyAndLayoutMethods};
|
use crate::abi::{HasDataLayout, Size};
|
||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
|
fn classify_ret<Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
C: HasDataLayout,
|
||||||
C: LayoutOf<Ty = Ty> + HasDataLayout,
|
|
||||||
{
|
{
|
||||||
if !ret.layout.is_aggregate() {
|
if !ret.layout.is_aggregate() {
|
||||||
ret.extend_integer_width_to(32);
|
ret.extend_integer_width_to(32);
|
||||||
@ -14,10 +13,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
|
fn classify_arg<Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
C: HasDataLayout,
|
||||||
C: LayoutOf<Ty = Ty> + HasDataLayout,
|
|
||||||
{
|
{
|
||||||
let dl = cx.data_layout();
|
let dl = cx.data_layout();
|
||||||
let size = arg.layout.size;
|
let size = arg.layout.size;
|
||||||
@ -35,10 +33,9 @@ where
|
|||||||
*offset = offset.align_to(align) + size.align_to(align);
|
*offset = offset.align_to(align) + size.align_to(align);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
|
pub fn compute_abi_info<Ty, C>(cx: &C, fn_abi: &mut FnAbi<'_, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
C: HasDataLayout,
|
||||||
C: LayoutOf<Ty = Ty> + HasDataLayout,
|
|
||||||
{
|
{
|
||||||
let mut offset = Size::ZERO;
|
let mut offset = Size::ZERO;
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// FIXME: This needs an audit for correctness and completeness.
|
// FIXME: This needs an audit for correctness and completeness.
|
||||||
|
|
||||||
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
|
use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
|
||||||
use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{HasDataLayout, TyAbiInterface};
|
||||||
|
|
||||||
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
|
fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
|
arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| {
|
||||||
// Ensure we have at most eight uniquely addressable members.
|
// Ensure we have at most eight uniquely addressable members.
|
||||||
@ -26,8 +26,8 @@ where
|
|||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !ret.layout.is_aggregate() {
|
if !ret.layout.is_aggregate() {
|
||||||
ret.extend_integer_width_to(64);
|
ret.extend_integer_width_to(64);
|
||||||
@ -52,8 +52,8 @@ where
|
|||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !arg.layout.is_aggregate() {
|
if !arg.layout.is_aggregate() {
|
||||||
arg.extend_integer_width_to(64);
|
arg.extend_integer_width_to(64);
|
||||||
@ -76,8 +76,8 @@ where
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
classify_ret(cx, &mut fn_abi.ret);
|
classify_ret(cx, &mut fn_abi.ret);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::abi::call::{ArgAbi, FnAbi, Uniform};
|
use crate::abi::call::{ArgAbi, FnAbi, Uniform};
|
||||||
use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{HasDataLayout, TyAbiInterface};
|
||||||
|
|
||||||
fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool
|
fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if val.layout.is_aggregate() {
|
if val.layout.is_aggregate() {
|
||||||
if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
|
if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
|
||||||
@ -20,8 +20,8 @@ where
|
|||||||
|
|
||||||
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
ret.extend_integer_width_to(32);
|
ret.extend_integer_width_to(32);
|
||||||
if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) {
|
if ret.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, ret) {
|
||||||
@ -31,8 +31,8 @@ where
|
|||||||
|
|
||||||
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
arg.extend_integer_width_to(32);
|
arg.extend_integer_width_to(32);
|
||||||
if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) {
|
if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) {
|
||||||
@ -43,8 +43,8 @@ where
|
|||||||
/// The purpose of this ABI is to match the C ABI (aka clang) exactly.
|
/// The purpose of this ABI is to match the C ABI (aka clang) exactly.
|
||||||
pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_c_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
classify_ret(cx, &mut fn_abi.ret);
|
classify_ret(cx, &mut fn_abi.ret);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
|
use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
|
||||||
use crate::abi::{self, HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{self, HasDataLayout, TyAbiInterface, TyAndLayout};
|
||||||
use crate::spec::HasTargetSpec;
|
use crate::spec::HasTargetSpec;
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
@ -10,8 +10,8 @@ pub enum Flavor {
|
|||||||
|
|
||||||
fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
|
fn is_single_fp_element<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
match layout.abi {
|
match layout.abi {
|
||||||
abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
|
abi::Abi::Scalar(ref scalar) => scalar.value.is_float(),
|
||||||
@ -28,8 +28,8 @@ where
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, flavor: Flavor)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
|
C: HasDataLayout + HasTargetSpec,
|
||||||
{
|
{
|
||||||
if !fn_abi.ret.is_ignore() {
|
if !fn_abi.ret.is_ignore() {
|
||||||
if fn_abi.ret.layout.is_aggregate() {
|
if fn_abi.ret.layout.is_aggregate() {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
|
// https://github.com/jckarter/clay/blob/master/compiler/src/externals.cpp
|
||||||
|
|
||||||
use crate::abi::call::{ArgAbi, CastTarget, FnAbi, Reg, RegKind};
|
use crate::abi::call::{ArgAbi, CastTarget, FnAbi, Reg, RegKind};
|
||||||
use crate::abi::{self, Abi, HasDataLayout, LayoutOf, Size, TyAndLayout, TyAndLayoutMethods};
|
use crate::abi::{self, Abi, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
|
||||||
|
|
||||||
/// Classification of "eightbyte" components.
|
/// Classification of "eightbyte" components.
|
||||||
// N.B., the order of the variants is from general to specific,
|
// N.B., the order of the variants is from general to specific,
|
||||||
@ -26,8 +26,8 @@ fn classify_arg<'a, Ty, C>(
|
|||||||
arg: &ArgAbi<'a, Ty>,
|
arg: &ArgAbi<'a, Ty>,
|
||||||
) -> Result<[Option<Class>; MAX_EIGHTBYTES], Memory>
|
) -> Result<[Option<Class>; MAX_EIGHTBYTES], Memory>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
fn classify<'a, Ty, C>(
|
fn classify<'a, Ty, C>(
|
||||||
cx: &C,
|
cx: &C,
|
||||||
@ -36,8 +36,8 @@ where
|
|||||||
off: Size,
|
off: Size,
|
||||||
) -> Result<(), Memory>
|
) -> Result<(), Memory>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
if !off.is_aligned(layout.align.abi) {
|
if !off.is_aligned(layout.align.abi) {
|
||||||
if !layout.is_zst() {
|
if !layout.is_zst() {
|
||||||
@ -172,8 +172,8 @@ const MAX_SSE_REGS: usize = 8; // XMM0-7
|
|||||||
|
|
||||||
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C> + Copy,
|
Ty: TyAbiInterface<'a, C> + Copy,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
let mut int_regs = MAX_INT_REGS;
|
let mut int_regs = MAX_INT_REGS;
|
||||||
let mut sse_regs = MAX_SSE_REGS;
|
let mut sse_regs = MAX_SSE_REGS;
|
||||||
|
@ -1174,9 +1174,9 @@ impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Trait for context types that can compute layouts of things.
|
/// Trait for context types that can compute layouts of things.
|
||||||
pub trait LayoutOf {
|
pub trait LayoutOf<'a>: Sized {
|
||||||
type Ty;
|
type Ty: TyAbiInterface<'a, Self>;
|
||||||
type TyAndLayout;
|
type TyAndLayout: MaybeResult<TyAndLayout<'a, Self::Ty>>;
|
||||||
|
|
||||||
fn layout_of(&self, ty: Self::Ty) -> Self::TyAndLayout;
|
fn layout_of(&self, ty: Self::Ty) -> Self::TyAndLayout;
|
||||||
fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyAndLayout {
|
fn spanned_layout_of(&self, ty: Self::Ty, _span: Span) -> Self::TyAndLayout {
|
||||||
@ -1184,9 +1184,6 @@ pub trait LayoutOf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `TyAndLayout` above will always be a `MaybeResult<TyAndLayout<'_, Self>>`.
|
|
||||||
/// We can't add the bound due to the lifetime, but this trait is still useful when
|
|
||||||
/// writing code that's generic over the `LayoutOf` impl.
|
|
||||||
pub trait MaybeResult<T> {
|
pub trait MaybeResult<T> {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
@ -1239,41 +1236,42 @@ pub struct PointeeInfo {
|
|||||||
pub address_space: AddressSpace,
|
pub address_space: AddressSpace,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TyAndLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
|
/// Trait that needs to be implemented by the higher-level type representation
|
||||||
fn for_variant(
|
/// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality.
|
||||||
|
pub trait TyAbiInterface<'a, C>: Sized {
|
||||||
|
fn ty_and_layout_for_variant(
|
||||||
this: TyAndLayout<'a, Self>,
|
this: TyAndLayout<'a, Self>,
|
||||||
cx: &C,
|
cx: &C,
|
||||||
variant_index: VariantIdx,
|
variant_index: VariantIdx,
|
||||||
) -> TyAndLayout<'a, Self>;
|
) -> TyAndLayout<'a, Self>;
|
||||||
fn field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> C::TyAndLayout;
|
fn ty_and_layout_field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> TyAndLayout<'a, Self>;
|
||||||
fn pointee_info_at(this: TyAndLayout<'a, Self>, cx: &C, offset: Size) -> Option<PointeeInfo>;
|
fn ty_and_layout_pointee_info_at(
|
||||||
|
this: TyAndLayout<'a, Self>,
|
||||||
|
cx: &C,
|
||||||
|
offset: Size,
|
||||||
|
) -> Option<PointeeInfo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||||
pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
|
pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
Ty: TyAbiInterface<'a, C>,
|
||||||
C: LayoutOf<Ty = Ty>,
|
|
||||||
{
|
{
|
||||||
Ty::for_variant(self, cx, variant_index)
|
Ty::ty_and_layout_for_variant(self, cx, variant_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Callers might want to use `C: LayoutOf<Ty=Ty, TyAndLayout: MaybeResult<Self>>`
|
pub fn field<C>(self, cx: &C, i: usize) -> Self
|
||||||
/// to allow recursion (see `might_permit_zero_init` below for an example).
|
|
||||||
pub fn field<C>(self, cx: &C, i: usize) -> C::TyAndLayout
|
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
Ty: TyAbiInterface<'a, C>,
|
||||||
C: LayoutOf<Ty = Ty>,
|
|
||||||
{
|
{
|
||||||
Ty::field(self, cx, i)
|
Ty::ty_and_layout_field(self, cx, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
|
pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
|
||||||
where
|
where
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
Ty: TyAbiInterface<'a, C>,
|
||||||
C: LayoutOf<Ty = Ty>,
|
|
||||||
{
|
{
|
||||||
Ty::pointee_info_at(self, cx, offset)
|
Ty::ty_and_layout_pointee_info_at(self, cx, offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1301,11 +1299,11 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||||||
/// FIXME: Once we removed all the conservatism, we could alternatively
|
/// FIXME: Once we removed all the conservatism, we could alternatively
|
||||||
/// create an all-0/all-undef constant and run the const value validator to see if
|
/// create an all-0/all-undef constant and run the const value validator to see if
|
||||||
/// this is a valid value for the given type.
|
/// this is a valid value for the given type.
|
||||||
pub fn might_permit_raw_init<C, E>(self, cx: &C, zero: bool) -> Result<bool, E>
|
pub fn might_permit_raw_init<C>(self, cx: &C, zero: bool) -> bool
|
||||||
where
|
where
|
||||||
Self: Copy,
|
Self: Copy,
|
||||||
Ty: TyAndLayoutMethods<'a, C>,
|
Ty: TyAbiInterface<'a, C>,
|
||||||
C: LayoutOf<Ty = Ty, TyAndLayout: MaybeResult<Self, Error = E>> + HasDataLayout,
|
C: HasDataLayout,
|
||||||
{
|
{
|
||||||
let scalar_allows_raw_init = move |s: &Scalar| -> bool {
|
let scalar_allows_raw_init = move |s: &Scalar| -> bool {
|
||||||
if zero {
|
if zero {
|
||||||
@ -1330,7 +1328,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||||||
};
|
};
|
||||||
if !valid {
|
if !valid {
|
||||||
// This is definitely not okay.
|
// This is definitely not okay.
|
||||||
return Ok(false);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have not found an error yet, we need to recursively descend into fields.
|
// If we have not found an error yet, we need to recursively descend into fields.
|
||||||
@ -1341,16 +1339,15 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
|||||||
}
|
}
|
||||||
FieldsShape::Arbitrary { offsets, .. } => {
|
FieldsShape::Arbitrary { offsets, .. } => {
|
||||||
for idx in 0..offsets.len() {
|
for idx in 0..offsets.len() {
|
||||||
let field = self.field(cx, idx).to_result()?;
|
if !self.field(cx, idx).might_permit_raw_init(cx, zero) {
|
||||||
if !field.might_permit_raw_init(cx, zero)? {
|
|
||||||
// We found a field that is unhappy with this kind of initialization.
|
// We found a field that is unhappy with this kind of initialization.
|
||||||
return Ok(false);
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(#66151): For now, we are conservative and do not check `self.variants`.
|
// FIXME(#66151): For now, we are conservative and do not check `self.variants`.
|
||||||
Ok(true)
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user