From dc4162b2d46262d393d683dd2f567e45e39b53e7 Mon Sep 17 00:00:00 2001 From: Luca Versari Date: Sat, 13 Jul 2024 19:35:05 +0200 Subject: [PATCH 1/3] Emit error when calling/declaring functions with unavailable vectors. On some architectures, vector types may have a different ABI when relevant target features are enabled. As discussed in https://github.com/rust-lang/lang-team/issues/235, this turns out to very easily lead to unsound code. This commit makes it an error to declare or call functions using those vector types in a context in which the corresponding target features are disabled, if using an ABI for which the difference is relevant. --- Cargo.lock | 1 + compiler/rustc_monomorphize/Cargo.toml | 1 + compiler/rustc_monomorphize/messages.ftl | 7 ++ compiler/rustc_monomorphize/src/collector.rs | 3 + .../src/collector/abi_check.rs | 97 +++++++++++++++++++ compiler/rustc_monomorphize/src/errors.rs | 18 ++++ library/core/src/primitive_docs.rs | 21 +--- tests/assembly/simd-bitmask.rs | 1 + tests/assembly/simd-intrinsic-gather.rs | 1 + tests/assembly/simd-intrinsic-mask-load.rs | 1 + tests/assembly/simd-intrinsic-mask-reduce.rs | 1 + tests/assembly/simd-intrinsic-mask-store.rs | 1 + tests/assembly/simd-intrinsic-scatter.rs | 1 + tests/assembly/simd-intrinsic-select.rs | 1 + tests/ui/simd-abi-checks.rs | 69 +++++++++++++ tests/ui/simd-abi-checks.stderr | 74 ++++++++++++++ 16 files changed, 278 insertions(+), 20 deletions(-) create mode 100644 compiler/rustc_monomorphize/src/collector/abi_check.rs create mode 100644 tests/ui/simd-abi-checks.rs create mode 100644 tests/ui/simd-abi-checks.stderr diff --git a/Cargo.lock b/Cargo.lock index 5f81a5a84966a..508fe6e01dab4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4139,6 +4139,7 @@ dependencies = [ name = "rustc_monomorphize" version = "0.0.0" dependencies = [ + "rustc_abi", "rustc_data_structures", "rustc_errors", "rustc_fluent_macro", diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index c7f1b9fa78454..6c881fd7e06ba 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -5,6 +5,7 @@ edition = "2021" [dependencies] # tidy-alphabetical-start +rustc_abi = { path = "../rustc_abi" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fluent_macro = { path = "../rustc_fluent_macro" } diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index 7210701d4828c..4de71c676a6d5 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -1,3 +1,10 @@ +monomorphize_abi_error_disabled_vector_type_call = + ABI error: this function call uses a {$required_feature} vector type, which is not enabled in the caller + .help = consider enabling it globally (-C target-feature=+{$required_feature}) or locally (#[target_feature(enable="{$required_feature}")]) +monomorphize_abi_error_disabled_vector_type_def = + ABI error: this function definition uses a {$required_feature} vector type, which is not enabled + .help = consider enabling it globally (-C target-feature=+{$required_feature}) or locally (#[target_feature(enable="{$required_feature}")]) + monomorphize_couldnt_dump_mono_stats = unexpected error occurred while dumping monomorphization stats: {$error} diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index b4d084d4dffc4..3f4d2fc6e31ef 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -205,6 +205,7 @@ //! this is not implemented however: a mono item will be produced //! regardless of whether it is actually needed or not. +mod abi_check; mod move_check; use std::path::PathBuf; @@ -766,6 +767,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> { self.used_mentioned_items.insert(MentionedItem::Fn(callee_ty)); let callee_ty = self.monomorphize(callee_ty); self.check_fn_args_move_size(callee_ty, args, *fn_span, location); + abi_check::check_call_site_abi(tcx, callee_ty, *fn_span, self.body.source.instance); visit_fn_use(self.tcx, callee_ty, true, source, &mut self.used_items) } mir::TerminatorKind::Drop { ref place, .. } => { @@ -1207,6 +1209,7 @@ fn collect_items_of_instance<'tcx>( mentioned_items: &mut MonoItems<'tcx>, mode: CollectionMode, ) { + abi_check::check_instance_abi(tcx, instance); let body = tcx.instance_mir(instance.def); // Naively, in "used" collection mode, all functions get added to *both* `used_items` and // `mentioned_items`. Mentioned items processing will then notice that they have already been diff --git a/compiler/rustc_monomorphize/src/collector/abi_check.rs b/compiler/rustc_monomorphize/src/collector/abi_check.rs new file mode 100644 index 0000000000000..ecc378ecd3d96 --- /dev/null +++ b/compiler/rustc_monomorphize/src/collector/abi_check.rs @@ -0,0 +1,97 @@ +use rustc_abi::Abi; +use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt}; +use rustc_span::def_id::DefId; +use rustc_span::{Span, Symbol}; +use rustc_target::abi::call::{FnAbi, PassMode}; + +use crate::errors::{AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef}; + +// Represents the least-constraining feature that is required for vector types up to a certain size +// to have their "proper" ABI. +const X86_VECTOR_FEATURES: &'static [(u64, &'static str)] = + &[(128, "sse"), (256, "avx"), (512, "avx512f")]; + +fn do_check_abi<'tcx>( + tcx: TyCtxt<'tcx>, + abi: &FnAbi<'tcx, Ty<'tcx>>, + target_feature_def: DefId, + emit_err: impl Fn(&'static str), +) { + let feature_def = if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" { + X86_VECTOR_FEATURES + } else if tcx.sess.target.arch == "aarch64" { + // ABI on aarch64 does not depend on target features. + return; + } else { + // FIXME: add support for non-tier1 architectures + return; + }; + let codegen_attrs = tcx.codegen_fn_attrs(target_feature_def); + for arg_abi in abi.args.iter().chain(std::iter::once(&abi.ret)) { + let size = arg_abi.layout.size; + if matches!(arg_abi.layout.abi, Abi::Vector { .. }) + && !matches!(arg_abi.mode, PassMode::Indirect { .. }) + { + let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) { + Some((_, feature)) => feature, + None => panic!("Unknown vector size: {}; arg = {:?}", size.bits(), arg_abi), + }; + let feature_sym = Symbol::intern(feature); + if !tcx.sess.unstable_target_features.contains(&feature_sym) + && !codegen_attrs.target_features.iter().any(|x| x.name == feature_sym) + { + emit_err(feature); + } + } + } +} + +/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments +/// or return values for which the corresponding target feature is not enabled. +pub fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { + let param_env = ParamEnv::reveal_all(); + let Ok(abi) = tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) else { + // An error will be reported during codegen if we cannot determine the ABI of this + // function. + return; + }; + do_check_abi(tcx, abi, instance.def_id(), |required_feature| { + tcx.dcx().emit_err(AbiErrorDisabledVectorTypeDef { + span: tcx.def_span(instance.def_id()), + required_feature, + }); + }) +} + +/// Checks that a call expression does not try to pass a vector-passed argument which requires a +/// target feature that the caller does not have, as doing so causes UB because of ABI mismatch. +pub fn check_call_site_abi<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + span: Span, + caller: InstanceKind<'tcx>, +) { + let param_env = ParamEnv::reveal_all(); + let callee_abi = match *ty.kind() { + ty::FnPtr(..) => tcx.fn_abi_of_fn_ptr(param_env.and((ty.fn_sig(tcx), ty::List::empty()))), + ty::FnDef(def_id, args) => { + // Intrinsics are handled separately by the compiler. + if tcx.intrinsic(def_id).is_some() { + return; + } + let instance = ty::Instance::expect_resolve(tcx, param_env, def_id, args, span); + tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) + } + _ => { + panic!("Invalid function call"); + } + }; + + let Ok(callee_abi) = callee_abi else { + // ABI failed to compute; this will not get through codegen. + return; + }; + do_check_abi(tcx, callee_abi, caller.def_id(), |required_feature| { + tcx.dcx().emit_err(AbiErrorDisabledVectorTypeCall { span, required_feature }); + }) +} diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index d5fae6e23cb45..e99321252bdc9 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -92,3 +92,21 @@ pub(crate) struct StartNotFound; pub(crate) struct UnknownCguCollectionMode<'a> { pub mode: &'a str, } + +#[derive(Diagnostic)] +#[diag(monomorphize_abi_error_disabled_vector_type_def)] +#[help] +pub struct AbiErrorDisabledVectorTypeDef<'a> { + #[primary_span] + pub span: Span, + pub required_feature: &'a str, +} + +#[derive(Diagnostic)] +#[diag(monomorphize_abi_error_disabled_vector_type_call)] +#[help] +pub struct AbiErrorDisabledVectorTypeCall<'a> { + #[primary_span] + pub span: Span, + pub required_feature: &'a str, +} diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 89936dc12ac36..f391d008e3d2c 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1752,8 +1752,7 @@ mod prim_ref {} /// /// For two signatures to be considered *ABI-compatible*, they must use a compatible ABI string, /// must take the same number of arguments, the individual argument types and the return types must -/// be ABI-compatible, and the target feature requirements must be met (see the subsection below for -/// the last point). The ABI string is declared via `extern "ABI" fn(...) -> ...`; note that +/// be ABI-compatible. The ABI string is declared via `extern "ABI" fn(...) -> ...`; note that /// `fn name(...) -> ...` implicitly uses the `"Rust"` ABI string and `extern fn name(...) -> ...` /// implicitly uses the `"C"` ABI string. /// @@ -1821,24 +1820,6 @@ mod prim_ref {} /// Behavior since transmuting `None::>` to `NonZero` violates the non-zero /// requirement. /// -/// #### Requirements concerning target features -/// -/// Under some conditions, the signature used by the caller and the callee can be ABI-incompatible -/// even if the exact same ABI string and types are being used. As an example, the -/// `std::arch::x86_64::__m256` type has a different `extern "C"` ABI when the `avx` feature is -/// enabled vs when it is not enabled. -/// -/// Therefore, to ensure ABI compatibility when code using different target features is combined -/// (such as via `#[target_feature]`), we further require that one of the following conditions is -/// met: -/// -/// - The function uses the `"Rust"` ABI string (which is the default without `extern`). -/// - Caller and callee are using the exact same set of target features. For the callee we consider -/// the features enabled (via `#[target_feature]` and `-C target-feature`/`-C target-cpu`) at the -/// declaration site; for the caller we consider the features enabled at the call site. -/// - Neither any argument nor the return value involves a SIMD type (`#[repr(simd)]`) that is not -/// behind a pointer indirection (i.e., `*mut __m256` is fine, but `(i32, __m256)` is not). -/// /// ### Trait implementations /// /// In this documentation the shorthand `fn(T₁, T₂, …, Tₙ)` is used to represent non-variadic diff --git a/tests/assembly/simd-bitmask.rs b/tests/assembly/simd-bitmask.rs index 9a355cc162f67..8d99c3694b3c5 100644 --- a/tests/assembly/simd-bitmask.rs +++ b/tests/assembly/simd-bitmask.rs @@ -1,3 +1,4 @@ +//@ ignore-test //@ revisions: x86 x86-avx2 x86-avx512 aarch64 //@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel //@ [x86] needs-llvm-components: x86 diff --git a/tests/assembly/simd-intrinsic-gather.rs b/tests/assembly/simd-intrinsic-gather.rs index 2cbb6cfbb50d9..28af5693b7267 100644 --- a/tests/assembly/simd-intrinsic-gather.rs +++ b/tests/assembly/simd-intrinsic-gather.rs @@ -1,3 +1,4 @@ +//@ ignore-test //@ revisions: x86-avx512 //@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel //@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq diff --git a/tests/assembly/simd-intrinsic-mask-load.rs b/tests/assembly/simd-intrinsic-mask-load.rs index b650e1cee3036..812bfbb2e81f4 100644 --- a/tests/assembly/simd-intrinsic-mask-load.rs +++ b/tests/assembly/simd-intrinsic-mask-load.rs @@ -1,3 +1,4 @@ +//@ ignore-test //@ revisions: x86-avx2 x86-avx512 //@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel //@ [x86-avx2] compile-flags: -C target-feature=+avx2 diff --git a/tests/assembly/simd-intrinsic-mask-reduce.rs b/tests/assembly/simd-intrinsic-mask-reduce.rs index 61d7aa590938c..423605df02599 100644 --- a/tests/assembly/simd-intrinsic-mask-reduce.rs +++ b/tests/assembly/simd-intrinsic-mask-reduce.rs @@ -1,3 +1,4 @@ +//@ ignore-test // verify that simd mask reductions do not introduce additional bit shift operations //@ revisions: x86 aarch64 //@ [x86] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel diff --git a/tests/assembly/simd-intrinsic-mask-store.rs b/tests/assembly/simd-intrinsic-mask-store.rs index 95a3b28b96796..a5e38cc68be67 100644 --- a/tests/assembly/simd-intrinsic-mask-store.rs +++ b/tests/assembly/simd-intrinsic-mask-store.rs @@ -1,3 +1,4 @@ +//@ ignore-test //@ revisions: x86-avx2 x86-avx512 //@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel //@ [x86-avx2] compile-flags: -C target-feature=+avx2 diff --git a/tests/assembly/simd-intrinsic-scatter.rs b/tests/assembly/simd-intrinsic-scatter.rs index 679972d9b86f7..af88a8f6a5ca3 100644 --- a/tests/assembly/simd-intrinsic-scatter.rs +++ b/tests/assembly/simd-intrinsic-scatter.rs @@ -1,3 +1,4 @@ +//@ ignore-test //@ revisions: x86-avx512 //@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel //@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq diff --git a/tests/assembly/simd-intrinsic-select.rs b/tests/assembly/simd-intrinsic-select.rs index 57fd36fd9e302..a94b3654067a4 100644 --- a/tests/assembly/simd-intrinsic-select.rs +++ b/tests/assembly/simd-intrinsic-select.rs @@ -1,3 +1,4 @@ +//@ ignore-test //@ revisions: x86-avx2 x86-avx512 aarch64 //@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel //@ [x86-avx2] compile-flags: -C target-feature=+avx2 diff --git a/tests/ui/simd-abi-checks.rs b/tests/ui/simd-abi-checks.rs new file mode 100644 index 0000000000000..b604a825babfb --- /dev/null +++ b/tests/ui/simd-abi-checks.rs @@ -0,0 +1,69 @@ +//@ only-x86_64 +//@ build-fail + +#![feature(avx512_target_feature)] +#![feature(portable_simd)] +#![allow(improper_ctypes_definitions)] + +use std::arch::x86_64::*; + +#[repr(transparent)] +struct Wrapper(__m256); + +unsafe extern "C" fn w(_: Wrapper) { + //~^ ABI error: this function definition uses a avx vector type, which is not enabled + todo!() +} + +unsafe extern "C" fn f(_: __m256) { + //~^ ABI error: this function definition uses a avx vector type, which is not enabled + todo!() +} + +unsafe extern "C" fn g() -> __m256 { + //~^ ABI error: this function definition uses a avx vector type, which is not enabled + todo!() +} + +#[target_feature(enable = "avx2")] +unsafe extern "C" fn favx(_: __m256) { + todo!() +} + +#[target_feature(enable = "avx")] +unsafe extern "C" fn gavx() -> __m256 { + todo!() +} + +fn as_f64x8(d: __m512d) -> std::simd::f64x8 { + unsafe { std::mem::transmute(d) } +} + +unsafe fn test() { + let arg = std::mem::transmute([0.0f64; 8]); + as_f64x8(arg); +} + +fn main() { + unsafe { + f(g()); + //~^ ERROR ABI error: this function call uses a avx vector type, which is not enabled in the caller + //~| ERROR ABI error: this function call uses a avx vector type, which is not enabled in the caller + } + + unsafe { + favx(gavx()); + //~^ ERROR ABI error: this function call uses a avx vector type, which is not enabled in the caller + //~| ERROR ABI error: this function call uses a avx vector type, which is not enabled in the caller + } + + unsafe { + test(); + } + + unsafe { + w(Wrapper(g())); + //~^ ERROR ABI error: this function call uses a avx vector type, which is not enabled in the caller + //~| ERROR ABI error: this function call uses a avx vector type, which is not enabled in the caller + } +} diff --git a/tests/ui/simd-abi-checks.stderr b/tests/ui/simd-abi-checks.stderr new file mode 100644 index 0000000000000..8a0cdb08e922e --- /dev/null +++ b/tests/ui/simd-abi-checks.stderr @@ -0,0 +1,74 @@ +error: ABI error: this function call uses a avx vector type, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:49:11 + | +LL | f(g()); + | ^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: ABI error: this function call uses a avx vector type, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:49:9 + | +LL | f(g()); + | ^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: ABI error: this function call uses a avx vector type, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:55:14 + | +LL | favx(gavx()); + | ^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: ABI error: this function call uses a avx vector type, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:55:9 + | +LL | favx(gavx()); + | ^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: ABI error: this function call uses a avx vector type, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:65:19 + | +LL | w(Wrapper(g())); + | ^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: ABI error: this function call uses a avx vector type, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:65:9 + | +LL | w(Wrapper(g())); + | ^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: ABI error: this function definition uses a avx vector type, which is not enabled + --> $DIR/simd-abi-checks.rs:23:1 + | +LL | unsafe extern "C" fn g() -> __m256 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: ABI error: this function definition uses a avx vector type, which is not enabled + --> $DIR/simd-abi-checks.rs:18:1 + | +LL | unsafe extern "C" fn f(_: __m256) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: ABI error: this function definition uses a avx vector type, which is not enabled + --> $DIR/simd-abi-checks.rs:13:1 + | +LL | unsafe extern "C" fn w(_: Wrapper) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + +error: aborting due to 9 previous errors + From 372afd9c4a66f41f39dc9876ff43a0ffffad22d4 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 16 Oct 2024 00:54:44 +0900 Subject: [PATCH 2/3] Fix errors after rebase --- compiler/rustc_monomorphize/src/collector/abi_check.rs | 4 ++-- compiler/rustc_monomorphize/src/errors.rs | 4 ++-- src/tools/tidy/src/issues.txt | 1 + src/tools/tidy/src/ui_tests.rs | 2 +- .../131342-2.rs => ui/issues/issue-131342-2.rs} | 3 ++- tests/ui/layout/post-mono-layout-cycle-2.rs | 1 - tests/ui/layout/post-mono-layout-cycle-2.stderr | 10 +++++----- tests/ui/layout/post-mono-layout-cycle.rs | 1 - tests/ui/layout/post-mono-layout-cycle.stderr | 10 +++++----- 9 files changed, 18 insertions(+), 18 deletions(-) rename tests/{crashes/131342-2.rs => ui/issues/issue-131342-2.rs} (91%) diff --git a/compiler/rustc_monomorphize/src/collector/abi_check.rs b/compiler/rustc_monomorphize/src/collector/abi_check.rs index ecc378ecd3d96..7778573edffb5 100644 --- a/compiler/rustc_monomorphize/src/collector/abi_check.rs +++ b/compiler/rustc_monomorphize/src/collector/abi_check.rs @@ -48,7 +48,7 @@ fn do_check_abi<'tcx>( /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments /// or return values for which the corresponding target feature is not enabled. -pub fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { +pub(crate) fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { let param_env = ParamEnv::reveal_all(); let Ok(abi) = tcx.fn_abi_of_instance(param_env.and((instance, ty::List::empty()))) else { // An error will be reported during codegen if we cannot determine the ABI of this @@ -65,7 +65,7 @@ pub fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { /// Checks that a call expression does not try to pass a vector-passed argument which requires a /// target feature that the caller does not have, as doing so causes UB because of ABI mismatch. -pub fn check_call_site_abi<'tcx>( +pub(crate) fn check_call_site_abi<'tcx>( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span, diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index e99321252bdc9..3005374f16052 100644 --- a/compiler/rustc_monomorphize/src/errors.rs +++ b/compiler/rustc_monomorphize/src/errors.rs @@ -96,7 +96,7 @@ pub(crate) struct UnknownCguCollectionMode<'a> { #[derive(Diagnostic)] #[diag(monomorphize_abi_error_disabled_vector_type_def)] #[help] -pub struct AbiErrorDisabledVectorTypeDef<'a> { +pub(crate) struct AbiErrorDisabledVectorTypeDef<'a> { #[primary_span] pub span: Span, pub required_feature: &'a str, @@ -105,7 +105,7 @@ pub struct AbiErrorDisabledVectorTypeDef<'a> { #[derive(Diagnostic)] #[diag(monomorphize_abi_error_disabled_vector_type_call)] #[help] -pub struct AbiErrorDisabledVectorTypeCall<'a> { +pub(crate) struct AbiErrorDisabledVectorTypeCall<'a> { #[primary_span] pub span: Span, pub required_feature: &'a str, diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 22126674c156b..515d798abe1c7 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1529,6 +1529,7 @@ ui/issues/issue-12920.rs ui/issues/issue-13027.rs ui/issues/issue-13058.rs ui/issues/issue-13105.rs +ui/issues/issue-131342-2.rs ui/issues/issue-13167.rs ui/issues/issue-13202.rs ui/issues/issue-13204.rs diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 11f9d5bb03df7..41f7778c95272 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -17,7 +17,7 @@ use ignore::Walk; const ENTRY_LIMIT: u32 = 901; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1672; +const ISSUES_ENTRY_LIMIT: u32 = 1673; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/crashes/131342-2.rs b/tests/ui/issues/issue-131342-2.rs similarity index 91% rename from tests/crashes/131342-2.rs rename to tests/ui/issues/issue-131342-2.rs index 79b6a837a49fb..48425afc293ab 100644 --- a/tests/crashes/131342-2.rs +++ b/tests/ui/issues/issue-131342-2.rs @@ -1,5 +1,6 @@ -//@ known-bug: #131342 +//@ check-pass // see also: 131342.rs +#![allow(unconditional_recursion)] fn main() { problem_thingy(Once); diff --git a/tests/ui/layout/post-mono-layout-cycle-2.rs b/tests/ui/layout/post-mono-layout-cycle-2.rs index 356f1e777c7d0..e9a5292fbbdfb 100644 --- a/tests/ui/layout/post-mono-layout-cycle-2.rs +++ b/tests/ui/layout/post-mono-layout-cycle-2.rs @@ -45,7 +45,6 @@ where T: Blah, { async fn ice(&mut self) { - //~^ ERROR a cycle occurred during layout computation let arr: [(); 0] = []; self.t.iter(arr.into_iter()).await; } diff --git a/tests/ui/layout/post-mono-layout-cycle-2.stderr b/tests/ui/layout/post-mono-layout-cycle-2.stderr index ad01c2694faf5..ea69b39706f48 100644 --- a/tests/ui/layout/post-mono-layout-cycle-2.stderr +++ b/tests/ui/layout/post-mono-layout-cycle-2.stderr @@ -12,12 +12,12 @@ LL | Blah::iter(self, iterator).await | = note: a recursive `async fn` call must introduce indirection such as `Box::pin` to avoid an infinitely sized future -error: a cycle occurred during layout computation - --> $DIR/post-mono-layout-cycle-2.rs:47:5 +note: the above error was encountered while instantiating `fn main::{closure#0}` + --> $DIR/post-mono-layout-cycle-2.rs:16:15 | -LL | async fn ice(&mut self) { - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | match fut.as_mut().poll(ctx) { + | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0733`. diff --git a/tests/ui/layout/post-mono-layout-cycle.rs b/tests/ui/layout/post-mono-layout-cycle.rs index 8d136190c0052..6753c01267ecd 100644 --- a/tests/ui/layout/post-mono-layout-cycle.rs +++ b/tests/ui/layout/post-mono-layout-cycle.rs @@ -14,7 +14,6 @@ struct Wrapper { } fn abi(_: Option>) {} -//~^ ERROR a cycle occurred during layout computation fn indirect() { abi::(None); diff --git a/tests/ui/layout/post-mono-layout-cycle.stderr b/tests/ui/layout/post-mono-layout-cycle.stderr index 47f7f30b1cb4c..e2f6ac595d006 100644 --- a/tests/ui/layout/post-mono-layout-cycle.stderr +++ b/tests/ui/layout/post-mono-layout-cycle.stderr @@ -5,12 +5,12 @@ error[E0391]: cycle detected when computing layout of `Wrapper<()>` = note: cycle used when computing layout of `core::option::Option>` = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error: a cycle occurred during layout computation - --> $DIR/post-mono-layout-cycle.rs:16:1 +note: the above error was encountered while instantiating `fn indirect::<()>` + --> $DIR/post-mono-layout-cycle.rs:23:5 | -LL | fn abi(_: Option>) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | indirect::<()>(); + | ^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0391`. From c28dc572fea7409f8f4bbdd59768446cddf6ca35 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Wed, 16 Oct 2024 00:54:52 +0900 Subject: [PATCH 3/3] Support s390x z13 vector ABI --- .../src/collector/abi_check.rs | 6 +- compiler/rustc_target/src/callconv/s390x.rs | 47 +++- .../spec/targets/s390x_unknown_linux_gnu.rs | 3 - .../spec/targets/s390x_unknown_linux_musl.rs | 3 - tests/assembly/s390x-vector-abi.rs | 228 ++++++++++++++++++ tests/ui/simd-abi-checks-s390x.rs | 163 +++++++++++++ tests/ui/simd-abi-checks-s390x.z10.stderr | 86 +++++++ ...simd-abi-checks-s390x.z13_no_vector.stderr | 86 +++++++ ...imd-abi-checks-s390x.z13_soft_float.stderr | 86 +++++++ 9 files changed, 690 insertions(+), 18 deletions(-) create mode 100644 tests/assembly/s390x-vector-abi.rs create mode 100644 tests/ui/simd-abi-checks-s390x.rs create mode 100644 tests/ui/simd-abi-checks-s390x.z10.stderr create mode 100644 tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr create mode 100644 tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr diff --git a/compiler/rustc_monomorphize/src/collector/abi_check.rs b/compiler/rustc_monomorphize/src/collector/abi_check.rs index 7778573edffb5..2c641ed0cd12e 100644 --- a/compiler/rustc_monomorphize/src/collector/abi_check.rs +++ b/compiler/rustc_monomorphize/src/collector/abi_check.rs @@ -2,7 +2,7 @@ use rustc_abi::Abi; use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt}; use rustc_span::def_id::DefId; use rustc_span::{Span, Symbol}; -use rustc_target::abi::call::{FnAbi, PassMode}; +use rustc_target::abi::call::{FnAbi, PassMode, RegKind}; use crate::errors::{AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef}; @@ -10,6 +10,7 @@ use crate::errors::{AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDe // to have their "proper" ABI. const X86_VECTOR_FEATURES: &'static [(u64, &'static str)] = &[(128, "sse"), (256, "avx"), (512, "avx512f")]; +const S390X_VECTOR_FEATURES: &'static [(u64, &'static str)] = &[(128, "vector")]; fn do_check_abi<'tcx>( tcx: TyCtxt<'tcx>, @@ -22,6 +23,8 @@ fn do_check_abi<'tcx>( } else if tcx.sess.target.arch == "aarch64" { // ABI on aarch64 does not depend on target features. return; + } else if tcx.sess.target.arch == "s390x" { + S390X_VECTOR_FEATURES } else { // FIXME: add support for non-tier1 architectures return; @@ -31,6 +34,7 @@ fn do_check_abi<'tcx>( let size = arg_abi.layout.size; if matches!(arg_abi.layout.abi, Abi::Vector { .. }) && !matches!(arg_abi.mode, PassMode::Indirect { .. }) + || matches!(&arg_abi.mode, PassMode::Cast { cast, .. } if cast.rest.unit.kind == RegKind::Vector) { let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) { Some((_, feature)) => feature, diff --git a/compiler/rustc_target/src/callconv/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs index 502e733126777..3eb8b88c3edcc 100644 --- a/compiler/rustc_target/src/callconv/s390x.rs +++ b/compiler/rustc_target/src/callconv/s390x.rs @@ -1,16 +1,35 @@ -// FIXME: The assumes we're using the non-vector ABI, i.e., compiling -// for a pre-z13 machine or using -mno-vx. - -use crate::abi::call::{ArgAbi, FnAbi, Reg}; -use crate::abi::{HasDataLayout, TyAbiInterface}; +use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind}; +use crate::abi::{Abi, HasDataLayout, Size, TyAbiInterface, TyAndLayout}; use crate::spec::HasTargetSpec; +fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>, expected_size: Size) -> bool +where + Ty: TyAbiInterface<'a, C> + Copy, +{ + match layout.abi { + Abi::Uninhabited | Abi::Scalar(_) | Abi::ScalarPair(..) => false, + Abi::Vector { .. } => layout.size == expected_size, + Abi::Aggregate { .. } => { + for i in 0..layout.fields.count() { + if contains_vector(cx, layout.field(cx, i), expected_size) { + return true; + } + } + false + } + } +} + fn classify_ret(ret: &mut ArgAbi<'_, Ty>) { - if !ret.layout.is_aggregate() && ret.layout.size.bits() <= 64 { + let size = ret.layout.size; + if size.bits() <= 128 && matches!(ret.layout.abi, Abi::Vector { .. }) { + return; + } + if !ret.layout.is_aggregate() && size.bits() <= 64 { ret.extend_integer_width_to(64); - } else { - ret.make_indirect(); + return; } + ret.make_indirect(); } fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) @@ -32,19 +51,25 @@ where } return; } - if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 { + + let size = arg.layout.size; + if size.bits() <= 128 && contains_vector(cx, arg.layout, size) { + arg.cast_to(Reg { kind: RegKind::Vector, size }); + return; + } + if !arg.layout.is_aggregate() && size.bits() <= 64 { arg.extend_integer_width_to(64); return; } if arg.layout.is_single_fp_element(cx) { - match arg.layout.size.bytes() { + match size.bytes() { 4 => arg.cast_to(Reg::f32()), 8 => arg.cast_to(Reg::f64()), _ => arg.make_indirect(), } } else { - match arg.layout.size.bytes() { + match size.bytes() { 1 => arg.cast_to(Reg::i8()), 2 => arg.cast_to(Reg::i16()), 4 => arg.cast_to(Reg::i32()), diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs index 3efbb46483613..a84a18a433ffc 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs @@ -6,9 +6,6 @@ pub(crate) fn target() -> Target { base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); - // FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector - // ABI. Pass the -vector feature string to LLVM to respect this assumption. - base.features = "-vector".into(); base.max_atomic_width = Some(128); base.min_global_align = Some(16); base.stack_probes = StackProbeType::Inline; diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs index 65b5c1167bdd8..4bde0fb729c75 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs @@ -6,9 +6,6 @@ pub(crate) fn target() -> Target { base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); - // FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector - // ABI. Pass the -vector feature string to LLVM to respect this assumption. - base.features = "-vector".into(); base.max_atomic_width = Some(128); base.min_global_align = Some(16); base.static_position_independent_executables = true; diff --git a/tests/assembly/s390x-vector-abi.rs b/tests/assembly/s390x-vector-abi.rs new file mode 100644 index 0000000000000..da3829587374f --- /dev/null +++ b/tests/assembly/s390x-vector-abi.rs @@ -0,0 +1,228 @@ +//@ revisions: z10 z10_vector z13 z13_no_vector +// ignore-tidy-linelength +//@ assembly-output: emit-asm +//@ compile-flags: -O -Z merge-functions=disabled +//@[z10] compile-flags: --target s390x-unknown-linux-gnu --cfg no_vector +//@[z10] needs-llvm-components: systemz +//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector +//@[z10_vector] needs-llvm-components: systemz +//@[z13] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 +//@[z13] needs-llvm-components: systemz +//@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector --cfg no_vector +//@[z13_no_vector] needs-llvm-components: systemz + +#![feature(no_core, lang_items, repr_simd, s390x_target_feature)] +#![no_core] +#![crate_type = "lib"] +#![allow(non_camel_case_types)] + +// Cases where vector feature is disabled are rejected. +// See tests/ui/simd-abi-checks-s390x.rs for test for them. + +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +#[lang = "freeze"] +pub trait Freeze {} + +impl Copy for [T; N] {} + +#[repr(simd)] +pub struct i8x8([i8; 8]); +#[repr(simd)] +pub struct i8x16([i8; 16]); +#[repr(simd)] +pub struct i8x32([i8; 32]); +#[repr(C)] +pub struct Wrapper(T); +#[repr(transparent)] +pub struct TransparentWrapper(T); + +impl Copy for i8 {} +impl Copy for i64 {} +impl Copy for i8x8 {} +impl Copy for i8x16 {} +impl Copy for i8x32 {} +impl Copy for Wrapper {} +impl Copy for TransparentWrapper {} + +// CHECK-LABEL: vector_ret_small: +// CHECK: vlrepg %v24, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + *x +} +// CHECK-LABEL: vector_ret: +// CHECK: vl %v24, 0(%r2), 3 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + *x +} +// CHECK-LABEL: vector_ret_large: +// z10: vl %v0, 16(%r3), 4 +// z10-NEXT: vl %v1, 0(%r3), 4 +// z10-NEXT: vst %v0, 16(%r2), 4 +// z10-NEXT: vst %v1, 0(%r2), 4 +// z10-NEXT: br %r14 +// z13: vl %v0, 0(%r3), 4 +// z13-NEXT: vl %v1, 16(%r3), 4 +// z13-NEXT: vst %v1, 16(%r2), 4 +// z13-NEXT: vst %v0, 0(%r2), 4 +// z13-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_ret_large(x: &i8x32) -> i8x32 { + *x +} + +// CHECK-LABEL: vector_wrapper_ret_small: +// CHECK: mvc 0(8,%r2), 0(%r3) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_ret_small(x: &Wrapper) -> Wrapper { + *x +} +// CHECK-LABEL: vector_wrapper_ret: +// CHECK: mvc 0(16,%r2), 0(%r3) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_ret(x: &Wrapper) -> Wrapper { + *x +} +// CHECK-LABEL: vector_wrapper_ret_large: +// z10: vl %v0, 16(%r3), 4 +// z10-NEXT: vl %v1, 0(%r3), 4 +// z10-NEXT: vst %v0, 16(%r2), 4 +// z10-NEXT: vst %v1, 0(%r2), 4 +// z10-NEXT: br %r14 +// z13: vl %v0, 16(%r3), 4 +// z13-NEXT: vst %v0, 16(%r2), 4 +// z13-NEXT: vl %v0, 0(%r3), 4 +// z13-NEXT: vst %v0, 0(%r2), 4 +// z13-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_ret_large(x: &Wrapper) -> Wrapper { + *x +} + +// CHECK-LABEL: vector_transparent_wrapper_ret_small: +// CHECK: vlrepg %v24, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_ret_small( + x: &TransparentWrapper, +) -> TransparentWrapper { + *x +} +// CHECK-LABEL: vector_transparent_wrapper_ret: +// CHECK: vl %v24, 0(%r2), 3 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_ret( + x: &TransparentWrapper, +) -> TransparentWrapper { + *x +} +// CHECK-LABEL: vector_transparent_wrapper_ret_large: +// z10: vl %v0, 16(%r3), 4 +// z10-NEXT: vl %v1, 0(%r3), 4 +// z10-NEXT: vst %v0, 16(%r2), 4 +// z10-NEXT: vst %v1, 0(%r2), 4 +// z10-NEXT: br %r14 +// z13: vl %v0, 0(%r3), 4 +// z13-NEXT: vl %v1, 16(%r3), 4 +// z13-NEXT: vst %v1, 16(%r2), 4 +// z13-NEXT: vst %v0, 0(%r2), 4 +// z13-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_ret_large( + x: &TransparentWrapper, +) -> TransparentWrapper { + *x +} + +// CHECK-LABEL: vector_arg_small: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_arg_small(x: i8x8) -> i64 { + unsafe { *(&x as *const i8x8 as *const i64) } +} +// CHECK-LABEL: vector_arg: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_arg(x: i8x16) -> i64 { + unsafe { *(&x as *const i8x16 as *const i64) } +} +// CHECK-LABEL: vector_arg_large: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_arg_large(x: i8x32) -> i64 { + unsafe { *(&x as *const i8x32 as *const i64) } +} + +// CHECK-LABEL: vector_wrapper_arg_small: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + unsafe { *(&x as *const Wrapper as *const i64) } +} +// CHECK-LABEL: vector_wrapper_arg: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + unsafe { *(&x as *const Wrapper as *const i64) } +} +// CHECK-LABEL: vector_wrapper_arg_large: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_wrapper_arg_large(x: Wrapper) -> i64 { + unsafe { *(&x as *const Wrapper as *const i64) } +} + +// CHECK-LABEL: vector_transparent_wrapper_arg_small: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} +// CHECK-LABEL: vector_transparent_wrapper_arg: +// CHECK: vlgvg %r2, %v24, 0 +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} +// CHECK-LABEL: vector_transparent_wrapper_arg_large: +// CHECK: lg %r2, 0(%r2) +// CHECK-NEXT: br %r14 +#[cfg_attr(no_vector, target_feature(enable = "vector"))] +#[no_mangle] +unsafe extern "C" fn vector_transparent_wrapper_arg_large(x: TransparentWrapper) -> i64 { + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} diff --git a/tests/ui/simd-abi-checks-s390x.rs b/tests/ui/simd-abi-checks-s390x.rs new file mode 100644 index 0000000000000..31a91e73af9cd --- /dev/null +++ b/tests/ui/simd-abi-checks-s390x.rs @@ -0,0 +1,163 @@ +//@ revisions: z10 z13_no_vector z13_soft_float +//@ build-fail +//@[z10] compile-flags: --target s390x-unknown-linux-gnu +//@[z10] needs-llvm-components: systemz +//@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector +//@[z13_no_vector] needs-llvm-components: systemz +// FIXME: +soft-float itself doesn't set -vector +//@[z13_soft_float] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector,+soft-float +//@[z13_soft_float] needs-llvm-components: systemz + +#![feature(no_core, lang_items, repr_simd, s390x_target_feature)] +#![no_core] +#![crate_type = "lib"] +#![allow(non_camel_case_types, improper_ctypes_definitions)] + +#[lang = "sized"] +pub trait Sized {} +#[lang = "copy"] +pub trait Copy {} +#[lang = "freeze"] +pub trait Freeze {} + +impl Copy for [T; N] {} + +#[repr(simd)] +pub struct i8x8([i8; 8]); +#[repr(simd)] +pub struct i8x16([i8; 16]); +#[repr(simd)] +pub struct i8x32([i8; 32]); +#[repr(C)] +pub struct Wrapper(T); +#[repr(transparent)] +pub struct TransparentWrapper(T); + +impl Copy for i8 {} +impl Copy for i64 {} +impl Copy for i8x8 {} +impl Copy for i8x16 {} +impl Copy for i8x32 {} +impl Copy for Wrapper {} +impl Copy for TransparentWrapper {} + +#[no_mangle] +extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + //~^ ABI error: this function definition uses a vector vector type, which is not enabled + *x +} +#[no_mangle] +extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + //~^ ABI error: this function definition uses a vector vector type, which is not enabled + *x +} +#[no_mangle] +extern "C" fn vector_ret_large(x: &i8x32) -> i8x32 { + // Ok + *x +} + +#[no_mangle] +#[target_feature(enable = "vector")] +unsafe extern "C" fn vector_ret_target_feature_small(x: &i8x8) -> i8x8 { + // Ok + *x +} +#[no_mangle] +#[target_feature(enable = "vector")] +unsafe extern "C" fn vector_target_feature_ret(x: &i8x16) -> i8x16 { + // Ok + *x +} +#[no_mangle] +#[target_feature(enable = "vector")] +unsafe extern "C" fn vector_ret_target_feature_large(x: &i8x32) -> i8x32 { + // Ok + *x +} + +#[no_mangle] +extern "C" fn vector_wrapper_ret_small(x: &Wrapper) -> Wrapper { + // Ok + *x +} +#[no_mangle] +extern "C" fn vector_wrapper_ret(x: &Wrapper) -> Wrapper { + // Ok + *x +} +#[no_mangle] +extern "C" fn vector_wrapper_ret_large(x: &Wrapper) -> Wrapper { + // Ok + *x +} + +#[no_mangle] +extern "C" fn vector_transparent_wrapper_ret_small( + x: &TransparentWrapper, +) -> TransparentWrapper { + //~^^^ ABI error: this function definition uses a vector vector type, which is not enabled + *x +} +#[no_mangle] +extern "C" fn vector_transparent_wrapper_ret( + x: &TransparentWrapper, +) -> TransparentWrapper { + //~^^^ ABI error: this function definition uses a vector vector type, which is not enabled + *x +} +#[no_mangle] +extern "C" fn vector_transparent_wrapper_ret_large( + x: &TransparentWrapper, +) -> TransparentWrapper { + // Ok + *x +} + +#[no_mangle] +extern "C" fn vector_arg_small(x: i8x8) -> i64 { + //~^ ABI error: this function definition uses a vector vector type, which is not enabled + unsafe { *(&x as *const i8x8 as *const i64) } +} +#[no_mangle] +extern "C" fn vector_arg(x: i8x16) -> i64 { + //~^ ABI error: this function definition uses a vector vector type, which is not enabled + unsafe { *(&x as *const i8x16 as *const i64) } +} +#[no_mangle] +extern "C" fn vector_arg_large(x: i8x32) -> i64 { + // Ok + unsafe { *(&x as *const i8x32 as *const i64) } +} + +#[no_mangle] +extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + //~^ ABI error: this function definition uses a vector vector type, which is not enabled + unsafe { *(&x as *const Wrapper as *const i64) } +} +#[no_mangle] +extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + //~^ ABI error: this function definition uses a vector vector type, which is not enabled + unsafe { *(&x as *const Wrapper as *const i64) } +} +#[no_mangle] +extern "C" fn vector_wrapper_arg_large(x: Wrapper) -> i64 { + // Ok + unsafe { *(&x as *const Wrapper as *const i64) } +} + +#[no_mangle] +extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + //~^ ABI error: this function definition uses a vector vector type, which is not enabled + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} +#[no_mangle] +extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + //~^ ABI error: this function definition uses a vector vector type, which is not enabled + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} +#[no_mangle] +extern "C" fn vector_transparent_wrapper_arg_large(x: TransparentWrapper) -> i64 { + // Ok + unsafe { *(&x as *const TransparentWrapper as *const i64) } +} diff --git a/tests/ui/simd-abi-checks-s390x.z10.stderr b/tests/ui/simd-abi-checks-s390x.z10.stderr new file mode 100644 index 0000000000000..f3323d12c4fd2 --- /dev/null +++ b/tests/ui/simd-abi-checks-s390x.z10.stderr @@ -0,0 +1,86 @@ +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:45:1 + | +LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:50:1 + | +LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:96:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret_small( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |_____________________________^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:103:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |______________________________^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:118:1 + | +LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:123:1 + | +LL | extern "C" fn vector_arg(x: i8x16) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:134:1 + | +LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:139:1 + | +LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:150:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:155:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: aborting due to 10 previous errors + diff --git a/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr b/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr new file mode 100644 index 0000000000000..f3323d12c4fd2 --- /dev/null +++ b/tests/ui/simd-abi-checks-s390x.z13_no_vector.stderr @@ -0,0 +1,86 @@ +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:45:1 + | +LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:50:1 + | +LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:96:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret_small( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |_____________________________^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:103:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |______________________________^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:118:1 + | +LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:123:1 + | +LL | extern "C" fn vector_arg(x: i8x16) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:134:1 + | +LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:139:1 + | +LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:150:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:155:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: aborting due to 10 previous errors + diff --git a/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr b/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr new file mode 100644 index 0000000000000..f3323d12c4fd2 --- /dev/null +++ b/tests/ui/simd-abi-checks-s390x.z13_soft_float.stderr @@ -0,0 +1,86 @@ +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:45:1 + | +LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:50:1 + | +LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:96:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret_small( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |_____________________________^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:103:1 + | +LL | / extern "C" fn vector_transparent_wrapper_ret( +LL | | x: &TransparentWrapper, +LL | | ) -> TransparentWrapper { + | |______________________________^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:118:1 + | +LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:123:1 + | +LL | extern "C" fn vector_arg(x: i8x16) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:134:1 + | +LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:139:1 + | +LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:150:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: ABI error: this function definition uses a vector vector type, which is not enabled + --> $DIR/simd-abi-checks-s390x.rs:155:1 + | +LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider enabling it globally (-C target-feature=+vector) or locally (#[target_feature(enable="vector")]) + +error: aborting due to 10 previous errors +