diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index b089f6333eef4..246f710b098d3 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -474,6 +474,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se &mut sess.early_sess.opts.target_modifiers, &target_config, &sess.early_sess.target, + &*codegen_backend, ); sess.check_config = parse_check_cfg(&sess, config.crate_check_cfg); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 1d6e2ac2e94cf..08c3756a41a06 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -95,6 +95,7 @@ pub(crate) fn add_target_modifiers( tmod: &mut BTreeMap, target_config: &TargetConfig, target: &Target, + cg_backend: &dyn CodegenBackend, ) { // Record relevant target features as target modifier. // Join all target-modifier target features into a single comma-separated string, @@ -108,6 +109,9 @@ pub(crate) fn add_target_modifiers( .collect::>() .join(","); tmod.insert(OptionsTargetModifiers::TargetFeatures, target_feature_modifier); + + // Record the codegen backend name as target modifier. + tmod.insert(OptionsTargetModifiers::CodegenBackendName, cg_backend.name().to_string()); } /// Ensures that all target features required by the ABI are present. diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 70302bbef51cb..a2cd205f76e92 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -390,7 +390,7 @@ impl CStore { assert!(local_features.len() > 0 || extern_features.len() > 0); let diag = format!( - "mixing target features will cause an ABI mismatch in crate `{local_crate}`" + "mixing target features may cause an ABI mismatch in crate `{local_crate}`" ); let mut diag = tcx.dcx().struct_warn(diag); diag.help("some target features modify the ABI so Rust crates compiled with different values for these target features cannot be used together safely"); @@ -411,6 +411,16 @@ impl CStore { diag.help("if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=target-feature` to silence this warning"); diag.emit(); } + "codegen-backend-name" => { + let diag = format!( + "mixing codegen backends while using backend-specific target features may cause an ABI mismatch in crate `{local_crate}`" + ); + let mut diag = tcx.dcx().struct_err(diag); + diag.help("this crate has `-Zllvm-target-features` set, which means different codegen backends could interpret the target features differently, or ignore them entirely"); + diag.help("some target features modify the ABI so Rust crates compiled with different target features cannot be used together safely"); + diag.help("if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=codegen-backend-name` to silence this warning"); + diag.emit(); + } _ => panic!("unhandled synthetic target feature {opt_name}"), } return; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index ef503a627a40f..3d602dcf01d53 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -175,6 +175,25 @@ mod target_modifier_consistency_check { }; l_tech_value == r_tech_value } + pub(super) fn codegen_backend_name( + sess: &Session, + l: &TargetModifier, + r: Option<&TargetModifier>, + ) -> bool { + let l_val = l.value_name.as_str(); + let r_val = match r { + Some(r) => r.value_name.as_str(), + None => option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("dummy"), + }; + if l_val == r_val { + // Same codegen backend: all good. + // (We assume codegen backends with the same name are compatible wrt target features.) + return true; + } + // If the codegen backends differ, there must be no LLVM target features. (Those are + // themselves a target modifier so we know they are consistent across the crate graph.) + sess.opts.unstable_opts.llvm_target_feature.is_empty() + } } impl TargetModifier { @@ -207,6 +226,9 @@ impl TargetModifier { return target_modifier_consistency_check::target_cpu(sess, self, other); } }, + OptionsTargetModifiers::CodegenBackendName => { + return target_modifier_consistency_check::codegen_backend_name(sess, self, other); + } _ => {} }; match other { @@ -246,9 +268,14 @@ macro_rules! top_level_options { $tmod_variant($tmod_enum), )? )* + // Synthetic target modifiers, manually computed. + /// List of target features that are actually target modifiers. TargetFeatures, + /// Name of the codegen backend. + /// (Not the full path to the .so file to avoid storing file system paths.) + CodegenBackendName, } impl OptionsTargetModifiers { @@ -268,6 +295,13 @@ macro_rules! top_level_options { tech_value: format!("{:?}", user_value), } } + Self::CodegenBackendName => { + ExtendedTargetModifierInfo { + prefix: String::new(), + name: "codegen-backend-name".into(), + tech_value: format!("{:?}", user_value), + } + } #[allow(unreachable_patterns)] _ => panic!("unknown target modifier option: {self:?}"), @@ -286,7 +320,7 @@ macro_rules! top_level_options { )* // Synthetic target modifiers. The names must match `reparse` above. - if flag_name == "target-feature" { + if flag_name == "target-feature" || flag_name == "codegen-backend-name" { return true; } @@ -350,6 +384,7 @@ macro_rules! top_level_options { )? )* tmod_push_impl(OptionsTargetModifiers::TargetFeatures, &self.target_modifiers, &mut mods); + tmod_push_impl(OptionsTargetModifiers::CodegenBackendName, &self.target_modifiers, &mut mods); mods.sort_by(|a, b| a.opt.cmp(&b.opt)); mods } diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs index 902835da78c5c..4b6b1e6610b06 100644 --- a/src/tools/compiletest/src/runtest/codegen_units.rs +++ b/src/tools/compiletest/src/runtest/codegen_units.rs @@ -17,7 +17,7 @@ impl TestCx<'_> { const PREFIX: &str = "MONO_ITEM "; const CGU_MARKER: &str = "@@"; - // Some MonoItems can contain {closure@/path/to/checkout/tests/codgen-units/test.rs} + // Some MonoItems can contain {closure@/path/to/checkout/tests/codegen-units/test.rs} // To prevent the current dir from leaking, we just replace the entire path to the test // file with TEST_PATH. let actual: Vec = proc_res diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/with_llvm_target_feature.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/with_llvm_target_feature.rs new file mode 100644 index 0000000000000..5b6770d7d9deb --- /dev/null +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/with_llvm_target_feature.rs @@ -0,0 +1,8 @@ +//! A crate that uses the default codegen backend and an LLVM target feature. + +//@ compile-flags: --target arm-unknown-linux-gnueabi --emit=metadata +//@ needs-llvm-components: arm +//@ compile-flags: -Zllvm-target-feature=+thumb2 + +#![feature(no_core)] +#![no_core] diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.rs b/tests/ui-fulldeps/codegen-backend/hotplug.rs index ce310ba3e315e..37bc84317e7a3 100644 --- a/tests/ui-fulldeps/codegen-backend/hotplug.rs +++ b/tests/ui-fulldeps/codegen-backend/hotplug.rs @@ -6,7 +6,7 @@ //@ normalize-stdout: "libthe_backend.dylib" -> "libthe_backend.so" //@ normalize-stdout: "the_backend.dll" -> "libthe_backend.so" -// Pick a target that requires no target features, so that no warning is shown +// Pick a target that requires no target features in the ABI check, so that no warning is shown // about missing target features. //@ compile-flags: --target arm-unknown-linux-gnueabi //@ needs-llvm-components: arm diff --git a/tests/ui-fulldeps/codegen-backend/llvm-target-features.rs b/tests/ui-fulldeps/codegen-backend/llvm-target-features.rs new file mode 100644 index 0000000000000..9f814806cfe29 --- /dev/null +++ b/tests/ui-fulldeps/codegen-backend/llvm-target-features.rs @@ -0,0 +1,20 @@ +//! When using llvm-target-features, we cannot mix codegen backends. + +//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) +//@ ignore-backends: gcc + +//@ aux-codegen-backend: the_backend.rs +//@ aux-build: with_llvm_target_feature.rs + +// Pick a target that requires no target features in the ABI check, so that no warning is shown +// about missing target features. +//@ compile-flags: --target arm-unknown-linux-gnueabi --crate-type=lib +//@ needs-llvm-components: arm +//@ compile-flags: -Zllvm-target-feature=+thumb2 + +#![feature(no_core)] +#![no_core] + +extern crate with_llvm_target_feature; + +//~? ERROR: mixing codegen backends while using backend-specific target features may cause an ABI mismatch diff --git a/tests/ui-fulldeps/codegen-backend/llvm-target-features.stderr b/tests/ui-fulldeps/codegen-backend/llvm-target-features.stderr new file mode 100644 index 0000000000000..028458ab3ca4c --- /dev/null +++ b/tests/ui-fulldeps/codegen-backend/llvm-target-features.stderr @@ -0,0 +1,8 @@ +error: mixing codegen backends while using backend-specific target features may cause an ABI mismatch in crate `llvm_target_features` + | + = help: this crate has `-Zllvm-target-features` set, which means different codegen backends could interpret the target features differently, or ignore them entirely + = help: some target features modify the ABI so Rust crates compiled with different target features cannot be used together safely + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=codegen-backend-name` to silence this warning + +error: aborting due to 1 previous error + diff --git a/tests/ui/target-feature/abi-relevant-target-modifier.baseline.stderr b/tests/ui/target-feature/abi-relevant-target-modifier.baseline.stderr index fbf2ac5bff976..fc4f5085844c4 100644 --- a/tests/ui/target-feature/abi-relevant-target-modifier.baseline.stderr +++ b/tests/ui/target-feature/abi-relevant-target-modifier.baseline.stderr @@ -1,4 +1,4 @@ -warning: mixing target features will cause an ABI mismatch in crate `abi_relevant_target_modifier` +warning: mixing target features may cause an ABI mismatch in crate `abi_relevant_target_modifier` | = help: some target features modify the ABI so Rust crates compiled with different values for these target features cannot be used together safely = help: the target feature atomics-32 is enabled in `using_atomics_32` but disabled in this crate diff --git a/tests/ui/target-feature/abi-relevant-target-modifier.rs b/tests/ui/target-feature/abi-relevant-target-modifier.rs index cb09064903ba2..8294c63d15e5e 100644 --- a/tests/ui/target-feature/abi-relevant-target-modifier.rs +++ b/tests/ui/target-feature/abi-relevant-target-modifier.rs @@ -11,4 +11,4 @@ extern crate using_atomics_32; -//[baseline]~? WARN mixing target features will cause an ABI mismatch +//[baseline]~? WARN mixing target features may cause an ABI mismatch