From 07db2bfe395a2787376c3cf068bbfe9e1e2eb4d0 Mon Sep 17 00:00:00 2001 From: Caleb Zulawski Date: Sat, 2 Jan 2021 23:49:28 -0500 Subject: [PATCH] Implement floating point SIMD intrinsics over all vector widths, and limit SIMD vector lengths. --- compiler/rustc_codegen_llvm/src/context.rs | 117 --------------- compiler/rustc_codegen_llvm/src/intrinsic.rs | 133 ++++++++---------- compiler/rustc_middle/src/ty/layout.rs | 7 + compiler/rustc_typeck/src/check/check.rs | 22 +++ ...imd-type-generic-monomorphisation-empty.rs | 12 ++ ...type-generic-monomorphisation-empty.stderr | 4 + ...type-generic-monomorphisation-oversized.rs | 12 ++ ...-generic-monomorphisation-oversized.stderr | 4 + src/test/ui/simd-type.rs | 9 ++ src/test/ui/simd-type.stderr | 20 ++- 10 files changed, 141 insertions(+), 199 deletions(-) create mode 100644 src/test/ui/simd-type-generic-monomorphisation-empty.rs create mode 100644 src/test/ui/simd-type-generic-monomorphisation-empty.stderr create mode 100644 src/test/ui/simd-type-generic-monomorphisation-oversized.rs create mode 100644 src/test/ui/simd-type-generic-monomorphisation-oversized.stderr diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 8dd40308075ed..df3ef26d1ad5e 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -498,25 +498,6 @@ impl CodegenCx<'b, 'tcx> { let t_f32 = self.type_f32(); let t_f64 = self.type_f64(); - macro_rules! vector_types { - ($id_out:ident: $elem_ty:ident, $len:expr) => { - let $id_out = self.type_vector($elem_ty, $len); - }; - ($($id_out:ident: $elem_ty:ident, $len:expr;)*) => { - $(vector_types!($id_out: $elem_ty, $len);)* - } - } - vector_types! { - t_v2f32: t_f32, 2; - t_v4f32: t_f32, 4; - t_v8f32: t_f32, 8; - t_v16f32: t_f32, 16; - - t_v2f64: t_f64, 2; - t_v4f64: t_f64, 4; - t_v8f64: t_f64, 8; - } - ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f32", fn(t_f32) -> t_i32); ifn!("llvm.wasm.trunc.saturate.unsigned.i32.f64", fn(t_f64) -> t_i32); ifn!("llvm.wasm.trunc.saturate.unsigned.i64.f32", fn(t_f32) -> t_i64); @@ -540,124 +521,40 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.sideeffect", fn() -> void); ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32); - ifn!("llvm.powi.v2f32", fn(t_v2f32, t_i32) -> t_v2f32); - ifn!("llvm.powi.v4f32", fn(t_v4f32, t_i32) -> t_v4f32); - ifn!("llvm.powi.v8f32", fn(t_v8f32, t_i32) -> t_v8f32); - ifn!("llvm.powi.v16f32", fn(t_v16f32, t_i32) -> t_v16f32); ifn!("llvm.powi.f64", fn(t_f64, t_i32) -> t_f64); - ifn!("llvm.powi.v2f64", fn(t_v2f64, t_i32) -> t_v2f64); - ifn!("llvm.powi.v4f64", fn(t_v4f64, t_i32) -> t_v4f64); - ifn!("llvm.powi.v8f64", fn(t_v8f64, t_i32) -> t_v8f64); ifn!("llvm.pow.f32", fn(t_f32, t_f32) -> t_f32); - ifn!("llvm.pow.v2f32", fn(t_v2f32, t_v2f32) -> t_v2f32); - ifn!("llvm.pow.v4f32", fn(t_v4f32, t_v4f32) -> t_v4f32); - ifn!("llvm.pow.v8f32", fn(t_v8f32, t_v8f32) -> t_v8f32); - ifn!("llvm.pow.v16f32", fn(t_v16f32, t_v16f32) -> t_v16f32); ifn!("llvm.pow.f64", fn(t_f64, t_f64) -> t_f64); - ifn!("llvm.pow.v2f64", fn(t_v2f64, t_v2f64) -> t_v2f64); - ifn!("llvm.pow.v4f64", fn(t_v4f64, t_v4f64) -> t_v4f64); - ifn!("llvm.pow.v8f64", fn(t_v8f64, t_v8f64) -> t_v8f64); ifn!("llvm.sqrt.f32", fn(t_f32) -> t_f32); - ifn!("llvm.sqrt.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.sqrt.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.sqrt.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.sqrt.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.sqrt.f64", fn(t_f64) -> t_f64); - ifn!("llvm.sqrt.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.sqrt.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.sqrt.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.sin.f32", fn(t_f32) -> t_f32); - ifn!("llvm.sin.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.sin.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.sin.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.sin.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.sin.f64", fn(t_f64) -> t_f64); - ifn!("llvm.sin.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.sin.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.sin.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.cos.f32", fn(t_f32) -> t_f32); - ifn!("llvm.cos.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.cos.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.cos.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.cos.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.cos.f64", fn(t_f64) -> t_f64); - ifn!("llvm.cos.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.cos.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.cos.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.exp.f32", fn(t_f32) -> t_f32); - ifn!("llvm.exp.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.exp.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.exp.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.exp.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.exp.f64", fn(t_f64) -> t_f64); - ifn!("llvm.exp.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.exp.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.exp.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.exp2.f32", fn(t_f32) -> t_f32); - ifn!("llvm.exp2.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.exp2.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.exp2.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.exp2.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.exp2.f64", fn(t_f64) -> t_f64); - ifn!("llvm.exp2.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.exp2.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.exp2.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.log.f32", fn(t_f32) -> t_f32); - ifn!("llvm.log.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.log.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.log.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.log.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.log.f64", fn(t_f64) -> t_f64); - ifn!("llvm.log.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.log.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.log.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.log10.f32", fn(t_f32) -> t_f32); - ifn!("llvm.log10.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.log10.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.log10.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.log10.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.log10.f64", fn(t_f64) -> t_f64); - ifn!("llvm.log10.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.log10.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.log10.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.log2.f32", fn(t_f32) -> t_f32); - ifn!("llvm.log2.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.log2.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.log2.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.log2.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.log2.f64", fn(t_f64) -> t_f64); - ifn!("llvm.log2.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.log2.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.log2.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.fma.f32", fn(t_f32, t_f32, t_f32) -> t_f32); - ifn!("llvm.fma.v2f32", fn(t_v2f32, t_v2f32, t_v2f32) -> t_v2f32); - ifn!("llvm.fma.v4f32", fn(t_v4f32, t_v4f32, t_v4f32) -> t_v4f32); - ifn!("llvm.fma.v8f32", fn(t_v8f32, t_v8f32, t_v8f32) -> t_v8f32); - ifn!("llvm.fma.v16f32", fn(t_v16f32, t_v16f32, t_v16f32) -> t_v16f32); ifn!("llvm.fma.f64", fn(t_f64, t_f64, t_f64) -> t_f64); - ifn!("llvm.fma.v2f64", fn(t_v2f64, t_v2f64, t_v2f64) -> t_v2f64); - ifn!("llvm.fma.v4f64", fn(t_v4f64, t_v4f64, t_v4f64) -> t_v4f64); - ifn!("llvm.fma.v8f64", fn(t_v8f64, t_v8f64, t_v8f64) -> t_v8f64); ifn!("llvm.fabs.f32", fn(t_f32) -> t_f32); - ifn!("llvm.fabs.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.fabs.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.fabs.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.fabs.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.fabs.f64", fn(t_f64) -> t_f64); - ifn!("llvm.fabs.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.fabs.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.fabs.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.minnum.f32", fn(t_f32, t_f32) -> t_f32); ifn!("llvm.minnum.f64", fn(t_f64, t_f64) -> t_f64); @@ -665,24 +562,10 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.maxnum.f64", fn(t_f64, t_f64) -> t_f64); ifn!("llvm.floor.f32", fn(t_f32) -> t_f32); - ifn!("llvm.floor.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.floor.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.floor.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.floor.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.floor.f64", fn(t_f64) -> t_f64); - ifn!("llvm.floor.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.floor.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.floor.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.ceil.f32", fn(t_f32) -> t_f32); - ifn!("llvm.ceil.v2f32", fn(t_v2f32) -> t_v2f32); - ifn!("llvm.ceil.v4f32", fn(t_v4f32) -> t_v4f32); - ifn!("llvm.ceil.v8f32", fn(t_v8f32) -> t_v8f32); - ifn!("llvm.ceil.v16f32", fn(t_v16f32) -> t_v16f32); ifn!("llvm.ceil.f64", fn(t_f64) -> t_f64); - ifn!("llvm.ceil.v2f64", fn(t_v2f64) -> t_v2f64); - ifn!("llvm.ceil.v4f64", fn(t_v4f64) -> t_v4f64); - ifn!("llvm.ceil.v8f64", fn(t_v8f64) -> t_v8f64); ifn!("llvm.trunc.f32", fn(t_f32) -> t_f32); ifn!("llvm.trunc.f64", fn(t_f64) -> t_f64); diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index bf0d499e6c491..81728b8def97f 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1009,7 +1009,7 @@ fn generic_simd_intrinsic( } fn simd_simple_float_intrinsic( - name: &str, + name: Symbol, in_elem: &::rustc_middle::ty::TyS<'_>, in_ty: &::rustc_middle::ty::TyS<'_>, in_len: u64, @@ -1036,93 +1036,70 @@ fn generic_simd_intrinsic( } } } - let ety = match in_elem.kind() { - ty::Float(f) if f.bit_width() == 32 => { - if in_len < 2 || in_len > 16 { - return_error!( - "unsupported floating-point vector `{}` with length `{}` \ - out-of-range [2, 16]", - in_ty, - in_len - ); - } - "f32" - } - ty::Float(f) if f.bit_width() == 64 => { - if in_len < 2 || in_len > 8 { + + let (elem_ty_str, elem_ty) = if let ty::Float(f) = in_elem.kind() { + let elem_ty = bx.cx.type_float_from_ty(*f); + match f.bit_width() { + 32 => ("f32", elem_ty), + 64 => ("f64", elem_ty), + _ => { return_error!( - "unsupported floating-point vector `{}` with length `{}` \ - out-of-range [2, 8]", - in_ty, - in_len + "unsupported element type `{}` of floating-point vector `{}`", + f.name_str(), + in_ty ); } - "f64" - } - ty::Float(f) => { - return_error!( - "unsupported element type `{}` of floating-point vector `{}`", - f.name_str(), - in_ty - ); - } - _ => { - return_error!("`{}` is not a floating-point type", in_ty); } + } else { + return_error!("`{}` is not a floating-point type", in_ty); }; - let llvm_name = &format!("llvm.{0}.v{1}{2}", name, in_len, ety); - let intrinsic = bx.get_intrinsic(&llvm_name); - let c = - bx.call(intrinsic, &args.iter().map(|arg| arg.immediate()).collect::>(), None); + let vec_ty = bx.type_vector(elem_ty, in_len); + + let (intr_name, fn_ty) = match name { + sym::simd_fsqrt => ("sqrt", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fsin => ("sin", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fcos => ("cos", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fabs => ("fabs", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_floor => ("floor", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_ceil => ("ceil", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fexp => ("exp", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fexp2 => ("exp2", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_flog10 => ("log10", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_flog2 => ("log2", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_flog => ("log", bx.type_func(&[vec_ty], vec_ty)), + sym::simd_fpowi => ("powi", bx.type_func(&[vec_ty, bx.type_i32()], vec_ty)), + sym::simd_fpow => ("pow", bx.type_func(&[vec_ty, vec_ty], vec_ty)), + sym::simd_fma => ("fma", bx.type_func(&[vec_ty, vec_ty, vec_ty], vec_ty)), + _ => return_error!("unrecognized intrinsic `{}`", name), + }; + + let llvm_name = &format!("llvm.{0}.v{1}{2}", intr_name, in_len, elem_ty_str); + let f = bx.declare_cfn(&llvm_name, fn_ty); + llvm::SetUnnamedAddress(f, llvm::UnnamedAddr::No); + let c = bx.call(f, &args.iter().map(|arg| arg.immediate()).collect::>(), None); unsafe { llvm::LLVMRustSetHasUnsafeAlgebra(c) }; Ok(c) } - match name { - sym::simd_fsqrt => { - return simd_simple_float_intrinsic("sqrt", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_fsin => { - return simd_simple_float_intrinsic("sin", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_fcos => { - return simd_simple_float_intrinsic("cos", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_fabs => { - return simd_simple_float_intrinsic("fabs", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_floor => { - return simd_simple_float_intrinsic("floor", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_ceil => { - return simd_simple_float_intrinsic("ceil", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_fexp => { - return simd_simple_float_intrinsic("exp", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_fexp2 => { - return simd_simple_float_intrinsic("exp2", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_flog10 => { - return simd_simple_float_intrinsic("log10", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_flog2 => { - return simd_simple_float_intrinsic("log2", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_flog => { - return simd_simple_float_intrinsic("log", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_fpowi => { - return simd_simple_float_intrinsic("powi", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_fpow => { - return simd_simple_float_intrinsic("pow", in_elem, in_ty, in_len, bx, span, args); - } - sym::simd_fma => { - return simd_simple_float_intrinsic("fma", in_elem, in_ty, in_len, bx, span, args); - } - _ => { /* fallthrough */ } + if std::matches!( + name, + sym::simd_fsqrt + | sym::simd_fsin + | sym::simd_fcos + | sym::simd_fabs + | sym::simd_floor + | sym::simd_ceil + | sym::simd_fexp + | sym::simd_fexp2 + | sym::simd_flog10 + | sym::simd_flog2 + | sym::simd_flog + | sym::simd_fpowi + | sym::simd_fpow + | sym::simd_fma + ) { + return simd_simple_float_intrinsic(name, in_elem, in_ty, in_len, bx, span, args); } // FIXME: use: diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 4475d4e9f2dea..c9be59ca46c28 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -694,10 +694,17 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }; // SIMD vectors of zero length are not supported. + // Additionally, lengths are capped at 2^16 as a fixed maximum backends must + // support. // // Can't be caught in typeck if the array length is generic. if e_len == 0 { tcx.sess.fatal(&format!("monomorphising SIMD type `{}` of zero length", ty)); + } else if e_len > 65536 { + tcx.sess.fatal(&format!( + "monomorphising SIMD type `{}` of length greater than 65536", + ty, + )); } // Compute the ABI of the element type: diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 9c60e8933d4db..8abd3a98d4b80 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1098,6 +1098,28 @@ pub fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { .emit(); return; } + + let len = if let ty::Array(_ty, c) = e.kind() { + c.try_eval_usize(tcx, tcx.param_env(def.did)) + } else { + Some(fields.len() as u64) + }; + if let Some(len) = len { + if len == 0 { + struct_span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty").emit(); + return; + } else if len > 65536 { + struct_span_err!( + tcx.sess, + sp, + E0075, + "SIMD vector cannot have more than 65536 elements" + ) + .emit(); + return; + } + } + match e.kind() { ty::Param(_) => { /* struct(T, T, T, T) is ok */ } _ if e.is_machine() => { /* struct(u8, u8, u8, u8) is ok */ } diff --git a/src/test/ui/simd-type-generic-monomorphisation-empty.rs b/src/test/ui/simd-type-generic-monomorphisation-empty.rs new file mode 100644 index 0000000000000..0121404c74935 --- /dev/null +++ b/src/test/ui/simd-type-generic-monomorphisation-empty.rs @@ -0,0 +1,12 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics)] + +// error-pattern:monomorphising SIMD type `Simd<0_usize>` of zero length + +#[repr(simd)] +struct Simd([f32; N]); + +fn main() { + let _ = Simd::<0>([]); +} diff --git a/src/test/ui/simd-type-generic-monomorphisation-empty.stderr b/src/test/ui/simd-type-generic-monomorphisation-empty.stderr new file mode 100644 index 0000000000000..00fde199b12a2 --- /dev/null +++ b/src/test/ui/simd-type-generic-monomorphisation-empty.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd<0_usize>` of zero length + +error: aborting due to previous error + diff --git a/src/test/ui/simd-type-generic-monomorphisation-oversized.rs b/src/test/ui/simd-type-generic-monomorphisation-oversized.rs new file mode 100644 index 0000000000000..48bf8345db977 --- /dev/null +++ b/src/test/ui/simd-type-generic-monomorphisation-oversized.rs @@ -0,0 +1,12 @@ +// build-fail + +#![feature(repr_simd, platform_intrinsics)] + +// error-pattern:monomorphising SIMD type `Simd<65537_usize>` of length greater than 65536 + +#[repr(simd)] +struct Simd([f32; N]); + +fn main() { + let _ = Simd::<65537>([0.; 65537]); +} diff --git a/src/test/ui/simd-type-generic-monomorphisation-oversized.stderr b/src/test/ui/simd-type-generic-monomorphisation-oversized.stderr new file mode 100644 index 0000000000000..c8dab7bfbe883 --- /dev/null +++ b/src/test/ui/simd-type-generic-monomorphisation-oversized.stderr @@ -0,0 +1,4 @@ +error: monomorphising SIMD type `Simd<65537_usize>` of length greater than 65536 + +error: aborting due to previous error + diff --git a/src/test/ui/simd-type.rs b/src/test/ui/simd-type.rs index a320df85138e5..269715d5e8ed0 100644 --- a/src/test/ui/simd-type.rs +++ b/src/test/ui/simd-type.rs @@ -6,6 +6,9 @@ #[repr(simd)] struct empty; //~ ERROR SIMD vector cannot be empty +#[repr(simd)] +struct empty2([f32; 0]); //~ ERROR SIMD vector cannot be empty + #[repr(simd)] struct i64f64(i64, f64); //~ ERROR SIMD vector should be homogeneous @@ -17,4 +20,10 @@ struct FooV(Foo, Foo); //~ ERROR SIMD vector element type should be a primitive #[repr(simd)] struct FooV2([Foo; 2]); //~ ERROR SIMD vector element type should be a primitive scalar (integer/float/pointer) type +#[repr(simd)] +struct TooBig([f32; 65537]); //~ ERROR SIMD vector cannot have more than 65536 elements + +#[repr(simd)] +struct JustRight([u128; 65536]); + fn main() {} diff --git a/src/test/ui/simd-type.stderr b/src/test/ui/simd-type.stderr index 23004c785918c..5fe12c9822769 100644 --- a/src/test/ui/simd-type.stderr +++ b/src/test/ui/simd-type.stderr @@ -4,25 +4,37 @@ error[E0075]: SIMD vector cannot be empty LL | struct empty; | ^^^^^^^^^^^^^ -error[E0076]: SIMD vector should be homogeneous +error[E0075]: SIMD vector cannot be empty --> $DIR/simd-type.rs:10:1 | +LL | struct empty2([f32; 0]); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0076]: SIMD vector should be homogeneous + --> $DIR/simd-type.rs:13:1 + | LL | struct i64f64(i64, f64); | ^^^^^^^^^^^^^^^^^^^^^^^^ SIMD elements must have the same type error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/simd-type.rs:15:1 + --> $DIR/simd-type.rs:18:1 | LL | struct FooV(Foo, Foo); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0077]: SIMD vector element type should be a primitive scalar (integer/float/pointer) type - --> $DIR/simd-type.rs:18:1 + --> $DIR/simd-type.rs:21:1 | LL | struct FooV2([Foo; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error[E0075]: SIMD vector cannot have more than 65536 elements + --> $DIR/simd-type.rs:24:1 + | +LL | struct TooBig([f32; 65537]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0075, E0076, E0077. For more information about an error, try `rustc --explain E0075`.