Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_target::abi: add Primitive variant to FieldsShape. #70629

Merged
merged 1 commit into from
Apr 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc_codegen_llvm/type_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}

Expand Down
6 changes: 6 additions & 0 deletions src/librustc_data_structures/stable_hasher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) };
Expand Down
15 changes: 11 additions & 4 deletions src/librustc_middle/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
}
Expand All @@ -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,
Expand Down
10 changes: 6 additions & 4 deletions src/librustc_mir/interpret/validity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -642,10 +643,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(())
}

Expand Down
5 changes: 4 additions & 1 deletion src/librustc_mir/interpret/visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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(())
}
Expand Down Expand Up @@ -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)?;
anyska marked this conversation as resolved.
Show resolved Hide resolved
},
Expand Down
1 change: 1 addition & 0 deletions src/librustc_target/abi/call/mips64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ where
let mut prefix_index = 0;

match arg.layout.fields {
abi::FieldsShape::Primitive => unreachable!(),
anyska marked this conversation as resolved.
Show resolved Hide resolved
abi::FieldsShape::Array { .. } => {
// Arrays are passed indirectly
arg.make_indirect();
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_target/abi/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 3 additions & 0 deletions src/librustc_target/abi/call/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
29 changes: 21 additions & 8 deletions src/librustc_target/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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,
anyska marked this conversation as resolved.
Show resolved Hide resolved

/// 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 },
Expand Down Expand Up @@ -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);
Expand All @@ -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 } => {
Expand All @@ -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];
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 1 addition & 3 deletions src/test/ui/layout/debug.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,7 @@ LL | type Test = Result<i32, i32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: layout_of(i32) = Layout {
fields: Union(
0,
),
fields: Primitive,
variants: Single {
index: 0,
},
Expand Down