about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_monomorphize/messages.ftl48
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs35
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs107
3 files changed, 107 insertions, 83 deletions
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 463c42b69b1..bdeab12ab50 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -1,18 +1,40 @@
-monomorphize_abi_error_disabled_vector_type_call =
-  this function call uses SIMD vector type `{$ty}` which (with the chosen ABI) 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 =
-  this function definition uses SIMD vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled
-  .label = function defined here
+monomorphize_abi_error_disabled_vector_type =
+  this function {$is_call ->
+    [true] call
+    *[false] definition
+  } uses SIMD vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled{$is_call ->
+    [true] {" "}in the caller
+    *[false] {""}
+  }
+  .label = function {$is_call ->
+    [true] called
+    *[false] defined
+  } here
   .help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
 
-monomorphize_abi_error_unsupported_vector_type_call =
-  this function call uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI
-  .label = function called here
-monomorphize_abi_error_unsupported_vector_type_def =
-  this function definition uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI
-  .label = function defined here
+monomorphize_abi_error_unsupported_vector_type =
+  this function {$is_call ->
+    [true] call
+    *[false] definition
+  } uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI
+  .label = function {$is_call ->
+    [true] called
+    *[false] defined
+  } here
+
+monomorphize_abi_required_target_feature =
+  this function {$is_call ->
+    [true] call
+    *[false] definition
+  } uses ABI "{$abi}" which requires the `{$required_feature}` target feature, which is not enabled{$is_call ->
+    [true] {" "}in the caller
+    *[false] {""}
+  }
+  .label = function {$is_call ->
+    [true] called
+    *[false] 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/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 75687a80b82..8dafbbca905 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -70,37 +70,36 @@ pub(crate) struct UnknownCguCollectionMode<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[diag(monomorphize_abi_error_disabled_vector_type_def)]
+#[diag(monomorphize_abi_error_disabled_vector_type)]
 #[help]
-pub(crate) struct AbiErrorDisabledVectorTypeDef<'a> {
+pub(crate) struct AbiErrorDisabledVectorType<'a> {
     #[label]
     pub span: Span,
     pub required_feature: &'a str,
     pub ty: Ty<'a>,
+    /// Whether this is a problem at a call site or at a declaration.
+    pub is_call: bool,
 }
 
 #[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,
-    pub ty: Ty<'a>,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(monomorphize_abi_error_unsupported_vector_type_def)]
-pub(crate) struct AbiErrorUnsupportedVectorTypeDef<'a> {
+#[diag(monomorphize_abi_error_unsupported_vector_type)]
+pub(crate) struct AbiErrorUnsupportedVectorType<'a> {
     #[label]
     pub span: Span,
     pub ty: Ty<'a>,
+    /// Whether this is a problem at a call site or at a declaration.
+    pub is_call: bool,
 }
 
-#[derive(LintDiagnostic)]
-#[diag(monomorphize_abi_error_unsupported_vector_type_call)]
-pub(crate) struct AbiErrorUnsupportedVectorTypeCall<'a> {
+#[derive(Diagnostic)]
+#[diag(monomorphize_abi_required_target_feature)]
+#[help]
+pub(crate) struct AbiRequiredTargetFeature<'a> {
+    #[primary_span]
     #[label]
     pub span: Span,
-    pub ty: Ty<'a>,
+    pub required_feature: &'a str,
+    pub abi: &'a str,
+    /// Whether this is a problem at a call site or at a declaration.
+    pub is_call: bool,
 }
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 8e93bdc61d0..4c8dd933317 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -6,13 +6,10 @@ use rustc_middle::mir::{self, traversal};
 use rustc_middle::ty::{self, Instance, InstanceKind, 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::callconv::{FnAbi, PassMode};
+use rustc_span::{DUMMY_SP, Span, Symbol, sym};
+use rustc_target::callconv::{Conv, FnAbi, PassMode};
 
-use crate::errors::{
-    AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef,
-    AbiErrorUnsupportedVectorTypeCall, AbiErrorUnsupportedVectorTypeDef,
-};
+use crate::errors;
 
 fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
     match mode {
@@ -27,16 +24,21 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
 
 /// Checks whether a certain function ABI is compatible with the target features currently enabled
 /// for a certain function.
-/// If not, `emit_err` is called, with `Some(feature)` if a certain feature should be enabled and
-/// with `None` if no feature is known that would make the ABI compatible.
+/// `is_call` indicates whether this is a call-site check or a definition-site check;
+/// this is only relevant for the wording in the emitted error.
 fn do_check_abi<'tcx>(
     tcx: TyCtxt<'tcx>,
     abi: &FnAbi<'tcx, Ty<'tcx>>,
-    target_feature_def: DefId,
-    mut emit_err: impl FnMut(Ty<'tcx>, Option<&'static str>),
+    def_id: DefId,
+    is_call: bool,
+    span: impl Fn() -> Span,
 ) {
     let feature_def = tcx.sess.target.features_for_correct_vector_abi();
-    let codegen_attrs = tcx.codegen_fn_attrs(target_feature_def);
+    let codegen_attrs = tcx.codegen_fn_attrs(def_id);
+    let have_feature = |feat: Symbol| {
+        tcx.sess.unstable_target_features.contains(&feat)
+            || codegen_attrs.target_features.iter().any(|x| x.name == feat)
+    };
     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) {
@@ -44,18 +46,46 @@ fn do_check_abi<'tcx>(
             let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
                 Some((_, feature)) => feature,
                 None => {
-                    emit_err(arg_abi.layout.ty, None);
+                    let span = span();
+                    tcx.emit_node_span_lint(
+                        ABI_UNSUPPORTED_VECTOR_TYPES,
+                        CRATE_HIR_ID,
+                        span,
+                        errors::AbiErrorUnsupportedVectorType {
+                            span,
+                            ty: arg_abi.layout.ty,
+                            is_call,
+                        },
+                    );
                     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(arg_abi.layout.ty, Some(&feature));
+            if !have_feature(Symbol::intern(feature)) {
+                // Emit error.
+                let span = span();
+                tcx.emit_node_span_lint(
+                    ABI_UNSUPPORTED_VECTOR_TYPES,
+                    CRATE_HIR_ID,
+                    span,
+                    errors::AbiErrorDisabledVectorType {
+                        span,
+                        required_feature: feature,
+                        ty: arg_abi.layout.ty,
+                        is_call,
+                    },
+                );
             }
         }
     }
+    // The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed.
+    if abi.conv == Conv::X86VectorCall && !have_feature(sym::sse2) {
+        tcx.dcx().emit_err(errors::AbiRequiredTargetFeature {
+            span: span(),
+            required_feature: "sse2",
+            abi: "vectorcall",
+            is_call,
+        });
+    }
 }
 
 /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
@@ -68,24 +98,13 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
         // function.
         return;
     };
-    do_check_abi(tcx, abi, instance.def_id(), |ty, required_feature| {
-        let span = tcx.def_span(instance.def_id());
-        if let Some(required_feature) = required_feature {
-            tcx.emit_node_span_lint(
-                ABI_UNSUPPORTED_VECTOR_TYPES,
-                CRATE_HIR_ID,
-                span,
-                AbiErrorDisabledVectorTypeDef { span, required_feature, ty },
-            );
-        } else {
-            tcx.emit_node_span_lint(
-                ABI_UNSUPPORTED_VECTOR_TYPES,
-                CRATE_HIR_ID,
-                span,
-                AbiErrorUnsupportedVectorTypeDef { span, ty },
-            );
-        }
-    })
+    do_check_abi(
+        tcx,
+        abi,
+        instance.def_id(),
+        /*is_call*/ false,
+        || tcx.def_span(instance.def_id()),
+    )
 }
 
 /// Checks that a call expression does not try to pass a vector-passed argument which requires a
@@ -122,23 +141,7 @@ fn check_call_site_abi<'tcx>(
         // ABI failed to compute; this will not get through codegen.
         return;
     };
-    do_check_abi(tcx, callee_abi, caller.def_id(), |ty, required_feature| {
-        if let Some(required_feature) = required_feature {
-            tcx.emit_node_span_lint(
-                ABI_UNSUPPORTED_VECTOR_TYPES,
-                CRATE_HIR_ID,
-                span,
-                AbiErrorDisabledVectorTypeCall { span, required_feature, ty },
-            );
-        } else {
-            tcx.emit_node_span_lint(
-                ABI_UNSUPPORTED_VECTOR_TYPES,
-                CRATE_HIR_ID,
-                span,
-                AbiErrorUnsupportedVectorTypeCall { span, ty },
-            );
-        }
-    });
+    do_check_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
 }
 
 fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {