Auto merge of #70629 - anyska:fields-variant, r=oli-obk
rustc_target::abi: add Primitive variant to FieldsShape. Originally suggested by @eddyb.
This commit is contained in:
commit
b2c1a606fe
@ -81,7 +81,7 @@ fn uncached_llvm_type<'a, 'tcx>(
|
||||
};
|
||||
|
||||
match layout.fields {
|
||||
FieldsShape::Union(_) => {
|
||||
FieldsShape::Primitive | FieldsShape::Union(_) => {
|
||||
let fill = cx.type_padding_filler(layout.size, layout.align.abi);
|
||||
let packed = false;
|
||||
match name {
|
||||
@ -368,7 +368,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
||||
_ => {}
|
||||
}
|
||||
match self.fields {
|
||||
FieldsShape::Union(_) => {
|
||||
FieldsShape::Primitive | FieldsShape::Union(_) => {
|
||||
bug!("TyAndLayout::llvm_field_index({:?}): not applicable", self)
|
||||
}
|
||||
|
||||
|
@ -210,6 +210,12 @@ impl<CTX> HashStable<CTX> for ::std::num::NonZeroU32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX> HashStable<CTX> for ::std::num::NonZeroUsize {
|
||||
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
|
||||
self.get().hash_stable(ctx, hasher)
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX> HashStable<CTX> for f32 {
|
||||
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
|
||||
let val: u32 = unsafe { ::std::mem::transmute(*self) };
|
||||
|
@ -22,6 +22,7 @@ use std::cmp;
|
||||
use std::fmt;
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::ops::Bound;
|
||||
|
||||
pub trait IntegerExt {
|
||||
@ -518,7 +519,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
// The never type.
|
||||
ty::Never => tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldsShape::Union(0),
|
||||
fields: FieldsShape::Primitive,
|
||||
abi: Abi::Uninhabited,
|
||||
largest_niche: None,
|
||||
align: dl.i8_align,
|
||||
@ -744,7 +745,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
|
||||
return Ok(tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index },
|
||||
fields: FieldsShape::Union(variants[index].len()),
|
||||
fields: FieldsShape::Union(
|
||||
NonZeroUsize::new(variants[index].len())
|
||||
.ok_or(LayoutError::Unknown(ty))?,
|
||||
),
|
||||
abi,
|
||||
largest_niche: None,
|
||||
align,
|
||||
@ -1988,7 +1992,7 @@ where
|
||||
if index == variant_index &&
|
||||
// Don't confuse variants of uninhabited enums with the enum itself.
|
||||
// For more details see https://github.com/rust-lang/rust/issues/69763.
|
||||
this.fields != FieldsShape::Union(0) =>
|
||||
this.fields != FieldsShape::Primitive =>
|
||||
{
|
||||
this.layout
|
||||
}
|
||||
@ -2006,7 +2010,10 @@ where
|
||||
let tcx = cx.tcx();
|
||||
tcx.intern_layout(Layout {
|
||||
variants: Variants::Single { index: variant_index },
|
||||
fields: FieldsShape::Union(fields),
|
||||
fields: match NonZeroUsize::new(fields) {
|
||||
Some(fields) => FieldsShape::Union(fields),
|
||||
None => FieldsShape::Arbitrary { offsets: vec![], memory_index: vec![] },
|
||||
},
|
||||
abi: Abi::Uninhabited,
|
||||
largest_niche: None,
|
||||
align: tcx.data_layout.i8_align,
|
||||
|
@ -6,6 +6,7 @@
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::Write;
|
||||
use std::num::NonZeroUsize;
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
@ -647,10 +648,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn visit_union(&mut self, op: OpTy<'tcx, M::PointerTag>, fields: usize) -> InterpResult<'tcx> {
|
||||
// Empty unions are not accepted by rustc. But uninhabited enums
|
||||
// claim to be unions, so allow them, too.
|
||||
assert!(op.layout.abi.is_uninhabited() || fields > 0);
|
||||
fn visit_union(
|
||||
&mut self,
|
||||
_op: OpTy<'tcx, M::PointerTag>,
|
||||
_fields: NonZeroUsize,
|
||||
) -> InterpResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,8 @@ use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_target::abi::{FieldsShape, VariantIdx, Variants};
|
||||
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use super::{InterpCx, MPlaceTy, Machine, OpTy};
|
||||
|
||||
// A thing that we can project into, and that has a layout.
|
||||
@ -130,7 +132,7 @@ macro_rules! make_value_visitor {
|
||||
}
|
||||
/// Visits the given value as a union. No automatic recursion can happen here.
|
||||
#[inline(always)]
|
||||
fn visit_union(&mut self, _v: Self::V, _fields: usize) -> InterpResult<'tcx>
|
||||
fn visit_union(&mut self, _v: Self::V, _fields: NonZeroUsize) -> InterpResult<'tcx>
|
||||
{
|
||||
Ok(())
|
||||
}
|
||||
@ -208,6 +210,7 @@ macro_rules! make_value_visitor {
|
||||
|
||||
// Visit the fields of this value.
|
||||
match v.layout().fields {
|
||||
FieldsShape::Primitive => {},
|
||||
FieldsShape::Union(fields) => {
|
||||
self.visit_union(v, fields)?;
|
||||
},
|
||||
|
@ -88,6 +88,7 @@ where
|
||||
let mut prefix_index = 0;
|
||||
|
||||
match arg.layout.fields {
|
||||
abi::FieldsShape::Primitive => unreachable!(),
|
||||
abi::FieldsShape::Array { .. } => {
|
||||
// Arrays are passed indirectly
|
||||
arg.make_indirect();
|
||||
|
@ -308,13 +308,16 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
|
||||
}
|
||||
|
||||
Abi::ScalarPair(..) | Abi::Aggregate { .. } => {
|
||||
// Helper for computing `homogenous_aggregate`, allowing a custom
|
||||
// Helper for computing `homogeneous_aggregate`, allowing a custom
|
||||
// starting offset (used below for handling variants).
|
||||
let from_fields_at =
|
||||
|layout: Self,
|
||||
start: Size|
|
||||
-> Result<(HomogeneousAggregate, Size), Heterogeneous> {
|
||||
let is_union = match layout.fields {
|
||||
FieldsShape::Primitive => {
|
||||
unreachable!("aggregates can't have `FieldsShape::Primitive`")
|
||||
}
|
||||
FieldsShape::Array { count, .. } => {
|
||||
assert_eq!(start, Size::ZERO);
|
||||
|
||||
|
@ -87,6 +87,9 @@ where
|
||||
},
|
||||
Abi::Vector { .. } | Abi::Uninhabited => return Err(CannotUseFpConv),
|
||||
Abi::ScalarPair(..) | Abi::Aggregate { .. } => match arg_layout.fields {
|
||||
FieldsShape::Primitive => {
|
||||
unreachable!("aggregates can't have `FieldsShape::Primitive`")
|
||||
}
|
||||
FieldsShape::Union(_) => {
|
||||
if !arg_layout.is_zst() {
|
||||
return Err(CannotUseFpConv);
|
||||
|
@ -4,6 +4,7 @@ pub use Primitive::*;
|
||||
use crate::spec::Target;
|
||||
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::num::NonZeroUsize;
|
||||
use std::ops::{Add, AddAssign, Deref, Mul, Range, RangeInclusive, Sub};
|
||||
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
@ -619,10 +620,11 @@ impl Scalar {
|
||||
/// Describes how the fields of a type are located in memory.
|
||||
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub enum FieldsShape {
|
||||
/// Scalar primitives and `!`, which never have fields.
|
||||
Primitive,
|
||||
|
||||
/// All fields start at no offset. The `usize` is the field count.
|
||||
///
|
||||
/// In the case of primitives the number of fields is `0`.
|
||||
Union(usize),
|
||||
Union(NonZeroUsize),
|
||||
|
||||
/// Array/vector-like placement, with all fields of identical types.
|
||||
Array { stride: Size, count: u64 },
|
||||
@ -660,7 +662,8 @@ pub enum FieldsShape {
|
||||
impl FieldsShape {
|
||||
pub fn count(&self) -> usize {
|
||||
match *self {
|
||||
FieldsShape::Union(count) => count,
|
||||
FieldsShape::Primitive => 0,
|
||||
FieldsShape::Union(count) => count.get(),
|
||||
FieldsShape::Array { count, .. } => {
|
||||
let usize_count = count as usize;
|
||||
assert_eq!(usize_count as u64, count);
|
||||
@ -672,8 +675,16 @@ impl FieldsShape {
|
||||
|
||||
pub fn offset(&self, i: usize) -> Size {
|
||||
match *self {
|
||||
FieldsShape::Primitive => {
|
||||
unreachable!("FieldsShape::offset: `Primitive`s have no fields")
|
||||
}
|
||||
FieldsShape::Union(count) => {
|
||||
assert!(i < count, "tried to access field {} of union with {} fields", i, count);
|
||||
assert!(
|
||||
i < count.get(),
|
||||
"tried to access field {} of union with {} fields",
|
||||
i,
|
||||
count
|
||||
);
|
||||
Size::ZERO
|
||||
}
|
||||
FieldsShape::Array { stride, count } => {
|
||||
@ -687,6 +698,9 @@ impl FieldsShape {
|
||||
|
||||
pub fn memory_index(&self, i: usize) -> usize {
|
||||
match *self {
|
||||
FieldsShape::Primitive => {
|
||||
unreachable!("FieldsShape::memory_index: `Primitive`s have no fields")
|
||||
}
|
||||
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
|
||||
FieldsShape::Arbitrary { ref memory_index, .. } => {
|
||||
let r = memory_index[i];
|
||||
@ -718,7 +732,7 @@ impl FieldsShape {
|
||||
}
|
||||
|
||||
(0..self.count()).map(move |i| match *self {
|
||||
FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
|
||||
FieldsShape::Primitive | FieldsShape::Union(_) | FieldsShape::Array { .. } => i,
|
||||
FieldsShape::Arbitrary { .. } => {
|
||||
if use_small {
|
||||
inverse_small[i] as usize
|
||||
@ -887,7 +901,6 @@ impl Niche {
|
||||
#[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)]
|
||||
pub struct Layout {
|
||||
/// Says where the fields are located within the layout.
|
||||
/// Primitives and uninhabited enums appear as unions without fields.
|
||||
pub fields: FieldsShape,
|
||||
|
||||
/// Encodes information about multi-variant layouts.
|
||||
@ -923,7 +936,7 @@ impl Layout {
|
||||
let align = scalar.value.align(cx);
|
||||
Layout {
|
||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||
fields: FieldsShape::Union(0),
|
||||
fields: FieldsShape::Primitive,
|
||||
abi: Abi::Scalar(scalar),
|
||||
largest_niche,
|
||||
size,
|
||||
|
@ -316,9 +316,7 @@ LL | type Test = Result<i32, i32>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: layout_of(i32) = Layout {
|
||||
fields: Union(
|
||||
0,
|
||||
),
|
||||
fields: Primitive,
|
||||
variants: Single {
|
||||
index: 0,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user