Rollup merge of #146667 - calebzulawski:simd-mono-lane-limit, r=lcnr,RalfJung
Add an attribute to check the number of lanes in a SIMD vector after monomorphization Allows std::simd to drop the `LaneCount<N>: SupportedLaneCount` trait and maintain good error messages. Also, extends rust-lang/rust#145967 by including spans in layout errors for all ADTs. r? ``@RalfJung`` cc ``@workingjubilee`` ``@programmerjake``
This commit is contained in:
commit
fab06469ee
36 changed files with 251 additions and 82 deletions
|
|
@ -1,40 +1,4 @@
|
|||
use std::num::IntErrorKind;
|
||||
|
||||
use rustc_hir::limit::Limit;
|
||||
|
||||
use super::prelude::*;
|
||||
use crate::session_diagnostics::LimitInvalid;
|
||||
|
||||
impl<S: Stage> AcceptContext<'_, '_, S> {
|
||||
fn parse_limit_int(&self, nv: &NameValueParser) -> Option<Limit> {
|
||||
let Some(limit) = nv.value_as_str() else {
|
||||
self.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
|
||||
return None;
|
||||
};
|
||||
|
||||
let error_str = match limit.as_str().parse() {
|
||||
Ok(i) => return Some(Limit::new(i)),
|
||||
Err(e) => match e.kind() {
|
||||
IntErrorKind::PosOverflow => "`limit` is too large",
|
||||
IntErrorKind::Empty => "`limit` must be a non-negative integer",
|
||||
IntErrorKind::InvalidDigit => "not a valid integer",
|
||||
IntErrorKind::NegOverflow => {
|
||||
panic!(
|
||||
"`limit` should never negatively overflow since we're parsing into a usize and we'd get Empty instead"
|
||||
)
|
||||
}
|
||||
IntErrorKind::Zero => {
|
||||
panic!("zero is a valid `limit` so should have returned Ok() when parsing")
|
||||
}
|
||||
kind => panic!("unimplemented IntErrorKind variant: {:?}", kind),
|
||||
},
|
||||
};
|
||||
|
||||
self.emit_err(LimitInvalid { span: self.attr_span, value_span: nv.value_span, error_str });
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct CrateNameParser;
|
||||
|
||||
|
|
|
|||
|
|
@ -49,3 +49,21 @@ impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser {
|
|||
Some(AttributeKind::RustcObjectLifetimeDefault)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcSimdMonomorphizeLaneLimitParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser {
|
||||
const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
let ArgParser::NameValue(nv) = args else {
|
||||
cx.expected_name_value(cx.attr_span, None);
|
||||
return None;
|
||||
};
|
||||
Some(AttributeKind::RustcSimdMonomorphizeLaneLimit(cx.parse_limit_int(nv)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,15 @@
|
|||
use std::num::IntErrorKind;
|
||||
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_feature::is_builtin_attr_name;
|
||||
use rustc_hir::RustcVersion;
|
||||
use rustc_hir::limit::Limit;
|
||||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::parser::ArgParser;
|
||||
use crate::parser::{ArgParser, NameValueParser};
|
||||
use crate::session_diagnostics::LimitInvalid;
|
||||
|
||||
/// Parse a rustc version number written inside string literal in an attribute,
|
||||
/// like appears in `since = "1.0.0"`. Suffixes like "-dev" and "-nightly" are
|
||||
|
|
@ -85,3 +89,34 @@ pub(crate) fn parse_single_integer<S: Stage>(
|
|||
};
|
||||
Some(num.0)
|
||||
}
|
||||
|
||||
impl<S: Stage> AcceptContext<'_, '_, S> {
|
||||
pub(crate) fn parse_limit_int(&self, nv: &NameValueParser) -> Option<Limit> {
|
||||
let Some(limit) = nv.value_as_str() else {
|
||||
self.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
|
||||
return None;
|
||||
};
|
||||
|
||||
let error_str = match limit.as_str().parse() {
|
||||
Ok(i) => return Some(Limit::new(i)),
|
||||
Err(e) => match e.kind() {
|
||||
IntErrorKind::PosOverflow => "`limit` is too large",
|
||||
IntErrorKind::Empty => "`limit` must be a non-negative integer",
|
||||
IntErrorKind::InvalidDigit => "not a valid integer",
|
||||
IntErrorKind::NegOverflow => {
|
||||
panic!(
|
||||
"`limit` should never negatively overflow since we're parsing into a usize and we'd get Empty instead"
|
||||
)
|
||||
}
|
||||
IntErrorKind::Zero => {
|
||||
panic!("zero is a valid `limit` so should have returned Ok() when parsing")
|
||||
}
|
||||
kind => panic!("unimplemented IntErrorKind variant: {:?}", kind),
|
||||
},
|
||||
};
|
||||
|
||||
self.emit_err(LimitInvalid { span: self.attr_span, value_span: nv.value_span, error_str });
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ use crate::attributes::prototype::CustomMirParser;
|
|||
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
|
||||
RustcObjectLifetimeDefaultParser,
|
||||
RustcObjectLifetimeDefaultParser, RustcSimdMonomorphizeLaneLimitParser,
|
||||
};
|
||||
use crate::attributes::semantics::MayDangleParser;
|
||||
use crate::attributes::stability::{
|
||||
|
|
@ -198,6 +198,7 @@ attribute_parsers!(
|
|||
Single<RustcLayoutScalarValidRangeEnd>,
|
||||
Single<RustcLayoutScalarValidRangeStart>,
|
||||
Single<RustcObjectLifetimeDefaultParser>,
|
||||
Single<RustcSimdMonomorphizeLaneLimitParser>,
|
||||
Single<SanitizeParser>,
|
||||
Single<ShouldPanicParser>,
|
||||
Single<SkipDuringMethodDispatchParser>,
|
||||
|
|
|
|||
|
|
@ -439,7 +439,10 @@ pub(crate) struct FullyMonomorphizedLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
|
|||
impl<'tcx> LayoutOfHelpers<'tcx> for FullyMonomorphizedLayoutCx<'tcx> {
|
||||
#[inline]
|
||||
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||
if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
|
||||
if let LayoutError::SizeOverflow(_)
|
||||
| LayoutError::InvalidSimd { .. }
|
||||
| LayoutError::ReferencesError(_) = err
|
||||
{
|
||||
self.0.sess.dcx().span_fatal(span, err.to_string())
|
||||
} else {
|
||||
self.0
|
||||
|
|
@ -458,7 +461,9 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for FullyMonomorphizedLayoutCx<'tcx> {
|
|||
span: Span,
|
||||
fn_abi_request: FnAbiRequest<'tcx>,
|
||||
) -> ! {
|
||||
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
|
||||
if let FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) =
|
||||
err
|
||||
{
|
||||
self.0.sess.dcx().emit_fatal(Spanned { span, node: err })
|
||||
} else {
|
||||
match fn_abi_request {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,10 @@ impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> {
|
|||
impl<'tcx> LayoutOfHelpers<'tcx> for GlobalAsmContext<'_, 'tcx> {
|
||||
#[inline]
|
||||
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||
if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
|
||||
if let LayoutError::SizeOverflow(_)
|
||||
| LayoutError::InvalidSimd { .. }
|
||||
| LayoutError::ReferencesError(_) = err
|
||||
{
|
||||
self.tcx.sess.dcx().span_fatal(span, err.to_string())
|
||||
} else {
|
||||
self.tcx
|
||||
|
|
|
|||
|
|
@ -529,7 +529,10 @@ impl<'gcc, 'tcx> HasX86AbiOpt for CodegenCx<'gcc, 'tcx> {
|
|||
impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
|
||||
#[inline]
|
||||
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||
if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
|
||||
if let LayoutError::SizeOverflow(_)
|
||||
| LayoutError::InvalidSimd { .. }
|
||||
| LayoutError::ReferencesError(_) = err
|
||||
{
|
||||
self.tcx.dcx().emit_fatal(respan(span, err.into_diagnostic()))
|
||||
} else {
|
||||
self.tcx.dcx().emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err })
|
||||
|
|
@ -545,7 +548,9 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|||
span: Span,
|
||||
fn_abi_request: FnAbiRequest<'tcx>,
|
||||
) -> ! {
|
||||
if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
|
||||
if let FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) =
|
||||
err
|
||||
{
|
||||
self.tcx.dcx().emit_fatal(respan(span, err))
|
||||
} else {
|
||||
match fn_abi_request {
|
||||
|
|
|
|||
|
|
@ -1044,7 +1044,10 @@ impl<'tcx, 'll> HasTypingEnv<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
|
||||
#[inline]
|
||||
fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
|
||||
if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
|
||||
if let LayoutError::SizeOverflow(_)
|
||||
| LayoutError::ReferencesError(_)
|
||||
| LayoutError::InvalidSimd { .. } = err
|
||||
{
|
||||
self.tcx.dcx().emit_fatal(Spanned { span, node: err.into_diagnostic() })
|
||||
} else {
|
||||
self.tcx.dcx().emit_fatal(ssa_errors::FailedToGetLayout { span, ty, err })
|
||||
|
|
@ -1061,7 +1064,11 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
|
|||
fn_abi_request: FnAbiRequest<'tcx>,
|
||||
) -> ! {
|
||||
match err {
|
||||
FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::Cycle(_)) => {
|
||||
FnAbiError::Layout(
|
||||
LayoutError::SizeOverflow(_)
|
||||
| LayoutError::Cycle(_)
|
||||
| LayoutError::InvalidSimd { .. },
|
||||
) => {
|
||||
self.tcx.dcx().emit_fatal(Spanned { span, node: err });
|
||||
}
|
||||
_ => match fn_abi_request {
|
||||
|
|
|
|||
|
|
@ -477,8 +477,8 @@ pub(crate) fn spanned_type_di_node<'ll, 'tcx>(
|
|||
ty::CoroutineClosure(..) => build_closure_env_di_node(cx, unique_type_id),
|
||||
ty::Coroutine(..) => enums::build_coroutine_di_node(cx, unique_type_id),
|
||||
ty::Adt(def, ..) => match def.adt_kind() {
|
||||
AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id),
|
||||
AdtKind::Union => build_union_type_di_node(cx, unique_type_id),
|
||||
AdtKind::Struct => build_struct_type_di_node(cx, unique_type_id, span),
|
||||
AdtKind::Union => build_union_type_di_node(cx, unique_type_id, span),
|
||||
AdtKind::Enum => enums::build_enum_type_di_node(cx, unique_type_id, span),
|
||||
},
|
||||
ty::Tuple(_) => build_tuple_type_di_node(cx, unique_type_id),
|
||||
|
|
@ -1076,6 +1076,7 @@ fn visibility_di_flags<'ll, 'tcx>(
|
|||
fn build_struct_type_di_node<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
unique_type_id: UniqueTypeId<'tcx>,
|
||||
span: Span,
|
||||
) -> DINodeCreationResult<'ll> {
|
||||
let struct_type = unique_type_id.expect_ty();
|
||||
let ty::Adt(adt_def, _) = struct_type.kind() else {
|
||||
|
|
@ -1083,7 +1084,7 @@ fn build_struct_type_di_node<'ll, 'tcx>(
|
|||
};
|
||||
assert!(adt_def.is_struct());
|
||||
let containing_scope = get_namespace_for_item(cx, adt_def.did());
|
||||
let struct_type_and_layout = cx.layout_of(struct_type);
|
||||
let struct_type_and_layout = cx.spanned_layout_of(struct_type, span);
|
||||
let variant_def = adt_def.non_enum_variant();
|
||||
let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
|
||||
Some(file_metadata_from_def_id(cx, Some(adt_def.did())))
|
||||
|
|
@ -1276,6 +1277,7 @@ fn build_closure_env_di_node<'ll, 'tcx>(
|
|||
fn build_union_type_di_node<'ll, 'tcx>(
|
||||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
unique_type_id: UniqueTypeId<'tcx>,
|
||||
span: Span,
|
||||
) -> DINodeCreationResult<'ll> {
|
||||
let union_type = unique_type_id.expect_ty();
|
||||
let (union_def_id, variant_def) = match union_type.kind() {
|
||||
|
|
@ -1283,7 +1285,7 @@ fn build_union_type_di_node<'ll, 'tcx>(
|
|||
_ => bug!("build_union_type_di_node on a non-ADT"),
|
||||
};
|
||||
let containing_scope = get_namespace_for_item(cx, union_def_id);
|
||||
let union_ty_and_layout = cx.layout_of(union_type);
|
||||
let union_ty_and_layout = cx.spanned_layout_of(union_type, span);
|
||||
let type_name = compute_debuginfo_type_name(cx.tcx, union_type, false);
|
||||
let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers {
|
||||
Some(file_metadata_from_def_id(cx, Some(union_def_id)))
|
||||
|
|
|
|||
|
|
@ -1211,6 +1211,12 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
|||
"the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
|
||||
niche optimizations in the standard library",
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_simd_monomorphize_lane_limit, Normal, template!(NameValueStr: "N"), ErrorFollowing,
|
||||
EncodeCrossCrate::Yes,
|
||||
"the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \
|
||||
for better error messages",
|
||||
),
|
||||
rustc_attr!(
|
||||
rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
|
||||
EncodeCrossCrate::Yes,
|
||||
|
|
|
|||
|
|
@ -651,6 +651,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_object_lifetime_default]`.
|
||||
RustcObjectLifetimeDefault,
|
||||
|
||||
/// Represents `#[rustc_simd_monomorphize_lane_limit = "N"]`.
|
||||
RustcSimdMonomorphizeLaneLimit(Limit),
|
||||
|
||||
/// Represents `#[sanitize]`
|
||||
///
|
||||
/// the on set and off set are distjoint since there's a third option: unset.
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ impl AttributeKind {
|
|||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcObjectLifetimeDefault => No,
|
||||
RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate
|
||||
Sanitize { .. } => No,
|
||||
ShouldPanic { .. } => No,
|
||||
SkipDuringMethodDispatch { .. } => No,
|
||||
|
|
|
|||
|
|
@ -219,6 +219,7 @@ fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError
|
|||
}
|
||||
Unknown(..)
|
||||
| SizeOverflow(..)
|
||||
| InvalidSimd { .. }
|
||||
| NormalizationFailure(..)
|
||||
| ReferencesError(..)
|
||||
| Cycle(..) => {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,12 @@ middle_layout_references_error =
|
|||
middle_layout_size_overflow =
|
||||
values of the type `{$ty}` are too big for the target architecture
|
||||
|
||||
middle_layout_simd_too_many =
|
||||
the SIMD type `{$ty}` has more elements than the limit {$max_lanes}
|
||||
|
||||
middle_layout_simd_zero_length =
|
||||
the SIMD type `{$ty}` has zero elements
|
||||
|
||||
middle_layout_too_generic = the type `{$ty}` does not have a fixed layout
|
||||
|
||||
middle_layout_unknown =
|
||||
|
|
|
|||
|
|
@ -143,6 +143,12 @@ pub enum LayoutError<'tcx> {
|
|||
#[diag(middle_layout_size_overflow)]
|
||||
Overflow { ty: Ty<'tcx> },
|
||||
|
||||
#[diag(middle_layout_simd_too_many)]
|
||||
SimdTooManyLanes { ty: Ty<'tcx>, max_lanes: u64 },
|
||||
|
||||
#[diag(middle_layout_simd_zero_length)]
|
||||
SimdZeroLength { ty: Ty<'tcx> },
|
||||
|
||||
#[diag(middle_layout_normalization_failure)]
|
||||
NormalizationFailure { ty: Ty<'tcx>, failure_ty: String },
|
||||
|
||||
|
|
|
|||
|
|
@ -218,6 +218,15 @@ impl fmt::Display for ValidityRequirement {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
|
||||
pub enum SimdLayoutError {
|
||||
/// The vector has 0 lanes.
|
||||
ZeroLength,
|
||||
/// The vector has more lanes than supported or permitted by
|
||||
/// #\[rustc_simd_monomorphize_lane_limit\].
|
||||
TooManyLanes(u64),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable, TyEncodable, TyDecodable)]
|
||||
pub enum LayoutError<'tcx> {
|
||||
/// A type doesn't have a sensible layout.
|
||||
|
|
@ -230,6 +239,8 @@ pub enum LayoutError<'tcx> {
|
|||
Unknown(Ty<'tcx>),
|
||||
/// The size of a type exceeds [`TargetDataLayout::obj_size_bound`].
|
||||
SizeOverflow(Ty<'tcx>),
|
||||
/// A SIMD vector has invalid layout, such as zero-length or too many lanes.
|
||||
InvalidSimd { ty: Ty<'tcx>, kind: SimdLayoutError },
|
||||
/// The layout can vary due to a generic parameter.
|
||||
///
|
||||
/// Unlike `Unknown`, this variant is a "soft" error and indicates that the layout
|
||||
|
|
@ -257,6 +268,10 @@ impl<'tcx> LayoutError<'tcx> {
|
|||
match self {
|
||||
Unknown(_) => middle_layout_unknown,
|
||||
SizeOverflow(_) => middle_layout_size_overflow,
|
||||
InvalidSimd { kind: SimdLayoutError::TooManyLanes(_), .. } => {
|
||||
middle_layout_simd_too_many
|
||||
}
|
||||
InvalidSimd { kind: SimdLayoutError::ZeroLength, .. } => middle_layout_simd_zero_length,
|
||||
TooGeneric(_) => middle_layout_too_generic,
|
||||
NormalizationFailure(_, _) => middle_layout_normalization_failure,
|
||||
Cycle(_) => middle_layout_cycle,
|
||||
|
|
@ -271,6 +286,10 @@ impl<'tcx> LayoutError<'tcx> {
|
|||
match self {
|
||||
Unknown(ty) => E::Unknown { ty },
|
||||
SizeOverflow(ty) => E::Overflow { ty },
|
||||
InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(max_lanes) } => {
|
||||
E::SimdTooManyLanes { ty, max_lanes }
|
||||
}
|
||||
InvalidSimd { ty, kind: SimdLayoutError::ZeroLength } => E::SimdZeroLength { ty },
|
||||
TooGeneric(ty) => E::TooGeneric { ty },
|
||||
NormalizationFailure(ty, e) => {
|
||||
E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
|
||||
|
|
@ -293,6 +312,12 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
|
|||
LayoutError::SizeOverflow(ty) => {
|
||||
write!(f, "values of the type `{ty}` are too big for the target architecture")
|
||||
}
|
||||
LayoutError::InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(max_lanes) } => {
|
||||
write!(f, "the SIMD type `{ty}` has more elements than the limit {max_lanes}")
|
||||
}
|
||||
LayoutError::InvalidSimd { ty, kind: SimdLayoutError::ZeroLength } => {
|
||||
write!(f, "the SIMD type `{ty}` has zero elements")
|
||||
}
|
||||
LayoutError::NormalizationFailure(t, e) => write!(
|
||||
f,
|
||||
"unable to determine layout for `{}` because `{}` cannot be normalized",
|
||||
|
|
@ -374,6 +399,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
|||
e @ LayoutError::Cycle(_)
|
||||
| e @ LayoutError::Unknown(_)
|
||||
| e @ LayoutError::SizeOverflow(_)
|
||||
| e @ LayoutError::InvalidSimd { .. }
|
||||
| e @ LayoutError::NormalizationFailure(..)
|
||||
| e @ LayoutError::ReferencesError(_),
|
||||
) => return Err(e),
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::MacroEscape( .. )
|
||||
| AttributeKind::RustcLayoutScalarValidRangeStart(..)
|
||||
| AttributeKind::RustcLayoutScalarValidRangeEnd(..)
|
||||
| AttributeKind::RustcSimdMonomorphizeLaneLimit(..)
|
||||
| AttributeKind::ExportStable
|
||||
| AttributeKind::FfiConst(..)
|
||||
| AttributeKind::UnstableFeatureBound(..)
|
||||
|
|
|
|||
|
|
@ -1943,6 +1943,7 @@ symbols! {
|
|||
rustc_regions,
|
||||
rustc_reservation_impl,
|
||||
rustc_serialize,
|
||||
rustc_simd_monomorphize_lane_limit,
|
||||
rustc_skip_during_method_dispatch,
|
||||
rustc_specialization_trait,
|
||||
rustc_std_internal_symbol,
|
||||
|
|
|
|||
|
|
@ -279,6 +279,7 @@ pub(crate) mod rustc {
|
|||
LayoutError::Unknown(..)
|
||||
| LayoutError::ReferencesError(..)
|
||||
| LayoutError::TooGeneric(..)
|
||||
| LayoutError::InvalidSimd { .. }
|
||||
| LayoutError::NormalizationFailure(..) => Self::UnknownLayout,
|
||||
LayoutError::SizeOverflow(..) => Self::SizeOverflow,
|
||||
LayoutError::Cycle(err) => Self::TypeError(*err),
|
||||
|
|
|
|||
|
|
@ -78,19 +78,6 @@ pub(crate) struct UnexpectedFnPtrAssociatedItem {
|
|||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ty_utils_zero_length_simd_type)]
|
||||
pub(crate) struct ZeroLengthSimdType<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ty_utils_oversized_simd_type)]
|
||||
pub(crate) struct OversizedSimdType<'tcx> {
|
||||
pub ty: Ty<'tcx>,
|
||||
pub max_lanes: u64,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ty_utils_non_primitive_simd_type)]
|
||||
pub(crate) struct NonPrimitiveSimdType<'tcx> {
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@ use rustc_abi::{
|
|||
VariantIdx, Variants, WrappingRange,
|
||||
};
|
||||
use rustc_hashes::Hash64;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::traits::ObligationCause;
|
||||
use rustc_middle::ty::layout::{
|
||||
FloatExt, HasTyCtxt, IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout,
|
||||
FloatExt, HasTyCtxt, IntegerExt, LayoutCx, LayoutError, LayoutOf, SimdLayoutError, TyAndLayout,
|
||||
};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
use rustc_middle::ty::{
|
||||
|
|
@ -23,7 +25,7 @@ use rustc_span::{Symbol, sym};
|
|||
use tracing::{debug, instrument};
|
||||
use {rustc_abi as abi, rustc_hir as hir};
|
||||
|
||||
use crate::errors::{NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType};
|
||||
use crate::errors::NonPrimitiveSimdType;
|
||||
|
||||
mod invariant;
|
||||
|
||||
|
|
@ -121,11 +123,11 @@ fn map_error<'tcx>(
|
|||
}
|
||||
LayoutCalculatorError::ZeroLengthSimdType => {
|
||||
// Can't be caught in typeck if the array length is generic.
|
||||
cx.tcx().dcx().emit_fatal(ZeroLengthSimdType { ty })
|
||||
LayoutError::InvalidSimd { ty, kind: SimdLayoutError::ZeroLength }
|
||||
}
|
||||
LayoutCalculatorError::OversizedSimdType { max_lanes } => {
|
||||
// Can't be caught in typeck if the array length is generic.
|
||||
cx.tcx().dcx().emit_fatal(OversizedSimdType { ty, max_lanes })
|
||||
LayoutError::InvalidSimd { ty, kind: SimdLayoutError::TooManyLanes(max_lanes) }
|
||||
}
|
||||
LayoutCalculatorError::NonPrimitiveSimdType(field) => {
|
||||
// This error isn't caught in typeck, e.g., if
|
||||
|
|
@ -563,6 +565,22 @@ fn layout_of_uncached<'tcx>(
|
|||
|
||||
let e_ly = cx.layout_of(e_ty)?;
|
||||
|
||||
// Check for the rustc_simd_monomorphize_lane_limit attribute and check the lane limit
|
||||
if let Some(limit) = find_attr!(
|
||||
tcx.get_all_attrs(def.did()),
|
||||
AttributeKind::RustcSimdMonomorphizeLaneLimit(limit) => limit
|
||||
) {
|
||||
if !limit.value_within_limit(e_len as usize) {
|
||||
return Err(map_error(
|
||||
&cx,
|
||||
ty,
|
||||
rustc_abi::LayoutCalculatorError::OversizedSimdType {
|
||||
max_lanes: limit.0 as u64,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
map_layout(cx.calc.simd_type(e_ly, e_len, def.repr().packed()))?
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,5 +65,10 @@
|
|||
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
||||
the type's layout depended on the type's layout itself. {# #}
|
||||
</p>
|
||||
{% when Err(LayoutError::InvalidSimd {..}) %}
|
||||
<p> {# #}
|
||||
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
|
||||
the vector type had zero elements or too many elements. {# #}
|
||||
</p>
|
||||
{% endmatch %}
|
||||
</div> {# #}
|
||||
|
|
|
|||
5
tests/ui/simd/auxiliary/simd-lane-limit.rs
Normal file
5
tests/ui/simd/auxiliary/simd-lane-limit.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#![feature(rustc_attrs, repr_simd)]
|
||||
|
||||
#[repr(simd, packed)]
|
||||
#[rustc_simd_monomorphize_lane_limit = "8"]
|
||||
pub struct Simd<T, const N: usize>(pub [T; N]);
|
||||
|
|
@ -6,7 +6,5 @@
|
|||
struct Simd<T, const N: usize>([T; N]);
|
||||
|
||||
fn main() {
|
||||
let _too_big = Simd([1_u16; 54321]);
|
||||
let _too_big = Simd([1_u16; 54321]); //~ ERROR the SIMD type `Simd<u16, 54321>` has more elements than the limit 32768
|
||||
}
|
||||
|
||||
//~? ERROR monomorphising SIMD type `Simd<u16, 54321>` of length greater than 32768
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
error: monomorphising SIMD type `Simd<u16, 54321>` of length greater than 32768
|
||||
error: the SIMD type `Simd<u16, 54321>` has more elements than the limit 32768
|
||||
--> $DIR/monomorphize-too-long.rs:9:9
|
||||
|
|
||||
LL | let _too_big = Simd([1_u16; 54321]);
|
||||
| ^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,5 @@
|
|||
struct Simd<T, const N: usize>([T; N]);
|
||||
|
||||
fn main() {
|
||||
let _empty = Simd([1.0; 0]);
|
||||
let _empty = Simd([1.0; 0]); //~ ERROR the SIMD type `Simd<f64, 0>` has zero elements
|
||||
}
|
||||
|
||||
//~? ERROR monomorphising SIMD type `Simd<f64, 0>` of zero length
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
error: monomorphising SIMD type `Simd<f64, 0>` of zero length
|
||||
error: the SIMD type `Simd<f64, 0>` has zero elements
|
||||
--> $DIR/monomorphize-zero-length.rs:9:9
|
||||
|
|
||||
LL | let _empty = Simd([1.0; 0]);
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
12
tests/ui/simd/simd-lane-limit-err-npow2.rs
Normal file
12
tests/ui/simd/simd-lane-limit-err-npow2.rs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
//@ build-fail
|
||||
//@ aux-crate:simd=simd-lane-limit.rs
|
||||
|
||||
extern crate simd;
|
||||
|
||||
use simd::Simd;
|
||||
|
||||
fn main() {
|
||||
// test non-power-of-two, since #[repr(simd, packed)] has unusual layout
|
||||
let _x: Simd<i32, 24> = Simd([0; 24]);
|
||||
//~^ ERROR the SIMD type `simd::Simd<i32, 24>` has more elements than the limit 8
|
||||
}
|
||||
8
tests/ui/simd/simd-lane-limit-err-npow2.stderr
Normal file
8
tests/ui/simd/simd-lane-limit-err-npow2.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: the SIMD type `simd::Simd<i32, 24>` has more elements than the limit 8
|
||||
--> $DIR/simd-lane-limit-err-npow2.rs:10:9
|
||||
|
|
||||
LL | let _x: Simd<i32, 24> = Simd([0; 24]);
|
||||
| ^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
11
tests/ui/simd/simd-lane-limit-err.rs
Normal file
11
tests/ui/simd/simd-lane-limit-err.rs
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
//@ build-fail
|
||||
//@ aux-crate:simd=simd-lane-limit.rs
|
||||
|
||||
extern crate simd;
|
||||
|
||||
use simd::Simd;
|
||||
|
||||
fn main() {
|
||||
let _x: Simd<i32, 16> = Simd([0; 16]);
|
||||
//~^ ERROR the SIMD type `simd::Simd<i32, 16>` has more elements than the limit 8
|
||||
}
|
||||
8
tests/ui/simd/simd-lane-limit-err.stderr
Normal file
8
tests/ui/simd/simd-lane-limit-err.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: the SIMD type `simd::Simd<i32, 16>` has more elements than the limit 8
|
||||
--> $DIR/simd-lane-limit-err.rs:9:9
|
||||
|
|
||||
LL | let _x: Simd<i32, 16> = Simd([0; 16]);
|
||||
| ^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
14
tests/ui/simd/simd-lane-limit-ok.rs
Normal file
14
tests/ui/simd/simd-lane-limit-ok.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
//@ build-pass
|
||||
//@ aux-crate:simd=simd-lane-limit.rs
|
||||
|
||||
extern crate simd;
|
||||
|
||||
use simd::Simd;
|
||||
|
||||
fn main() {
|
||||
let _x: Simd<i32, 4> = Simd([0; 4]);
|
||||
let _y: Simd<i32, 8> = Simd([0; 8]);
|
||||
|
||||
// test non-power-of-two, since #[repr(simd, packed)] has unusual layout
|
||||
let _z: Simd<i32, 6> = Simd([0; 6]);
|
||||
}
|
||||
|
|
@ -6,7 +6,5 @@
|
|||
struct Simd<const N: usize>([f32; N]);
|
||||
|
||||
fn main() {
|
||||
let _ = Simd::<0>([]);
|
||||
let _empty = Simd::<0>([]); //~ ERROR the SIMD type `Simd<0>` has zero elements
|
||||
}
|
||||
|
||||
//~? ERROR monomorphising SIMD type `Simd<0>` of zero length
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
error: monomorphising SIMD type `Simd<0>` of zero length
|
||||
error: the SIMD type `Simd<0>` has zero elements
|
||||
--> $DIR/type-generic-monomorphisation-empty.rs:9:9
|
||||
|
|
||||
LL | let _empty = Simd::<0>([]);
|
||||
| ^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
struct Simd<const N: usize>([f32; N]);
|
||||
|
||||
fn main() {
|
||||
let _ = Simd::<65536>([0.; 65536]);
|
||||
let _x = Simd::<65536>([0.; 65536]);
|
||||
//~^ ERROR the SIMD type `Simd<65536>` has more elements than the limit 32768
|
||||
}
|
||||
|
||||
//~? ERROR monomorphising SIMD type `Simd<65536>` of length greater than 32768
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
error: monomorphising SIMD type `Simd<65536>` of length greater than 32768
|
||||
error: the SIMD type `Simd<65536>` has more elements than the limit 32768
|
||||
--> $DIR/type-generic-monomorphisation-oversized.rs:9:9
|
||||
|
|
||||
LL | let _x = Simd::<65536>([0.; 65536]);
|
||||
| ^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue