From d47415fb000412c39c2be38ac11175bb93de68d0 Mon Sep 17 00:00:00 2001 From: Luca Versari Date: Sat, 13 Jul 2024 19:35:05 +0200 Subject: [PATCH] Emit warning when calling/declaring functions with unavailable vectors. On some architectures, vector types may have a different ABI depending on whether the relevant target features are enabled. (The ABI when the feature is disabled is often not specified, but LLVM implements some de-facto ABI.) As discussed in rust-lang/lang-team#235, this turns out to very easily lead to unsound code. This commit makes it a post-monomorphization future-incompat warning 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. This ensures that these functions are always called with a consistent ABI. See the [nomination comment](https://github.com/rust-lang/rust/pull/127731#issuecomment-2288558187) for more discussion. Part of #116558 --- compiler/rustc_lint_defs/src/builtin.rs | 67 ++++++ compiler/rustc_middle/src/query/keys.rs | 8 + compiler/rustc_middle/src/query/mod.rs | 5 + compiler/rustc_monomorphize/messages.ftl | 9 + compiler/rustc_monomorphize/src/collector.rs | 4 + .../src/collector/abi_check.rs | 201 ++++++++++++++++++ compiler/rustc_monomorphize/src/errors.rs | 18 ++ compiler/rustc_target/src/target_features.rs | 17 ++ tests/ui/simd-abi-checks.rs | 81 +++++++ tests/ui/simd-abi-checks.stderr | 93 ++++++++ tests/ui/sse-abi-checks.rs | 24 +++ tests/ui/sse-abi-checks.stderr | 13 ++ 12 files changed, 540 insertions(+) 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 create mode 100644 tests/ui/sse-abi-checks.rs create mode 100644 tests/ui/sse-abi-checks.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 06a3e4a674303..51146cfd2e9aa 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -16,6 +16,7 @@ declare_lint_pass! { /// that are used by other parts of the compiler. HardwiredLints => [ // tidy-alphabetical-start + ABI_UNSUPPORTED_VECTOR_TYPES, ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_ASSOCIATED_ITEMS, AMBIGUOUS_GLOB_IMPORTS, @@ -5031,3 +5032,69 @@ declare_lint! { }; crate_level_only } + +declare_lint! { + /// The `abi_unsupported_vector_types` lint detects function definitions and calls + /// whose ABI depends on enabling certain target features, but those features are not enabled. + /// + /// ### Example + /// + /// ```rust,ignore (fails on non-x86_64) + /// extern "C" fn missing_target_feature(_: std::arch::x86_64::__m256) { + /// todo!() + /// } + /// + /// #[target_feature(enable = "avx")] + /// unsafe extern "C" fn with_target_feature(_: std::arch::x86_64::__m256) { + /// todo!() + /// } + /// + /// fn main() { + /// let v = unsafe { std::mem::zeroed() }; + /// unsafe { with_target_feature(v); } + /// } + /// ``` + /// + /// ```text + /// warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller + /// --> lint_example.rs:18:12 + /// | + /// | unsafe { with_target_feature(v); } + /// | ^^^^^^^^^^^^^^^^^^^^^^ function called here + /// | + /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + /// = note: for more information, see issue #116558 + /// = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + /// = note: `#[warn(abi_unsupported_vector_types)]` on by default + /// + /// + /// warning: ABI error: this function definition uses a avx vector type, which is not enabled + /// --> lint_example.rs:3:1 + /// | + /// | pub extern "C" fn with_target_feature(_: std::arch::x86_64::__m256) { + /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + /// | + /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + /// = note: for more information, see issue #116558 + /// = help: consider enabling it globally (-C target-feature=+avx) or locally (#[target_feature(enable="avx")]) + /// ``` + /// + /// + /// + /// ### Explanation + /// + /// The C ABI for `__m256` requires the value to be passed in an AVX register, + /// which is only possible when the `avx` target feature is enabled. + /// Therefore, `missing_target_feature` cannot be compiled without that target feature. + /// A similar (but complementary) message is triggered when `with_target_feature` is called + /// by a function that does not enable the `avx` target feature. + /// + /// Note that this lint is very similar to the `-Wpsabi` warning in `gcc`/`clang`. + pub ABI_UNSUPPORTED_VECTOR_TYPES, + Warn, + "this function call or definition uses a vector type which is not enabled", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reference: "issue #116558 ", + }; +} diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index ba7b57c891c52..ab106d4c2ae1c 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -591,3 +591,11 @@ impl<'tcx> Key for (ValidityRequirement, ty::ParamEnvAnd<'tcx, Ty<'tcx>>) { } } } + +impl<'tcx> Key for (Ty<'tcx>, DefId) { + type Cache = DefaultCache; + + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.1.default_span(tcx) + } +} diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 088b5d4ec965f..0f2595a46a0c5 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2315,6 +2315,11 @@ rustc_queries! { desc { "whether the item should be made inlinable across crates" } separate_provide_extern } + + query check_feature_dependent_abi(key: ty::Instance<'tcx>) { + desc { "check for feature-dependent ABI" } + cache_on_disk_if { true } + } } rustc_query_append! { define_callbacks! } diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl index 7210701d4828c..6da387bbebcc7 100644 --- a/compiler/rustc_monomorphize/messages.ftl +++ b/compiler/rustc_monomorphize/messages.ftl @@ -1,3 +1,12 @@ +monomorphize_abi_error_disabled_vector_type_call = + ABI error: this function call uses a vector type that requires the `{$required_feature}` target feature, which is not enabled in the caller + .label = function called here + .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 vector type that requires the `{$required_feature}` target feature, which is not enabled + .label = function defined here + .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 8df6e63deeb18..63afad5df4971 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; @@ -1207,6 +1208,8 @@ fn collect_items_of_instance<'tcx>( mentioned_items: &mut MonoItems<'tcx>, mode: CollectionMode, ) { + tcx.ensure().check_feature_dependent_abi(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 @@ -1623,4 +1626,5 @@ pub(crate) fn collect_crate_mono_items<'tcx>( pub(crate) fn provide(providers: &mut Providers) { providers.hooks.should_codegen_locally = should_codegen_locally; + abi_check::provide(providers); } 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..6af1fbfb05f8a --- /dev/null +++ b/compiler/rustc_monomorphize/src/collector/abi_check.rs @@ -0,0 +1,201 @@ +//! This module ensures that if a function's ABI requires a particular target feature, +//! that target feature is enabled both on the callee and all callers. +use rustc_hir::CRATE_HIR_ID; +use rustc_hir::def::DefKind; +use rustc_middle::mir::visit::Visitor as MirVisitor; +use rustc_middle::mir::{self, Location, traversal}; +use rustc_middle::query::Providers; +use rustc_middle::ty::inherent::*; +use rustc_middle::ty::{self, Instance, InstanceKind, ParamEnv, Ty, TyCtxt}; +use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES; +use rustc_span::def_id::DefId; +use rustc_span::{DUMMY_SP, Span, Symbol}; +use rustc_target::abi::call::{FnAbi, PassMode}; +use rustc_target::abi::{BackendRepr, RegKind}; + +use crate::errors::{AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef}; + +fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool { + match mode { + PassMode::Ignore | PassMode::Indirect { .. } => false, + PassMode::Cast { pad_i32: _, cast } => { + cast.prefix.iter().any(|r| r.is_some_and(|x| x.kind == RegKind::Vector)) + || cast.rest.unit.kind == RegKind::Vector + } + PassMode::Direct(..) | PassMode::Pair(..) => matches!(repr, BackendRepr::Vector { .. }), + } +} + +fn do_check_abi<'tcx>( + tcx: TyCtxt<'tcx>, + abi: &FnAbi<'tcx, Ty<'tcx>>, + target_feature_def: DefId, + mut emit_err: impl FnMut(&'static str), +) { + let Some(feature_def) = tcx.sess.target.features_for_correct_vector_abi() else { + 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 uses_vector_registers(&arg_abi.mode, &arg_abi.layout.backend_repr) { + // Find the first feature that provides at least this vector size. + let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) { + Some((_, feature)) => feature, + None => { + emit_err(""); + continue; + } + }; + 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. +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| { + let span = tcx.def_span(instance.def_id()); + tcx.emit_node_span_lint( + ABI_UNSUPPORTED_VECTOR_TYPES, + CRATE_HIR_ID, + span, + AbiErrorDisabledVectorTypeDef { span, 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. +fn check_call_site_abi<'tcx>( + tcx: TyCtxt<'tcx>, + callee: Ty<'tcx>, + span: Span, + caller: InstanceKind<'tcx>, +) { + if callee.fn_sig(tcx).abi().is_rust() { + // "Rust" ABI never passes arguments in vector registers. + return; + } + let param_env = ParamEnv::reveal_all(); + let callee_abi = match *callee.kind() { + ty::FnPtr(..) => { + tcx.fn_abi_of_fn_ptr(param_env.and((callee.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, DUMMY_SP); + 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.emit_node_span_lint( + ABI_UNSUPPORTED_VECTOR_TYPES, + CRATE_HIR_ID, + span, + AbiErrorDisabledVectorTypeCall { span, required_feature }, + ); + }); +} + +struct MirCallesAbiCheck<'a, 'tcx> { + tcx: TyCtxt<'tcx>, + body: &'a mir::Body<'tcx>, + instance: Instance<'tcx>, +} + +impl<'a, 'tcx> MirVisitor<'tcx> for MirCallesAbiCheck<'a, 'tcx> { + fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, _: Location) { + match terminator.kind { + mir::TerminatorKind::Call { ref func, ref fn_span, .. } + | mir::TerminatorKind::TailCall { ref func, ref fn_span, .. } => { + let callee_ty = func.ty(self.body, self.tcx); + let callee_ty = self.instance.instantiate_mir_and_normalize_erasing_regions( + self.tcx, + ty::ParamEnv::reveal_all(), + ty::EarlyBinder::bind(callee_ty), + ); + check_call_site_abi(self.tcx, callee_ty, *fn_span, self.body.source.instance); + } + _ => {} + } + } +} + +fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { + let body = tcx.instance_mir(instance.def); + let mut visitor = MirCallesAbiCheck { tcx, body, instance }; + for (bb, data) in traversal::mono_reachable(body, tcx, instance) { + visitor.visit_basic_block_data(bb, data) + } +} + +fn should_check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool { + // We do not need to check the instance for feature-dependent ABI if we can determine that the + // function has "Rust" or "rust-call" ABI, which is known not to be feature-dependent. + // Note that the check is still correct on Rust ABI functions, but somewhat expensive. Hence, + // checking for "Rust" ABI is just an optimization. + // We also avoid to try to determine the type of the instance, as doing so involves running a + // query that does not usually run for unchanged functions in incremental builds. + match instance.def { + // We only need to check for user-defined functions - if all user-defined functions are + // fine, so are the `instance`s derived by the compiler. + InstanceKind::Item(def) => { + // fn_sig ICEs on defs that are not functions. + if matches!(tcx.def_kind(def), DefKind::Fn | DefKind::AssocFn) { + !tcx.fn_sig(def).skip_binder().abi().is_rust() + } else if matches!(tcx.def_kind(def), DefKind::Ctor(..) | DefKind::Closure) { + // Struct constructors and closures do not give control of their ABI to the user. + false + } else { + true + } + } + InstanceKind::ReifyShim(..) + | InstanceKind::FnPtrShim(..) + | InstanceKind::Virtual(..) + | InstanceKind::VTableShim(..) + | InstanceKind::Intrinsic(..) + | InstanceKind::DropGlue(..) + | InstanceKind::CloneShim(..) + | InstanceKind::FnPtrAddrShim(..) + | InstanceKind::AsyncDropGlueCtorShim(..) + | InstanceKind::ThreadLocalShim(..) + | InstanceKind::ClosureOnceShim { .. } + | InstanceKind::ConstructCoroutineInClosureShim { .. } => false, + } +} + +fn check_feature_dependent_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) { + if should_check_instance_abi(tcx, instance) { + check_instance_abi(tcx, instance); + } + check_callees_abi(tcx, instance); +} + +pub(super) fn provide(providers: &mut Providers) { + *providers = Providers { check_feature_dependent_abi, ..*providers } +} diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs index d5fae6e23cb45..5048a8d5d993f 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(LintDiagnostic)] +#[diag(monomorphize_abi_error_disabled_vector_type_def)] +#[help] +pub(crate) struct AbiErrorDisabledVectorTypeDef<'a> { + #[label] + pub span: Span, + pub required_feature: &'a str, +} + +#[derive(LintDiagnostic)] +#[diag(monomorphize_abi_error_disabled_vector_type_call)] +#[help] +pub(crate) struct AbiErrorDisabledVectorTypeCall<'a> { + #[label] + pub span: Span, + pub required_feature: &'a str, +} diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 3df8f0590a354..94f771954e145 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -524,6 +524,13 @@ pub fn all_known_features() -> impl Iterator { .map(|(f, s, _)| (f, s)) } +// These arrays represent the least-constraining feature that is required for vector types up to a +// certain size to have their "proper" ABI on each architecture. +// Note that they must be kept sorted by vector size. +const X86_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = + &[(128, "sse"), (256, "avx"), (512, "avx512f")]; +const AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI: &'static [(u64, &'static str)] = &[(128, "neon")]; + impl super::spec::Target { pub fn supported_target_features( &self, @@ -545,6 +552,16 @@ impl super::spec::Target { } } + // Returns None if we do not support ABI checks on the given target yet. + pub fn features_for_correct_vector_abi(&self) -> Option<&'static [(u64, &'static str)]> { + match &*self.arch { + "x86" | "x86_64" => Some(X86_FEATURES_FOR_CORRECT_VECTOR_ABI), + "aarch64" => Some(AARCH64_FEATURES_FOR_CORRECT_VECTOR_ABI), + // FIXME: add support for non-tier1 architectures + _ => None, + } + } + pub fn tied_target_features(&self) -> &'static [&'static [&'static str]] { match &*self.arch { "aarch64" | "arm64ec" => AARCH64_TIED_FEATURES, diff --git a/tests/ui/simd-abi-checks.rs b/tests/ui/simd-abi-checks.rs new file mode 100644 index 0000000000000..094c89930b752 --- /dev/null +++ b/tests/ui/simd-abi-checks.rs @@ -0,0 +1,81 @@ +//@ only-x86_64 +//@ build-pass +//@ ignore-pass (test emits codegen-time warnings) + +#![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 vector type that requires the `avx` target feature, which is not enabled + //~| WARNING this was previously accepted by the compiler + todo!() +} + +unsafe extern "C" fn f(_: __m256) { + //~^ ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled + //~| WARNING this was previously accepted by the compiler + todo!() +} + +unsafe extern "C" fn g() -> __m256 { + //~^ ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled + //~| WARNING this was previously accepted by the compiler + todo!() +} + +#[target_feature(enable = "avx")] +unsafe extern "C" fn favx() -> __m256 { + todo!() +} + +// avx2 implies avx, so no error here. +#[target_feature(enable = "avx2")] +unsafe extern "C" fn gavx(_: __m256) { + todo!() +} + +// No error because of "Rust" ABI. +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()); + //~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + //~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + //~| WARNING this was previously accepted by the compiler + //~| WARNING this was previously accepted by the compiler + } + + unsafe { + gavx(favx()); + //~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + //~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + //~| WARNING this was previously accepted by the compiler + //~| WARNING this was previously accepted by the compiler + } + + unsafe { + test(); + } + + unsafe { + w(Wrapper(g())); + //~^ WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + //~| WARNING ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + //~| WARNING this was previously accepted by the compiler + //~| WARNING this was previously accepted by the compiler + } +} diff --git a/tests/ui/simd-abi-checks.stderr b/tests/ui/simd-abi-checks.stderr new file mode 100644 index 0000000000000..aa7e940016981 --- /dev/null +++ b/tests/ui/simd-abi-checks.stderr @@ -0,0 +1,93 @@ +warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:55:11 + | +LL | f(g()); + | ^^^ function called here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + = note: `#[warn(abi_unsupported_vector_types)]` on by default + +warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:55:9 + | +LL | f(g()); + | ^^^^^^ function called here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + +warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:63:14 + | +LL | gavx(favx()); + | ^^^^^^ function called here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + +warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:63:9 + | +LL | gavx(favx()); + | ^^^^^^^^^^^^ function called here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + +warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:75:19 + | +LL | w(Wrapper(g())); + | ^^^ function called here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + +warning: ABI error: this function call uses a vector type that requires the `avx` target feature, which is not enabled in the caller + --> $DIR/simd-abi-checks.rs:75:9 + | +LL | w(Wrapper(g())); + | ^^^^^^^^^^^^^^^ function called here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + +warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled + --> $DIR/simd-abi-checks.rs:26:1 + | +LL | unsafe extern "C" fn g() -> __m256 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + +warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled + --> $DIR/simd-abi-checks.rs:20:1 + | +LL | unsafe extern "C" fn f(_: __m256) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + +warning: ABI error: this function definition uses a vector type that requires the `avx` target feature, which is not enabled + --> $DIR/simd-abi-checks.rs:14:1 + | +LL | unsafe extern "C" fn w(_: Wrapper) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) + +warning: 9 warnings emitted + diff --git a/tests/ui/sse-abi-checks.rs b/tests/ui/sse-abi-checks.rs new file mode 100644 index 0000000000000..d2afd38fcc85f --- /dev/null +++ b/tests/ui/sse-abi-checks.rs @@ -0,0 +1,24 @@ +//! Ensure we trigger abi_unsupported_vector_types for target features that are usually enabled +//! on a target, but disabled in this file via a `-C` flag. +//@ compile-flags: --crate-type=rlib --target=i686-unknown-linux-gnu -C target-feature=-sse,-sse2 +//@ build-pass +//@ ignore-pass (test emits codegen-time warnings) +//@ needs-llvm-components: x86 +#![feature(no_core, lang_items, repr_simd)] +#![no_core] +#![allow(improper_ctypes_definitions)] + +#[lang = "sized"] +trait Sized {} + +#[lang = "copy"] +trait Copy {} + +#[repr(simd)] +pub struct SseVector([i64; 2]); + +#[no_mangle] +pub unsafe extern "C" fn f(_: SseVector) { + //~^ ABI error: this function definition uses a vector type that requires the `sse` target feature, which is not enabled + //~| WARNING this was previously accepted by the compiler +} diff --git a/tests/ui/sse-abi-checks.stderr b/tests/ui/sse-abi-checks.stderr new file mode 100644 index 0000000000000..77c4e1fc07ab4 --- /dev/null +++ b/tests/ui/sse-abi-checks.stderr @@ -0,0 +1,13 @@ +warning: ABI error: this function definition uses a vector type that requires the `sse` target feature, which is not enabled + --> $DIR/sse-abi-checks.rs:21:1 + | +LL | pub unsafe extern "C" fn f(_: SseVector) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116558 + = help: consider enabling it globally (`-C target-feature=+sse`) or locally (`#[target_feature(enable="sse")]`) + = note: `#[warn(abi_unsupported_vector_types)]` on by default + +warning: 1 warning emitted +