about summary refs log tree commit diff
path: root/compiler/rustc_monomorphize
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_monomorphize')
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml2
-rw-r--r--compiler/rustc_monomorphize/messages.ftl48
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs24
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs36
-rw-r--r--compiler/rustc_monomorphize/src/mono_checks/abi_check.rs112
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs2
-rw-r--r--compiler/rustc_monomorphize/src/partitioning/autodiff.rs2
7 files changed, 130 insertions, 96 deletions
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index 5462105e5e8..36b76d261de 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "rustc_monomorphize"
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index 540ce7cc4ce..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 a SIMD vector type that (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 a SIMD vector type that (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 a SIMD vector type that is not currently supported with the chosen ABI
-  .label = function called here
-monomorphize_abi_error_unsupported_vector_type_def =
-  this function definition uses a SIMD vector type that 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/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index ae31ed59391..d7cb8f18f82 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -323,7 +323,7 @@ impl<'tcx> MonoItems<'tcx> {
         self.items.entry(item.node).or_insert(item.span);
     }
 
-    fn items(&self) -> impl Iterator<Item = MonoItem<'tcx>> + '_ {
+    fn items(&self) -> impl Iterator<Item = MonoItem<'tcx>> {
         self.items.keys().cloned()
     }
 }
@@ -478,25 +478,24 @@ fn collect_items_rec<'tcx>(
             );
             recursion_depth_reset = None;
 
-            let item = tcx.hir().item(item_id);
-            if let hir::ItemKind::GlobalAsm(asm) = item.kind {
+            let item = tcx.hir_item(item_id);
+            if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
                 for (op, op_sp) in asm.operands {
-                    match op {
+                    match *op {
                         hir::InlineAsmOperand::Const { .. } => {
                             // Only constants which resolve to a plain integer
                             // are supported. Therefore the value should not
                             // depend on any other items.
                         }
-                        hir::InlineAsmOperand::SymFn { anon_const } => {
-                            let fn_ty =
-                                tcx.typeck_body(anon_const.body).node_type(anon_const.hir_id);
+                        hir::InlineAsmOperand::SymFn { expr } => {
+                            let fn_ty = tcx.typeck(item_id.owner_id).expr_ty(expr);
                             visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items);
                         }
                         hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
-                            let instance = Instance::mono(tcx, *def_id);
+                            let instance = Instance::mono(tcx, def_id);
                             if tcx.should_codegen_locally(instance) {
                                 trace!("collecting static {:?}", def_id);
-                                used_items.push(dummy_spanned(MonoItem::Static(*def_id)));
+                                used_items.push(dummy_spanned(MonoItem::Static(def_id)));
                             }
                         }
                         hir::InlineAsmOperand::In { .. }
@@ -1509,6 +1508,13 @@ impl<'v> RootCollector<'_, 'v> {
                         }
                         _ => unreachable!(),
                     };
+                    let Ok(instance) = self.tcx.try_normalize_erasing_regions(
+                        ty::TypingEnv::fully_monomorphized(),
+                        instance,
+                    ) else {
+                        // Don't ICE on an impossible-to-normalize closure.
+                        return;
+                    };
                     let mono_item = create_fn_mono_item(self.tcx, instance, DUMMY_SP);
                     if mono_item.node.is_instantiable(self.tcx) {
                         self.output.push(mono_item);
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index fc8d63b5888..8dafbbca905 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -1,6 +1,7 @@
 use std::path::PathBuf;
 
 use rustc_macros::{Diagnostic, LintDiagnostic};
+use rustc_middle::ty::Ty;
 use rustc_span::{Span, Symbol};
 
 #[derive(Diagnostic)]
@@ -69,33 +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,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(monomorphize_abi_error_unsupported_vector_type_def)]
-pub(crate) struct AbiErrorUnsupportedVectorTypeDef {
+#[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 {
+#[derive(Diagnostic)]
+#[diag(monomorphize_abi_required_target_feature)]
+#[help]
+pub(crate) struct AbiRequiredTargetFeature<'a> {
+    #[primary_span]
     #[label]
     pub span: Span,
+    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 a0be7f11d70..4c8dd933317 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -1,19 +1,15 @@
 //! 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_abi::{BackendRepr, RegKind};
+use rustc_abi::{BackendRepr, ExternAbi, RegKind};
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::{self, traversal};
-use rustc_middle::ty::inherent::*;
 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 {
@@ -28,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(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) {
@@ -45,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(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(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
@@ -69,24 +98,13 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
         // function.
         return;
     };
-    do_check_abi(tcx, abi, instance.def_id(), |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 },
-            );
-        } else {
-            tcx.emit_node_span_lint(
-                ABI_UNSUPPORTED_VECTOR_TYPES,
-                CRATE_HIR_ID,
-                span,
-                AbiErrorUnsupportedVectorTypeDef { span },
-            );
-        }
-    })
+    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
@@ -97,7 +115,7 @@ fn check_call_site_abi<'tcx>(
     span: Span,
     caller: InstanceKind<'tcx>,
 ) {
-    if callee.fn_sig(tcx).abi().is_rust() {
+    if callee.fn_sig(tcx).abi() == ExternAbi::Rust {
         // "Rust" ABI never passes arguments in vector registers.
         return;
     }
@@ -123,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(), |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 },
-            );
-        } else {
-            tcx.emit_node_span_lint(
-                ABI_UNSUPPORTED_VECTOR_TYPES,
-                CRATE_HIR_ID,
-                span,
-                AbiErrorUnsupportedVectorTypeCall { span },
-            );
-        }
-    });
+    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>) {
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index d826d03918e..b1b6f10e0fe 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -1269,7 +1269,7 @@ fn dump_mono_items_stats<'tcx>(
     output_directory: &Option<PathBuf>,
     crate_name: Symbol,
 ) -> Result<(), Box<dyn std::error::Error>> {
-    let output_directory = if let Some(ref directory) = output_directory {
+    let output_directory = if let Some(directory) = output_directory {
         fs::create_dir_all(directory)?;
         directory
     } else {
diff --git a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
index bce31bf0748..0c855508434 100644
--- a/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
+++ b/compiler/rustc_monomorphize/src/partitioning/autodiff.rs
@@ -66,7 +66,7 @@ pub(crate) fn find_autodiff_source_functions<'tcx>(
     let mut autodiff_items: Vec<AutoDiffItem> = vec![];
     for (item, instance) in autodiff_mono_items {
         let target_id = instance.def_id();
-        let cg_fn_attr = tcx.codegen_fn_attrs(target_id).autodiff_item.clone();
+        let cg_fn_attr = &tcx.codegen_fn_attrs(target_id).autodiff_item;
         let Some(target_attrs) = cg_fn_attr else {
             continue;
         };